Codebase list python-faraday / b25f6e4
New upstream version 3.14.3 Sophie Brun 3 years ago
515 changed file(s) with 526 addition(s) and 149406 deletion(s). Raw diff Collapse all Expand all
7878 # Editable install hoook
7979 _install
8080 faraday_plugins/
81 faraday/frontend/
0 .clone_and_replace_www:
1 script:
2 - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/faradaysec/faraday-angular.git frontend
3 - cd frontend
4 - (git branch -a | grep $CI_COMMIT_REF_NAME) && export FRONT_REF=$CI_COMMIT_REF_NAME || export FRONT_REF=white/master
5 - (git branch -a | grep $ANGULAR_REF) && export FRONT_REF=$ANGULAR_REF || export FRONT_REF=$FRONT_REF
6 - echo $FRONT_REF
7 - git checkout $FRONT_REF
8 - cd ..
9 - rm faraday/server/www
10 - mv frontend/www/ faraday/server/www/
11 - rm -fr frontend
12
013 generate_build_file:
114 image: registry.gitlab.com/faradaysec/devops
215 stage: pre_build
316 script:
417 - "/bin/mkdir faraday_copy"
18 - !reference [.clone_and_replace_www, script]
519 - "/usr/bin/rsync -aq --exclude 'faraday_copy' --exclude '.cache' . faraday_copy"
620 - "/bin/tar -zcf faraday.tar.gz faraday_copy"
721 rules:
2438 - mkdir -p ~/.config/cachix
2539 - export USER=$(whoami)
2640 - echo "$CACHIX_CONFG" >~/.config/cachix/cachix.dhall
41 - !reference [ .clone_and_replace_www, script ]
2742 - cachix use faradaysec
2843 - nix-build
2944 - tar cf /py3.tar $(nix-store --query --requisites $(readlink result))
11 tags:
22 - hypothesis
33 image: nixorg/nix
4 stage: testing
4 stage: test
55 allow_failure: true
66 script:
77 - nix-env -if pynixify/nixpkgs.nix -A cachix
22 tags:
33 - faradaytests
44 image: nixorg/nix
5 stage: testing # This should be after build_and_push_to_cachix to improve performance
5 stage: test # This should be after build_and_push_to_cachix to improve performance
66 script:
77 - nix-env -if pynixify/nixpkgs.nix -A cachix
88 - mkdir -p ~/.config/cachix
2929 .postgresql_test_nix_base:
3030 tags:
3131 - faradaytests
32 stage: testing
32 stage: test
3333 coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
3434 script:
3535 - nix-env -if pynixify/nixpkgs.nix -A cachix
6464 .sqlite_test_nix_base:
6565 tags:
6666 - faradaytests
67 stage: testing
67 stage: test
6868 coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
6969 script:
7070 - nix-env -if pynixify/nixpkgs.nix -A cachix
00 .unit_tests_base:
11 tags:
22 - faradaytests
3 stage: testing
3 stage: test
44 coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
55 script:
66 - export LC_ALL=C.UTF-8
00 qa_integration:
11 stage: upload_testing
22 variables:
3 REMOTE_BRANCH: $CI_COMMIT_BRANCH
3 REMOTE_BRANCH: $CI_COMMIT_REF_NAME
44 MAIN_COMMIT_SHA: $CI_COMMIT_SHA
55 trigger:
66 project: faradaysec/qa/automation
4545 - local: .gitlab/ci/publish/.set-tag-gitlab-ci.yml
4646 - local: .gitlab/ci/publish/.docker-publish-gitlab-ci.yml
4747
48 - template: Security/Secret-Detection.gitlab-ci.yml
49
4850 stages:
4951 - pre_testing
50 - testing
52 - test
5153 - post_testing
5254 - pre_build
5355 - build
33 rev: v3.1.0
44 hooks:
55 - id: trailing-whitespace
6 exclude: '^faraday/server/www/'
67 - id: end-of-file-fixer
8 exclude: '^faraday/server/www/'
79 - id: check-json
10 exclude: '^faraday/server/www/'
811 - id: check-yaml
12 exclude: '^faraday/server/www/'
913 - id: debug-statements
14 exclude: '^faraday/server/www/'
1015 - repo: https://gitlab.com/pycqa/flake8
1116 rev: 3.8.3
1217 hooks:
1318 - id: flake8
19 exclude: '^faraday/server/www/'
1420 additional_dependencies: [flake8-typing-imports==1.9.0]
1521 - repo: https://github.com/ikamensh/flynt/
1622 rev: '0.56'
00 The PRIMARY AUTHORS are:
11
2 * Ciro Goyeneche
23 * Daniel Foguelman
34 * Diego Nadares
45 * Eric Horvat
1415 * Jorge Luis González Iznaga
1516 * Leonardo Lazzaro
1617 * Marcelo Pedraza
18 * Manuel Jose Sotomayor Torrealba
1719 * Mariano Marchetta
1820 * Martín Rocha
1921 * Matias Ariel Ré Medina
2022 * Matias Lang
2123 * Micaela Ranea Sánchez
24 * Nahuel Aloso
2225 * Nicolas Rebagliati
2326 * Sebastian Brachi
2427 * Sebastian Kulesz
5154 * tsxltjecwb
5255 * Ulisses Albuquerque
5356 * xtr4nge
54
1313 * ADD v3 API, which includes:
1414 * All endpoints ends without `/`
1515 * `PATCH {model}/id` endpoints
16 * Bulk update via PATCH `{model}` endpoints
17 * Bulk delete via DELETE `{model}` endpoints
16 * ~~Bulk update via PATCH `{model}` endpoints~~ In a future release
17 * ~~Bulk delete via DELETE `{model}` endpoints~~ In a future release
1818 * Endpoints removed:
1919 * `/v2/ws/<workspace_id>/activate/`
2020 * `/v2/ws/<workspace_id>/change_readonly/`
0 Mar 30th, 2021
0 * MOD MAYOR Breaking change: Use frontend from other repository
1 * ADD `last_run` to executors and agents
2 * ADD ignore info vulns option (from faraday-plugins 1.4.3)
3 * ADD invalid logins are registered in `audit.log`
4 * ADD agent registration tokens are now 6-digit short and automatically regenerated every 30 seconds
5 * MOD Fix logout redirect loop
6 * REMOVE support for native SSL
00 New features in the latest update
11 =====================================
22
3
4 3.14.3 [Mar 30th, 2021]:
5 ---
6 * MOD MAYOR Breaking change: Use frontend from other repository
7 * ADD `last_run` to executors and agents
8 * ADD ignore info vulns option (from faraday-plugins 1.4.3)
9 * ADD invalid logins are registered in `audit.log`
10 * ADD agent registration tokens are now 6-digit short and automatically regenerated every 30 seconds
11 * MOD Fix logout redirect loop
12 * REMOVE support for native SSL
313
414 3.14.2 [Feb 26th, 2021]:
515 ---
818 * nextnet
919 * openscap
1020 * FIX old versions of Nessus plugins bugs
11
1221
1322 3.14.1 [Feb 17th, 2021]:
1423 ---
2837 * ADD v3 API, which includes:
2938 * All endpoints ends without `/`
3039 * `PATCH {model}/id` endpoints
31 * Bulk update via PATCH `{model}` endpoints
32 * Bulk delete via DELETE `{model}` endpoints
40 * ~~Bulk update via PATCH `{model}` endpoints~~ In a future release
41 * ~~Bulk delete via DELETE `{model}` endpoints~~ In a future release
3342 * Endpoints removed:
3443 * `/v2/ws/<workspace_id>/activate/`
3544 * `/v2/ws/<workspace_id>/change_readonly/`
1111
1212 Designed for simplicity, users should notice no difference between their own terminal application and the one included in Faraday. Developed with a specialized set of functionalities, users improve their own work. Do you remember the last time you programmed without an IDE? What IDEs are to programming, Faraday is to pentesting.
1313
14 ![GUI - GTK](https://raw.github.com/wiki/infobyte/faraday/images/client/gtk_main_window.png)
14 [![asciicast](https://asciinema.org/a/384132.svg)](https://asciinema.org/a/384132)
1515
1616 To read about the latest features check out the [release notes](https://github.com/infobyte/faraday/blob/master/RELEASE.md)!
1717
2020
2121 Refer to the [releases page](https://github.com/infobyte/faraday/releases) for the latest pre-made installers for all supported operating systems.
2222
23 Check out our documentation for detailed information on how to install Faraday in all of our supported platforms:
23 Check out our documentation for detailed information on how to install Faraday in all of our supported platforms
2424
25 ![Supported Os](https://raw.github.com/wiki/infobyte/faraday/images/platform/supported.png)
25 ### Install from repo
26 ```shell
27 $ pip install virtualenv
28 $ virtualenv faraday_venv
29 $ source faraday_env/bin/activate
30 $ git clone [email protected]:infobyte/faraday.git
31 $ cd faraday
32 $ git clone [email protected]:infobyte/faraday-angular.git faraday/frontend
33 $ pip install .
34 ```
2635
27 To begin the installation process, check out our [Installation Wiki](https://github.com/infobyte/faraday/wiki/Install-Guide).
36 For more information about the installation, check out our [Installation Wiki](https://github.com/infobyte/faraday/wiki/Install-Guide).
2837
2938 ## Development
3039
3746 Once you installed faraday packages, you will need to initialize the faraday database:
3847
3948 ```
40 sudo faraday-manage initdb
49 # first add your user to the faraday group
50 $ faraday-manage initdb
4151 ```
4252
4353 This will give you a *randomly generated password* to log into the web UI.
4454 Now you can start the server with:
4555
4656 ```
47 systemctl start faraday-server
57 $ sudo systemctl start faraday-server
4858 ```
4959
5060 In your browser, now you can go to localhost:5985 and login with "faraday" as username, and the password generated in the initdb step.
5767
5868 ## API
5969
60 This is a branch for a PoC of automatically generating the API documentation in the [OpenAPI/swagger](https://www.openapis.org/) format.
61 To generate the API docs, for example, to use with swagger UI, run:
70 Check out the documentation of our API [here](https://api.faradaysec.com/).
6271
63 ```
64 faraday-manage openapi-yaml
65 ```
72 ## Cli
6673
74 Try [faraday-cli](https://github.com/infobyte/faraday-cli) to easily upload for information to faraday.
75
76 Check out the documentation [here](https://docs.faraday-cli.faradaysec.com/).
6777
6878 ## Plugins list
6979
8797
8898 [Faraday Agents Dispatcher](https://github.com/infobyte/faraday_agent_dispatcher) helps user develop integrations with Faraday written in any language.
8999 Agents collects information from different network location using different tools. You can use [FaradaySEC](https://www.faradaysec.com) to orchestrate tool execution.
90
91 ### Conflicts
92
93 If two plugins produce clashing information for an individual element, a conflict that the user will have to resolve is generated. An example is if **user1** incorporates host *127.0.0.1 OS:Linux* and **user2** incorporates *127.0.0.1 OS: Linux Ubuntu 13.10*.
94
95 On our [GTK interface](https://github.com/infobyte/faraday/wiki/Usage#gtk-gui) there's a button on the bottom right corner of the main window displaying the number of conflicts in the current workspace. To resolve them, just click on the button and a window will open where you can edit the conflicting objects and select which one to keep.
96
97 ### Faraday plugin
98
99 Using our plugin you can perform various actions using the command line, for example:
100
101 $ cd faraday-dev/bin/
102 $ ./fplugin create_host 192.154.33.222 Android
103 1a7b2981c7becbcb3d5318056eb29a58817f5e67
104 $ ./fplugin filter_services http ssh -p 21 -a
105 Filtering services for ports: 21, 22, 80, 443, 8080, 8443
106
107 192.168.20.1 ssh [22] tcp open None
108 192.168.20.1 http [443] tcp open None
109 192.168.20.7 ssh [22] tcp open Linux
110 192.168.20.7 http [443] tcp open Linux
111 192.168.20.11 ssh [22] tcp open Linux
112
113
114 Read more about the [Faraday Plugin](https://github.com/infobyte/faraday/wiki/faraday-plugin).
115
116100
117101 ### CSV Exporting
118102
00 New features in the latest update
11 =====================================
22
3
4 3.14.3 [Mar 30th, 2021]:
5 ---
6 * MOD MAYOR Breaking change: Use frontend from other repository
7 * ADD `last_run` to executors and agents
8 * ADD ignore info vulns option (from faraday-plugins 1.4.3)
9 * ADD invalid logins are registered in `audit.log`
10 * ADD agent registration tokens are now 6-digit short and automatically regenerated every 30 seconds
11 * MOD Fix logout redirect loop
12 * REMOVE support for native SSL
313
414 3.14.2 [Feb 26th, 2021]:
515 ---
818 * nextnet
919 * openscap
1020 * FIX old versions of Nessus plugins bugs
11
1221
1322 3.14.1 [Feb 17th, 2021]:
1423 ---
2837 * ADD v3 API, which includes:
2938 * All endpoints ends without `/`
3039 * `PATCH {model}/id` endpoints
31 * Bulk update via PATCH `{model}` endpoints
32 * Bulk delete via DELETE `{model}` endpoints
40 * ~~Bulk update via PATCH `{model}` endpoints~~ In a future release
41 * ~~Bulk delete via DELETE `{model}` endpoints~~ In a future release
3342 * Endpoints removed:
3443 * `/v2/ws/<workspace_id>/activate/`
3544 * `/v2/ws/<workspace_id>/change_readonly/`
11 # Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
22 # See the file 'doc/LICENSE' for the license information
33
4 __version__ = '3.14.2'
4 __version__ = '3.14.3'
55 __license_version__ = __version__
0 """add last_run to executors
1
2 Revision ID: 077b7c925ded
3 Revises: 6471033046cb
4 Create Date: 2021-02-26 15:17:31.824177+00:00
5
6 """
7 from alembic import op
8 import sqlalchemy as sa
9
10
11 # revision identifiers, used by Alembic.
12 revision = '077b7c925ded'
13 down_revision = '6471033046cb'
14 branch_labels = None
15 depends_on = None
16
17
18 def upgrade():
19 op.add_column('executor', sa.Column('last_run', sa.DateTime(), nullable=True))
20
21
22 def downgrade():
23 op.drop_column('executor', 'last_run')
0 """alter otp secret length in user
1
2 Revision ID: a4def820a5bb
3 Revises: 077b7c925ded
4 Create Date: 2021-03-17 20:23:03.864089+00:00
5
6 """
7 from alembic import op
8 import sqlalchemy as sa
9
10
11 # revision identifiers, used by Alembic.
12 revision = 'a4def820a5bb'
13 down_revision = 'fa12b8322112'
14 branch_labels = None
15 depends_on = None
16
17
18 def upgrade():
19
20 op.alter_column('faraday_user',
21 'otp_secret',
22 type_=sa.String(32),
23 existing_type=sa.String(16),
24 existing_nullable=True)
25
26
27 OTP_STATES = ["disabled", "requested", "confirmed"]
28
29
30 def downgrade():
31 print("The otp secret is going down from 32-char to 16-char length. If its actual values can't fix, "
32 "we are deactivating 2FA in that user!")
33
34 users = sa.table(
35 'faraday_user',
36 sa.column('otp_secret', sa.String),
37 sa.column('id', sa.Integer),
38 sa.Column('state_otp', sa.Enum(*OTP_STATES, 'user_otp_states')),
39 )
40
41 conn = op.get_bind()
42 res = conn.execute('SELECT otp_secret, id FROM faraday_user').fetchall()
43
44 for user in res:
45 if user[0] and len(user[0]) > 16:
46 op.execute(
47 users.update().where(users.c.id == user[1]).values({'otp_secret': None, 'state_otp': "disabled"})
48 )
49
50 op.alter_column('faraday_user',
51 'otp_secret',
52 type_=sa.String(16),
53 existing_type=sa.String(32),
54 existing_nullable=True)
0 """update_workflow_modules
1
2 Revision ID: fa12b8322112
3 Revises: 077b7c925ded
4 Create Date: 2021-03-12 20:42:03.286727+00:00
5
6 """
7 from alembic import op
8 import sqlalchemy as sa
9 from faraday.server.fields import JSONType
10 from depot.fields.sqlalchemy import UploadedFileField
11 from sqlalchemy.dialects import postgresql
12
13 # revision identifiers, used by Alembic.
14 revision = 'fa12b8322112'
15 down_revision = '077b7c925ded'
16 branch_labels = None
17 depends_on = None
18
19
20 def upgrade():
21 # ### commands auto generated by Alembic - but checked! ###
22 op.add_column('action', sa.Column('description', sa.String(), nullable=True, default=""))
23 op.execute("UPDATE action SET description = ''")
24 op.alter_column('action', 'description', nullable=False)
25 op.drop_constraint('condition_rule_id_fkey', 'condition', type_='foreignkey')
26 op.create_foreign_key('condition_rule_id_fkey', 'condition', 'rule', ['rule_id'], ['id'], ondelete='CASCADE')
27 op.add_column('rule', sa.Column('description', sa.String(), nullable=True, default=""))
28 op.execute("UPDATE rule SET description = ''")
29 op.alter_column('rule', 'description', nullable=False)
30 op.drop_column('rule', 'object')
31 op.add_column('rule', sa.Column('name', sa.String()))
32 op.create_unique_constraint('ux_rule_name', 'rule', ['name'])
33
34 # Data migration: takes a few steps...
35 # Model table
36 t_rule = sa.Table(
37 'rule',
38 sa.MetaData(),
39 sa.Column('description', sa.String),
40 sa.Column('id', sa.Integer),
41 sa.Column('model', sa.String),
42 sa.Column('object_parent', sa.String),
43 sa.Column('fields', sa.JSON),
44 sa.Column('enabled', sa.Boolean),
45 sa.Column('workspace_id', sa.Integer,),
46 sa.Column('name', sa.String)
47 )
48 connection = op.get_bind()
49 # We need id and model
50 results = connection.execute(sa.select([
51 t_rule.c.id,
52 t_rule.c.model,
53 ])).fetchall()
54 # Iterate over all selected data tuples.
55 for id_, model in results:
56 # Update the new columns.
57 connection.execute(t_rule.update().where(t_rule.c.id == id_).values(
58 name=f'Rule for model {model}, {id_}',
59 ))
60 op.alter_column('rule', 'name', nullable=False)
61
62
63 def downgrade():
64 # ### commands auto generated by Alembic - but checked! ###
65 op.drop_constraint('ux_rule_name', 'rule', type_='unique')
66 op.drop_column('rule', 'name')
67 op.add_column('rule', sa.Column('object', postgresql.JSONB(astext_type=sa.Text()), autoincrement=False))
68 op.execute("UPDATE rule SET object = to_json(''::text)")
69 op.alter_column('rule', 'object', nullable=False)
70 op.drop_column('rule', 'description')
71 op.drop_constraint('condition_rule_id_fkey', 'condition', type_='foreignkey')
72 op.create_foreign_key('condition_rule_id_fkey', 'condition', 'rule', ['rule_id'], ['id'])
73 op.drop_column('action', 'description')
74 # ### end Alembic commands ###
373373 return ws
374374
375375 def _get_base_query(self, workspace_name):
376 base = super(GenericWorkspacedView, self)._get_base_query()
376 base = super()._get_base_query()
377377 return base.join(Workspace).filter(
378378 Workspace.id == self._get_workspace(workspace_name).id)
379379
395395 return context
396396
397397 def before_request(self, name, *args, **kwargs):
398 sup = super(GenericWorkspacedView, self)
398 sup = super()
399399 if hasattr(sup, 'before_request'):
400400 sup.before_request(name, *args, **kwargs)
401401 if (self._get_workspace(kwargs['workspace_name']).readonly and
589589
590590 pagination_metadata = query.paginate(page=page, per_page=per_page, error_out=False)
591591 return pagination_metadata.items, pagination_metadata
592 return super(PaginatedMixin, self)._paginate(query)
592 return super()._paginate(query)
593593
594594
595595 class FilterAlchemyMixin:
842842 application/json:
843843 schema: {schema_class}
844844 """
845 return super(RetrieveWorkspacedMixin, self).get(object_id, workspace_name=workspace_name)
845 return super().get(object_id, workspace_name=workspace_name)
846846
847847
848848 class RetrieveMultiWorkspacedMixin(RetrieveWorkspacedMixin):
10231023 application/json:
10241024 schema: {schema_class}
10251025 """
1026 return super(CreateWorkspacedMixin, self).post(workspace_name=workspace_name)
1026 return super().post(workspace_name=workspace_name)
10271027
10281028 def _perform_create(self, data, workspace_name):
10291029 assert not db.session.new
12201220 application/json:
12211221 schema: {schema_class}
12221222 """
1223 return super(UpdateWorkspacedMixin, self).put(object_id, workspace_name=workspace_name)
1223 return super().put(object_id, workspace_name=workspace_name)
12241224
12251225 def _perform_update(self, object_id, obj, data, workspace_name=None, partial=False):
12261226 # # Make sure that if I created new objects, I had properly commited them
12301230 obj.workspace = self._get_workspace(workspace_name)
12311231
12321232 self._set_command_id(obj, False)
1233 return super(UpdateWorkspacedMixin, self)._perform_update(
1234 object_id, obj, data, workspace_name)
1233 return super()._perform_update(object_id, obj, data, workspace_name)
12351234
12361235
12371236 class PatchableWorkspacedMixin(PatchableMixin):
12701269 application/json:
12711270 schema: {schema_class}
12721271 """
1273 return super(PatchableWorkspacedMixin, self).patch(object_id, workspace_name=workspace_name)
1272 return super().patch(object_id, workspace_name=workspace_name)
12741273
12751274
12761275 class DeleteMixin:
13221321 204:
13231322 description: The resource was deleted successfully
13241323 """
1325 return super(DeleteWorkspacedMixin, self).delete(object_id, workspace_name=workspace_name)
1324 return super().delete(object_id, workspace_name=workspace_name)
13261325
13271326 def _perform_delete(self, obj, workspace_name=None):
13281327 with db.session.no_autoflush:
13291328 obj.workspace = self._get_workspace(workspace_name)
13301329
1331 return super(DeleteWorkspacedMixin, self)._perform_delete(
1332 obj, workspace_name)
1330 return super()._perform_delete(obj, workspace_name)
13331331
13341332
13351333 class CountWorkspacedMixin:
15431541 validators to not blankable fields
15441542 """
15451543 def _add_column_kwargs(self, kwargs, column):
1546 super(CustomModelConverter, self)._add_column_kwargs(kwargs, column)
1544 super()._add_column_kwargs(kwargs, column)
15471545 if not column.info.get('allow_blank', True):
15481546 kwargs['validate'].append(Length(min=1))
15491547
15501548
15511549 class CustomModelSchemaOpts(ModelSchemaOpts):
15521550 def __init__(self, *args, **kwargs):
1553 super(CustomModelSchemaOpts, self).__init__(*args, **kwargs)
1551 super().__init__(*args, **kwargs)
15541552 self.model_converter = CustomModelConverter
15551553
15561554
15851583 TYPE_MAPPING[str] = NullToBlankString
15861584
15871585 def __init__(self, *args, **kwargs):
1588 super(AutoSchema, self).__init__(*args, **kwargs)
1586 super().__init__(*args, **kwargs)
15891587 self.unknown = EXCLUDE
15901588
15911589 class FilterAlchemyModelConverter(ModelConverter):
15941592 It is used to make filteralchemy support not nullable columns"""
15951593
15961594 def _add_column_kwargs(self, kwargs, column):
1597 super(FilterAlchemyModelConverter, self)._add_column_kwargs(kwargs,
1598 column)
1595 super()._add_column_kwargs(kwargs, column)
15991596 kwargs['required'] = False
16001597
16011598
55 import flask
66 import logging
77
8 import pyotp
89 from flask import Blueprint, abort, request, make_response, jsonify
910 from flask_classful import route
1011 from marshmallow import fields, Schema, EXCLUDE
2930 from faraday.server.events import changes_queue
3031
3132 agent_api = Blueprint('agent_api', __name__)
33 agent_creation_api = Blueprint('agent_creation_api', __name__)
3234
3335 logger = logging.getLogger(__name__)
3436
3941 )
4042 id = fields.Integer(dump_only=True)
4143 name = fields.String(dump_only=True)
44 last_run = fields.DateTime(dump_only=True)
4245
4346 class Meta:
4447 model = Executor
4548 fields = (
4649 'id',
4750 'name',
51 'last_run',
4852 'parameters_metadata',
4953 )
5054
5862 update_date = fields.DateTime(dump_only=True)
5963 is_online = fields.Boolean(dump_only=True)
6064 executors = fields.Nested(ExecutorSchema(), dump_only=True, many=True)
65 last_run = fields.DateTime(dump_only=True)
6166
6267 class Meta:
6368 model = Agent
7277 'token',
7378 'is_online',
7479 'active',
75 'executors'
80 'executors',
81 'last_run'
7682 )
7783
7884
128134
129135 def _perform_create(self, data, **kwargs):
130136 token = data.pop('token')
131 if not faraday_server.agent_token:
137 if not faraday_server.agent_registration_secret:
132138 # someone is trying to use the token, but no token was generated yet.
133139 abort(401, "Invalid Token")
134 if token != faraday_server.agent_token:
140 if not pyotp.TOTP(faraday_server.agent_registration_secret).verify(token, valid_window=1):
135141 abort(401, "Invalid Token")
136142
137143 workspace_names = data.pop('workspaces')
160166 for workspace_name in workspace_names
161167 )
162168
163 agent = super(AgentCreationView, self)._perform_create(data, **kwargs)
169 agent = super()._perform_create(data, **kwargs)
164170 agent.workspaces = workspaces
165171
166172 db.session.add(agent)
186192 )
187193
188194 def __init__(self, *args, **kwargs):
189 super(AgentRunSchema, self).__init__(*args, **kwargs)
195 super().__init__(*args, **kwargs)
190196 self.unknown = EXCLUDE
191197
192198
329335 parameters_data=executor_data["args"],
330336 command=command
331337 )
338 executor.last_run = datetime.utcnow()
332339 db.session.add(agent_execution)
333340 db.session.commit()
334341
356363 @route('/<int:agent_id>', methods=['DELETE'])
357364 def remove_workspace(self, workspace_name, agent_id):
358365 # This endpoint is not an exception for V3, overrides logic of DELETE
359 return super(AgentV3View, self).remove_workspace(workspace_name, agent_id)
366 return super().remove_workspace(workspace_name, agent_id)
360367
361368 @route('/<int:agent_id>/run', methods=['POST'])
362369 def run_agent(self, workspace_name, agent_id):
363 return super(AgentV3View, self).run_agent(workspace_name, agent_id)
370 return super().run_agent(workspace_name, agent_id)
364371
365372 remove_workspace.__doc__ = AgentView.remove_workspace.__doc__
366373 run_agent.__doc__ = AgentView.run_agent.__doc__
368375
369376 AgentWithWorkspacesView.register(agent_api)
370377 AgentWithWorkspacesV3View.register(agent_api)
371 AgentCreationView.register(agent_api)
372 AgentCreationV3View.register(agent_api)
378 AgentCreationView.register(agent_creation_api)
379 AgentCreationV3View.register(agent_creation_api)
373380 AgentView.register(agent_api)
374381 AgentV3View.register(agent_api)
00 # Faraday Penetration Test IDE
11 # Copyright (C) 2019 Infobyte LLC (http://www.infobytesec.com/)
22 # See the file 'doc/LICENSE' for the license information
3 import flask
3 import datetime
4
45 from flask import Blueprint
5 from flask_wtf.csrf import validate_csrf
6 from wtforms import ValidationError
76 from marshmallow import fields, Schema
87 from faraday.server.api.base import (
98 GenericView,
109 )
1110 from faraday.server.config import faraday_server
12
11 import pyotp
1312
1413 agent_auth_token_api = Blueprint('agent_auth_token_api', __name__)
1514
1615
1716 class AgentAuthTokenSchema(Schema):
1817 token = fields.String(required=True)
18 expires_in = fields.Float(required=True)
1919
2020
2121 class AgentAuthTokenView(GenericView):
2626 """
2727 ---
2828 get:
29 summary: "Get a token to register new agents."
29 summary: "Get the current TOTP token to register new agents."
3030 tags: ["Agent"]
3131 responses:
3232 200:
3939 200:
4040 description: Ok
4141 """
42 totp = pyotp.TOTP(faraday_server.agent_registration_secret)
4243 return AgentAuthTokenSchema().dump(
43 {'token': faraday_server.agent_token})
44
45 def post(self):
46 """
47 ---
48 post:
49 summary: "Generate a new token to register new agents."
50 tags: ["Agent"]
51 responses:
52 200:
53 description: Ok
54 content:
55 application/json:
56 schema: AgentAuthTokenSchema
57 """
58 from faraday.server.app import save_new_agent_creation_token # pylint:disable=import-outside-toplevel
59 try:
60 validate_csrf(flask.request.form.get('csrf_token'))
61 except ValidationError:
62 flask.abort(403)
63 save_new_agent_creation_token()
64 return AgentAuthTokenSchema().dump(
65 {'token': faraday_server.agent_token})
44 {'token': totp.now(),
45 'expires_in': totp.interval - datetime.datetime.now().timestamp() % totp.interval})
6646
6747
6848 class AgentAuthTokenV3View(AgentAuthTokenView):
7151
7252 AgentAuthTokenView.register(agent_auth_token_api)
7353 AgentAuthTokenV3View.register(agent_auth_token_api)
74
75
76 # I'm Py3
6868 """Used like a nested field with many objects, but it decides which
6969 schema to use based on the type of each vuln"""
7070 def __init__(self, *args, **kwargs):
71 super(PolymorphicVulnerabilityField, self).__init__(*args, **kwargs)
71 super().__init__(*args, **kwargs)
7272 self.many = kwargs.get('many', False)
7373 self.vuln_schema = VulnerabilitySchema()
7474 self.vulnweb_schema = BulkVulnerabilityWebSchema()
144144
145145 @route('/activity_feed')
146146 def activity_feed(self, workspace_name):
147 return super(CommandV3View, self).activity_feed(workspace_name)
147 return super().activity_feed(workspace_name)
148148
149149 @route('/last', methods=['GET'])
150150 def last_command(self, workspace_name):
151 return super(CommandV3View, self).last_command(workspace_name)
151 return super().last_command(workspace_name)
152152
153153 activity_feed.__doc__ = CommandView.activity_feed.__doc__
154154 last_command.__doc__ = CommandView.last_command.__doc__
4545 raise InvalidUsage('Can\'t comment inexistent object')
4646 if obj.workspace != workspace:
4747 raise InvalidUsage('Can\'t comment object of another workspace')
48 return super(CommentCreateMixing, self)._perform_create(data, workspace_name)
48 return super()._perform_create(data, workspace_name)
4949
5050
5151 class CommentView(CommentCreateMixing, ReadWriteWorkspacedView):
7979 'object': self.schema_class().dump(comment),
8080 }
8181 ))
82 res = super(UniqueCommentView, self)._perform_create(data, workspace_name)
82 res = super()._perform_create(data, workspace_name)
8383 return res
8484
8585
4848 for read_only_key in ['field_name', 'table_name', 'field_type']:
4949 if read_only_key in data:
5050 data.pop(read_only_key)
51 return super(CustomFieldsSchemaView, self)._update_object(obj, data)
51 return super()._update_object(obj, data)
5252
5353
5454 class CustomFieldsSchemaV3View(CustomFieldsSchemaView, PatchableMixin):
243243 hostnames = parse_hosts(host_dict.pop('hostnames'))
244244 other_fields = {'owned': False, 'mac': u'00:00:00:00:00:00', 'default_gateway_ip': u'None'}
245245 host_dict.update(other_fields)
246 host = super(HostsView, self)._perform_create(host_dict, workspace_name)
246 host = super()._perform_create(host_dict, workspace_name)
247247 host.workspace = workspace
248248 for name in hostnames:
249249 get_or_create(db.session, Hostname, name=name, host=host, workspace=host.workspace)
348348
349349 def _perform_create(self, data, **kwargs):
350350 hostnames = data.pop('hostnames', [])
351 host = super(HostsView, self)._perform_create(data, **kwargs)
351 host = super()._perform_create(data, **kwargs)
352352 for name in hostnames:
353353 get_or_create(db.session, Hostname, name=name, host=host,
354354 workspace=host.workspace)
366366 # A commit is required here, otherwise it breaks (i'm not sure why)
367367 db.session.commit()
368368
369 return super(HostsView, self)._update_object(obj, data)
369 return super()._update_object(obj, data)
370370
371371 def _filter_query(self, query):
372 query = super(HostsView, self)._filter_query(query)
372 query = super()._filter_query(query)
373373 search_term = flask.request.args.get('search', None)
374374 if search_term is not None:
375375 like_term = '%' + search_term + '%'
445445
446446 @route('/<host_id>/services')
447447 def service_list(self, workspace_name, host_id):
448 return super(HostsV3View, self).service_list(workspace_name, host_id)
448 return super().service_list(workspace_name, host_id)
449449
450450 @route('/<host_id>/tools_history')
451451 def tool_impacted_by_host(self, workspace_name, host_id):
452 return super(HostsV3View, self).tool_impacted_by_host(workspace_name, host_id)
452 return super().tool_impacted_by_host(workspace_name, host_id)
453453
454454 @route('/bulk_create', methods=['POST'])
455455 def bulk_create(self, workspace_name):
456 return super(HostsV3View, self).bulk_create(workspace_name)
456 return super().bulk_create(workspace_name)
457457
458458 @route('/countVulns')
459459 def count_vulns(self, workspace_name):
460 return super(HostsV3View, self).count_vulns()
460 return super().count_vulns()
461461
462462 service_list.__doc__ = HostsView.service_list.__doc__
463463 tool_impacted_by_host.__doc__ = HostsView.tool_impacted_by_host.__doc__
131131 port_number = data.get("port", "1")
132132 if not port_number.isdigit():
133133 abort(make_response(jsonify(message="Invalid Port number"), 400))
134 return super(ServiceView, self)._perform_create(data, **kwargs)
134 return super()._perform_create(data, **kwargs)
135135
136136
137137 class ServiceV3View(ServiceView, PatchableWorkspacedMixin):
181181 schema: VulnerabilityTemplateSchema
182182 """
183183 with lock:
184 return super(VulnerabilityTemplateView, self).post(**kwargs)
184 return super().post(**kwargs)
185185
186186 def _get_schema_instance(self, route_kwargs, **kwargs):
187 schema = super(VulnerabilityTemplateView, self)._get_schema_instance(
187 schema = super()._get_schema_instance(
188188 route_kwargs, **kwargs)
189189
190190 return schema
261261 for vuln in vulns_to_create:
262262 try:
263263 vuln_schema = schema.load(vuln)
264 super(VulnerabilityTemplateView, self)._perform_create(vuln_schema)
264 super()._perform_create(vuln_schema)
265265 db.session.commit()
266266 except ValidationError as e:
267267 vulns_with_errors.append((vuln.get('_id', ''), vuln['name']))
327327
328328 @route('/bulk_create', methods=['POST'])
329329 def bulk_create(self):
330 return super(VulnerabilityTemplateV3View, self).bulk_create()
330 return super().bulk_create()
331331
332332 bulk_create.__doc__ = VulnerabilityTemplateView.bulk_create.__doc__
333333
438438 pass
439439 request.args = ImmutableMultiDict(new_args)
440440
441 query = super(VulnerabilityFilterSet, self).filter()
441 query = super().filter()
442442
443443 if command_id:
444444 # query = query.filter(CommandObject.command_id == int(command_id))
477477
478478 def _validate_uniqueness(self, obj, object_id=None):
479479 unique_fields = self.unique_fields_by_class[obj.__class__.__name__]
480 super(VulnerabilityView, self)._validate_uniqueness(
481 obj, object_id, unique_fields)
480 super()._validate_uniqueness(obj, object_id, unique_fields)
482481
483482 def _get_schema_instance(self, route_kwargs, **kwargs):
484 schema = super(VulnerabilityView, self)._get_schema_instance(
485 route_kwargs, **kwargs)
483 schema = super()._get_schema_instance(route_kwargs, **kwargs)
486484
487485 return schema
488486
496494 references = data.pop('references', [])
497495 policyviolations = data.pop('policy_violations', [])
498496 try:
499 obj = super(VulnerabilityView, self)._perform_create(data, **kwargs)
497 obj = super()._perform_create(data, **kwargs)
500498 except TypeError:
501499 # TypeError is raised when trying to instantiate an sqlalchemy model
502500 # with invalid attributes, for example VulnerabilityWeb with host_id
538536 def _update_object(self, obj, data, **kwargs):
539537 data.pop('type', '') # It's forbidden to change vuln type!
540538 data.pop('tool', '')
541 return super(VulnerabilityView, self)._update_object(obj, data)
539 return super()._update_object(obj, data)
542540
543541 def _perform_update(self, object_id, obj, data, workspace_name=None, partial=False):
544542 attachments = data.pop('_attachments', None if partial else {})
545 obj = super(VulnerabilityView, self)._perform_update(object_id, obj, data, workspace_name)
543 obj = super()._perform_update(object_id, obj, data, workspace_name)
546544 db.session.flush()
547545 if attachments is not None:
548546 self._process_attachments(obj, attachments)
555553 This is too complex to get_joinedloads so I have to
556554 override the function
557555 """
558 query = super(VulnerabilityView, self)._get_eagerloaded_query(
556 query = super()._get_eagerloaded_query(
559557 *args, **kwargs)
560558 joinedloads = [
561559 joinedload(Vulnerability.host)
583581 ), *joinedloads)
584582
585583 def _filter_query(self, query):
586 query = super(VulnerabilityView, self)._filter_query(query)
584 query = super()._filter_query(query)
587585 search_term = flask.request.args.get('search', None)
588586 if search_term is not None:
589587 # TODO migration: add more fields to free text search
647645 200:
648646 description: Ok
649647 """
650 res = super(VulnerabilityView, self).count(**kwargs)
648 res = super().count(**kwargs)
651649
652650 def convert_group(group):
653651 group = group.copy()
10941092
10951093 @route('/<int:vuln_id>/attachment', methods=['POST'])
10961094 def post_attachment(self, workspace_name, vuln_id):
1097 return super(VulnerabilityV3View, self).post_attachment(workspace_name, vuln_id)
1095 return super().post_attachment(workspace_name, vuln_id)
10981096
10991097 @route('/<int:vuln_id>/attachment/<attachment_filename>', methods=['GET'])
11001098 def get_attachment(self, workspace_name, vuln_id, attachment_filename):
1101 return super(VulnerabilityV3View, self).get_attachment(workspace_name, vuln_id, attachment_filename)
1099 return super().get_attachment(workspace_name, vuln_id, attachment_filename)
11021100
11031101 @route('/<int:vuln_id>/attachment', methods=['GET'])
11041102 def get_attachments_by_vuln(self, workspace_name, vuln_id):
1105 return super(VulnerabilityV3View, self).get_attachments_by_vuln(workspace_name, vuln_id)
1103 return super().get_attachments_by_vuln(workspace_name, vuln_id)
11061104
11071105 @route('/<int:vuln_id>/attachment/<attachment_filename>', methods=['DELETE'])
11081106 def delete_attachment(self, workspace_name, vuln_id, attachment_filename):
1109 return super(VulnerabilityV3View, self).delete_attachment(workspace_name, vuln_id, attachment_filename)
1107 return super().delete_attachment(workspace_name, vuln_id, attachment_filename)
11101108
11111109 @route('/export_csv', methods=['GET'])
11121110 def export_csv(self, workspace_name):
1113 return super(VulnerabilityV3View, self).export_csv(workspace_name)
1111 return super().export_csv(workspace_name)
11141112
11151113 @route('/top_users', methods=['GET'])
11161114 def top_users(self, workspace_name):
1117 return super(VulnerabilityV3View, self).top_users(workspace_name)
1115 return super().top_users(workspace_name)
11181116
11191117 post_attachment.__doc__ = VulnerabilityView.post_attachment.__doc__
11201118 get_attachment.__doc__ = VulnerabilityView.post_attachment.__doc__
262262 abort(make_response(jsonify(message="Workspace start date can't be greater than the end date"), 400))
263263
264264 scope = data.pop('scope', [])
265 workspace = super(WorkspaceView, self)._perform_create(data, **kwargs)
265 workspace = super()._perform_create(data, **kwargs)
266266 workspace.set_scope(scope)
267267
268268 db.session.commit()
271271 def _update_object(self, obj, data, **kwargs):
272272 scope = data.pop('scope', [])
273273 obj.set_scope(scope)
274 return super(WorkspaceView, self)._update_object(obj, data)
274 return super()._update_object(obj, data)
275275
276276 def _dump(self, obj, route_kwargs, **kwargs):
277277 # When the object was created or updated it doesn't have the stats
278278 # loaded so I have to query it again
279279 if not kwargs.get('many') and obj.vulnerability_total_count is None:
280280 obj = self._get_object(obj.name)
281 return super(WorkspaceView, self)._dump(obj, route_kwargs, **kwargs)
281 return super()._dump(obj, route_kwargs, **kwargs)
282282
283283 @route('/<workspace_id>/activate/', methods=["PUT"])
284284 def activate(self, workspace_id):
44 import string
55 import datetime
66
7 import pyotp
78 import requests
9 from flask_limiter import Limiter
10 from flask_limiter.util import get_remote_address
811 from itsdangerous import TimedJSONWebSignatureSerializer, SignatureExpired, BadSignature
912 from random import SystemRandom
1013
240243 config.write(configfile)
241244
242245
243 def save_new_agent_creation_token():
246 def save_new_agent_creation_token_secret():
244247 assert LOCAL_CONFIG_FILE.exists()
245248 config = ConfigParser()
246249 config.read(LOCAL_CONFIG_FILE)
247 rng = SystemRandom()
248 agent_token = "".join([rng.choice(string.ascii_letters + string.digits) for _ in range(25)])
249 config.set('faraday_server', 'agent_token', agent_token)
250 registration_secret = pyotp.random_base32()
251 config.set('faraday_server', 'agent_registration_secret', registration_secret)
250252 with open(LOCAL_CONFIG_FILE, 'w') as configfile:
251253 config.write(configfile)
252 faraday.server.config.faraday_server.agent_token = agent_token
254 faraday.server.config.faraday_server.agent_registration_secret = registration_secret
253255
254256
255257 def expire_session(app, user):
299301 for rule_ in CustomFlask.SKIP_RULES:
300302 if rule_ == rule:
301303 return
302 return super(CustomFlask, self).add_url_rule(rule, endpoint, view_func, **options)
304 return super().add_url_rule(rule, endpoint, view_func, **options)
303305
304306 app = CustomFlask(__name__, static_folder=None)
305307
317319 else:
318320 app.config['SECRET_KEY'] = secret_key
319321
320 if faraday.server.config.faraday_server.agent_token is None:
321 save_new_agent_creation_token()
322 if faraday.server.config.faraday_server.agent_registration_secret is None:
323 save_new_agent_creation_token_secret()
322324
323325 login_failed_message = ("Invalid username or password", 'error')
324326
328330 'WTF_CSRF_ENABLED': False,
329331 'SECURITY_USER_IDENTITY_ATTRIBUTES': ['username'],
330332 'SECURITY_POST_LOGIN_VIEW': '/_api/session',
331 'SECURITY_POST_LOGOUT_VIEW': '/_api/logout',
332333 'SECURITY_POST_CHANGE_VIEW': '/_api/change',
333334 'SECURITY_RESET_PASSWORD_TEMPLATE': '/security/reset.html',
334335 'SECURITY_POST_RESET_VIEW': '/',
403404 db,
404405 user_model=User,
405406 role_model=None) # We won't use flask security roles feature
407
408 from faraday.server.api.modules.agent import agent_creation_api # pylint: disable=import-outside-toplevel
409
410 app.limiter = Limiter(
411 app,
412 key_func=get_remote_address,
413 default_limits=[]
414 )
415 if not testing:
416 app.limiter.limit(faraday.server.config.limiter_config.login_limit)(agent_creation_api)
417
418 app.register_blueprint(agent_creation_api)
419
406420 Security(app, app.user_datastore, login_form=CustomLoginForm)
407421 # Make API endpoints require a login user by default. Based on
408422 # https://stackoverflow.com/questions/13428708/best-way-to-make-flask-logins-login-required-the-default
418432 register_blueprints(app)
419433 register_handlers(app)
420434
421 app.view_functions['agent_api.AgentCreationView:post'].is_public = True
422 app.view_functions['agent_api.AgentCreationV3View:post'].is_public = True
435 app.view_functions['agent_creation_api.AgentCreationView:post'].is_public = True
436 app.view_functions['agent_creation_api.AgentCreationV3View:post'].is_public = True
423437
424438 return app
425439
443457
444458 def validate(self):
445459
460 user_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
461 time_now = datetime.datetime.now()
462
446463 # Use super of LoginForm, not super of CustomLoginForm, since I
447464 # want to skip the LoginForm validate logic
448465 if not super(LoginForm, self).validate():
466 audit_logger.warning(f"Invalid Login - User [{self.email.data}] from IP [{user_ip}] at [{time_now}]")
449467 return False
450468 self.email.data = remove_null_caracters(self.email.data)
451469
452470 self.user = _datastore.get_user(self.email.data)
453471
454472 if self.user is None:
473 audit_logger.warning(f"Invalid Login - User [{self.email.data}] from IP [{user_ip}] at [{time_now}] - "
474 f"Reason: [Invalid Username]")
455475 self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
456476 return False
457477
458478 self.user.password = remove_null_caracters(self.user.password)
459479 if not self.user.password:
480 audit_logger.warning(f"Invalid Login - User [{self.email.data}] from IP [{user_ip}] at [{time_now}] - "
481 f"Reason: [Invalid Password]")
460482 self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
461483 return False
462484 self.password.data = remove_null_caracters(self.password.data)
463485 if not verify_and_update_password(self.password.data, self.user):
486 audit_logger.warning(f"Invalid Login - User [{self.email.data}] from IP [{user_ip}] at [{time_now}] - "
487 f"Reason: [Invalid Password]")
464488 self.email.errors.append(get_message('USER_DOES_NOT_EXIST')[0])
465489 return False
466490 # if requires_confirmation(self.user):
467491 # self.email.errors.append(get_message('CONFIRMATION_REQUIRED')[0])
468492 # return False
469493 if not self.user.is_active:
494 audit_logger.warning(f"Invalid Login - User [{self.email.data}] from IP [{user_ip}] at [{time_now}] - "
495 f"Reason: [Disabled Account]")
470496 self.email.errors.append(get_message('DISABLED_ACCOUNT')[0])
471497 return False
472498 return True
106106 section = faraday_server
107107 elif section_name == 'ldap':
108108 section = ldap
109 elif section_name == 'ssl':
110 section = ssl
111 elif section_name == 'websocket_ssl':
112 section = websocket_ssl
113109 elif section_name == 'storage':
114110 section = storage
115111 elif section_name == 'logger':
116112 section = logger_config
113 elif section_name == 'limiter':
114 section = limiter_config
117115 elif section_name == 'smtp':
118116 section = smtp
119117 else:
129127 class DashboardConfigObject(ConfigSection):
130128 def __init__(self):
131129 self.show_vulns_by_price = False
130
131
132 class LimiterConfigObject(ConfigSection):
133 def __init__(self):
134 self.enabled = False
135 self.login_limit = "10/minutes"
132136
133137
134138 class FaradayServerConfigObject(ConfigSection):
139143 self.websocket_port = None
140144 self.session_timeout = 12
141145 self.api_token_expiration = 43200 # Default as 12 hs
142 self.agent_token = None
146 self.agent_registration_secret = None
143147 self.debug = False
144148 self.custom_plugins_folder = None
149 self.ignore_info_severity = False
145150
146151
147152 class LDAPConfigObject(ConfigSection):
158163 self.use_start_tls = None
159164
160165
161 class SSLConfigObject(ConfigSection):
162 def __init__(self):
163 self.certificate = None
164 self.keyfile = None
165 self.port = None
166 self.enabled = False
167
168
169 class WebsocketSSLConfigObject(ConfigSection):
170 def __init__(self):
171 self.keyfile = None
172 self.certificate = None
173 self.enabled = False
174
175166
176167 class SmtpConfigObject(ConfigSection):
177168 def __init__(self):
202193 dashboard = DashboardConfigObject()
203194 faraday_server = FaradayServerConfigObject()
204195 ldap = LDAPConfigObject()
205 ssl = SSLConfigObject()
206 websocket_ssl = WebsocketSSLConfigObject()
207196 storage = StorageConfigObject()
208197 logger_config = LoggerConfig()
209198 smtp = SmtpConfigObject()
199 limiter_config = LimiterConfigObject()
210200
211201 parse_and_bind_configuration()
212202
219209 'lic_db': CONST_LICENSES_DB,
220210 'vuln_model_db': CONST_VULN_MODEL_DB,
221211 'show_vulns_by_price': dashboard.show_vulns_by_price,
222 'websocket_ssl': websocket_ssl.enabled,
223212 'websocket_port': faraday_server.websocket_port,
224213 }
225214 return doc
5151 if image_format:
5252 content_type = f'image/{image_format}'
5353 self.generate_thumbnail(content)
54 return super(FaradayUploadedFile, self).process_content(
54 return super().process_content(
5555 content, filename, content_type)
5656
5757 def generate_thumbnail(self, content):
33 import logging
44 import operator
55 import string
6 from datetime import datetime
6 from datetime import datetime, timedelta
77 from functools import partial
88 from random import SystemRandom
99
106106 return self._engine
107107
108108 # Call original metohd and register events
109 rv = super(CustomEngineConnector, self).get_engine()
109 rv = super().get_engine()
110110 if uri.startswith('sqlite://'):
111111 with self._lock:
112112 @event.listens_for(rv, "connect")
530530 else:
531531 getter, setter = parent._default_getset(parent.collection_class)
532532
533 super(CustomAssociationSet, self).__init__(
533 super().__init__(
534534 lazy_collection, creator, getter, setter, parent)
535535
536536 def _create(self, value):
706706 "flushing the session"
707707 kwargs['object_id'] = object_.id
708708 kwargs['object_type'] = object_type
709 return super(CommandObject, self).__init__(**kwargs)
709 return super().__init__(**kwargs)
710710
711711
712712 def _make_created_objects_sum(object_type_filter):
13111311 )
13121312
13131313 def __init__(self, name=None, **kwargs):
1314 super(ReferenceTemplate, self).__init__(name=name,
1315 **kwargs)
1314 super().__init__(name=name, **kwargs)
13161315
13171316
13181317 class Reference(Metadata):
13381337 )
13391338
13401339 def __init__(self, name=None, workspace_id=None, **kwargs):
1341 super(Reference, self).__init__(name=name,
1342 workspace_id=workspace_id,
1343 **kwargs)
1340 super().__init__(name=name, workspace_id=workspace_id, **kwargs)
13441341
13451342 @property
13461343 def parent(self):
14221419 )
14231420
14241421 def __init__(self, name=None, **kwargs):
1425 super(PolicyViolationTemplate, self).__init__(name=name,
1426 **kwargs)
1422 super().__init__(name=name, **kwargs)
14271423
14281424
14291425 class PolicyViolation(Metadata):
14521448 )
14531449
14541450 def __init__(self, name=None, workspace_id=None, **kwargs):
1455 super(PolicyViolation, self).__init__(name=name,
1456 workspace_id=workspace_id,
1457 **kwargs)
1451 super().__init__(name=name, workspace_id=workspace_id, **kwargs)
14581452
14591453 @property
14601454 def parent(self):
17801774 role = Column(Enum(*ROLES, name='user_roles'),
17811775 nullable=False, default='client')
17821776 _otp_secret = Column(
1783 String(16),
1777 String(32),
17841778 name="otp_secret", nullable=True)
17851779 state_otp = Column(Enum(*OTP_STATES, name='user_otp_states'), nullable=False, default="disabled")
17861780 preferences = Column(JSONType, nullable=True, default={})
17971791 kwargs.pop('roles')
17981792 except KeyError:
17991793 pass
1800 super(User, self).__init__(*args, **kwargs)
1794 super().__init__(*args, **kwargs)
18011795
18021796 def __repr__(self):
18031797 return f"<{'LDAP ' if self.is_ldap else ''}User: {self.username}>"
21892183 backref=backref('executors', cascade="all, delete-orphan"),
21902184 )
21912185 parameters_metadata = Column(JSONType, nullable=False, default={})
2186 last_run = Column(DateTime)
21922187 # workspace_id = Column(Integer, ForeignKey('workspace.id'), index=True, nullable=False)
21932188 # workspace = relationship('Workspace', backref=backref('executors', cascade="all, delete-orphan"))
21942189
22692264 return 'offline'
22702265 else:
22712266 return 'paused'
2267
2268 @property
2269 def last_run(self):
2270 execs = db.session.query(Executor).filter_by(agent_id=self.id)
2271 if execs:
2272 _last_run = None
2273 for exe in execs:
2274 if _last_run is None or (exe.last_run is not None and _last_run - exe.last_run <= timedelta()):
2275 _last_run = exe.last_run
2276 return _last_run
2277 return None
22722278
22732279
22742280 class AgentExecution(Metadata):
3838 class FaradayCustomField(fields.Field):
3939 def __init__(self, table_name='vulnerability', *args, **kwargs):
4040 self.table_name = table_name
41 super(FaradayCustomField, self).__init__(*args, **kwargs)
41 super().__init__(*args, **kwargs)
4242
4343 def _serialize(self, value, attr, obj, **kwargs):
4444 if not value:
102102 def __init__(self, field_name='id', *args, **kwargs):
103103 self.field_name = field_name
104104 self.many = kwargs.get('many', False)
105 super(PrimaryKeyRelatedField, self).__init__(*args, **kwargs)
105 super().__init__(*args, **kwargs)
106106
107107 def _serialize(self, value, attr, obj):
108108 if self.many:
132132
133133 def __init__(self, target_schema, *args, **kwargs):
134134 self.target_schema = target_schema
135 super(SelfNestedField, self).__init__(*args, **kwargs)
135 super().__init__(*args, **kwargs)
136136
137137 def _serialize(self, value, attr, obj):
138138 return self.target_schema.dump(obj)
167167 if kwargs.get('required'):
168168 self.read_field.required = self.write_field.required = True
169169
170 super(MutableField, self).__init__(**kwargs)
170 super().__init__(**kwargs)
171171
172172 def _serialize(self, value, attr, obj):
173173
185185
186186 def _add_to_schema(self, field_name, schema):
187187 # Propagate to child fields
188 super(MutableField, self)._add_to_schema(field_name, schema)
188 super()._add_to_schema(field_name, schema)
189189 self.read_field._add_to_schema(field_name, schema)
190190 self.write_field._add_to_schema(field_name, schema)
191191
197197 """
198198
199199 def _serialize(self, value, attr, obj):
200 ret = super(SeverityField, self)._serialize(value, attr, obj)
200 ret = super()._serialize(value, attr, obj)
201201 if ret == 'medium':
202202 return 'med'
203203 elif ret == 'informational':
205205 return ret
206206
207207 def _deserialize(self, value, attr, data, **kwargs):
208 ret = super(SeverityField, self)._serialize(value, attr, data)
208 ret = super()._serialize(value, attr, data)
209209 if ret == 'med':
210210 return 'medium'
211211 elif ret == 'info':
224224 """
225225
226226 def __init__(self, *args, **kwargs):
227 super(NullToBlankString, self).__init__(*args, **kwargs)
227 super().__init__(*args, **kwargs)
228228 # Always make the field nullable because it is translated
229229 self.allow_none = True
230230 self.default = ''
275275 # TODO migration: write me some tests!!!
276276
277277 def __init__(self, load_as_tz_aware=False, *args, **kwargs):
278 super(StrictDateTimeField, self).__init__(*args, **kwargs)
278 super().__init__(*args, **kwargs)
279279 self.load_as_tz_aware = load_as_tz_aware
280280
281281 def _deserialize(self, value, attr, data, **kwargs):
282282 if isinstance(value, datetime.datetime):
283283 date = value
284284 else:
285 date = super(StrictDateTimeField, self)._deserialize(value, attr, data)
285 date = super()._deserialize(value, attr, data)
286286 if self.load_as_tz_aware:
287287 # If datetime is TZ naive, set UTC timezone
288288 if date.tzinfo is None or date.tzinfo.utcoffset(date) is None:
2222 def __init__(self, upload_reports_queue, *args, **kwargs):
2323 super().__init__(*args, **kwargs)
2424 self.upload_reports_queue = upload_reports_queue
25 self.plugins_manager = PluginsManager(config.faraday_server.custom_plugins_folder)
25 self.plugins_manager = PluginsManager(config.faraday_server.custom_plugins_folder,
26 ignore_info=config.faraday_server.ignore_info_severity)
2627 self.__event = threading.Event()
2728
2829 def stop(self):
195195 class BooleanToIntColumn(expression.FunctionElement):
196196
197197 def __init__(self, expression):
198 super(BooleanToIntColumn, self).__init__()
198 super().__init__()
199199 self.expression_str = expression
200200
201201
1818 from marshmallow import Schema, fields, ValidationError, types, validate, post_load
1919 from marshmallow_sqlalchemy.convert import ModelConverter
2020
21 from faraday.server.models import VulnerabilityWeb, Host, Service, VulnerabilityTemplate
21 from faraday.server.models import VulnerabilityWeb, Host, Service, VulnerabilityTemplate, Workspace, User
2222 from faraday.server.utils.search import OPERATORS
2323 from faraday.server.fields import JSONType
2424
182182 def _model_class(self):
183183 return Host
184184
185 class FlaskRestlessWorkspaceFilterSchema(FlaskRestlessFilterSchema):
186 def _model_class(self):
187 return Workspace
188
189 class FlaskRestlessUserFilterSchema(FlaskRestlessFilterSchema):
190 def _model_class(self):
191 return User
192
193
185194
186195 class FlaskRestlessOperator(Schema):
187196 _or = fields.Nested("self", attribute='or', data_key='or')
190199 model_filter_schemas = [
191200 FlaskRestlessHostFilterSchema,
192201 FlaskRestlessVulnerabilityFilterSchema,
202 FlaskRestlessWorkspaceFilterSchema,
203 FlaskRestlessUserFilterSchema,
193204 FlaskRestlessVulnerabilityTemplateFilterSchema,
194205 ]
195206
274285 FlaskRestlessVulnerabilityFilterSchema,
275286 FlaskRestlessVulnerabilityTemplateFilterSchema,
276287 FlaskRestlessHostFilterSchema,
288 FlaskRestlessWorkspaceFilterSchema,
289 FlaskRestlessUserFilterSchema,
277290 ]
278291
279292 def load(
4848 class CleanHttpHeadersResource(Resource):
4949 def render(self, request):
5050 request.responseHeaders.removeHeader('Server')
51 return super(CleanHttpHeadersResource, self).render(request)
51 return super().render(request)
5252
5353
5454 class FileWithoutDirectoryListing(File, CleanHttpHeadersResource):
5656 return ForbiddenResource()
5757
5858 def render(self, request):
59 ret = super(FileWithoutDirectoryListing, self).render(request)
59 ret = super().render(request)
6060 if self.type == 'text/html':
6161 request.responseHeaders.addRawHeader('Content-Security-Policy',
6262 'frame-ancestors \'self\'')
6767 class FaradayWSGIResource(WSGIResource):
6868 def render(self, request):
6969 request.responseHeaders.removeHeader('Server')
70 return super(FaradayWSGIResource, self).render(request)
70 return super().render(request)
7171
7272
7373 class FaradayRedirectResource(Redirect):
7474 def render(self, request):
7575 request.responseHeaders.removeHeader('Server')
76 return super(FaradayRedirectResource, self).render(request)
76 return super().render(request)
7777
7878
7979 class WebServer:
8282 WEB_UI_LOCAL_PATH = faraday.server.config.FARADAY_BASE / 'server/www'
8383
8484 def __init__(self):
85 self.__ssl_enabled = faraday.server.config.ssl.enabled
86 logger.info('Starting web server at %s://%s:%s/',
87 'https' if self.__ssl_enabled else 'http',
88 faraday.server.config.faraday_server.bind_address,
89 faraday.server.config.ssl.port if self.__ssl_enabled else faraday.server.config.faraday_server.port)
90 self.__websocket_ssl_enabled = faraday.server.config.websocket_ssl.enabled
85 logger.info(f'Starting web server at http://'
86 f'{faraday.server.config.faraday_server.bind_address}:'
87 f'{faraday.server.config.faraday_server.port}/')
9188 self.__websocket_port = faraday.server.config.faraday_server.websocket_port or 9000
9289 self.__config_server()
9390 self.__build_server_tree()
9491
9592 def __config_server(self):
9693 self.__bind_address = faraday.server.config.faraday_server.bind_address
97 if self.__ssl_enabled:
98 self.__listen_port = int(faraday.server.config.ssl.port)
99 else:
100 self.__listen_port = int(faraday.server.config.faraday_server.port)
94 self.__listen_port = int(faraday.server.config.faraday_server.port)
10195
10296 def __load_ssl_certs(self):
10397 certs = (faraday.server.config.ssl.keyfile, faraday.server.config.ssl.certificate)
124118
125119 def __build_websockets_resource(self):
126120 websocket_port = int(faraday.server.config.faraday_server.websocket_port)
127 url = f'{self.__bind_address}:{websocket_port}/websockets'
128 if self.__websocket_ssl_enabled:
129 url = 'wss://' + url
130 else:
131 url = 'ws://' + url
121 url = f'ws://{self.__bind_address}:{websocket_port}/websockets'
132122 # logger.info(u"Websocket listening at {url}".format(url=url))
133 logger.info('Starting websocket server at port {0} with bind address {1}. '
134 'SSL {2}'.format(
135 self.__websocket_port,
136 self.__bind_address,
137 self.__ssl_enabled
138 ))
139
123 logger.info(f'Starting websocket server at port '
124 f'{self.__websocket_port} with bind address {self.__bind_address}.')
140125 factory = WorkspaceServerFactory(url=url)
141126 factory.protocol = BroadcastServerProtocol
142127 return factory
161146 logPath=log_path,
162147 logFormatter=proxiedLogFormatter)
163148 site.displayTracebacks = False
164 if self.__ssl_enabled:
165 ssl_context = self.__load_ssl_certs()
166 self.__listen_func = functools.partial(
167 reactor.listenSSL,
168 contextFactory=ssl_context)
169 else:
170 self.__listen_func = reactor.listenTCP
149 self.__listen_func = reactor.listenTCP
171150
172151 try:
173152 self.install_signal()
181160 self.__listen_port, site,
182161 interface=self.__bind_address)
183162 # websockets
184 if faraday.server.config.websocket_ssl.enabled:
185
186 try:
187 contextFactory = ssl.DefaultOpenSSLContextFactory(
188 faraday.server.config.websocket_ssl.keyfile.strip('\''),
189 faraday.server.config.websocket_ssl.certificate.strip('\'')
190 )
191
192 listenWS(self.__build_websockets_resource(), interface=self.__bind_address, contextFactory=contextFactory)
193
194 except SSLError as e:
195 logger.error('Could not start websockets due to a SSL Config error. Some web functionality will not be available')
196 except error.CannotListenError:
197 logger.warn('Could not start websockets, address already open. This is ok is you wan to run multiple instances.')
198 except Exception as ex:
199 logger.warn(f'Could not start websocket, error: {ex}')
200 else:
201 try:
202 listenWS(self.__build_websockets_resource(), interface=self.__bind_address)
203 except error.CannotListenError:
204 logger.warn('Could not start websockets, address already open. This is ok is you wan to run multiple instances.')
205 except Exception as ex:
206 logger.warn(f'Could not start websocket, error: {ex}')
163 try:
164 listenWS(self.__build_websockets_resource(), interface=self.__bind_address)
165 except error.CannotListenError:
166 logger.warn('Could not start websockets, address already open. This is ok is you wan to run multiple instances.')
167 except Exception as ex:
168 logger.warn(f'Could not start websocket, error: {ex}')
207169 logger.info('Faraday Server is ready')
208170 reactor.addSystemEventTrigger('before', 'shutdown', signal_handler)
209171 reactor.run()
0 ../frontend/www
faraday/server/www/android-icon-144x144.png less more
Binary diff not shown
faraday/server/www/android-icon-192x192.png less more
Binary diff not shown
faraday/server/www/android-icon-36x36.png less more
Binary diff not shown
faraday/server/www/android-icon-48x48.png less more
Binary diff not shown
faraday/server/www/android-icon-72x72.png less more
Binary diff not shown
faraday/server/www/android-icon-96x96.png less more
Binary diff not shown
faraday/server/www/apple-icon-114x114.png less more
Binary diff not shown
faraday/server/www/apple-icon-120x120.png less more
Binary diff not shown
faraday/server/www/apple-icon-144x144.png less more
Binary diff not shown
faraday/server/www/apple-icon-152x152.png less more
Binary diff not shown
faraday/server/www/apple-icon-180x180.png less more
Binary diff not shown
faraday/server/www/apple-icon-57x57.png less more
Binary diff not shown
faraday/server/www/apple-icon-60x60.png less more
Binary diff not shown
faraday/server/www/apple-icon-72x72.png less more
Binary diff not shown
faraday/server/www/apple-icon-76x76.png less more
Binary diff not shown
faraday/server/www/apple-icon-precomposed.png less more
Binary diff not shown
faraday/server/www/apple-icon.png less more
Binary diff not shown
+0
-2
faraday/server/www/browserconfig.xml less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>
+0
-149
faraday/server/www/dashboard-v3.css less more
0 .dashboard .filter-wrapper .confirm-button {
1 position: relative;
2 bottom: 4px;
3 }
4
5 .dashboard .faraday-page-header {
6 margin-bottom: 0px;
7 }
8
9 .bg-white {
10 background-color: #FFF;
11 }
12
13 .border-right {
14 border-right: 1px solid #e7e7e7;
15 }
16
17 .small-widget-height {
18 height: 195px;
19 }
20
21 .dashboard-label-wrapper {
22 text-align: left;
23 margin-top: 10px;
24 margin-bottom: 10px;
25 }
26
27 .dashboard-label-wrapper > .label {
28 padding: 5px;
29 width: 100%;
30 display: block;
31 }
32
33 .label-gray {
34 background-color: #a1a1a1;
35 }
36
37 .m0 {
38 margin: 0px !important;
39 }
40
41 .mt-md {
42 margin-top: 10px;
43 }
44
45 .p0 {
46 padding: 0px !important;
47 }
48
49 .pl0 {
50 padding-left: 0px !important;
51 }
52
53 .p-md {
54 padding: 10px;
55 }
56
57 .ph-sm {
58 padding-left: 5px;
59 padding-right: 5px;
60 }
61
62 .ph-md {
63 padding-left: 10px;
64 padding-right: 10px;
65 }
66
67 .ph-xl {
68 padding-left: 30px;
69 padding-right: 30px;
70 }
71
72 .ph-xxl {
73 padding-left: 45px;
74 padding-right: 45px;
75 }
76
77 .pl-xs{
78 padding-left: 3px;
79 }
80
81 .pl-sm {
82 padding-left: 5px;
83 }
84
85 .pl {
86 padding-left: 15px;
87 }
88
89 .pr-sm {
90 padding-right: 5px;
91 }
92
93 .pr {
94 padding-right: 15px !important;
95 }
96
97 .progress-bar-tall {
98 height: 57px;
99 }
100
101 .progress-bar-tall > .progress-bar > span {
102 top: 20px;
103 position: relative;
104 }
105
106 .progress-bar-light-blue > .progress-bar {
107 background-color: #00a8e1;
108 }
109
110 .panel {
111 -webkit-box-shadow: none;
112 box-shadow: none;
113 border-radius: 0px;
114 }
115
116 .text-left {
117 text-align: left !important;
118 }
119
120 .dashboard .progress-bar span {
121 font-weight: bold;
122 }
123
124 .dashboard table thead th span {
125 color: #3393d4;
126 }
127
128 .fg-blue {
129 color: #3393d4;
130 }
131
132 .fg-light-gray {
133 color: #d2d2d2;
134 }
135
136 .seccion.dashboard article header h2{
137 margin: 0px;
138 padding-left: 20px;
139 padding-right: 20px;
140 }
141
142 @media (min-width:991px) and (max-width:1380px) {
143 .dashboard h2 {
144 font-size: 10px !important;
145 line-height: 20px !important;
146 padding-top: 5px !important;
147 }
148 }
+0
-1071
faraday/server/www/estilos-v3.css less more
0 #login-main {
1 background-image: url(images/fondo_faraday.svg) !important;
2 width: 100%;
3 height: 100%;
4 display: inline-block;
5 position: fixed;
6 background-size: cover;
7 background-repeat: no-repeat;
8 background-position: center center;
9 }
10
11 #login-container {
12 width: 410px;
13 margin-top: 160px;
14 background-color: #FFF;
15 margin-left: auto;
16 margin-right: auto;
17 box-shadow: 0 0 1em black;
18 }
19
20 #form-signin {
21 padding: 60px 36px 40px 36px;
22 height: 378px;
23 }
24
25 #form-signin > h3 {
26 font-weight: 600;
27 font-size: 21px;
28 }
29
30 .height-39px {
31 height: 39px;
32 }
33
34 .border-red {
35 border-top-color: #00a8e1;
36 }
37
38 .border-strong {
39 border-top-style: solid;
40 border-top-width: 5px;
41 }
42
43 .mt-sm {
44 margin-top: 10px;
45 }
46
47 .margin-top-18px {
48 margin-top: 18px;
49 }
50
51 .margin-top-22px {
52 margin-top: 22px;
53 }
54
55 .margin-top-30px {
56 margin-top: 30px;
57 }
58
59 .margin-top-37px {
60 margin-top: 37px;
61 }
62
63 .margin-top-65px {
64 margin-top: 65px;
65 }
66
67 .clear-margin {
68 margin: 0px;
69 }
70
71 .clear-margin-bottom {
72 margin-bottom: 0px;
73 }
74
75 .btn-frd {
76 display: inline-block;
77 padding: 10px 12px;
78 margin-bottom: 0;
79 font-size: 13px;
80 font-weight: 600;
81 line-height: 1.42857143;
82 text-align: center;
83 white-space: nowrap;
84 vertical-align: middle;
85 -ms-touch-action: manipulation;
86 touch-action: manipulation;
87 cursor: pointer;
88 -webkit-user-select: none;
89 -moz-user-select: none;
90 -ms-user-select: none;
91 user-select: none;
92 background-image: none;
93 border: 1px solid transparent;
94 border-radius: 0px;
95 color: #FFF;
96 }
97
98 .btn-frd.disabled, .btn-frd[disabled], fieldset[disabled] .btn-frd {
99 cursor: not-allowed;
100 filter: alpha(opacity=65);
101 -webkit-box-shadow: none;
102 box-shadow: none;
103 opacity: .65;
104 }
105
106 .btn-xl {
107 height: 54px;
108 }
109
110 .bg-blue {
111 background-color: #2c8dee;
112 }
113
114 .fg-blue {
115 color: #2c8dee
116 }
117
118 .fg-white {
119 color: white
120 }
121
122 .fg-red {
123 color: #00a8e1;
124 }
125
126 .font-bold {
127 font-weight: bold;
128 }
129
130 .font-xs {
131 font-size: 11px;
132 }
133
134 .frd-icon {
135 background-repeat: no-repeat;
136 }
137
138 .frd-icon-lock {
139 background-image: url("images/icon-login-password-lock.svg");
140 width: 20px;
141 height: 20px;
142 }
143
144 #form-signin .placeholder .frd-icon-lock {
145 position: relative;
146 bottom: 5px;
147 }
148
149 #footer-login {
150 position: fixed;
151 bottom: 0px;
152 right: 15px;
153 }
154
155 .justify-flex-start {
156 justify-content: flex-start !important;
157 }
158
159 .max-sized-table {
160 max-width: 1200px;
161 }
162
163 .loading-spinner {
164 position: absolute;
165 top: 180px;
166 left: 50%;
167 z-index: 1000;
168 font-size: 30px;
169 }
170
171 .no-info-overlay {
172 background-color: #EEE;
173 width: 100%;
174 height: 38px;
175 position: relative;
176 z-index: 999;
177 text-align: center;
178 }
179
180 .no-info-text {
181 margin-top: 8px;
182 font-size: 11px;
183 padding-top: 10px;
184 }
185
186 .height-auto {
187 height: auto !important;
188 }
189
190 .rotate-180 {
191 transform: rotate(180deg);
192 }
193
194 .file-name {
195 display: inline-block;
196 font-size: smaller;
197 padding-left: 10px;
198 }
199
200 .remove-uploaded-file{
201 margin-left: 10px;
202 cursor: pointer;
203 width: 10px;
204 height: auto;
205 border-radius: 50%;
206 padding: 2px 6px;
207 }
208
209 .remove-uploaded-file:hover{
210 background-color: #ddd;
211 }
212
213 .file-container {
214 overflow: hidden;
215 position: relative;
216 }
217
218 .file-container button {
219 border-radius: 0px;
220 }
221
222 .no-border-radius {
223 border-radius: 0px;
224 }
225
226 .file-container [type=file] {
227 cursor: inherit;
228 display: block;
229 filter: alpha(opacity=0);
230 opacity: 0;
231 position: absolute;
232 right: 0;
233 top: -6px;
234 width: 105px;
235 height: 34px;
236 }
237
238 .file-selected {
239 z-index: -999;
240 }
241 .jumbotron {
242 background-color: #f4f3f4;
243 }
244
245 .btn {
246 border-radius: 0px;
247 }
248
249 .feed-icon{
250 width: 18px;
251 padding-bottom: 5px;
252 margin-right: 3px;
253 }
254
255
256 .little-gray{
257 color: #a2a1a1;
258 }
259
260 .hide-border-top{
261 border-top: none!important;
262 }
263
264 .margin-right-15px{
265 margin-right: 15px;
266 }
267
268 .nav-tabs {
269 border-bottom: none !important;
270 }
271
272 .nav-tabs > li.active > a, .nav-tabs > li.active > a:focus, .nav-tabs > li.active > a:hover {
273 color: #67aef9;
274 cursor: default;
275 background-color: #fff;
276 border: none;
277 border-bottom: 3px solid #67aef9;
278 font-weight: bold;
279 }
280
281 .nav-tabs > li > a {
282 color: #8c9799;
283 }
284
285 .nav > li:not(.active) > a:hover {
286 background-color: #fff !important;
287 border-color: #fff #fff #ddd !important;
288 }
289
290 .edit-vulns-dropdowns {
291 margin-bottom: 15px;
292 }
293
294 .primary-btn {
295 width: calc(100% - 29px);
296 }
297
298 .secondary-btn {
299 left: -5px;
300 position: relative;
301 }
302
303 .btn-change-property {
304 border: none;
305 padding: 5px;
306 color: #fff;
307 font-weight: bold;
308 }
309
310 .data-name {
311 font-size: 1.5em;
312 font-weight: bold;
313 color: #5e6667;
314 }
315
316 .modal-data-name {
317 margin: 25px 0;
318 }
319
320 .tab-pane-header {
321 color: #5e6667;
322 font-size: 1.2em;
323 font-weight: bold;
324 margin-bottom: 15px;
325 }
326
327 .tab-pane-container {
328 width: 100%;
329 overflow-y: auto;
330 max-height: calc(100% - 175px);
331 height: 100%;
332 }
333
334 .btn-primary-white {
335 background-color: #fff;
336 border: 1px solid #ddd;
337 border-right: none;
338 color: #5e6667;
339 text-transform: capitalize;
340 font-weight: normal;
341 }
342
343 .btn-secondary-white{
344 background-color: #fff;
345 border: 1px solid #ddd;
346 border-left: none;
347 color: #5e6667;
348 }
349
350 .edit-name-icon {
351 color: #999;
352 cursor: pointer;
353 margin-left: 10px;
354 }
355
356 /*.modal-data-name:hover .edit-name-icon {*/
357 /*display: inline-flex;*/
358 /*}*/
359
360 #inp-edit-name{
361 font-weight: bold;
362 color: #5e6667;
363 }
364
365 .fields-of-vulnWeb {
366 position: relative;
367 top: 22px;
368 }
369
370 /* The container */
371 .radio-container {
372 display: block;
373 position: relative;
374 padding-left: 55px;
375 margin-bottom: 12px;
376 cursor: pointer;
377 font-size: 22px;
378 -webkit-user-select: none;
379 -moz-user-select: none;
380 -ms-user-select: none;
381 user-select: none;
382 }
383
384 /* Hide the browser's default radio button */
385 .radio-container input {
386 position: absolute;
387 opacity: 0;
388 cursor: pointer;
389 }
390
391 /* Create a custom radio button */
392 .checkmark {
393 position: absolute;
394 top: 5px;
395 left: 25px;
396 height: 20px;
397 width: 20px;
398 background-color: #ddd;
399 border-radius: 50%;
400 }
401
402 /* On mouse-over, add a grey background color */
403 .radio-container:hover input ~ .checkmark {
404 background-color: #ccc;
405 }
406
407 /* When the radio button is checked, add a blue background */
408 .radio-container input:checked ~ .checkmark {
409 background-color: #008000;
410 }
411
412 /* Create the indicator (the dot/circle - hidden when not checked) */
413 .checkmark:after {
414 content: "";
415 position: absolute;
416 display: none;
417 }
418
419 /* Show the indicator (dot/circle) when checked */
420 .radio-container input:checked ~ .checkmark:after {
421 display: block;
422 top: 6px;
423 left: 6px;
424 }
425
426 /* Style the indicator (dot/circle) */
427 .radio-container .checkmark:after {
428 top: 9px;
429 left: 9px;
430 width: 8px;
431 height: 8px;
432 border-radius: 50%;
433 background: white;
434 }
435
436 .customs-radio-inline{
437 display: inline-flex;
438 }
439
440
441
442 /* The container */
443 .chbox-container {
444 display: block;
445 position: relative;
446 padding-left: 55px;
447 margin-bottom: 12px;
448 cursor: pointer;
449 font-size: 22px;
450 -webkit-user-select: none;
451 -moz-user-select: none;
452 -ms-user-select: none;
453 user-select: none;
454 top: -5px;
455 }
456
457 /* Hide the browser's default checkbox */
458 .chbox-container input {
459 position: absolute;
460 opacity: 0;
461 cursor: pointer;
462 height: 0;
463 width: 0;
464 }
465
466 /* On mouse-over, add a grey background color */
467 .chbox-container:hover input ~ .checkmark {
468 background-color: #ccc;
469 }
470
471 /* When the checkbox is checked, add a blue background */
472 .chbox-container input:checked ~ .checkmark {
473 background-color: #488be6;
474 }
475
476 /* Create the checkmark/indicator (hidden when not checked) */
477 .checkmark:after {
478 content: "";
479 position: absolute;
480 display: none;
481 }
482
483 /* Show the checkmark when checked */
484 .chbox-container input:checked ~ .checkmark:after {
485 display: block;
486 }
487
488 /* Style the checkmark/indicator */
489 .chbox-container .checkmark:after {
490 left: 8px;
491 top: 5px;
492 width: 5px;
493 height: 10px;
494 border: solid white;
495 border-width: 0 3px 3px 0;
496 -webkit-transform: rotate(45deg);
497 -ms-transform: rotate(45deg);
498 transform: rotate(45deg);
499 }
500
501 .chbox-container .checkmark{
502 top: 0;
503 }
504
505 .custom-divider {
506 border-top: 1px solid #ddd;
507 margin: 10px 0 15px 0;
508 }
509
510 li.nav-item.has-error:not(.active) {
511 border-bottom: 1px dashed #a94442;
512 }
513
514 li.nav-item.has-error:not(.active) a {
515 color: #a94442;
516 }
517
518 .nav-item{
519 margin-right: 40px;
520 }
521
522 .active-toggle{
523 width: 3%;
524 text-align: center!important;
525 }
526
527 .active-toggle-container{
528 cursor: pointer;
529 }
530
531 .forbidden-error {
532 text-align: center;
533 overflow-wrap: break-word;
534 position: relative;
535 top: 220px;
536 color: #aeaeb1;
537 }
538 .active-toggle{
539 width: 3%;
540 text-align: center!important;
541 }
542
543 .active-toggle-container{
544 cursor: pointer;
545 }
546
547 .forbidden-error {
548 text-align: center;
549 overflow-wrap: break-word;
550 position: relative;
551 top: 220px;
552 color: #aeaeb1;
553 }
554
555 .last-item-field {
556 margin-bottom: 25px;
557 }
558
559
560 /* ANGULAR SIMPLE PAGINATION */
561
562 .simple-pagination p {
563 display: inline-block;
564 line-height: 24px;
565 margin: 0 10px 0 0;
566 }
567
568 .simple-pagination__button {
569 background: #fff;
570 border: none;
571 padding: 0px 6px;
572 }
573
574 button[disabled], html input[disabled] {
575 cursor: default!important;
576 color: #ddd;
577 }
578
579 .simple-pagination__page-limit__option:after {
580 content: ' | ';
581 }
582
583 .simple-pagination__page-limit .active {
584 font-weight: bold;
585 }
586
587 .simple-pagination {
588 text-align: center;
589 margin-bottom: 15px;
590 }
591
592 .toogle-img-container {
593 width: 46px;
594 }
595
596 .settings {
597 border: 1px solid #ddd;
598 border-radius: 4px;
599 margin-right: 16px;
600 min-height: 756px;
601 }
602
603 .setting-header {
604 background-color: #e7e6e7;
605 padding: 1px 24px 12px;
606 border-bottom: 1px solid #ddd;
607 box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16), 0 2px 10px 0 rgba(0,0,0,0.12);
608 }
609
610 .setting-body {
611 height: 100%;
612 }
613
614 .setting-sidebar {
615 min-height: 678px;
616 padding-left: 0;
617 padding-right: 0;
618 border-right: 1px solid #ddd;
619 }
620
621 .setting-sidebar ul {
622 margin-top: 24px;
623 }
624
625 .setting-sidebar li {
626 width: 100%;
627 padding: 10px 24px;
628 cursor: pointer;
629 font-size: 1.1em;
630 font-weight: 600;
631 }
632
633 .setting-sidebar li.active {
634 border-left: 5px solid #00a8e1;
635 padding-left: 19px;
636 color: #00a8e1;
637 }
638
639 .setting-sidebar li:hover{
640 border-left: 5px solid #888;
641 padding-left: 19px;
642 color: #444;
643 background-color: #eee;
644 }
645
646 .cf-container {
647 padding: 32px;
648 height: 600px;
649 overflow-y: auto;
650 }
651
652 .cf-item {
653 padding: 16px 0px!important;
654 border-top: 1px solid #ddd;
655 }
656
657 .cf-type {
658 border: 1px solid #ddd;
659 max-width: 80px;
660 text-align: center;
661 border-radius: 3px;
662 margin-top: 10px;
663 color: #fff;
664 font-weight: bold;
665 }
666
667 .type-int{
668 border: 1px solid #932ebe;
669 background-color: #932ebe;
670 }
671
672 .type-str{
673 border: 1px solid #2e97bd;
674 background-color: #2e97bd;
675 }
676
677 .type-list{
678 border: 1px solid #a1ce31;
679 background-color: #a1ce31;
680 }
681
682 .type-choice{
683 border: 1px solid #be2743;
684 background-color: #be2743;
685 }
686
687 h3.cf-display-name {
688 margin-top: 0;
689 }
690
691 .cf-detail {
692 border-left: 1px solid #ddd;
693 height: 600px;
694 padding: 8px 24px;
695 }
696
697 .cf-actions {
698 color: #aaa;
699 text-align: center;
700 padding-top: 32px;
701 }
702
703 .btn-cf-choice {
704 margin-bottom: 30px;
705 padding-left: 0;
706 padding-right: 0;
707 }
708
709
710 span.cf-icon-action {
711 font-size: 10px;
712 cursor: pointer;
713 }
714
715 span.cf-icon-action:hover {
716 color: #777;
717 }
718
719 .btn-tools {
720 margin-top: 45px;
721 float: right;
722 }
723
724
725 /**
726 * The dndDraggingSource class will be applied to
727 * the source element of a drag operation. It makes
728 * sense to hide it to give the user the feeling
729 * that he's actually moving it.
730 */
731 .dndDraggingSource {
732 display: none;
733 }
734
735
736 /**
737 * An element with .dndPlaceholder class will be
738 * added to the dnd-list while the user is dragging
739 * over it.
740 */
741 .dndPlaceholder {
742 background-color: #ddd;
743 display: block;
744 min-height: 120px;
745 border:2px dashed #aaa;
746 }
747
748 div[dnd-list] > div{
749 border-top-right-radius: 4px;
750 border-top-left-radius: 4px;
751 padding: 10px 15px;
752 margin-bottom: -1px;
753 }
754
755 .header-btns {
756 width: 100%;
757 padding: 20px 8px;
758 }
759
760 .right-main{
761 overflow-x: hidden;
762 }
763
764 #slide {
765 transition: 0.5s;
766 position: absolute;
767 right: -33.3%;
768 }
769
770 .show-slide{
771 transition: 0.5s!important;
772 width: 33.3%!important;
773 right: 0!important;
774 }
775
776 #main-panel{
777 width: 100%;
778 transition: 0.5s;
779 }
780
781 .slice-main-panel{
782 transition: 0.5s;
783 width: 66.6%!important;
784 }
785
786 .right-main{
787 overflow-x: hidden;
788 }
789
790 .left-main{
791 overflow-x: hidden;
792 }
793
794 #vuln-preview {
795 position: fixed;
796 z-index: 100000;
797 top: 139px;
798 height: calc(100% - 139px);
799 background-color: #fff;
800 border-left: 1px solid #ddd;
801 border-top: solid 4px #e5e5e5;
802 width: 0;
803 transition: 0.5s;
804 right: -75%;
805 padding: 16px;
806 }
807
808 #vuln-preview.show-preview{
809 transition: width 0.3s!important;
810 width: 70%!important;
811 right: 0!important;
812 }
813
814 .faraday-page-header{
815 width: 100%;
816 }
817
818 .faraday-page-header.show-preview{
819 transition: width 0.3s!important;
820 width: 74.5%!important;
821 }
822
823 #btn_bar.show-preview{
824 transition: width 0.3s!important;
825 width: 73.2%!important;
826 }
827
828 .preview-header {
829 width: 100%;
830 padding: 5px 10px 20px;
831 }
832
833 .preview-section {
834 border-top: 1px solid #ddd;
835 padding: 24px 0;
836 margin-bottom: 22px;
837 }
838
839 .preview-section .form-group{
840 margin-bottom: 0;
841 }
842
843 .preview-icon {
844 color: #aaa;
845 cursor: pointer;
846 text-align: center;
847 padding: 6px 8px;
848 font-size: 0.8em;
849 }
850
851 .preview-icon:hover {
852 background-color: #ddd;
853 color: #777;
854 border-radius: 50px;
855 box-shadow: 2px 2px 10px 0px #aaa;
856 }
857
858 .preview-tag {
859 background-color: #ddd;
860 padding: 2px 8px;
861 border-radius: 3px;
862 font-weight: bold;
863 color: #555;
864 box-shadow: 2px 2px 2px 0 #aaa;
865 margin-right: 10px;
866 }
867
868 .preview-section.row {
869 margin-right: 0;
870 margin-left: 0;
871 margin-bottom: 0;
872 padding-bottom: 12px;
873 }
874
875 .preview-section .tab-pane-header {
876 font-size: 1.1em;
877 overflow-wrap: break-word;
878 }
879
880 .prev-apply-template.active{
881 /*transition: 0.1s;*/
882 width: 75%!important;
883 }
884
885 .prev-apply-template {
886 padding-right: 0;
887 }
888
889 .pretty-text.tab-pane-header {
890 font-size: 1.01em;
891 /* font-weight: normal; */
892 color: #aaa;
893 }
894
895 .text-code {
896 background-color: #f9f9f9;
897 padding: 15px 10px;
898 font-weight: normal;
899 color: #777!important;
900 min-height: 150px;
901 overflow-wrap: break-word;
902 }
903
904 .show-scroll {
905 height: 230px;
906 overflow-y: auto;
907 }
908
909 .show-scroll input {
910 color: #444!important;
911 }
912
913 .margin-bottom-24{
914 margin-bottom: 24px;
915 }
916
917 .input-evidence {
918 height: 40px;
919 width: 100%;
920 position: absolute;
921 top: 0;
922 left: -15px;
923 opacity: 0;
924 cursor: pointer;
925 }
926
927 .upload-options button {
928 margin-bottom: 5px;
929 }
930
931 #attachment-img{
932 max-width: 100%;
933 max-height: 100%;
934 display: block;
935 margin-left: auto;
936 margin-right: auto;
937 }
938
939 ul#nav-tabs-container {
940 margin-left: 50px;
941 }
942
943 .padding-left-0{
944 padding-left: 0;
945 }
946
947 .margin-left-0{
948 margin-left: 0;
949 }
950
951 .desc-container {
952 height: 65%;
953 overflow-y: auto;
954 }
955
956 .height-100{
957 height: 100%;
958 }
959
960 .line-breaks{
961 white-space: pre-wrap;
962 line-height: 1.5;
963 overflow-wrap: break-word;
964 }
965
966 .custom-panel-heading{
967 padding: 15px!important;
968 text-transform: uppercase;
969 }
970
971 .custom-panel-body{
972 background-color: #f4f3f4;
973 }
974
975 .agent-token-container {
976 font-size: 1.5em;
977 margin-right: 20px;
978 padding: 12px;
979 }
980
981 #agent-table td {
982 text-align: left!important;
983 }
984
985 .tag-blue {
986 background-color: #2e97bd;
987 color: white;
988 text-transform: uppercase;
989 }
990
991 .tag-green {
992 background-color: #a1ce31;
993 color: white;
994 text-transform: uppercase;
995 }
996
997 .tag-yellow {
998 background-color: #dfbf35;
999 color: white;
1000 text-transform: uppercase;
1001 }
1002
1003 .tag-red {
1004 background-color: #df3936;
1005 color: white;
1006 text-transform: uppercase;
1007 }
1008
1009 .tag-gray {
1010 background-color: #999999;
1011 color: white;
1012 text-transform: uppercase;
1013 }
1014
1015 #agent-table .preview-tag {
1016 box-shadow: none;
1017 font-size: 0.8em;
1018 }
1019
1020 #btn_clear_search {
1021 position: absolute;
1022 height: 30px;
1023 border-radius: 2px;
1024 right: 15px;
1025 padding-top: 3px;
1026 }
1027
1028 .panel-default .workspace-selector-wrapper {
1029 padding: 0;
1030 }
1031
1032 .workspace-selector-wrapper.inside-admin:hover {
1033 background-color: transparent;
1034 }
1035
1036 .switcher-wrapper.inside-admin:hover {
1037 background-color: #ebebeb;
1038 }
1039
1040 .workflow-workspace-switcher {
1041 display: table !important;
1042 margin: auto;
1043 }
1044
1045 .workflow-workspace-switcher .title {
1046 margin-top: 5px;
1047 font-size: 16px;
1048 font-weight: bold;
1049 }
1050
1051 .remember-me span{
1052 display: inline-block !important;
1053 width: fit-content;
1054 margin-left: 20px;
1055 }
1056
1057 .remember-me input{
1058 display: inline-block;
1059 width: fit-content;
1060 width: -moz-max-content;
1061 margin-top: 0;
1062 top: -2.5px;
1063 left: 0;
1064 }
1065
1066 .no-overflow {
1067 overflow: hidden;
1068 text-overflow: ellipsis;
1069 white-space: nowrap;
1070 }
+0
-1420
faraday/server/www/estilos.css less more
0 /* Faraday Penetration Test IDE */
1 /* Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) */
2 /* See the file 'doc/LICENSE' for the license information */
3 /*reset*/
4 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {margin:0;padding:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body {line-height:1}ol,ul {list-style:none}blockquote,q {quotes:none}:focus {outline:0}ins {text-decoration:none}del {text-decoration:line-through}table {border-collapse:collapse;border-spacing:0}ul,li {list-style:none}.clearfix:after{content:".";display:block;clear:both;visibility:hidden;line-height:0; height:0}
5 .clearfix{display:inline-block}html[xmlns] .clearfix{display:block}* html .clearfix{height:1%}
6 /**/
7 html#no-overflow{overflow-x:hidden;}
8 .login {
9 background: #3a3a3a !important;
10 position: fixed;
11 }
12 html {
13 height: 100%;
14 width: 100%;
15 }
16 body {
17 font-family: "Open Sans" !important;
18 color: #2D2F31;
19 height: 100%;
20 width: 100%;
21 background: #F5F5F5 !important;
22 }
23 h1, h2, h3, h4, h5, h6 {
24 font-family: "Open Sans" !important;
25 }
26 p, div {
27 font-family: "Open Sans" !important;
28 }
29 ul{padding:0 0 0 0;margin-bottom: 20px;}
30 a {
31 text-decoration:none;
32 outline-style:none;
33 color: #DF3936;
34 }
35 a:hover{cursor: pointer;}
36 p {margin-bottom: 1em;}
37 ::-moz-selection {
38 background-color:#444;
39 color:#fff
40 }
41 ::selection {
42 background-color:#444;
43 color:#fff;
44 }
45 .wrapper{width:auto;}
46 /* FILAS COLUMNAS */
47 .fila {
48 width: 100%;
49 padding:40px 0 0 10px;
50 }
51 .columna {
52 margin: 10px 5px 0px;
53 float: left;
54 }
55 .cursor{cursor: pointer;}
56 #compound .columna{
57 width: 492px;
58 margin-top: -42px;
59 position: relative;
60 margin-top: -33px;
61 }
62 .unmedio, .doscuartos {width: 420px;}
63 .untercio {width: 273px;}
64 .uncuarto {width: 200px;}
65 .unquinto {width: 85px;}
66 .unsexto {width: 85px;}
67 .head{
68 background-color: #00a8e1;
69 width: 50px;
70 border-radius: 10px;
71 margin-bottom: 5px;
72 }
73
74 header.head {
75 margin-top: 9px;
76 height: 72px;
77 text-align: left;
78 position: fixed;
79 z-index:1000;
80 background-color: #00a8e1;
81 }
82 header.head .logo {
83 margin: 7px 12px;
84 width: 38px;
85 }
86 header.head nav {
87 height: 50px;
88 float: right;
89 margin-right: 20px;
90 }
91 header.head nav ul ul {
92 display: none;
93 }
94 header.head nav .menu li {
95 float: left;
96 }
97
98 header.head nav .menu li a {
99 display: inline-block;
100 color:#fff;
101 font-size: 14px;
102 text-align: center;
103 padding: 0 20px;
104 height: 50px;
105 line-height: 50px;
106 transition: all .3s ease;
107 -ms-transition: all .3s ease;
108 -moz-transition: all .3s ease;
109 -webkit-transition: all .3s ease;
110 }
111 header.head nav .menu li a.activo, header.head nav .menu li a:hover {
112 background: #00a8e1;
113 }
114
115 .left-nav {
116 border-top: 9px solid #464646;
117 width: 68px;
118 height: 100%;
119 position: fixed;
120 top:0px;
121 height: 100%;
122 }
123 aside nav.index{padding-top:55px;}
124 aside nav a {
125 display: block;
126 padding: 8px 0;
127 color: #fff;
128 opacity: .4;
129 text-align: center;
130 transition: all .3s ease;
131 -ms-transition: all .3s ease;
132 -moz-transition: all .3s ease;
133 -webkit-transition: all .3s ease;
134 }
135 aside nav a:hover {
136 background-color: #d9d9d9;
137 opacity: 1;
138 }
139
140 aside nav a.active {
141 background-color: #d9d9d9;
142 opacity: 1;
143 }
144
145 .left-nav ul{
146 margin-top: 10px;
147 }
148
149 .left-nav {
150 width: 64px;
151 z-index: 1;
152 }
153
154 .left-nav .head {
155 height: 72px;
156 text-align: left;
157 z-index:1000;
158 background-color: #00a8e1;
159 padding: 12px;
160 display: flex;
161 justify-content: center;
162 align-items: center;
163 }
164
165 .left-nav .head a img{
166 height: 24px;
167 width: 24px;
168 flex:1
169 }
170
171 .left-nav nav a img{
172 height: 30px;
173 width: 30px;
174 }
175
176 .left-nav {
177 background-color: #E7E6E7;
178 }
179
180 .right-main {
181 position: absolute;
182 top: 0px;
183 border-top: 3px solid #464646;
184 right: 0;
185 bottom: 0;
186 left: 64px;
187 background-color: #F4F3F4;
188 -webkit-border-top-left-radius: 10px;
189 -moz-border-radius-topleft: 10px;
190 border-top-left-radius: 10px;
191 }
192
193 .left-main {
194 position: absolute;
195 width: 100%;
196 top: 0px;
197 border-top: 3px solid #464646;
198 right: 0;
199 bottom: 0;
200 background-color: #F4F3F4;
201 -webkit-border-top-left-radius: 10px;
202 -moz-border-radius-topleft: 10px;
203 border-top-left-radius: 10px;
204 }
205
206 .left-main-without-pagination {
207 top: 0px;
208 right: 0;
209 bottom: 0;
210 background-color: #F4F3F4;
211 -webkit-border-top-left-radius: 10px;
212 -moz-border-radius-topleft: 10px;
213 border-top-left-radius: 10px;
214 }
215
216 .seccion {
217 padding: 0px;
218 width: 100%;
219 float: left;
220 }
221 .seccion.treemap{
222 width: 983px;
223 margin-left: 16%;
224 height:577px;
225 padding-top: 1%;
226 }
227 .seccion.treemap #chart{height: 538px}
228 .main{overflow-y: auto;height: 340px;overflow-x: hidden;}
229 article.untercio{
230 width: 293px;
231 height: 380px;
232 }
233 .untercio article{
234 height: 20%;
235 }
236 .seccion article {
237 min-height: 85px;
238 font-size: 11px;
239 text-align: left;
240 }
241 .seccion article header {
242 background: #FFFFFF;
243 min-height: 40px;
244 text-align: left;
245 }
246 .seccion article header h2 {
247 color: #101010;
248 font-size: 14px;
249 width: 100%;
250 margin: 0 12px;
251 padding: 0;
252 line-height: 40px;
253 }
254 .seccion article section {
255 padding: 0px;
256 }
257 .seccion2 {
258 background: #E8EFF0;
259 float: left;
260 width: 55%;
261 overflow-y: auto;
262 max-height: 533px;
263 float: right;
264 overflow-x: hidden;
265 }
266 .seccion2 p {
267 text-align: left;
268 margin-top: 15px;
269 }
270 .sin_padding {
271 padding: 0 !important;
272 background: #E8EFF0;
273 position: relative;
274 }
275 .sin_padding h2{padding-bottom: 16px;}
276
277 /* ==== General COLORS ==== */
278 /* Backgrounds Legacy */
279 .fondo-rojo, .fondo-high, .fondo-error, .fondo-opened {background-color: #DF3936 !important;}
280 .fondo-negro {background-color: #000 !important;}
281 .fondo-gris1, .fondo-critical {background-color: #932ebe !important;}
282 .fondo-gris1, .fondo-unclassified {background-color: #999 !important;}
283 .fondo-blanco {background-color: #fff !important;}
284 .fondo-info, .fondo-risk-accepted {background-color: #2e97bd !important;}
285 .fondo-informational, .fondo-risk-accepted {background-color: #2e97bd !important;}
286 .fondo-naranja, .fondo-medium, .fondo-med, .fondo-re-opened {background-color: #DFBF35 !important;}
287 .fondo-amarillo, .fondo-low, .fondo-closed , .fondo-created{background-color: #A1CE31 !important;}
288 .fondo-violeta {background-color: #932ebe !important;}
289 /* Backgrounds New */
290 .background-unclassified {
291 background-color: #ffffff !important;
292 border: solid 1px #999999;
293 }
294 .background-info {
295 background-color: #ffffff !important;
296 border: solid 1px #2e97bd;
297 }
298 .background-low {
299 background-color: #ffffff !important;
300 border: solid 1px #a1ce31;
301 }
302 .background-med {
303 background-color: #ffffff !important;
304 border: solid 1px #dfbf35;
305 }
306 .background-high {
307 background-color: #ffffff !important;
308 border: solid 1px #df3936;
309 }
310 .background-critical {
311 background-color: #ffffff !important;
312 border: solid 1px #932ebe;
313 }
314 /* Texts Legacy*/
315 .texto-rojo {color: #DF3936;}
316 .texto-negro {color: #000;}
317 .texto-gris1 {color: #2D2F31;}
318 .texto-blanco {color: #6B6565;}
319 /* Texts New*/
320 .text-unclassified {
321 color: #999999 !important;
322 }
323 .text-info {
324 color: #2e97bd !important;
325 }
326 .text-low {
327 color: #a1ce31 !important;
328 }
329 .text-med {
330 color: #dfbf35 !important;
331 }
332 .text-high {
333 color: #df3936 !important;
334 }
335 .text-critical {
336 color: #932ebe !important;
337 }
338 /* Opacity */
339 .opacity-low {
340 opacity: 0.6;
341 }
342 .opacity-med {
343 opacity: 0.8;
344 }
345 .opacity-high {
346 opacity: 1;
347 }
348 /* Big Home menu */
349 .home-list {
350 margin-top: 20px;
351 }
352 .home-list .item {
353 background: #fff;
354 border: 1px solid #d4d5d6;
355 border-radius: 2px;
356 padding: 20px;
357 margin: 0px 15px 15px 0;
358 width: 190px;
359 height: 170px;
360 text-align: center;
361 display: inline-block;
362 float: left;
363 transition: all .3s ease;
364 -ms-transition: all .3s ease;
365 -moz-transition: all .3s ease;
366 -webkit-transition: all .3s ease;
367 }
368 .home-list .item:hover {
369 background-image: linear-gradient(to bottom,#cc3333 0,#df3936 100%);
370 background-image: -webkit-linear-gradient(top,#cc3333 0,#df3936 100%);
371 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cc3333', endColorstr='#df3936', GradientType=0);
372 filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
373 background-repeat: repeat-x;
374 box-shadow: 0 0 10px rgba(0,0,0,0.3);
375 border-color: #df3936;
376 }
377 .home-list .item:hover * {
378 color: #fff;
379 text-shadow: 0 -1px 0 #bf3030;
380 }
381 .home-list .item img {
382 width: 55px;
383 max-width: 70px;
384 max-height: 53px;
385 margin-bottom: 6px;
386 /* display: block; */
387 }
388 .home-list .item span {
389 display: block;
390 height: 35px;
391 color: #df3936;
392 font-size: 19px !important;
393 font-weight: bold !important;
394 text-transform: uppercase;
395 letter-spacing: -.025em;
396 line-height: 17px !important;
397 margin-bottom: 10px;
398 }
399 .home-list .item small {
400 display: block;
401 height: 48px;
402 color: #b2b2b2;
403 font-size: 9px;
404 line-height: 1.25;
405 }
406
407 /* Home Menu grande > Community */
408 .home-list.community .item:nth-child(4) {clear:left;}
409 /* Home Menu grande > Professional */
410 .home-list.professional .item:nth-child(5) {clear:left;}
411 /* Home Menu grande > Corporate */
412 .home-list.corporate .item:nth-child(5), .home-list.corporate .item:nth-child(9), .home-list.corporate .item:nth-child(13) {clear:left;}
413
414 /* Home Animate Icon Order FlipIn */
415 .item:nth-child(0) {-webkit-animation-delay: 0s;}
416 .item:nth-child(1) {-webkit-animation-delay: 0.1s;}
417 .item:nth-child(2) {-webkit-animation-delay: 0.2s;}
418 .item:nth-child(3) {-webkit-animation-delay: 0.3s;}
419 .item:nth-child(4) {-webkit-animation-delay: 0.4s;}
420 .item:nth-child(5) {-webkit-animation-delay: 0.5s;}
421 .item:nth-child(6) {-webkit-animation-delay: 0.6s;}
422 .item:nth-child(7) {-webkit-animation-delay: 0.7s;}
423 .item:nth-child(8) {-webkit-animation-delay: 0.8s;}
424 .item:nth-child(9) {-webkit-animation-delay: 0.9s;}
425 .item:nth-child(10) {-webkit-animation-delay: 1.0s;}
426 .item:nth-child(11) {-webkit-animation-delay: 1.1s;}
427 .item:nth-child(12) {-webkit-animation-delay: 1.2s;}
428
429 /* Icons on Home */
430 .icons-color-home{color: #B3B4B5;}
431 .fa.host{font-size: 2.6em;}
432
433 /* Datos con nro grande, titulo y texto */
434 .dato1 {
435 color: #858585;
436 }
437 .dato1 .nro {
438 font-size: 34px;
439 font-weight: 300;
440 color: #DF3936;
441 }
442
443 /* datos grandes con fondo de color */
444 .dato2 * {
445 text-align: center;
446 }
447 .dato2:hover {
448
449 }
450 .dato2 .nro {
451 font-size: 300%;
452 font-weight: 400;
453 letter-spacing: -.1em;
454 }
455 .dato2 .txt {
456 font-size: 11px;
457 text-transform: uppercase;
458 }
459 .dato2 span{
460 cursor: pointer;
461 }
462
463
464 .dato-left * {
465 text-align: left;
466 }
467 .dato-left:hover {
468
469 }
470 .dato-left .nro {
471 font-size: 300%;
472 font-weight: 400;
473 letter-spacing: -.1em;
474 }
475 .dato-left .txt {
476 font-size: 11px;
477 text-transform: uppercase;
478 }
479 .dato-left span{
480 cursor: pointer;
481 }
482
483
484 /* TABLES - Table sorter for status report*/
485 ul.label-list {
486 list-style-type:none;
487 white-space:nowrap;
488 }
489 ul.label-list li {
490 display: inline;
491 }
492
493 .label-list span.label, .label-list a span.label {
494 font-size: 12px !important;
495 margin: 5px;
496 }
497 table thead th span {
498 color: black;
499 }
500 table thead th a {
501 color: #2E91D8;
502 font-weight: normal;
503 }
504 table thead th a:hover {
505 color: #ddd;
506 text-decoration: underline;
507 }
508
509 table.tablesorter {
510 font-size: 12px;
511 width: 100%;
512 text-align: center;
513 }
514 .tablesorter thead th {
515 height: 30px;
516 border: 1px solid!important;
517 }
518 .tablesorter tbody {
519 max-height: 205px;
520 overflow-y: auto;
521 }
522 .main thead tr{position: absolute;top:38px;}
523 #no-overflow thead,#no-overflow tbody,#no-overflow tr,#no-overflow td,#no-overflow th { display: block; }
524 table.tablesorter thead tr .header {
525 background-repeat: no-repeat;
526 background-position: center right;
527 cursor: pointer;
528 }
529 table.tablesorter thead tr th, table.tablesorter tfoot tr th {
530 background-color: #FFFFFF;
531 color: #fff;
532 border: 1px solid #FFF;
533 font-size: 12px;
534 }
535
536 table.tablesorter tbody td {
537 color: #3D3D3D;
538 background-color: #FFF;
539 vertical-align: top;
540 }
541 table.tablesorter tbody tr.odd td {
542 background-color:#F0F0F6;
543 }
544
545 table.tablesorter thead tr th:first-child,
546 table.tablesorter tbody tr td:first-child {
547 padding-left: 5px;
548 }
549 .tablesorter tr:after {
550 content: ' ';
551 display: block;
552 visibility: hidden;
553 clear: both;
554 }
555
556 table.tablesorter thead tr .headerSortUp {
557 background-image: url(images/asc.gif);
558 }
559 table.tablesorter thead tr .headerSortDown {
560 background-image: url(images/desc.gif);
561 }
562
563 div.modal-body .col-md-6.vuln_table{width: 63%}
564 div.modal-button .btn.btn-success{float: right}
565 div.modal-footer button.btn{bottom: 1%;right: 1%;}
566 div.modal-footer button.btn.btn-success{right: 10%}
567 div.modal-footer button.btn-footer{position: absolute;}
568 .modal-content table.csv-export.status-report{
569 width: 60%;
570 }
571
572 #buttonAtRight {
573 right: 0;
574 }
575 /* Table Status Report */
576 table.status-report {
577 /* background-color: #CDCDCD; */
578 margin:0 0 15px;
579 font-size: 12px;
580 width: 100%;
581 }
582 table.status-report thead th {
583 white-space: nowrap;
584 }
585 table.status-report thead th a {
586 color: #3a3a3a;
587 text-shadow: 0 1px 0 #fff;
588 }
589 table.status-report thead tr th, table.status-report tfoot tr th {
590 background-image: linear-gradient(to bottom,#E8EFF0 0,#DDDDDD 100%);
591 background-image: -webkit-linear-gradient(top,#E8EFF0 0,#DDDDDD 100%);
592 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#E8EFF0', endColorstr='#DDDDDD', GradientType=0);
593 filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
594 background-repeat: repeat-x;
595 border: none;
596 font-size: 14px;
597 padding: 10px 5px;
598 letter-spacing: -.05em;
599 font-weight: normal;
600 text-transform: uppercase;
601 }
602
603 table.status-report thead tr .header {
604 background-repeat: no-repeat;
605 background-position: center right;
606 cursor: pointer;
607 }
608
609 table.status-report tbody td {
610 color: #3D3D3D;
611 padding: 5px;
612 }
613
614 table.status-report tbody tr.odd td {
615 background-color:#F0F0F6;
616 }
617
618 table.status-report thead tr th:first-child,
619 table.status-report tbody tr td:first-child {
620 padding-left: 5px;
621 }
622 table.status-report span.label {
623 text-transform:uppercase;
624 font-weight:normal
625 }
626 table.table tbody tr:nth-child(even) {
627 background-color: #f1f1f1;
628 }
629 table.table tbody tr:nth-child(odd) {
630 background-color: #f9f9f9;
631 }
632 table.table tbody tr:hover{
633 background-color: #ecebea;
634 }
635 .multi-selected {
636 background-color: #f2dede !important;
637 }
638
639 table.last-vuln th{text-align: center;}
640 #list .tablesorter thead th:first-child{width: 49%;}
641 #list .tablesorter thead th {
642 width: 36%;
643 text-align: center;
644 border:1px solid;
645 }
646 #list tbody{display: block}
647 #list .tablesorter tr {display: block;}
648 #list .tablesorter tbody td {width: 51.6%}
649 #list .tablesorter tbody td:nth-child(2){width: 51%;word-break: break-all;}
650 #list .tablesorter thead th:last-child{width: 19%}
651 /* Fixed */
652 .table-fixed thead {
653 width: 100%;
654 }
655 .table-fixed tbody {
656 height: 230px;
657 overflow-y: auto;
658 width: 100%;
659 }
660 .table-fixed thead, .table-fixed tbody, .table-fixed tr, .table-fixed td, .table-fixed th {
661 display: block;
662 }
663 .table-fixed tbody td, .table-fixed thead > tr> th {
664 float: left;
665 border-bottom-width: 0;
666 }
667 .table-fixed th{text-align: center}
668 .table-fixed th{padding-right: 6%!important;}
669 #compound tbody{display: block;max-height: 370px}
670 #compound .tablesorter tbody td span,#compound .tablesorter tbody td img{margin-right: 25px}
671 article#compound.panel{
672 height: 93px;
673 padding-bottom: 428px;
674 background: transparent;
675 border: 0px solid;
676 }
677 article#compound.panel-default table{margin-bottom: 0px}
678 article#compound.panel-default input{
679 width: 90px;
680 float: right;
681 }
682 article#compound.panel-default input.btn.btn-danger{width: 43px}
683 div.col-md-6.left-big-box{width: 45%;margin: -200px 0 5px}
684 div.col-md-6.left-big-box table.table-striped.last-vuln td:nth-child(4){word-break: break-all;}
685
686 .table-striped tbody tr:nth-child(odd){background: #f9f9f9;}
687 .table-striped tbody tr:nth-child(even){background: #FFF;}
688
689 /* Workspaces Table */
690 table.workspaces-list tbody tr:nth-child(odd) span.label {background: #e1372f !important}
691 table.workspaces-list tbody tr:nth-child(even) span.label {background: #4c4c4c !important}
692
693 /* Users Table */
694 table.users-list tbody tr span.label {
695 background: #4c4c4c !important;
696 }
697
698
699 /* modal window */ /* collapse */
700 table.status-report tbody td:nth-child(5), .modal-content td{
701 max-width: 265px;
702 word-wrap: break-word;
703 }
704 div.modal-button{float:right;}
705 /* select */
706 select.ng-valid{
707 font-size: 15px;
708 height: 32px;
709 }
710 /* End Table sorter*/
711
712 /* D3 */
713 #text{font-weight: bold;margin:-18px 3px -4px 0px;float: right;}
714 #treemap {
715 /*font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;*/
716 position: relative;
717 }
718 .node {
719 border: solid 1px white;
720 font: 12px Ubuntu,sans-serif;
721 line-height: 12px;
722 overflow: hidden;
723 position: absolute;
724 font-weight: bold;
725 color: #FFF;
726 text-indent: 2px;
727 }
728
729 .bar {
730 fill: steelblue;
731 }
732 .bar:hover {
733 opacity: 0.5;
734 }
735 #bar svg{margin-left: -10px;}
736
737 #contenido{text-align: left;}
738 #sequence {
739 height: 0px;
740 }
741 #sequence text, #legend text {
742 font-weight: 600;
743 fill: #fff;
744 }
745 #chart path {
746 stroke: #fff;
747 }
748 text.host-name{font-size: 13px;font-weight:bold;}
749 /* Line Chart */
750 .axis path,
751 .axis line {
752 fill: none;
753 stroke: #000;
754 shape-rendering: crispEdges;
755 }
756
757 .x.axis path {
758 display: none;
759 }
760
761 .line {
762 fill: none;
763 stroke: steelblue;
764 stroke-width: 4px;
765 opacity: 0.5;
766 }
767 .line-hover {
768 stroke: #e769ab ;
769 stroke-width:4px;
770 opacity: 0.9;
771 }
772 /* End of D3*/
773
774 /* reports */
775 #treemap, #bar, #cake{height:195px}
776 #vulns .columna{margin-left:2%}
777 #vulns .main{width:100%;height:105px}
778 #vulns-by-price .main{width:100% !important;height: 140px !important;}
779 #vulns .columna.unsexto{margin: auto;}
780 #summarized .main{height:197px}
781 #summarized .panel.panel-default,#byservices .panel.panel-default{max-height: 239px}
782 #byservices .main{height:197px}
783 #byservices .alert, #summarized .alert{width: 100%}
784 #compound header, #list header{min-height: 40px;}
785 .status .seccion2{width: 100%;}
786 /* End of reports*/
787
788 /*BOOTSTRAP*/
789 /* Custom Bootstrap Danger dropdown styles */
790 .dropdown-menu-danger {
791 background-image: linear-gradient(to bottom, #d9534f 0px, #c12e2a 100%);
792 background-repeat: repeat-x;
793 border-color: #b92c28;
794 }
795 .dropdown-menu-danger li a {
796 color: #ffffff !important;
797 text-shadow: 0 1px 0 rgba(0,0,0,.5);
798 &:focus {
799 background-color: #000000 !important;
800 background-image: linear-gradient(to bottom, #000000 0px, #c12e2a 100%) !important;
801 background-repeat: repeat-x;
802 color: #000000 !important;
803 }
804 }
805
806 #sec {
807 float: right;
808 margin-top: -34px;
809 }
810
811 #byservices .col-lg-3, #summarized .col-lg-3{width: 29%;margin:0px -2% 0px 0%;}
812 section .col-lg-2{margin: 0px -2% 0px 2px;padding-right: 1.9%;}
813 .col-lg-6 .panel{margin-bottom: 10px}
814 #list .col-lg-6, #vulns .col-lg-6, #vulns-by-price .col-lg-6{width: 55%;float: right;margin-bottom: 5px}
815
816 .panel{margin-bottom: 1%!important}
817 article.panel > span{
818 position: absolute;
819 width: 100%;
820 text-align: center;
821 font-weight: bold;
822 z-index: 1000;
823 }
824 article.panel > span > div{
825 display: block;
826 float: left;
827 text-align: center;
828 width: 50%;
829 border-radius: 10px;
830 color: #FFF;
831 }
832 .box{
833 display: flex;
834 flex-direction: row;
835 flex-wrap: wrap;
836 justify-content: center;
837 align-items: center;
838 }
839 #merge, #delete, #new, #tags, #group-by, #add-columns, left{margin:5px;float:right}
840 .left_auths{margin:5px;float:right;margin-top: -52px;}
841 .left_auth{margin:5px;float:right;margin-top: -40px;}
842
843 div.box div.columna {
844 background-color: #fff; color: #6B6565!important;
845 }
846 div.box div.columna:hover {
847 background-color: #E9E9E9; color: #6B6565!important;
848 }
849 #merge, #delete, #new{margin:5px;float:right;}
850 .input-sm{float: left;margin-bottom: 20px;}
851 /* Media */
852 @media screen and (min-width: 1380px){
853 .treemap{margin-left:13%;}
854 .seccion.treemap{margin-left: 20%}
855 #byservices .col-lg-3, #summarized .col-lg-3{width: 28%;margin: 0px -2% 0px 0.5%;}
856 #compound .tablesorter tbody td span, #compound .tablesorter tbody td img{margin-right: 50px}
857 #list .tablesorter tbody td:nth-child(2){width: 34%}
858 }
859 @media screen and (max-width:1000px) {
860 #no-overflow{overflow: auto!important }
861 .col-lg-2{width: 100%;margin: auto;}
862 section#main{height: 100%!important}
863 .treemap{left:256px!important;}
864 #compound .col-lg-6, #list .col-lg-6, #vulns .col-lg-6, #vulns-by-price .col-lg-6, #byservices .col-lg-3, #summarized .col-lg-3{
865 width: 100%;margin-top: 0%
866 }
867 }
868 /* End of media */
869 /* Styles for WS list */
870 .ws-name {
871 font: 120%/3 'Ubuntu',Helvetica,Arial,sans-serif !important;
872 font-size: 100%;
873 }
874 .ws-link {
875 float: left;
876 color: #ffffff;
877 text-decoration: none;
878 }
879 a.ws-link span.impact-ok{top: 2px;left: -4px;color: #5cb85c;}
880 a.ws-link span.impact-del{top: 3px;left: 2px;color: #d9534f;}
881 a.ws-link:hover {
882 color: #ffffff;
883 text-decoration: none;
884 }
885 /* End of WS list */
886 /* New Modal*/
887 div.panel-default .panel-body label{font-size: 15px}
888 i.pull-right.glyphicon.ng-scope.glyphicon-plus-sign{color:green;}
889 i.fa.fa-copy.copy-icon.fa-lg{margin-top: 10px;cursor: pointer;}
890 div.panel-collapse .panel-body{padding:0px;}
891 div.panel.panel-default div.panel-heading{padding: 0px}
892 div.panel-body table{width: 100%}
893 div.panel-body td{font-size: 15px; padding: 10px 20px; border-bottom: 1px solid #ECE9E9;}
894 a.ng-binding.ng-pristine, a.ng-binding.ng-scope{display: block; font-size: 15px; text-decoration: none; padding: 5px 15px}
895 a.ng-binding.ng-scope{padding: 10px;}
896 div.panel-heading a i.glyphicon{margin: -25px 10px;}
897 div.modal-body .alert-danger.target_not_selected{font-size: 15px}
898 div.modal-body .form-group:first-child button{float: right}
899 /* Pagination Modal New */
900 .showPagination ul.pagination{font-size: 15px;margin:auto;padding-left: 2%}
901 div.showPagination .col-md-2, div.showPagination .btn.btn-default{float:right;}
902 div.showPagination form#goToPageStatus{margin-top:-40px;}
903 input.form-control.vuln_per_page{width: 10%;margin: auto}
904 /* End */
905 .reference{margin-top: 5px;}
906 div.form-group.editArray{margin-bottom: 0px}
907 div.modal-footer.editArray{margin-top: 0px}
908 input#vuln-refs, input#vuln-policyviolations {border-radius: 5px 0 0 5px}
909 i.fa.fa-plus-circle{color: green;}
910 i.fa.fa-minus-circle{color: red;cursor: pointer;}
911 span.input-group-addon.button-radius{
912 border-radius: 4px!important;
913 border-left: 1px solid #ccc;
914 width: 20px;
915 cursor: pointer;
916 }
917 input#port
918 span#cakeText{width: 95%}
919 span#treemapTextModel{font-size: 14px}
920 .normal-size {
921 font-size: 14px !important;
922 }
923 /* Login */
924 .contenedor {
925 position: relative;
926 }
927 .centrado {
928 position: absolute;
929 width: 300px;
930 background: #00a8e1;
931 left: 50%;
932 margin-left: -150px;
933 top: 150px;
934 padding: 10px 20px 20px;
935 text-align: center;
936 color: #fff;
937 }
938 .footer_centrado {
939 position: absolute;
940 width: 50%;
941 left: 75%;
942 margin-left: -150px;
943 top: 95%;
944 text-align: center;
945 color: #fff;
946 }
947 .faraday-iso {
948 position: absolute;
949
950 width: 80px;
951
952
953 margin-left: -40px;
954
955 left: 50%;
956
957 top: -80px;
958
959 }
960
961 /* Login */
962 .upsize {
963 font-size: 13px;
964 cursor: pointer;
965 }
966 .onhover:hover {
967 text-decoration: underline;
968 }
969 div.input-margin{margin: 4px 0;}
970 div.col-md-8.protocol input#protocol{margin-top: 35px}
971 div#treemap_container{margin: 5% auto 0}
972 article#compound div.showPagination{margin-bottom: 30px}
973 article#compound .showPagination input.form-control{width:110px;}
974 article#compound .showPagination div.form-group{margin-top: 10px;}
975 article#compound.panel-default input{width: 90px;float: right}
976
977 article#compound .showPagination input#vuln-per-page{width: 75px!important;margin-right: 15%}
978 aside .alert.alert-danger.alert-dismissible{
979 position: fixed;
980 top: 45%;
981 left: 30%;
982 font-size: 15px;
983 z-index: 1000;
984 }
985
986 .label-unclassified {
987 color: #FFFFFF;
988 background-color: #444147;
989 border-color: #444147;
990 }
991
992 .label-unclassified:hover,
993 .label-unclassified:focus,
994 .label-unclassified:active,
995 .label-unclassified.active,
996 .open .dropdown-toggle.label-unclassified {
997 color: #FFFFFF;
998 background-color: #111012;
999 border-color: #444147;
1000 }
1001
1002 .label-unclassified:active,
1003 .label-unclassified.active,
1004 .open .dropdown-toggle.label-unclassified {
1005 background-image: none;
1006 }
1007
1008 .label-unclassified.disabled,
1009 .label-unclassified[disabled],
1010 fieldset[disabled] .label-unclassified,
1011 .label-unclassified.disabled:hover,
1012 .label-unclassified[disabled]:hover,
1013 fieldset[disabled] .label-unclassified:hover,
1014 .label-unclassified.disabled:focus,
1015 .label-unclassified[disabled]:focus,
1016 fieldset[disabled] .label-unclassified:focus,
1017 .label-unclassified.disabled:active,
1018 .label-unclassified[disabled]:active,
1019 fieldset[disabled] .label-unclassified:active,
1020 .label-unclassified.disabled.active,
1021 .label-unclassified[disabled].active,
1022 fieldset[disabled] .label-unclassified.active {
1023 background-color: #444147;
1024 border-color: #444147;
1025 }
1026
1027 .label-unclassified .badge {
1028 color: #444147;
1029 background-color: #FFFFFF;
1030 }
1031 .label-high {
1032 color: #ffffff;
1033 background-color: #DF3936;
1034 border-color: #DF3936;
1035 }
1036
1037 .label-high:hover,
1038 .label-high:focus,
1039 .label-high:active,
1040 .label-high.active,
1041 .open .dropdown-toggle.label-high {
1042 color: #ffffff;
1043 background-color: #992826;
1044 border-color: #DF3936;
1045 }
1046
1047 .label-high:active,
1048 .label-high.active,
1049 .open .dropdown-toggle.label-high {
1050 background-image: none;
1051 }
1052
1053 .label-high.disabled,
1054 .label-high[disabled],
1055 fieldset[disabled] .label-high,
1056 .label-high.disabled:hover,
1057 .label-high[disabled]:hover,
1058 fieldset[disabled] .label-high:hover,
1059 .label-high.disabled:focus,
1060 .label-high[disabled]:focus,
1061 fieldset[disabled] .label-high:focus,
1062 .label-high.disabled:active,
1063 .label-high[disabled]:active,
1064 fieldset[disabled] .label-high:active,
1065 .label-high.disabled.active,
1066 .label-high[disabled].active,
1067 fieldset[disabled] .label-high.active {
1068 background-color: #DF3936;
1069 border-color: #DF3936;
1070 }
1071
1072 .label-high .badge {
1073 color: #DF3936;
1074 background-color: #ffffff;
1075 }
1076 .btn-small-margin {
1077 margin-bottom: 15px !important;
1078 }
1079 .glyphicon-btn {
1080 top: 0 !important;
1081 }
1082 #tooltip-stacked-bar {
1083 position: absolute;
1084 text-align: center;
1085 width: 40px;
1086 height: auto;
1087 padding: 10px;
1088 background-color: white;
1089 -webkit-border-radius: 10px;
1090 -moz-border-radius: 10px;
1091 border-radius: 10px;
1092 -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
1093 -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
1094 box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
1095 pointer-events: none;
1096 }
1097 #tooltip-stacked-bar.hidden {
1098 display: none;
1099 }
1100 #tooltip-stacked-bar p {
1101 margin: 0;
1102 font-family: sans-serif;
1103 font-size: 16px;
1104 line-height: 20px;
1105 }
1106 .center-lg-6 {
1107 margin: 0 auto;
1108 text-align: center;
1109 width: 500px;
1110 }
1111 div#workspace-progress-reference.center-lg-6{padding-top: 15px}
1112 .col-lg-left{width: 46%!important;margin-top: -30px;}
1113 .col-lg-right{width: 53%!important;padding-left: 0px!important;}
1114 .no-margin-bottom{margin-bottom: 0px!important;}
1115 .wrapword{
1116 white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
1117 white-space: -pre-wrap; /* Opera 4-6 */
1118 white-space: -o-pre-wrap; /* Opera 7 */
1119 white-space: pre-wrap; /* css-3 */
1120 word-wrap: break-word; /* Internet Explorer 5.5+ */
1121 white-space: -webkit-pre-wrap; /* Newer versions of Chrome/Safari*/
1122 word-break: break-all;
1123 white-space: normal;
1124 }
1125 #counter{
1126 font-size: 12px;
1127 position: fixed;
1128 background: #999;
1129 opacity: 0.6;
1130 color: #FFF;
1131 display: block;
1132 right: 0px;
1133 border-radius: 7px 0px 0px 7px;
1134 padding: 5px;
1135 bottom: 40px;
1136 text-decoration: none!important;
1137 z-index: 100000;
1138 -webkit-transition: opacity 0.5s ease-out;
1139 -moz-transition: opacity 0.5s ease-out;
1140 -o-transition: opacity 0.5s ease-out;
1141 transition: opacity 0.5s ease-out;
1142 cursor: default;
1143 }
1144 #counter:hover{
1145 opacity: 0;
1146 }
1147 .counterNum{
1148 font-size: 15px;
1149 font-weight: bold;
1150 }
1151 .text-center{text-align: center; line-height: 40px;}
1152 .severities .color-unclassified, .severities .color-unclassified:hover{color: #999;}
1153 .severities .color-info, .severities .color-info:hover{color: #2e97bd;}
1154 .severities .color-low, .severities .color-low:hover{color: #A1CE31;}
1155 .severities .color-med, .severities .color-med:hover{color: #DFBF35;}
1156 .severities .color-high, .severities .color-high:hover{color: #DF3936;}
1157 .severities .color-critical, .severities .color-critical:hover{color: #932ebe;}
1158 .severities > button{
1159 width: 100%;
1160 text-align: left;
1161 }
1162 .severities > button > span{
1163 color: #000;
1164 float: right;
1165 margin-top: 8px;
1166 }
1167 .severities > .dropdown-menu-left{left: 14px;}
1168 .severities button.button-error{
1169 border-color: #a94442;
1170 -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
1171 box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
1172 }
1173 #bar .chart-container, #doughnut .chart-container{height: 130px}
1174 div.form-group.input-accordion{margin: 0px!important}
1175 /* Firefox */
1176 @-moz-document url-prefix() {
1177 .severities > button > span{margin-top: -10px;}
1178 }
1179 span.bold{font-weight: bold}
1180 div.jumbotron.jumbotron-font h1{font-size: 54px}
1181 /* Normalize datepicker */
1182 div.datepicker ul.dropdown-menu{width: 288px;}
1183 div.datepicker > p > ul > li > div > table{width: 97%}
1184 div.datepicker .btn-sm, .btn-group-sm > .btn{padding: 5px 7px}
1185 .disabled{color: #919191}
1186 div.btn-group .vulns-filter{left: -2px;}
1187 div.btn-group .dropdown-menu.margin{margin-left: 38px}
1188 /* UI GRID */
1189 .ui-grid-cell.ui-grid-disable-selection.ui-grid-row-header-cell{pointer-events: auto!important;}
1190 .grid {
1191 height: 100%;
1192 }
1193 .ui-grid-cell-contents{
1194 padding-top: 12px !important;
1195 }
1196 .ui-grid-cell-contents p{
1197 margin-bottom: 0;
1198 }
1199 .ui-grid-cell-contents.left-rows.text-center.ng-scope{white-space: normal!important; }
1200 .ui-grid .ui-grid-row:nth-child(odd) .ui-grid-cell .ui-grid-cell-contents .crop-text, .ui-grid .ui-grid-row:nth-child(even) .ui-grid-cell .ui-grid-cell-contents .crop-text, .ui-grid-cell-contents{
1201 white-space: pre;
1202 word-wrap: break-word!important;
1203 font-size: 13px !important;
1204 }
1205 .grid.ui-grid{font-family: 12px!important;}
1206 .ui-grid-cell-contents.row-tooltip.text-center{white-space: normal!important; }
1207 .white-space{white-space: pre!important; word-wrap: break-word;}
1208 .ui-grid-cell-contents.center > .pos-middle.crop-text{top: 2%!important;white-space: inherit!important;}
1209 .overflow-cell{
1210 height: 30px!important;
1211 overflow-y: auto!important;
1212 }
1213 div.ui-grid-header-cell .ui-grid-cell-contents{white-space: normal;}
1214 div.alert.alert-danger.alert-dismissible .ws-list{text-align: center; text-transform: uppercase; padding: 10px}
1215 div.alert.alert-danger.alert-dismissible .ws-list a:hover{text-decoration: none}
1216 .grid .ui-grid-header {
1217 padding: 3px 5px;
1218 }
1219 .ui-grid-text-center {
1220 text-align: center;
1221 }
1222 a.button-disable{cursor: not-allowed;pointer-events: none;opacity: 0.5}
1223 .almost-expired{background-color: #dca7a7 !important}
1224
1225 .row-fix:before,.row-fix:after {
1226 display: table;
1227 content: " ";
1228 }
1229
1230 .row-fix:after {
1231 clear: both;
1232 }
1233
1234 #custom-search-input{
1235 border: solid 1px #E4E4E4;
1236 border-radius: 6px;
1237 background-color: #fff;
1238 margin-top: 1%;
1239 }
1240
1241 #custom-search-input input{
1242 border: 0;
1243 box-shadow: none;
1244 }
1245
1246 #custom-search-input button{
1247 margin: 2px 0 0 0;
1248 background: none;
1249 box-shadow: none;
1250 border: 0;
1251 color: #666666;
1252 padding: 0 8px 0 10px;
1253 border-left: solid 1px #ccc;
1254 }
1255
1256 #custom-search-input button:hover{
1257 border: 0;
1258 box-shadow: none;
1259 border-left: solid 1px #ccc;
1260 }
1261
1262 #custom-search-input .glyphicon-search{
1263 font-size: 23px;
1264 }
1265
1266 .search_align {
1267 margin-right: 25%;
1268 }
1269 .workspace_label {
1270 display: inline;
1271 padding: 0.05em 0.6em 0.3em;
1272 font-size: 75%;
1273 font-weight: 700;
1274 line-height: 1;
1275 color: rgb(107, 105, 105);
1276 text-align: center;
1277 white-space: nowrap;
1278 vertical-align: baseline;
1279 border-radius: .25em;
1280 }
1281
1282 .ui-notification.info{
1283 color: #31708f;
1284 background-color: #d9edf7;
1285 }
1286
1287 .ui-notification a {
1288 color: #31708f;
1289 }
1290
1291 .ui-notification>h3{
1292 font-size:14px;
1293 font-weight:700;
1294 display:block;
1295 margin:0px 10px 0;
1296 padding:0 0 5px;
1297 text-align:right;
1298 border-bottom:1px solid rgba(255,255,255,.3)
1299 }
1300
1301 .capitalize {
1302 text-transform: capitalize;
1303 }
1304
1305 .small-size {
1306 font-size:10px;
1307 }
1308
1309 .header_right {
1310 float: right;
1311 margin: 8px;
1312 }
1313
1314 .accordion-expand-button {
1315 color: #008000;
1316 right: 10px;
1317 top: -25px !important;
1318 }
1319
1320 .accordion-expand-button-disabled {
1321 display: none !important;
1322 }
1323
1324 .header_right {
1325 /* TODO: this is a fast hack, maybe there is a better way to do this */
1326 margin-top: -2.25%;
1327 }
1328 .tooltip-inner {
1329 white-space: pre-wrap;
1330 }
1331
1332 /* deduplication of CSS - StatusResport */
1333 .label-impact {
1334 display: inline;
1335 padding: .2em .6em .3em;
1336 font-size: 100%;
1337 font-weight: 700;
1338 line-height: 1;
1339 color: #fff;
1340 text-align: center;
1341 white-space: nowrap;
1342 vertical-align: baseline;
1343 -webkit-border-radius: .25em;
1344 border-radius: .25em
1345 }
1346 .label-default-impact {
1347 background-color: #777
1348 }
1349 .label-success-impact {
1350 background-color: #5cb85c
1351 }
1352
1353 .overall{
1354 z-index: 1000000 !important;
1355 }
1356
1357 #btn_clear_search {
1358 position: absolute;
1359 height: 30px;
1360 border-radius: 2px;
1361 right: 15px;
1362 padding-top: 3px;
1363 }
1364
1365 .markdown-preview {
1366 height: 200px;
1367 overflow-x: auto;
1368 }
1369 .hr_divider{
1370 height:1px;
1371 border-width:0;
1372 background-color: #e5e5e5;
1373 margin: 5px 0 5px 0;
1374 }
1375 .ui-grid-selection-row-header-buttons {
1376 cursor: pointer !important;
1377 opacity: 1 !important;
1378
1379 }
1380
1381 .visible-overflow {
1382 overflow-y: visible !important;
1383 }
1384 .navigation-active{
1385 border-bottom: 1px solid #00a8e1 !important;
1386 }
1387 a {
1388 text-decoration: none !important;
1389 }
1390 .background-blue{
1391 background-color: #00a8e1 !important;
1392 border-color: #00a8e1 !important;
1393 color: white !important;
1394 }
1395 .col-s-1{
1396 padding-right: 15px;
1397 }
1398 .ui-grid-row:nth-child(odd):hover .ui-grid-cell{background:#ecebea}
1399 .ui-grid-row:nth-child(even):hover .ui-grid-cell{background:#ecebea}
1400
1401 .change-padding-to-margin {
1402 padding-bottom: 0px !important;
1403 margin-bottom: 15px;
1404 }
1405 .no-padding{
1406 padding: 0 !important;
1407 }
1408 .responsive_agent_command{
1409 width: 30em;
1410 white-space: nowrap;
1411 text-overflow: ellipsis;
1412 overflow: hidden;
1413 }
1414
1415 .forgot-password{
1416 margin-top: 10px;
1417 text-align: center;
1418 padding-bottom: 10px;
1419 }
faraday/server/www/favicon-16x16.png less more
Binary diff not shown
faraday/server/www/favicon-32x32.png less more
Binary diff not shown
faraday/server/www/favicon-96x96.png less more
Binary diff not shown
faraday/server/www/favicon.ico less more
Binary diff not shown
faraday/server/www/fonts/flexslider-icon.eot less more
Binary diff not shown
+0
-19
faraday/server/www/fonts/flexslider-icon.svg less more
0 <?xml version="1.0" standalone="no"?>
1 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
2 <svg xmlns="http://www.w3.org/2000/svg">
3 <metadata>
4 This is a custom SVG font generated by IcoMoon.
5 <iconset grid="14"></iconset>
6 </metadata>
7 <defs>
8 <font id="flexslider-icon" horiz-adv-x="448" >
9 <font-face units-per-em="448" ascent="384" descent="-64" />
10 <missing-glyph horiz-adv-x="448" />
11 <glyph unicode="&#xf001;" d="M 185.50-9.25l-163.00,162.75q-9.25,9.25 -9.25,22.625t 9.25,22.625l 163.00,162.75q 9.25,9.25 22.625,9.25t 22.625-9.25l 18.75-18.75q 9.25-9.25 9.25-22.625t-9.25-22.625l-121.50-121.50l 121.50-121.25q 9.25-9.50 9.25-22.75t-9.25-22.50l-18.75-18.75q-9.25-9.25 -22.625-9.25t-22.625,9.25z" horiz-adv-x="288" />
12 <glyph unicode="&#xf002;" d="M 274.75,176.00q0.00-13.00 -9.25-22.75l-163.00-162.75q-9.25-9.25 -22.50-9.25t-22.50,9.25l-19.00,18.75q-9.25,9.75 -9.25,22.75q0.00,13.25 9.25,22.50l 121.50,121.50l-121.50,121.25q-9.25,9.75 -9.25,22.75q0.00,13.25 9.25,22.50l 19.00,18.75q 9.00,9.50 22.50,9.50t 22.50-9.50l 163.00-162.75q 9.25-9.25 9.25-22.50z" horiz-adv-x="288" />
13 <glyph unicode="&#xf003;" d="M 346.00,152.25l-332.00-184.50q-5.75-3.25 -9.875-0.75t-4.125,9.00l0.00,368.00 q0.00,6.50 4.125,9.00t 9.875-0.75l 332.00-184.50q 5.75-3.25 5.75-7.75t-5.75-7.75z" horiz-adv-x="352" />
14 <glyph unicode="&#xf004;" d="M 384.00,336.00l0.00-352.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-128.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,352.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 128.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25zM 160.00,336.00l0.00-352.00 q0.00-6.50 -4.75-11.25t-11.25-4.75l-128.00,0.00 q-6.50,0.00 -11.25,4.75t-4.75,11.25l0.00,352.00 q0.00,6.50 4.75,11.25t 11.25,4.75l 128.00,0.00 q 6.50,0.00 11.25-4.75t 4.75-11.25z" horiz-adv-x="384" />
15 <glyph unicode="&#xf005;" d="M 402.75,208.00q0.00-13.25 -9.25-22.50l-162.75-162.75q-9.50-9.50 -22.75-9.50q-13.50,0.00 -22.50,9.50l-162.75,162.75q-9.50,9.00 -9.50,22.50q0.00,13.25 9.50,22.75l 18.50,18.75q 9.75,9.25 22.75,9.25q 13.25,0.00 22.50-9.25l 121.50-121.50l 121.50,121.50q 9.25,9.25 22.50,9.25q 13.00,0.00 22.75-9.25l 18.75-18.75q 9.25-9.75 9.25-22.75z" horiz-adv-x="416" />
16 <glyph unicode="&#x20;" horiz-adv-x="224" />
17 <glyph class="hidden" unicode="&#xf000;" d="M0,384L 448 -64L0 -64 z" horiz-adv-x="0" />
18 </font></defs></svg>
faraday/server/www/fonts/flexslider-icon.ttf less more
Binary diff not shown
faraday/server/www/fonts/flexslider-icon.woff less more
Binary diff not shown
faraday/server/www/fonts/font-awesome/FontAwesome.otf less more
Binary diff not shown
faraday/server/www/fonts/font-awesome/fontawesome-webfont.eot less more
Binary diff not shown
+0
-520
faraday/server/www/fonts/font-awesome/fontawesome-webfont.svg less more
0 <?xml version="1.0" standalone="no"?>
1 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
2 <svg xmlns="http://www.w3.org/2000/svg">
3 <metadata></metadata>
4 <defs>
5 <font id="fontawesomeregular" horiz-adv-x="1536" >
6 <font-face units-per-em="1792" ascent="1536" descent="-256" />
7 <missing-glyph horiz-adv-x="448" />
8 <glyph unicode=" " horiz-adv-x="448" />
9 <glyph unicode="&#x09;" horiz-adv-x="448" />
10 <glyph unicode="&#xa0;" horiz-adv-x="448" />
11 <glyph unicode="&#xa8;" horiz-adv-x="1792" />
12 <glyph unicode="&#xa9;" horiz-adv-x="1792" />
13 <glyph unicode="&#xae;" horiz-adv-x="1792" />
14 <glyph unicode="&#xb4;" horiz-adv-x="1792" />
15 <glyph unicode="&#xc6;" horiz-adv-x="1792" />
16 <glyph unicode="&#xd8;" horiz-adv-x="1792" />
17 <glyph unicode="&#x2000;" horiz-adv-x="768" />
18 <glyph unicode="&#x2001;" horiz-adv-x="1537" />
19 <glyph unicode="&#x2002;" horiz-adv-x="768" />
20 <glyph unicode="&#x2003;" horiz-adv-x="1537" />
21 <glyph unicode="&#x2004;" horiz-adv-x="512" />
22 <glyph unicode="&#x2005;" horiz-adv-x="384" />
23 <glyph unicode="&#x2006;" horiz-adv-x="256" />
24 <glyph unicode="&#x2007;" horiz-adv-x="256" />
25 <glyph unicode="&#x2008;" horiz-adv-x="192" />
26 <glyph unicode="&#x2009;" horiz-adv-x="307" />
27 <glyph unicode="&#x200a;" horiz-adv-x="85" />
28 <glyph unicode="&#x202f;" horiz-adv-x="307" />
29 <glyph unicode="&#x205f;" horiz-adv-x="384" />
30 <glyph unicode="&#x2122;" horiz-adv-x="1792" />
31 <glyph unicode="&#x221e;" horiz-adv-x="1792" />
32 <glyph unicode="&#x2260;" horiz-adv-x="1792" />
33 <glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
34 <glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
35 <glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
36 <glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
37 <glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
38 <glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
39 <glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
40 <glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
41 <glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
42 <glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
43 <glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
44 <glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
45 <glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
46 <glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
47 <glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
48 <glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
49 <glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " />
50 <glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
51 <glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
52 <glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
53 <glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
54 <glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
55 <glyph unicode="&#xf016;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z " />
56 <glyph unicode="&#xf017;" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
57 <glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
58 <glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" />
59 <glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
60 <glyph unicode="&#xf01b;" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
61 <glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
62 <glyph unicode="&#xf01d;" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
63 <glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
64 <glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
65 <glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" />
66 <glyph unicode="&#xf023;" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
67 <glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
68 <glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
69 <glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
70 <glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
71 <glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
72 <glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
73 <glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
74 <glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
75 <glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
76 <glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
77 <glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
78 <glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
79 <glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
80 <glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57 q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -4 -0.5 -13t-0.5 -13q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5 q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14z" />
81 <glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142 q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5 t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68.5 -0.5t67.5 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5 t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12z" />
82 <glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q6 2 81.5 21.5t111.5 37.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5 q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" />
83 <glyph unicode="&#xf034;" horiz-adv-x="1792" d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2 t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5 q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27 q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44v383z" />
84 <glyph unicode="&#xf035;" d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1 t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27 q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44v383zM1310 125q12 0 42 -19.5t57.5 -41.5 t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49 t26 49q4 3 36 30t59.5 49t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5z" />
85 <glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
86 <glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
87 <glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
88 <glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
89 <glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
90 <glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
91 <glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
92 <glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" />
93 <glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
94 <glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
95 <glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
96 <glyph unicode="&#xf042;" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
97 <glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
98 <glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
99 <glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
100 <glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" />
101 <glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
102 <glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
103 <glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
104 <glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
105 <glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
106 <glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
107 <glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
108 <glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
109 <glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
110 <glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
111 <glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
112 <glyph unicode="&#xf053;" horiz-adv-x="1280" d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" />
113 <glyph unicode="&#xf054;" horiz-adv-x="1280" d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" />
114 <glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
115 <glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
116 <glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
117 <glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
118 <glyph unicode="&#xf059;" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
119 <glyph unicode="&#xf05a;" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
120 <glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
121 <glyph unicode="&#xf05c;" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
122 <glyph unicode="&#xf05d;" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
123 <glyph unicode="&#xf05e;" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
124 <glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
125 <glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
126 <glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
127 <glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
128 <glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
129 <glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
130 <glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
131 <glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
132 <glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
133 <glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
134 <glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
135 <glyph unicode="&#xf06b;" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5 t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" />
136 <glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
137 <glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
138 <glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
139 <glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " />
140 <glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
141 <glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
142 <glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
143 <glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
144 <glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
145 <glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
146 <glyph unicode="&#xf077;" horiz-adv-x="1792" d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
147 <glyph unicode="&#xf078;" horiz-adv-x="1792" d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
148 <glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
149 <glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
150 <glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
151 <glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
152 <glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
153 <glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
154 <glyph unicode="&#xf080;" horiz-adv-x="2048" d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
155 <glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
156 <glyph unicode="&#xf082;" d="M1536 160q0 -119 -84.5 -203.5t-203.5 -84.5h-192v608h203l30 224h-233v143q0 54 28 83t96 29l132 1v207q-96 9 -180 9q-136 0 -218 -80.5t-82 -225.5v-166h-224v-224h224v-608h-544q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5v-960z" />
157 <glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
158 <glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
159 <glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
160 <glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
161 <glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
162 <glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" />
163 <glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
164 <glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" />
165 <glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
166 <glyph unicode="&#xf08c;" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
167 <glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
168 <glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
169 <glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
170 <glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
171 <glyph unicode="&#xf092;" d="M394 184q-8 -9 -20 3q-13 11 -4 19q8 9 20 -3q12 -11 4 -19zM352 245q9 -12 0 -19q-8 -6 -17 7t0 18q9 7 17 -6zM291 305q-5 -7 -13 -2q-10 5 -7 12q3 5 13 2q10 -5 7 -12zM322 271q-6 -7 -16 3q-9 11 -2 16q6 6 16 -3q9 -11 2 -16zM451 159q-4 -12 -19 -6q-17 4 -13 15 t19 7q16 -5 13 -16zM514 154q0 -11 -16 -11q-17 -2 -17 11q0 11 16 11q17 2 17 -11zM572 164q2 -10 -14 -14t-18 8t14 15q16 2 18 -9zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-224q-16 0 -24.5 1t-19.5 5t-16 14.5t-5 27.5v239q0 97 -52 142q57 6 102.5 18t94 39 t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103 q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -103t0.5 -68q0 -22 -11 -33.5t-22 -13t-33 -1.5 h-224q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
172 <glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" />
173 <glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" />
174 <glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
175 <glyph unicode="&#xf096;" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
176 <glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
177 <glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
178 <glyph unicode="&#xf099;" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
179 <glyph unicode="&#xf09a;" horiz-adv-x="1024" d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" />
180 <glyph unicode="&#xf09b;" d="M1536 640q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -39.5 7t-12.5 30v211q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5 q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23 q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -89t0.5 -54q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
181 <glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" />
182 <glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
183 <glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" />
184 <glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
185 <glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
186 <glyph unicode="&#xf0a2;" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5 t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
187 <glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
188 <glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
189 <glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
190 <glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
191 <glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580 q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100 q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
192 <glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
193 <glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
194 <glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
195 <glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
196 <glyph unicode="&#xf0ac;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5 q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5 q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5 t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3 q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25 q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5 t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5 t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21 q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5 q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3 q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5 t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5 q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7 q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" />
197 <glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
198 <glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
199 <glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
200 <glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
201 <glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " />
202 <glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
203 <glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
204 <glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " />
205 <glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
206 <glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
207 <glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
208 <glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" />
209 <glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
210 <glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
211 <glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
212 <glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
213 <glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
214 <glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
215 <glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
216 <glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" />
217 <glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
218 <glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
219 <glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
220 <glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
221 <glyph unicode="&#xf0d4;" d="M829 318q0 -76 -58.5 -112.5t-139.5 -36.5q-41 0 -80.5 9.5t-75.5 28.5t-58 53t-22 78q0 46 25 80t65.5 51.5t82 25t84.5 7.5q20 0 31 -2q2 -1 23 -16.5t26 -19t23 -18t24.5 -22t19 -22.5t17 -26t9 -26.5t4.5 -31.5zM755 863q0 -60 -33 -99.5t-92 -39.5q-53 0 -93 42.5 t-57.5 96.5t-17.5 106q0 61 32 104t92 43q53 0 93.5 -45t58 -101t17.5 -107zM861 1120l88 64h-265q-85 0 -161 -32t-127.5 -98t-51.5 -153q0 -93 64.5 -154.5t158.5 -61.5q22 0 43 3q-13 -29 -13 -54q0 -44 40 -94q-175 -12 -257 -63q-47 -29 -75.5 -73t-28.5 -95 q0 -43 18.5 -77.5t48.5 -56.5t69 -37t77.5 -21t76.5 -6q60 0 120.5 15.5t113.5 46t86 82.5t33 117q0 49 -20 89.5t-49 66.5t-58 47.5t-49 44t-20 44.5t15.5 42.5t37.5 39.5t44 42t37.5 59.5t15.5 82.5q0 60 -22.5 99.5t-72.5 90.5h83zM1152 672h128v64h-128v128h-64v-128 h-128v-64h128v-160h64v160zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
222 <glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M735 740q0 -36 32 -70.5t77.5 -68t90.5 -73.5t77 -104t32 -142q0 -90 -48 -173q-72 -122 -211 -179.5t-298 -57.5q-132 0 -246.5 41.5t-171.5 137.5q-37 60 -37 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 42 -47.5 74t-15.5 73q0 36 21 85q-46 -4 -68 -4 q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q77 66 182.5 98t217.5 32h418l-138 -88h-131q74 -63 112 -133t38 -160q0 -72 -24.5 -129.5t-59 -93t-69.5 -65t-59.5 -61.5t-24.5 -66zM589 836q38 0 78 16.5t66 43.5q53 57 53 159q0 58 -17 125t-48.5 129.5 t-84.5 103.5t-117 41q-42 0 -82.5 -19.5t-65.5 -52.5q-47 -59 -47 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26zM591 -37q58 0 111.5 13t99 39t73 73t27.5 109q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -48 2 q-53 0 -105 -7t-107.5 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -70 35 -123.5t91.5 -83t119 -44t127.5 -14.5zM1401 839h213v-108h-213v-219h-105v219h-212v108h212v217h105v-217z" />
223 <glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
224 <glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
225 <glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
226 <glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
227 <glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
228 <glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
229 <glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
230 <glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
231 <glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
232 <glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
233 <glyph unicode="&#xf0e1;" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
234 <glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
235 <glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
236 <glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
237 <glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
238 <glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
239 <glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
240 <glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" />
241 <glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
242 <glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
243 <glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
244 <glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
245 <glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
246 <glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
247 <glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
248 <glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
249 <glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" />
250 <glyph unicode="&#xf0f3;" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5 t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
251 <glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
252 <glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
253 <glyph unicode="&#xf0f6;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704 q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704z" />
254 <glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
255 <glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
256 <glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
257 <glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
258 <glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" />
259 <glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
260 <glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
261 <glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
262 <glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
263 <glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
264 <glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
265 <glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
266 <glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
267 <glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
268 <glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
269 <glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
270 <glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
271 <glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
272 <glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
273 <glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
274 <glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" />
275 <glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
276 <glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
277 <glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" />
278 <glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
279 <glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
280 <glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" />
281 <glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
282 <glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " />
283 <glyph unicode="&#xf116;" horiz-adv-x="1792" />
284 <glyph unicode="&#xf117;" horiz-adv-x="1792" />
285 <glyph unicode="&#xf118;" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5 t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
286 <glyph unicode="&#xf119;" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204 t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
287 <glyph unicode="&#xf11a;" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
288 <glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150 t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" />
289 <glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16 h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96 q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896 h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" />
290 <glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102 q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
291 <glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266 q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8 q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
292 <glyph unicode="&#xf120;" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" />
293 <glyph unicode="&#xf121;" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" />
294 <glyph unicode="&#xf122;" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" />
295 <glyph unicode="&#xf123;" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
296 <glyph unicode="&#xf124;" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
297 <glyph unicode="&#xf125;" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
298 <glyph unicode="&#xf126;" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497 q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" />
299 <glyph unicode="&#xf127;" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18 l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9 t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
300 <glyph unicode="&#xf128;" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" />
301 <glyph unicode="&#xf129;" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
302 <glyph unicode="&#xf12a;" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
303 <glyph unicode="&#xf12b;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80 h126z" />
304 <glyph unicode="&#xf12c;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126z" />
305 <glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
306 <glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89 q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117 q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" />
307 <glyph unicode="&#xf130;" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
308 <glyph unicode="&#xf131;" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23 t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" />
309 <glyph unicode="&#xf132;" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
310 <glyph unicode="&#xf133;" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
311 <glyph unicode="&#xf134;" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113 q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" />
312 <glyph unicode="&#xf135;" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
313 <glyph unicode="&#xf136;" horiz-adv-x="1792" d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
314 <glyph unicode="&#xf137;" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
315 <glyph unicode="&#xf138;" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
316 <glyph unicode="&#xf139;" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
317 <glyph unicode="&#xf13a;" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
318 <glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
319 <glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
320 <glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19 t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" />
321 <glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" />
322 <glyph unicode="&#xf140;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
323 <glyph unicode="&#xf141;" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
324 <glyph unicode="&#xf142;" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
325 <glyph unicode="&#xf143;" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
326 <glyph unicode="&#xf144;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" />
327 <glyph unicode="&#xf145;" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
328 <glyph unicode="&#xf146;" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
329 <glyph unicode="&#xf147;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
330 <glyph unicode="&#xf148;" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
331 <glyph unicode="&#xf149;" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
332 <glyph unicode="&#xf14a;" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
333 <glyph unicode="&#xf14b;" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
334 <glyph unicode="&#xf14c;" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
335 <glyph unicode="&#xf14d;" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
336 <glyph unicode="&#xf14e;" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
337 <glyph unicode="&#xf150;" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
338 <glyph unicode="&#xf151;" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
339 <glyph unicode="&#xf152;" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
340 <glyph unicode="&#xf153;" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26 l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" />
341 <glyph unicode="&#xf154;" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
342 <glyph unicode="&#xf155;" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5 t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50 t53 -63.5t31.5 -76.5t13 -94z" />
343 <glyph unicode="&#xf156;" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
344 <glyph unicode="&#xf157;" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" />
345 <glyph unicode="&#xf158;" horiz-adv-x="1280" d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128 q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
346 <glyph unicode="&#xf159;" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28 q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" />
347 <glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30 t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" />
348 <glyph unicode="&#xf15b;" d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" />
349 <glyph unicode="&#xf15c;" d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" />
350 <glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162 l230 -662h70z" />
351 <glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248 v119h121z" />
352 <glyph unicode="&#xf160;" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" />
353 <glyph unicode="&#xf161;" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" />
354 <glyph unicode="&#xf162;" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5 t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
355 <glyph unicode="&#xf163;" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13 q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" />
356 <glyph unicode="&#xf164;" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5 t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" />
357 <glyph unicode="&#xf165;" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121 t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" />
358 <glyph unicode="&#xf166;" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38 q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5 q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78l24 -69t23 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38 q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
359 <glyph unicode="&#xf167;" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51 q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99 q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51 q-28 38 -28 118v175q0 80 28 117q38 51 105 51q69 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" />
360 <glyph unicode="&#xf168;" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" />
361 <glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
362 <glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
363 <glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
364 <glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" />
365 <glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" />
366 <glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
367 <glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
368 <glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
369 <glyph unicode="&#xf172;" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
370 <glyph unicode="&#xf173;" horiz-adv-x="1024" d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14 q78 2 134 29z" />
371 <glyph unicode="&#xf174;" d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
372 <glyph unicode="&#xf175;" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
373 <glyph unicode="&#xf176;" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
374 <glyph unicode="&#xf177;" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
375 <glyph unicode="&#xf178;" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
376 <glyph unicode="&#xf179;" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" />
377 <glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
378 <glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5 h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" />
379 <glyph unicode="&#xf17c;" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18l-4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92 q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152 q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-14 -1 -7 -7l4 -2 q14 -4 18 -31q0 -3 8 2zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5 t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5 t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48 q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195 q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14 q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5 t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" />
380 <glyph unicode="&#xf17d;" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19 q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6 t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
381 <glyph unicode="&#xf17e;" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5 q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80 q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" />
382 <glyph unicode="&#xf180;" horiz-adv-x="1280" d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 55 38 102.5t120 47.5h888q95 0 127 -53t10 -159zM1227 1324 l-158 -790q4 17 35 173.5t69.5 350t53.5 266.5z" />
383 <glyph unicode="&#xf181;" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
384 <glyph unicode="&#xf182;" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
385 <glyph unicode="&#xf183;" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
386 <glyph unicode="&#xf184;" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
387 <glyph unicode="&#xf185;" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94 q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" />
388 <glyph unicode="&#xf186;" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
389 <glyph unicode="&#xf187;" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
390 <glyph unicode="&#xf188;" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19 t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" />
391 <glyph unicode="&#xf189;" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6 q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q17 19 38 30q53 26 239 24 q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2 q39 5 64 -2.5t31 -16.5z" />
392 <glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422 q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178 q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" />
393 <glyph unicode="&#xf18b;" d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495 q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
394 <glyph unicode="&#xf18c;" horiz-adv-x="1408" d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5 t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56 t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -5 1 -50.5t-1 -71.5q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5 t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" />
395 <glyph unicode="&#xf18d;" horiz-adv-x="1280" d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z " />
396 <glyph unicode="&#xf18e;" d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
397 <glyph unicode="&#xf190;" d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
398 <glyph unicode="&#xf191;" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
399 <glyph unicode="&#xf192;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
400 <glyph unicode="&#xf193;" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
401 <glyph unicode="&#xf194;" d="M1254 899q16 85 -21 132q-52 65 -187 45q-17 -3 -41 -12.5t-57.5 -30.5t-64.5 -48.5t-59.5 -70t-44.5 -91.5q80 7 113.5 -16t26.5 -99q-5 -52 -52 -143q-43 -78 -71 -99q-44 -32 -87 14q-23 24 -37.5 64.5t-19 73t-10 84t-8.5 71.5q-23 129 -34 164q-12 37 -35.5 69 t-50.5 40q-57 16 -127 -25q-54 -32 -136.5 -106t-122.5 -102v-7q16 -8 25.5 -26t21.5 -20q21 -3 54.5 8.5t58 10.5t41.5 -30q11 -18 18.5 -38.5t15 -48t12.5 -40.5q17 -46 53 -187q36 -146 57 -197q42 -99 103 -125q43 -12 85 -1.5t76 31.5q131 77 250 237 q104 139 172.5 292.5t82.5 226.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
402 <glyph unicode="&#xf195;" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
403 <glyph unicode="&#xf196;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
404 <glyph unicode="&#xf197;" horiz-adv-x="2176" d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40 t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29 q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" />
405 <glyph unicode="&#xf198;" horiz-adv-x="1664" d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9 q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102 t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8zM725 498l310 105l-105 315l-310 -107z" />
406 <glyph unicode="&#xf199;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69 q-46 32 -141.5 92.5t-142.5 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13 t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5z" />
407 <glyph unicode="&#xf19a;" horiz-adv-x="1792" d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5 t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21 t14.5 -24t14 -23q63 -107 63 -212zM909 573l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1570 1009q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5l235 678q59 169 59 276q0 42 -6 79zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286 t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 -215q173 0 331.5 68t273 182.5t182.5 273t68 331.5t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5t68 -331.5t182.5 -273 t273 -182.5t331.5 -68z" />
408 <glyph unicode="&#xf19b;" horiz-adv-x="1792" d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" />
409 <glyph unicode="&#xf19c;" horiz-adv-x="2048" d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64 q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
410 <glyph unicode="&#xf19d;" horiz-adv-x="2304" d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433 q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
411 <glyph unicode="&#xf19e;" d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0 q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
412 <glyph unicode="&#xf1a0;" horiz-adv-x="1280" d="M981 197q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -49 2q-53 0 -104.5 -7t-107 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -56 23.5 -102t61 -75.5t87 -50t100 -29t101.5 -8.5q58 0 111.5 13t99 39t73 73t27.5 109zM864 1055 q0 59 -17 125.5t-48 129t-84 103.5t-117 41q-42 0 -82.5 -19.5t-66.5 -52.5q-46 -59 -46 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26q37 0 77.5 16.5t65.5 43.5q53 56 53 159zM752 1536h417l-137 -88h-132q75 -63 113 -133t38 -160q0 -72 -24.5 -129.5 t-59.5 -93t-69.5 -65t-59 -61.5t-24.5 -66q0 -36 32 -70.5t77 -68t90.5 -73.5t77.5 -104t32 -142q0 -91 -49 -173q-71 -122 -209.5 -179.5t-298.5 -57.5q-132 0 -246.5 41.5t-172.5 137.5q-36 59 -36 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 41 -47.5 73.5 t-15.5 73.5q0 40 21 85q-46 -4 -68 -4q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q76 66 182 98t218 32z" />
413 <glyph unicode="&#xf1a1;" horiz-adv-x="1984" d="M831 572q0 -56 -40.5 -96t-96.5 -40q-57 0 -98 40t-41 96q0 57 41.5 98t97.5 41t96.5 -41t40.5 -98zM1292 711q56 0 96.5 -41t40.5 -98q0 -56 -40.5 -96t-96.5 -40q-57 0 -98 40t-41 96q0 57 41.5 98t97.5 41zM1984 722q0 -62 -31 -114t-83 -82q5 -33 5 -61 q0 -121 -68.5 -230.5t-197.5 -193.5q-125 -82 -285.5 -125.5t-335.5 -43.5q-176 0 -336.5 43.5t-284.5 125.5q-129 84 -197.5 193t-68.5 231q0 29 5 66q-48 31 -77 81.5t-29 109.5q0 94 66 160t160 66q83 0 148 -55q248 158 592 164l134 423q4 14 17.5 21.5t28.5 4.5 l347 -82q22 50 68.5 81t102.5 31q77 0 131.5 -54.5t54.5 -131.5t-54.5 -132t-131.5 -55q-76 0 -130.5 54t-55.5 131l-315 74l-116 -366q327 -14 560 -166q64 58 151 58q94 0 160 -66t66 -160zM1664 1459q-45 0 -77 -32t-32 -77t32 -77t77 -32t77 32t32 77t-32 77t-77 32z M77 722q0 -67 51 -111q49 131 180 235q-36 25 -82 25q-62 0 -105.5 -43.5t-43.5 -105.5zM1567 105q112 73 171.5 166t59.5 194t-59.5 193.5t-171.5 165.5q-116 75 -265.5 115.5t-313.5 40.5t-313.5 -40.5t-265.5 -115.5q-112 -73 -171.5 -165.5t-59.5 -193.5t59.5 -194 t171.5 -166q116 -75 265.5 -115.5t313.5 -40.5t313.5 40.5t265.5 115.5zM1850 605q57 46 57 117q0 62 -43.5 105.5t-105.5 43.5q-49 0 -86 -28q131 -105 178 -238zM1258 237q11 11 27 11t27 -11t11 -27.5t-11 -27.5q-99 -99 -319 -99h-2q-220 0 -319 99q-11 11 -11 27.5 t11 27.5t27 11t27 -11q77 -77 265 -77h2q188 0 265 77z" />
414 <glyph unicode="&#xf1a2;" d="M950 393q7 7 17.5 7t17.5 -7t7 -18t-7 -18q-65 -64 -208 -64h-1h-1q-143 0 -207 64q-8 7 -8 18t8 18q7 7 17.5 7t17.5 -7q49 -51 172 -51h1h1q122 0 173 51zM671 613q0 -37 -26 -64t-63 -27t-63 27t-26 64t26 63t63 26t63 -26t26 -63zM1214 1049q-29 0 -50 21t-21 50 q0 30 21 51t50 21q30 0 51 -21t21 -51q0 -29 -21 -50t-51 -21zM1216 1408q132 0 226 -94t94 -227v-894q0 -133 -94 -227t-226 -94h-896q-132 0 -226 94t-94 227v894q0 133 94 227t226 94h896zM1321 596q35 14 57 45.5t22 70.5q0 51 -36 87.5t-87 36.5q-60 0 -98 -48 q-151 107 -375 115l83 265l206 -49q1 -50 36.5 -85t84.5 -35q50 0 86 35.5t36 85.5t-36 86t-86 36q-36 0 -66 -20.5t-45 -53.5l-227 54q-9 2 -17.5 -2.5t-11.5 -14.5l-95 -302q-224 -4 -381 -113q-36 43 -93 43q-51 0 -87 -36.5t-36 -87.5q0 -37 19.5 -67.5t52.5 -45.5 q-7 -25 -7 -54q0 -98 74 -181.5t201.5 -132t278.5 -48.5q150 0 277.5 48.5t201.5 132t74 181.5q0 27 -6 54zM971 702q37 0 63 -26t26 -63t-26 -64t-63 -27t-63 27t-26 64t26 63t63 26z" />
415 <glyph unicode="&#xf1a3;" d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150 v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103 t385.5 -103t279.5 -279.5t103 -385.5z" />
416 <glyph unicode="&#xf1a4;" horiz-adv-x="1920" d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328 v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
417 <glyph unicode="&#xf1a5;" d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
418 <glyph unicode="&#xf1a6;" horiz-adv-x="2048" d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123 v-369h123z" />
419 <glyph unicode="&#xf1a7;" d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101 v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
420 <glyph unicode="&#xf1a8;" horiz-adv-x="2038" d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14 q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24 q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33 q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5 t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5zM1282 842q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43 q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5 t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM822 568l48 12l109 -177l-73 -48zM1323 51q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13 t-54 -9.5t-53.5 -7.5t-32 -4.5l-7 43q21 2 60.5 8.5t72 10t60.5 3.5h14zM866 679l-96 -20l-6 17q10 1 32.5 7t34.5 6q19 0 35 -10zM1061 45h31l10 -83l-41 -12v95zM1950 1535v1v-1zM1950 1535l-1 -5l-2 -2l1 3zM1950 1535l1 1z" />
421 <glyph unicode="&#xf1a9;" d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10 q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14 q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14 t55.5 63q28 41 42.5 101t14.5 106zM1536 506q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44 q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5t19.5 -177.5z" />
422 <glyph unicode="&#xf1aa;" d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5 t149.5 -87.5zM1536 78q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5 q76 -11 126.5 -68.5t50.5 -134.5zM1534 1202q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126 t135.5 51q85 0 145 -60.5t60 -145.5z" />
423 <glyph unicode="&#xf1ab;" d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5 q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28 q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5zM449 944q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032l-694 -233v-1031z M1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11 q73 -37 159.5 -61.5t157.5 -24.5q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5zM1536 1050v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3v1078q3 9 4 10q5 6 20 11q106 35 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5 q20 0 20 -21v-418z" />
424 <glyph unicode="&#xf1ac;" horiz-adv-x="1792" d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48 l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 512v128q0 14 -9 23 t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128 q14 0 23 9t9 23zM1184 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 256v128q0 14 -9 23t-23 9h-128 q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1536 896v256h-160q-40 0 -68 28t-28 68v160h-640v-512h896z" />
425 <glyph unicode="&#xf1ad;" d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9 t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 160v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64 q14 0 23 9t9 23zM384 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 -96v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9 t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM896 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 928v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 160v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9 t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23z" />
426 <glyph unicode="&#xf1ae;" horiz-adv-x="1280" d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68t68 28t68 -28l228 -228h368l228 228q28 28 68 28t68 -28t28 -68t-28 -68zM864 1152q0 -93 -65.5 -158.5 t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
427 <glyph unicode="&#xf1b0;" horiz-adv-x="1664" d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5 q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 86 56 191.5t139.5 192.5t187.5 146t193 59zM1071 819 q-61 0 -105 39t-63 92.5t-19 113.5q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5zM1503 923q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5q-77 0 -119 59t-42 139q0 74 35 152.5 t100.5 134t141.5 55.5z" />
428 <glyph unicode="&#xf1b1;" horiz-adv-x="768" d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" />
429 <glyph unicode="&#xf1b2;" horiz-adv-x="1792" d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z " />
430 <glyph unicode="&#xf1b3;" horiz-adv-x="2304" d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67 t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-5 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70 v-400l434 -186q36 -16 57 -48t21 -70z" />
431 <glyph unicode="&#xf1b4;" horiz-adv-x="2048" d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658 q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204 q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611v1260z" />
432 <glyph unicode="&#xf1b5;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5 t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216q0 -135 79 -217 t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20zM1126 722q113 0 124 -122h-254q4 56 39 89t91 33zM964 988h319v-77h-319v77z" />
433 <glyph unicode="&#xf1b6;" horiz-adv-x="1792" d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5 q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -322t-321.5 -133l-437 -319q-12 -129 -109 -218t-229 -89 q-121 0 -214 76t-118 192l-230 92v429l389 -157q79 48 173 48q13 0 35 -2l284 407q2 187 135.5 319t320.5 132q188 0 321.5 -133.5t133.5 -321.5z" />
434 <glyph unicode="&#xf1b7;" d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5 q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 255.5t-255.5 105.5 q-148 0 -253 -104.5t-107 -252.5l-225 -322q-9 1 -28 1q-75 0 -137 -37l-297 119v468q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5zM1289 887q0 -100 -71 -170.5t-171 -70.5t-170.5 70.5t-70.5 170.5t70.5 171t170.5 71q101 0 171.5 -70.5t70.5 -171.5z " />
435 <glyph unicode="&#xf1b8;" horiz-adv-x="1792" d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188 l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5 t36 -39.5t32 -35zM1550 1053l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436l313 195zM1407 1279l142 83l-220 -373l-419 20l151 86q-34 89 -75 166t-75.5 123.5t-64.5 80t-47 46.5l-17 13l405 -1 q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190z" />
436 <glyph unicode="&#xf1b9;" horiz-adv-x="2048" d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384 q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h768q98 0 179 -63.5t104 -157.5 l105 -419h28q93 0 158.5 -65.5t65.5 -158.5z" />
437 <glyph unicode="&#xf1ba;" horiz-adv-x="2048" d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5 t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" />
438 <glyph unicode="&#xf1bb;" d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384 q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
439 <glyph unicode="&#xf1bc;" d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64 q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37 q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
440 <glyph unicode="&#xf1bd;" d="M1397 1408q58 0 98.5 -40.5t40.5 -98.5v-1258q0 -58 -40.5 -98.5t-98.5 -40.5h-1258q-58 0 -98.5 40.5t-40.5 98.5v1258q0 58 40.5 98.5t98.5 40.5h1258zM1465 11v1258q0 28 -20 48t-48 20h-1258q-28 0 -48 -20t-20 -48v-1258q0 -28 20 -48t48 -20h1258q28 0 48 20t20 48 zM694 749l188 -387l533 145v-496q0 -7 -5.5 -12.5t-12.5 -5.5h-1258q-7 0 -12.5 5.5t-5.5 12.5v141l711 195l-212 439q4 1 12 2.5t12 1.5q170 32 303.5 21.5t221 -46t143.5 -94.5q27 -28 -25 -42q-64 -16 -256 -62l-97 198q-111 7 -240 -16zM1397 1287q7 0 12.5 -5.5 t5.5 -12.5v-428q-85 30 -188 52q-294 64 -645 12l-18 -3l-65 134h-233l85 -190q-132 -51 -230 -137v560q0 7 5.5 12.5t12.5 5.5h1258zM286 387q-14 -3 -26 4.5t-14 21.5q-24 203 166 305l129 -270z" />
441 <glyph unicode="&#xf1be;" horiz-adv-x="2304" d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11 q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245 q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785 l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242 q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236q0 -11 -8 -19 t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786q-13 2 -22 11t-9 22v899 q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" />
442 <glyph unicode="&#xf1c0;" d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127 t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5 t-103 128v128q0 69 103 128t280 93.5t385 34.5z" />
443 <glyph unicode="&#xf1c1;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197 q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8 q-1 1 -1 2t-0.5 1.5t-0.5 1.5q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" />
444 <glyph unicode="&#xf1c2;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4l-3 21q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5t-3.5 -21.5l-4 -21h-4l-2 21 q-2 26 -7 46l-99 438h90v107h-300z" />
445 <glyph unicode="&#xf1c3;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107 h-290v-107h68l189 -272l-194 -283h-68z" />
446 <glyph unicode="&#xf1c4;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" />
447 <glyph unicode="&#xf1c5;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" />
448 <glyph unicode="&#xf1c6;" d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400 v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5q0 25 8 52q21 63 120 396v128h128v-128h79 q22 0 39 -13t23 -34zM640 128q53 0 90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45t37.5 -45t90.5 -19z" />
449 <glyph unicode="&#xf1c7;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5 q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5t23.5 -42.5q18 -15 40 -15zM826 145q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5t20 -44.5q20 -17 44 -17z" />
450 <glyph unicode="&#xf1c8;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" />
451 <glyph unicode="&#xf1c9;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21t6.5 24l182 243 l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5zM662 6q-13 2 -20.5 13t-5.5 24l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5z" />
452 <glyph unicode="&#xf1ca;" d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406 q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14z" />
453 <glyph unicode="&#xf1cb;" horiz-adv-x="1792" d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546 q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
454 <glyph unicode="&#xf1cc;" horiz-adv-x="2048" d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94 q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55 t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97q14 -16 29.5 -34t34.5 -40t29 -34q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5 t-85 -189.5z" />
455 <glyph unicode="&#xf1cd;" horiz-adv-x="1792" d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194 q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5 t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
456 <glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348q0 222 101 414.5t276.5 317t390.5 155.5v-260q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 q0 230 -145.5 406t-366.5 221v260q215 -31 390.5 -155.5t276.5 -317t101 -414.5z" />
457 <glyph unicode="&#xf1d0;" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170 t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136 q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
458 <glyph unicode="&#xf1d1;" horiz-adv-x="1792" d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251 l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162 q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33 q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5 t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71 t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
459 <glyph unicode="&#xf1d2;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392 q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
460 <glyph unicode="&#xf1d3;" horiz-adv-x="1792" d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58 q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47 q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171 v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" />
461 <glyph unicode="&#xf1d4;" d="M825 547l343 588h-150q-21 -39 -63.5 -118.5t-68 -128.5t-59.5 -118.5t-60 -128.5h-3q-21 48 -44.5 97t-52 105.5t-46.5 92t-54 104.5t-49 95h-150l323 -589v-435h134v436zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
462 <glyph unicode="&#xf1d5;" horiz-adv-x="1280" d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5 t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153 t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" />
463 <glyph unicode="&#xf1d6;" horiz-adv-x="1792" d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5 q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20 t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5 t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" />
464 <glyph unicode="&#xf1d7;" horiz-adv-x="2048" d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25 q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5 q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109 q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" />
465 <glyph unicode="&#xf1d8;" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" />
466 <glyph unicode="&#xf1d9;" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137 l863 639l-478 -797z" />
467 <glyph unicode="&#xf1da;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298zM896 928v-448q0 -14 -9 -23 t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23z" />
468 <glyph unicode="&#xf1db;" d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
469 <glyph unicode="&#xf1dc;" horiz-adv-x="1792" d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15 t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18q-15 10 -45 12t-53 2 t-41 14t-18 45q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160 q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5 q0 -26 -12 -48t-36 -22z" />
470 <glyph unicode="&#xf1dd;" horiz-adv-x="1280" d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179 q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" />
471 <glyph unicode="&#xf1de;" d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
472 <glyph unicode="&#xf1e0;" d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5 t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" />
473 <glyph unicode="&#xf1e1;" d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5 t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
474 <glyph unicode="&#xf1e2;" horiz-adv-x="1792" d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5 t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23t9 23q10 9 23 9t23 -9l90 -91 q10 -9 10 -22.5t-10 -22.5zM1751 1129q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5t10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23zM1792 1312q0 -14 -9 -23t-23 -9h-96q-14 0 -23 9t-9 23t9 23t23 9h96q14 0 23 -9t9 -23zM1600 1504v-96q0 -14 -9 -23t-23 -9 t-23 9t-9 23v96q0 14 9 23t23 9t23 -9t9 -23zM1751 1449l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5t10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
475 <glyph unicode="&#xf1e3;" horiz-adv-x="1792" d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323 l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l139 298l326 40z" />
476 <glyph unicode="&#xf1e4;" horiz-adv-x="1792" d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t-46 -19h-383zM1216 224v-192q0 -14 -9 -23t-23 -9h-192 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1600 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23 zM1408 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1016v-13h-514v10q0 104 -382 102q-382 -1 -382 -102v-10h-514v13q0 17 8.5 43t34 64t65.5 75.5t110.5 76t160 67.5t224 47.5t293.5 18.5t293 -18.5t224 -47.5 t160.5 -67.5t110.5 -76t65.5 -75.5t34 -64t8.5 -43zM1792 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 962v-129q0 -27 -19 -46t-46 -19h-384q-27 0 -46 19t-19 46v129h514z" />
477 <glyph unicode="&#xf1e5;" horiz-adv-x="1792" d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" />
478 <glyph unicode="&#xf1e6;" horiz-adv-x="1792" d="M1755 1083q37 -37 37 -90t-37 -91l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234l401 400 q38 37 91 37t90 -37z" />
479 <glyph unicode="&#xf1e7;" horiz-adv-x="1792" d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5 t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1t53 1t54.5 4.5t61 8.5t62 13.5t67 19.5t67.5 27t72 34.5z M1763 621q-121 -149 -372 -252q84 -285 -23 -465q-66 -113 -183 -148q-104 -32 -182 15q-86 51 -82 164l-1 326v1q-8 2 -24.5 6t-23.5 5l-1 -338q4 -114 -83 -164q-79 -47 -183 -15q-117 36 -182 150q-105 180 -22 463q-251 103 -372 252q-25 37 -4 63t60 -1q3 -2 11 -7 t11 -8v694q0 72 47 123t114 51h1257q67 0 114 -51t47 -123v-694l21 15q39 27 60 1t-4 -63z" />
480 <glyph unicode="&#xf1e8;" horiz-adv-x="1792" d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
481 <glyph unicode="&#xf1e9;" d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36 q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q70 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 -1 119 -40q203 -66 242 -79.5 t47 -20.5q28 -22 22 -61zM778 803q5 -102 -54 -122q-58 -17 -114 71l-378 598q-8 35 19 62q41 43 207.5 89.5t224.5 31.5q40 -10 49 -45q3 -18 22 -305.5t24 -379.5zM1440 695q3 -39 -26 -59q-15 -10 -329 -86q-67 -15 -91 -23l1 2q-23 -6 -46 4t-37 32q-30 47 0 87 q1 1 75 102q125 171 150 204t34 39q28 19 65 2q48 -23 123 -133.5t81 -167.5v-3z" />
482 <glyph unicode="&#xf1ea;" horiz-adv-x="2048" d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19 t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
483 <glyph unicode="&#xf1eb;" horiz-adv-x="2048" d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121 q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" />
484 <glyph unicode="&#xf1ec;" horiz-adv-x="1792" d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5 t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38 h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" />
485 <glyph unicode="&#xf1ed;" horiz-adv-x="1792" d="M1112 1090q0 159 -237 159h-70q-32 0 -59.5 -21.5t-34.5 -52.5l-63 -276q-2 -5 -2 -16q0 -24 17 -39.5t41 -15.5h53q69 0 128.5 13t112.5 41t83.5 81.5t30.5 126.5zM1716 938q0 -265 -220 -428q-219 -161 -612 -161h-61q-32 0 -59 -21.5t-34 -52.5l-73 -316 q-8 -36 -40.5 -61.5t-69.5 -25.5h-213q-31 0 -53 20t-22 51q0 10 13 65h151q34 0 64 23.5t38 56.5l73 316q8 33 37.5 57t63.5 24h61q390 0 607 160t217 421q0 129 -51 207q183 -92 183 -335zM1533 1123q0 -264 -221 -428q-218 -161 -612 -161h-60q-32 0 -59.5 -22t-34.5 -53 l-73 -315q-8 -36 -40 -61.5t-69 -25.5h-214q-31 0 -52.5 19.5t-21.5 51.5q0 8 2 20l300 1301q8 36 40.5 61.5t69.5 25.5h444q68 0 125 -4t120.5 -15t113.5 -30t96.5 -50.5t77.5 -74t49.5 -103.5t18.5 -136z" />
486 <glyph unicode="&#xf1ee;" horiz-adv-x="1792" d="M602 949q19 -61 31 -123.5t17 -141.5t-14 -159t-62 -145q-21 81 -67 157t-95.5 127t-99 90.5t-78.5 57.5t-33 19q-62 34 -81.5 100t14.5 128t101 81.5t129 -14.5q138 -83 238 -177zM927 1236q11 -25 20.5 -46t36.5 -100.5t42.5 -150.5t25.5 -179.5t0 -205.5t-47.5 -209.5 t-105.5 -208.5q-51 -72 -138 -72q-54 0 -98 31q-57 40 -69 109t28 127q60 85 81 195t13 199.5t-32 180.5t-39 128t-22 52q-31 63 -8.5 129.5t85.5 97.5q34 17 75 17q47 0 88.5 -25t63.5 -69zM1248 567q-17 -160 -72 -311q-17 131 -63 246q25 174 -5 361q-27 178 -94 342 q114 -90 212 -211q9 -37 15 -80q26 -179 7 -347zM1520 1440q9 -17 23.5 -49.5t43.5 -117.5t50.5 -178t34 -227.5t5 -269t-47 -300t-112.5 -323.5q-22 -48 -66 -75.5t-95 -27.5q-39 0 -74 16q-67 31 -92.5 100t4.5 136q58 126 90 257.5t37.5 239.5t-3.5 213.5t-26.5 180.5 t-38.5 138.5t-32.5 90t-15.5 32.5q-34 65 -11.5 135.5t87.5 104.5q37 20 81 20q49 0 91.5 -25.5t66.5 -70.5z" />
487 <glyph unicode="&#xf1f0;" horiz-adv-x="2304" d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27 q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128 q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
488 <glyph unicode="&#xf1f1;" horiz-adv-x="2304" d="M671 603h-13q-47 0 -47 -32q0 -22 20 -22q17 0 28 15t12 39zM1066 639h62v3q1 4 0.5 6.5t-1 7t-2 8t-4.5 6.5t-7.5 5t-11.5 2q-28 0 -36 -38zM1606 603h-12q-48 0 -48 -32q0 -22 20 -22q17 0 28 15t12 39zM1925 629q0 41 -30 41q-19 0 -31 -20t-12 -51q0 -42 28 -42 q20 0 32.5 20t12.5 52zM480 770h87l-44 -262h-56l32 201l-71 -201h-39l-4 200l-34 -200h-53l44 262h81l2 -163zM733 663q0 -6 -4 -42q-16 -101 -17 -113h-47l1 22q-20 -26 -58 -26q-23 0 -37.5 16t-14.5 42q0 39 26 60.5t73 21.5q14 0 23 -1q0 3 0.5 5.5t1 4.5t0.5 3 q0 20 -36 20q-29 0 -59 -10q0 4 7 48q38 11 67 11q74 0 74 -62zM889 721l-8 -49q-22 3 -41 3q-27 0 -27 -17q0 -8 4.5 -12t21.5 -11q40 -19 40 -60q0 -72 -87 -71q-34 0 -58 6q0 2 7 49q29 -8 51 -8q32 0 32 19q0 7 -4.5 11.5t-21.5 12.5q-43 20 -43 59q0 72 84 72 q30 0 50 -4zM977 721h28l-7 -52h-29q-2 -17 -6.5 -40.5t-7 -38.5t-2.5 -18q0 -16 19 -16q8 0 16 2l-8 -47q-21 -7 -40 -7q-43 0 -45 47q0 12 8 56q3 20 25 146h55zM1180 648q0 -23 -7 -52h-111q-3 -22 10 -33t38 -11q30 0 58 14l-9 -54q-30 -8 -57 -8q-95 0 -95 95 q0 55 27.5 90.5t69.5 35.5q35 0 55.5 -21t20.5 -56zM1319 722q-13 -23 -22 -62q-22 2 -31 -24t-25 -128h-56l3 14q22 130 29 199h51l-3 -33q14 21 25.5 29.5t28.5 4.5zM1506 763l-9 -57q-28 14 -50 14q-31 0 -51 -27.5t-20 -70.5q0 -30 13.5 -47t38.5 -17q21 0 48 13 l-10 -59q-28 -8 -50 -8q-45 0 -71.5 30.5t-26.5 82.5q0 70 35.5 114.5t91.5 44.5q26 0 61 -13zM1668 663q0 -18 -4 -42q-13 -79 -17 -113h-46l1 22q-20 -26 -59 -26q-23 0 -37 16t-14 42q0 39 25.5 60.5t72.5 21.5q15 0 23 -1q2 7 2 13q0 20 -36 20q-29 0 -59 -10q0 4 8 48 q38 11 67 11q73 0 73 -62zM1809 722q-14 -24 -21 -62q-23 2 -31.5 -23t-25.5 -129h-56l3 14q19 104 29 199h52q0 -11 -4 -33q15 21 26.5 29.5t27.5 4.5zM1950 770h56l-43 -262h-53l3 19q-23 -23 -52 -23q-31 0 -49.5 24t-18.5 64q0 53 27.5 92t64.5 39q31 0 53 -29z M2061 640q0 148 -72.5 273t-198 198t-273.5 73q-181 0 -328 -110q127 -116 171 -284h-50q-44 150 -158 253q-114 -103 -158 -253h-50q44 168 171 284q-147 110 -328 110q-148 0 -273.5 -73t-198 -198t-72.5 -273t72.5 -273t198 -198t273.5 -73q181 0 328 110 q-120 111 -165 264h50q46 -138 152 -233q106 95 152 233h50q-45 -153 -165 -264q147 -110 328 -110q148 0 273.5 73t198 198t72.5 273zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
489 <glyph unicode="&#xf1f2;" horiz-adv-x="2304" d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42 q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604 v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569 q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73 t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" />
490 <glyph unicode="&#xf1f3;" horiz-adv-x="2304" d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260 l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279 v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040 q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168 q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5 t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21 h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5 t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
491 <glyph unicode="&#xf1f4;" horiz-adv-x="2304" d="M322 689h-15q-19 0 -19 18q0 28 19 85q5 15 15 19.5t28 4.5q77 0 77 -49q0 -41 -30.5 -59.5t-74.5 -18.5zM664 528q-47 0 -47 29q0 62 123 62l3 -3q-5 -88 -79 -88zM1438 687h-15q-19 0 -19 19q0 28 19 85q5 15 14.5 19t28.5 4q77 0 77 -49q0 -41 -30.5 -59.5 t-74.5 -18.5zM1780 527q-47 0 -47 30q0 62 123 62l3 -3q-5 -89 -79 -89zM373 894h-128q-8 0 -14.5 -4t-8.5 -7.5t-7 -12.5q-3 -7 -45 -190t-42 -192q0 -7 5.5 -12.5t13.5 -5.5h62q25 0 32.5 34.5l15 69t32.5 34.5q47 0 87.5 7.5t80.5 24.5t63.5 52.5t23.5 84.5 q0 36 -14.5 61t-41 36.5t-53.5 15.5t-62 4zM719 798q-38 0 -74 -6q-2 0 -8.5 -1t-9 -1.5l-7.5 -1.5t-7.5 -2t-6.5 -3t-6.5 -4t-5 -5t-4.5 -7t-4 -9q-9 -29 -9 -39t9 -10q5 0 21.5 5t19.5 6q30 8 58 8q74 0 74 -36q0 -11 -10 -14q-8 -2 -18 -3t-21.5 -1.5t-17.5 -1.5 q-38 -4 -64.5 -10t-56.5 -19.5t-45.5 -39t-15.5 -62.5q0 -38 26 -59.5t64 -21.5q24 0 45.5 6.5t33 13t38.5 23.5q-3 -7 -3 -15t5.5 -13.5t12.5 -5.5h56q1 1 7 3.5t7.5 3.5t5 3.5t5 5.5t2.5 8l45 194q4 13 4 30q0 81 -145 81zM1247 793h-74q-22 0 -39 -23q-5 -7 -29.5 -51 t-46.5 -81.5t-26 -38.5l-5 4q0 77 -27 166q-1 5 -3.5 8.5t-6 6.5t-6.5 5t-8.5 3t-8.5 1.5t-9.5 1t-9 0.5h-10h-8.5q-38 0 -38 -21l1 -5q5 -53 25 -151t25 -143q2 -16 2 -24q0 -19 -30.5 -61.5t-30.5 -58.5q0 -13 40 -13q61 0 76 25l245 415q10 20 10 26q0 9 -8 9zM1489 892 h-129q-18 0 -29 -23q-6 -13 -46.5 -191.5t-40.5 -190.5q0 -20 43 -20h7.5h9h9t9.5 1t8.5 2t8.5 3t6.5 4.5t5.5 6t3 8.5l21 91q2 10 10.5 17t19.5 7q47 0 87.5 7t80.5 24.5t63.5 52.5t23.5 84q0 36 -14.5 61t-41 36.5t-53.5 15.5t-62 4zM1835 798q-26 0 -74 -6 q-38 -6 -48 -16q-7 -8 -11 -19q-8 -24 -8 -39q0 -10 8 -10q1 0 41 12q30 8 58 8q74 0 74 -36q0 -12 -10 -14q-4 -1 -57 -7q-38 -4 -64.5 -10t-56.5 -19.5t-45.5 -39t-15.5 -62.5t26 -58.5t64 -21.5q24 0 45 6t34 13t38 24q-3 -15 -3 -16q0 -5 2 -8.5t6.5 -5.5t8 -3.5 t10.5 -2t9.5 -0.5h9.5h8q42 0 48 25l45 194q3 15 3 31q0 81 -145 81zM2157 889h-55q-25 0 -33 -40q-10 -44 -36.5 -167t-42.5 -190v-5q0 -16 16 -18h1h57q10 0 18.5 6.5t10.5 16.5l83 374h-1l1 5q0 7 -5.5 12.5t-13.5 5.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048 q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
492 <glyph unicode="&#xf1f5;" horiz-adv-x="2304" d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109 q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118 q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151 q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31 q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
493 <glyph unicode="&#xf1f6;" horiz-adv-x="2048" d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5 l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5 l418 363q10 8 23.5 7t21.5 -11z" />
494 <glyph unicode="&#xf1f7;" horiz-adv-x="2048" d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128 q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161 q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" />
495 <glyph unicode="&#xf1f8;" horiz-adv-x="1408" d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704 q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167 q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
496 <glyph unicode="&#xf1f9;" d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5 t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
497 <glyph unicode="&#xf1fa;" d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53 q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0 -39 12.5 -52t44.5 -13q28 1 57 5.5t73 24 t77 50t57 89.5t24 137q0 292 -174 466t-466 174q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51q228 0 405 144q11 9 24 8t21 -12l41 -49q8 -12 7 -24q-2 -13 -12 -22q-102 -83 -227.5 -128t-258.5 -45q-156 0 -298 61 t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q344 0 556 -212t212 -556z" />
498 <glyph unicode="&#xf1fb;" horiz-adv-x="1792" d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10 t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" />
499 <glyph unicode="&#xf1fc;" horiz-adv-x="1792" d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5 t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" />
500 <glyph unicode="&#xf1fd;" horiz-adv-x="1792" d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11t55.5 -11t52.5 -38q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5t47 37.5 q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-35 0 -55.5 11t-52.5 38q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-31 -15t-44 -7q-35 0 -56.5 11t-51.5 38q-29 25 -47 38t-58 27 t-86 14q-45 0 -85 -14.5t-58 -27t-48 -37.5q-21 -19 -32.5 -27t-31 -15t-43.5 -7q-35 0 -56.5 11t-51.5 38q-28 24 -47 37.5t-59 27.5t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-30 -27 -51.5 -38t-56.5 -11v192q0 80 56 136t136 56h64v448h256v-448h256v448h256v-448h256v448 h256v-448h64q80 0 136 -56t56 -136zM512 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1024 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51 t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1536 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150z" />
501 <glyph unicode="&#xf1fe;" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
502 <glyph unicode="&#xf200;" horiz-adv-x="1792" d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" />
503 <glyph unicode="&#xf201;" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9 t9 -23z" />
504 <glyph unicode="&#xf202;" horiz-adv-x="1792" d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20 q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43.5 206t116 176.5t172 121.5t204.5 46q87 0 159 -19t123.5 -50 t95 -80t72.5 -99t58.5 -117t50.5 -124.5t50 -130.5t55 -127q96 -200 233 -200q81 0 138.5 48.5t57.5 128.5q0 42 -19 72t-50.5 46t-72.5 31.5t-84.5 27t-87.5 34t-81 52t-65 82t-39 122.5q-3 16 -3 33q0 110 87.5 192t198.5 78q78 -3 120.5 -14.5t90.5 -53.5h-1 q12 -11 23 -24.5t26 -36t19 -27.5l-129 -99q-26 49 -54 70v1q-23 21 -97 21q-49 0 -84 -33t-35 -83z" />
505 <glyph unicode="&#xf203;" d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73 q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t133.5 -147.5t196 -56.5q186 0 279 110 q20 27 31 51l-60 109q-42 -80 -99 -116t-146 -36q-115 0 -191 87t-76 204q0 105 82 189t186 84q112 0 170 -53.5t104 -172.5q8 -21 25.5 -68.5t28.5 -76.5t31.5 -74.5t38.5 -74t45.5 -62.5t55.5 -53.5t66 -33t80 -13.5q107 0 183 69.5t76 174.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
506 <glyph unicode="&#xf204;" horiz-adv-x="2048" d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5 t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5 t-136.5 204t-51 248.5t51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5z" />
507 <glyph unicode="&#xf205;" horiz-adv-x="2048" d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5 t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" />
508 <glyph unicode="&#xf206;" horiz-adv-x="2304" d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94 q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 97 39.5 183.5t109.5 149.5l-65 98l-353 -469 q-18 -26 -51 -26h-197q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q114 0 215 -55l137 183h-224q-26 0 -45 19t-19 45t19 45t45 19h384v-128h435l-85 128h-222q-26 0 -45 19t-19 45t19 45t45 19h256q33 0 53 -28l267 -400 q91 44 192 44q185 0 316.5 -131.5t131.5 -316.5z" />
509 <glyph unicode="&#xf207;" d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5 h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5v128h-768v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5v128h-128v603q0 112 25 223l103 454q9 78 97.5 137t230 89t312.5 30t312.5 -30t230 -89t97.5 -137l105 -454q23 -102 23 -223z" />
510 <glyph unicode="&#xf208;" horiz-adv-x="2048" d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327 q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5 -319.5t-175.5 -263t-262.5 -176t-319.5 -65.5 q-246 0 -448.5 133t-301.5 350h-189q-36 0 -61 25t-25 61q0 35 25 60t61 25h132q-17 85 -17 170q0 167 65.5 319.5t175.5 263t262.5 176t320.5 65.5q245 0 447.5 -133t301.5 -350h188q36 0 61 -25t25 -61z" />
511 <glyph unicode="&#xf209;" horiz-adv-x="1280" d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q18 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119 t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169 152 427q0 43 -1 67t-11.5 62t-30.5 56q-56 49 -211.5 75.5 t-270.5 26.5q-37 0 -49 -11q-12 -5 -12 -35q0 -34 21.5 -60t55.5 -40t77.5 -23.5t87.5 -11.5t85 -4t70 0h23q24 0 40 -19q15 -19 19 -55q-28 -28 -96 -54q-61 -22 -93 -46q-64 -46 -108.5 -114t-44.5 -137q0 -31 18.5 -88.5t18.5 -87.5l-3 -12q-4 -12 -4 -14 q-137 10 -146 216q-8 -2 -41 -2q2 -7 2 -21q0 -53 -40.5 -89.5t-94.5 -36.5q-82 0 -166.5 78t-84.5 159q0 34 33 67q52 -64 60 -76q77 -104 133 -104q12 0 26.5 8.5t14.5 20.5q0 34 -87.5 145t-116.5 111q-43 0 -70 -44.5t-27 -90.5zM11 264q0 101 42.5 163t136.5 88 q-28 74 -28 104q0 62 61 123t122 61q29 0 70 -15q-163 462 -163 567q0 80 41 130.5t119 50.5q131 0 325 -581q6 -17 8 -23q6 16 29 79.5t43.5 118.5t54 127.5t64.5 123t70.5 86.5t76.5 36q71 0 112 -49t41 -122q0 -108 -159 -550q61 -15 100.5 -46t58.5 -78t26 -93.5 t7 -110.5q0 -150 -47 -280t-132 -225t-211 -150t-278 -55q-111 0 -223 42q-149 57 -258 191.5t-109 286.5z" />
512 <glyph unicode="&#xf20a;" horiz-adv-x="2048" d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206 q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307 t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14 t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" />
513 <glyph unicode="&#xf20b;" d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5 t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
514 <glyph unicode="&#xf20c;" d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55 q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410 q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" />
515 <glyph unicode="&#xf20d;" horiz-adv-x="1792" />
516 <glyph unicode="&#xf20e;" horiz-adv-x="1792" />
517 <glyph unicode="&#xf500;" horiz-adv-x="1792" />
518 </font>
519 </defs></svg>
faraday/server/www/fonts/font-awesome/fontawesome-webfont.ttf less more
Binary diff not shown
faraday/server/www/fonts/font-awesome/fontawesome-webfont.woff less more
Binary diff not shown
faraday/server/www/fonts/glyphicons-halflings-regular.eot less more
Binary diff not shown
+0
-288
faraday/server/www/fonts/glyphicons-halflings-regular.svg less more
0 <?xml version="1.0" standalone="no"?>
1 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
2 <svg xmlns="http://www.w3.org/2000/svg">
3 <metadata></metadata>
4 <defs>
5 <font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
6 <font-face units-per-em="1200" ascent="960" descent="-240" />
7 <missing-glyph horiz-adv-x="500" />
8 <glyph horiz-adv-x="0" />
9 <glyph horiz-adv-x="400" />
10 <glyph unicode=" " />
11 <glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
12 <glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
13 <glyph unicode="&#xa0;" />
14 <glyph unicode="&#xa5;" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
15 <glyph unicode="&#x2000;" horiz-adv-x="650" />
16 <glyph unicode="&#x2001;" horiz-adv-x="1300" />
17 <glyph unicode="&#x2002;" horiz-adv-x="650" />
18 <glyph unicode="&#x2003;" horiz-adv-x="1300" />
19 <glyph unicode="&#x2004;" horiz-adv-x="433" />
20 <glyph unicode="&#x2005;" horiz-adv-x="325" />
21 <glyph unicode="&#x2006;" horiz-adv-x="216" />
22 <glyph unicode="&#x2007;" horiz-adv-x="216" />
23 <glyph unicode="&#x2008;" horiz-adv-x="162" />
24 <glyph unicode="&#x2009;" horiz-adv-x="260" />
25 <glyph unicode="&#x200a;" horiz-adv-x="72" />
26 <glyph unicode="&#x202f;" horiz-adv-x="260" />
27 <glyph unicode="&#x205f;" horiz-adv-x="325" />
28 <glyph unicode="&#x20ac;" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
29 <glyph unicode="&#x20bd;" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
30 <glyph unicode="&#x2212;" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
31 <glyph unicode="&#x231b;" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
32 <glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
33 <glyph unicode="&#x2601;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
34 <glyph unicode="&#x26fa;" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
35 <glyph unicode="&#x2709;" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
36 <glyph unicode="&#x270f;" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
37 <glyph unicode="&#xe001;" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
38 <glyph unicode="&#xe002;" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
39 <glyph unicode="&#xe003;" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
40 <glyph unicode="&#xe005;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
41 <glyph unicode="&#xe006;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
42 <glyph unicode="&#xe007;" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
43 <glyph unicode="&#xe008;" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
44 <glyph unicode="&#xe009;" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
45 <glyph unicode="&#xe010;" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
46 <glyph unicode="&#xe011;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
47 <glyph unicode="&#xe012;" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
48 <glyph unicode="&#xe013;" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
49 <glyph unicode="&#xe014;" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
50 <glyph unicode="&#xe015;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
51 <glyph unicode="&#xe016;" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
52 <glyph unicode="&#xe017;" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
53 <glyph unicode="&#xe018;" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
54 <glyph unicode="&#xe019;" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
55 <glyph unicode="&#xe020;" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
56 <glyph unicode="&#xe021;" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
57 <glyph unicode="&#xe022;" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
58 <glyph unicode="&#xe023;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
59 <glyph unicode="&#xe024;" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
60 <glyph unicode="&#xe025;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
61 <glyph unicode="&#xe026;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
62 <glyph unicode="&#xe027;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
63 <glyph unicode="&#xe028;" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
64 <glyph unicode="&#xe029;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
65 <glyph unicode="&#xe030;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
66 <glyph unicode="&#xe031;" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
67 <glyph unicode="&#xe032;" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
68 <glyph unicode="&#xe033;" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
69 <glyph unicode="&#xe034;" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
70 <glyph unicode="&#xe035;" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
71 <glyph unicode="&#xe036;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
72 <glyph unicode="&#xe037;" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
73 <glyph unicode="&#xe038;" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
74 <glyph unicode="&#xe039;" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
75 <glyph unicode="&#xe040;" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
76 <glyph unicode="&#xe041;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
77 <glyph unicode="&#xe042;" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
78 <glyph unicode="&#xe043;" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
79 <glyph unicode="&#xe044;" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
80 <glyph unicode="&#xe045;" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
81 <glyph unicode="&#xe046;" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
82 <glyph unicode="&#xe047;" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
83 <glyph unicode="&#xe048;" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
84 <glyph unicode="&#xe049;" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
85 <glyph unicode="&#xe050;" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
86 <glyph unicode="&#xe051;" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
87 <glyph unicode="&#xe052;" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
88 <glyph unicode="&#xe053;" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
89 <glyph unicode="&#xe054;" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
90 <glyph unicode="&#xe055;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
91 <glyph unicode="&#xe056;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
92 <glyph unicode="&#xe057;" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
93 <glyph unicode="&#xe058;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
94 <glyph unicode="&#xe059;" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
95 <glyph unicode="&#xe060;" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
96 <glyph unicode="&#xe062;" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
97 <glyph unicode="&#xe063;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
98 <glyph unicode="&#xe064;" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
99 <glyph unicode="&#xe065;" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
100 <glyph unicode="&#xe066;" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
101 <glyph unicode="&#xe067;" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
102 <glyph unicode="&#xe068;" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
103 <glyph unicode="&#xe069;" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
104 <glyph unicode="&#xe070;" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
105 <glyph unicode="&#xe071;" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
106 <glyph unicode="&#xe072;" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
107 <glyph unicode="&#xe073;" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
108 <glyph unicode="&#xe074;" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
109 <glyph unicode="&#xe075;" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
110 <glyph unicode="&#xe076;" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
111 <glyph unicode="&#xe077;" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
112 <glyph unicode="&#xe078;" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
113 <glyph unicode="&#xe079;" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
114 <glyph unicode="&#xe080;" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
115 <glyph unicode="&#xe081;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
116 <glyph unicode="&#xe082;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
117 <glyph unicode="&#xe083;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
118 <glyph unicode="&#xe084;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
119 <glyph unicode="&#xe085;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
120 <glyph unicode="&#xe086;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
121 <glyph unicode="&#xe087;" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
122 <glyph unicode="&#xe088;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
123 <glyph unicode="&#xe089;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
124 <glyph unicode="&#xe090;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
125 <glyph unicode="&#xe091;" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
126 <glyph unicode="&#xe092;" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
127 <glyph unicode="&#xe093;" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
128 <glyph unicode="&#xe094;" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
129 <glyph unicode="&#xe095;" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
130 <glyph unicode="&#xe096;" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
131 <glyph unicode="&#xe097;" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
132 <glyph unicode="&#xe101;" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
133 <glyph unicode="&#xe102;" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
134 <glyph unicode="&#xe103;" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
135 <glyph unicode="&#xe104;" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
136 <glyph unicode="&#xe105;" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
137 <glyph unicode="&#xe106;" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
138 <glyph unicode="&#xe107;" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
139 <glyph unicode="&#xe108;" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
140 <glyph unicode="&#xe109;" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
141 <glyph unicode="&#xe110;" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
142 <glyph unicode="&#xe111;" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
143 <glyph unicode="&#xe112;" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
144 <glyph unicode="&#xe113;" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
145 <glyph unicode="&#xe114;" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
146 <glyph unicode="&#xe115;" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
147 <glyph unicode="&#xe116;" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
148 <glyph unicode="&#xe117;" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
149 <glyph unicode="&#xe118;" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
150 <glyph unicode="&#xe119;" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
151 <glyph unicode="&#xe120;" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
152 <glyph unicode="&#xe121;" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
153 <glyph unicode="&#xe122;" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
154 <glyph unicode="&#xe123;" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
155 <glyph unicode="&#xe124;" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
156 <glyph unicode="&#xe125;" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
157 <glyph unicode="&#xe126;" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
158 <glyph unicode="&#xe127;" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
159 <glyph unicode="&#xe128;" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
160 <glyph unicode="&#xe129;" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
161 <glyph unicode="&#xe130;" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
162 <glyph unicode="&#xe131;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
163 <glyph unicode="&#xe132;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
164 <glyph unicode="&#xe133;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
165 <glyph unicode="&#xe134;" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
166 <glyph unicode="&#xe135;" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
167 <glyph unicode="&#xe136;" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
168 <glyph unicode="&#xe137;" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
169 <glyph unicode="&#xe138;" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
170 <glyph unicode="&#xe139;" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
171 <glyph unicode="&#xe140;" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
172 <glyph unicode="&#xe141;" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
173 <glyph unicode="&#xe142;" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
174 <glyph unicode="&#xe143;" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
175 <glyph unicode="&#xe144;" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
176 <glyph unicode="&#xe145;" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
177 <glyph unicode="&#xe146;" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
178 <glyph unicode="&#xe148;" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
179 <glyph unicode="&#xe149;" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
180 <glyph unicode="&#xe150;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
181 <glyph unicode="&#xe151;" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
182 <glyph unicode="&#xe152;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
183 <glyph unicode="&#xe153;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
184 <glyph unicode="&#xe154;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
185 <glyph unicode="&#xe155;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
186 <glyph unicode="&#xe156;" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
187 <glyph unicode="&#xe157;" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
188 <glyph unicode="&#xe158;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
189 <glyph unicode="&#xe159;" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
190 <glyph unicode="&#xe160;" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
191 <glyph unicode="&#xe161;" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
192 <glyph unicode="&#xe162;" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
193 <glyph unicode="&#xe163;" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
194 <glyph unicode="&#xe164;" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
195 <glyph unicode="&#xe165;" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
196 <glyph unicode="&#xe166;" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
197 <glyph unicode="&#xe167;" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
198 <glyph unicode="&#xe168;" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
199 <glyph unicode="&#xe169;" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
200 <glyph unicode="&#xe170;" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
201 <glyph unicode="&#xe171;" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
202 <glyph unicode="&#xe172;" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
203 <glyph unicode="&#xe173;" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
204 <glyph unicode="&#xe174;" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
205 <glyph unicode="&#xe175;" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
206 <glyph unicode="&#xe176;" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
207 <glyph unicode="&#xe177;" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
208 <glyph unicode="&#xe178;" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
209 <glyph unicode="&#xe179;" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
210 <glyph unicode="&#xe180;" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
211 <glyph unicode="&#xe181;" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
212 <glyph unicode="&#xe182;" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
213 <glyph unicode="&#xe183;" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
214 <glyph unicode="&#xe184;" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
215 <glyph unicode="&#xe185;" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
216 <glyph unicode="&#xe186;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
217 <glyph unicode="&#xe187;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
218 <glyph unicode="&#xe188;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
219 <glyph unicode="&#xe189;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
220 <glyph unicode="&#xe190;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
221 <glyph unicode="&#xe191;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
222 <glyph unicode="&#xe192;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
223 <glyph unicode="&#xe193;" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
224 <glyph unicode="&#xe194;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
225 <glyph unicode="&#xe195;" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
226 <glyph unicode="&#xe197;" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
227 <glyph unicode="&#xe198;" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
228 <glyph unicode="&#xe199;" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
229 <glyph unicode="&#xe200;" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
230 <glyph unicode="&#xe201;" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
231 <glyph unicode="&#xe202;" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
232 <glyph unicode="&#xe203;" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
233 <glyph unicode="&#xe204;" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
234 <glyph unicode="&#xe205;" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
235 <glyph unicode="&#xe206;" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
236 <glyph unicode="&#xe209;" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
237 <glyph unicode="&#xe210;" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
238 <glyph unicode="&#xe211;" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
239 <glyph unicode="&#xe212;" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
240 <glyph unicode="&#xe213;" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
241 <glyph unicode="&#xe214;" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
242 <glyph unicode="&#xe215;" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
243 <glyph unicode="&#xe216;" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
244 <glyph unicode="&#xe218;" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
245 <glyph unicode="&#xe219;" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
246 <glyph unicode="&#xe221;" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
247 <glyph unicode="&#xe223;" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
248 <glyph unicode="&#xe224;" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
249 <glyph unicode="&#xe225;" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
250 <glyph unicode="&#xe226;" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
251 <glyph unicode="&#xe227;" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
252 <glyph unicode="&#xe230;" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
253 <glyph unicode="&#xe231;" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
254 <glyph unicode="&#xe232;" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
255 <glyph unicode="&#xe233;" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
256 <glyph unicode="&#xe234;" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
257 <glyph unicode="&#xe235;" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
258 <glyph unicode="&#xe236;" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
259 <glyph unicode="&#xe237;" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
260 <glyph unicode="&#xe238;" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
261 <glyph unicode="&#xe239;" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
262 <glyph unicode="&#xe240;" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
263 <glyph unicode="&#xe241;" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
264 <glyph unicode="&#xe242;" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
265 <glyph unicode="&#xe243;" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
266 <glyph unicode="&#xe244;" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
267 <glyph unicode="&#xe245;" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
268 <glyph unicode="&#xe246;" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
269 <glyph unicode="&#xe247;" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
270 <glyph unicode="&#xe248;" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
271 <glyph unicode="&#xe249;" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
272 <glyph unicode="&#xe250;" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
273 <glyph unicode="&#xe251;" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
274 <glyph unicode="&#xe252;" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
275 <glyph unicode="&#xe253;" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
276 <glyph unicode="&#xe254;" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
277 <glyph unicode="&#xe255;" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
278 <glyph unicode="&#xe256;" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
279 <glyph unicode="&#xe257;" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
280 <glyph unicode="&#xe258;" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
281 <glyph unicode="&#xe259;" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
282 <glyph unicode="&#xe260;" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
283 <glyph unicode="&#xf8ff;" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
284 <glyph unicode="&#x1f511;" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
285 <glyph unicode="&#x1f6aa;" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
286 </font>
287 </defs></svg>
faraday/server/www/fonts/glyphicons-halflings-regular.ttf less more
Binary diff not shown
faraday/server/www/fonts/glyphicons-halflings-regular.woff less more
Binary diff not shown
faraday/server/www/fonts/glyphicons-halflings-regular.woff2 less more
Binary diff not shown
faraday/server/www/fonts/opensans/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2 less more
Binary diff not shown
faraday/server/www/fonts/opensans/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2 less more
Binary diff not shown
faraday/server/www/fonts/opensans/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2 less more
Binary diff not shown
faraday/server/www/fonts/opensans/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2 less more
Binary diff not shown
faraday/server/www/fonts/opensans/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2 less more
Binary diff not shown
faraday/server/www/fonts/opensans/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2 less more
Binary diff not shown
faraday/server/www/fonts/opensans/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2 less more
Binary diff not shown
faraday/server/www/fonts/ubuntu/0ihfXUL2emPh0ROJezvraLO3LdcAZYWl9Si6vvxL-qU.woff less more
Binary diff not shown
faraday/server/www/fonts/ubuntu/_aijTyevf54tkVDLy-dlnLO3LdcAZYWl9Si6vvxL-qU.woff less more
Binary diff not shown
faraday/server/www/fonts/ubuntu/kbP_6ONYVgE-bLa9ZRbvvnYhjbSpvc47ee6xR_80Hnw.woff less more
Binary diff not shown
faraday/server/www/fonts/ubuntu/vRvZYZlUaogOuHbBTT1SNevvDin1pK8aKteLpeZ5c0A.woff less more
Binary diff not shown
+0
-138
faraday/server/www/header.css less more
0 .faraday-page-header {
1 margin-top: 0px;
2 padding-top: 9px;
3 padding-left: 13px;
4 margin-bottom: 10px;
5 display: flex;
6 flex-direction: row;
7 justify-content: space-between;
8 height: 70px;
9 }
10
11 .faraday-page-header h3 {
12 margin: 0px;
13 }
14
15 .faraday-page-header .icon {
16 width: 28px;
17 height: 28px;
18 }
19
20 .faraday-page-header .title {
21 font-size: 16px;
22 font-weight: bold;
23 display: inline-flex;
24 }
25
26 .faraday-page-header .subtitle {
27 font-size: 12px;
28 font-weight: 300;
29 color: #a3a3a3;
30 float: left;
31 }
32
33 .faraday-header-border-fix {
34 border-top: 3px solid #464646;
35 /*background-color: #464646;*/
36 }
37
38 .workspace-selector-wrapper, .icon-wrapper {
39 border-radius: 5px;
40 /*margin-right: 20px;*/
41 padding: 10px;
42 }
43
44 .icon-wrapper {
45 padding-top: 15px;
46 }
47
48 .workspace-selector-wrapper, .workspace-switcher {
49 display: flex;
50 }
51
52 .workspace-selector-wrapper:hover {
53 background-color: #ebebeb
54 }
55
56 .img-wrapper {
57 width: 36px;
58 }
59
60 .img-wrapper img {
61 float: left;
62 }
63
64 .switcher-wrapper {
65 min-width: 200px;
66 line-height: 1;
67 }
68
69 .switcher-wrapper .dropdown {
70 border: none;
71 background: none;
72 }
73
74 .switcher-wrapper .dropdown .open {
75 border: none;
76 background: none;
77 }
78
79 #workspaceSwitcher {
80 padding: 0px;
81 border: none;
82 background: none;
83 }
84
85 .controls-wrapper {
86 padding-top: 10px;
87 }
88
89 .controls-wrapper button, .user-dropdown{
90 padding: 6px;
91 font-size: 18px;
92 padding-left: 10px;
93 padding-right: 10px;
94 border: none;
95 background: none;
96 color: #7c7c7c;
97 }
98
99 .controls-wrapper button {
100 border-left: solid 1px #dddddd;
101 border-radius: 0px;
102 width:55px;
103 }
104
105 .workspace-switcher-title {
106 display: flex;
107 width: 190px;
108 }
109
110 .workspace-switcher-title .title{
111 width: 90%;
112 overflow: hidden;
113 }
114
115 .workspace-switcher-title .caret-container{
116 width: 10%;
117 position: relative;
118 top:8px;
119 color: #7c7c7c;
120 }
121
122 .workspace-switcher :hover{
123 background: none;
124 }
125
126 .user-menu-wrapper {
127 align-self: center;
128 margin-right: 30px;
129 }
130
131 .flex-spacer {
132 flex: 1;
133 }
134
135 .ws-label{
136 margin-bottom: 25px;
137 }
+0
-11
faraday/server/www/images/active.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
2 viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
3 <style type="text/css">
4 .st0{fill:#DEF1FE;}
5 .st1{fill:#1C87C3;}
6 </style>
7 <path class="st0" d="M8,15.4c-4.1,0-7.4-3.3-7.4-7.4S3.9,0.6,8,0.6s7.4,3.3,7.4,7.4S12.1,15.4,8,15.4z"/>
8 <path class="st1" d="M8,0.8c4,0,7.2,3.2,7.2,7.2S12,15.2,8,15.2S0.8,12,0.8,8S4,0.8,8,0.8 M8,0.4C3.8,0.4,0.4,3.8,0.4,8
9 s3.4,7.6,7.6,7.6s7.6-3.4,7.6-7.6S12.2,0.4,8,0.4L8,0.4z"/>
10 </svg>
faraday/server/www/images/asc.gif less more
Binary diff not shown
faraday/server/www/images/bg.gif less more
Binary diff not shown
faraday/server/www/images/cisco.png less more
Binary diff not shown
faraday/server/www/images/desc.gif less more
Binary diff not shown
+0
-294
faraday/server/www/images/faraday-iso.svg less more
0 <?xml version="1.0" encoding="iso-8859-1"?>
1 <!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3 <svg version="1.1" id="Layer_3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4 width="240.047px" height="330px" viewBox="0 0 240.047 330" style="enable-background:new 0 0 240.047 330;" xml:space="preserve"
5 >
6 <g id="Faraday">
7 <g id="Piel">
8 <rect x="150.03" y="75" style="fill:#F9EBE2;" width="15" height="15"/>
9 <rect x="165.034" y="75" style="fill:#F9EBE2;" width="15" height="15"/>
10 <rect x="120.024" y="90" style="fill:#F9EBE2;" width="15" height="15"/>
11 <rect x="135.027" y="90" style="fill:#F9EBE2;" width="15" height="15"/>
12 <rect x="150.03" y="90" style="fill:#F9EBE2;" width="15" height="15"/>
13 <rect x="165.034" y="90" style="fill:#F9EBE2;" width="15" height="15"/>
14 <rect x="180.037" y="90" style="fill:#F9EBE2;" width="15" height="15"/>
15 <rect x="60.01" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
16 <rect x="75.014" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
17 <rect x="90.017" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
18 <rect x="105.02" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
19 <rect x="120.024" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
20 <rect x="135.027" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
21 <rect x="150.03" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
22 <rect x="165.034" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
23 <rect x="180.037" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
24 <rect x="195.041" y="105" style="fill:#F9EBE2;" width="15" height="15"/>
25 <rect x="45.007" y="120" style="fill:#F9EBE2;" width="15" height="15"/>
26 <rect x="60.01" y="120" style="fill:#F9EBE2;" width="15" height="15"/>
27 <rect x="105.02" y="120" style="fill:#F9EBE2;" width="15" height="15"/>
28 <rect x="120.024" y="120" style="fill:#F9EBE2;" width="15" height="15"/>
29 <rect x="135.027" y="120" style="fill:#F9EBE2;" width="15" height="15"/>
30 <rect x="180.037" y="120" style="fill:#F9EBE2;" width="15" height="15"/>
31 <rect x="195.041" y="120" style="fill:#F9EBE2;" width="15" height="15"/>
32 <rect x="45.007" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
33 <rect x="75.014" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
34 <rect x="90.017" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
35 <rect x="105.02" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
36 <rect x="120.024" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
37 <rect x="135.027" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
38 <rect x="150.03" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
39 <rect x="165.034" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
40 <rect x="195.041" y="135" style="fill:#F9EBE2;" width="15" height="15"/>
41 <rect x="15" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
42 <rect x="45.007" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
43 <rect x="60.01" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
44 <rect x="75.014" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
45 <rect x="105.02" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
46 <rect x="120.024" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
47 <rect x="135.027" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
48 <rect x="165.034" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
49 <rect x="180.037" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
50 <rect x="195.041" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
51 <rect x="225.047" y="150" style="fill:#F9EBE2;" width="15" height="15"/>
52 <rect x="15" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
53 <rect x="30.003" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
54 <rect x="45.007" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
55 <rect x="60.01" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
56 <rect x="75.014" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
57 <rect x="90.017" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
58 <rect x="105.02" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
59 <rect x="120.024" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
60 <rect x="135.027" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
61 <rect x="150.03" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
62 <rect x="165.034" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
63 <rect x="180.037" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
64 <rect x="195.041" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
65 <rect x="210.044" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
66 <rect x="225.047" y="165" style="fill:#F9EBE2;" width="15" height="15"/>
67 <rect x="30.003" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
68 <rect x="45.007" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
69 <rect x="60.01" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
70 <rect x="75.014" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
71 <rect x="90.017" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
72 <rect x="105.02" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
73 <rect x="120.024" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
74 <rect x="135.027" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
75 <rect x="150.03" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
76 <rect x="165.034" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
77 <rect x="180.037" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
78 <rect x="195.041" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
79 <rect x="210.044" y="180" style="fill:#F9EBE2;" width="15" height="15"/>
80 <rect x="45.007" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
81 <rect x="60.01" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
82 <rect x="75.014" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
83 <rect x="90.017" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
84 <rect x="105.02" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
85 <rect x="120.024" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
86 <rect x="135.027" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
87 <rect x="150.03" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
88 <rect x="165.034" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
89 <rect x="180.037" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
90 <rect x="195.041" y="195" style="fill:#F9EBE2;" width="15" height="15"/>
91 <rect x="45.007" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
92 <rect x="60.01" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
93 <rect x="75.014" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
94 <rect x="90.017" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
95 <rect x="105.02" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
96 <rect x="120.024" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
97 <rect x="135.027" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
98 <rect x="150.03" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
99 <rect x="165.034" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
100 <rect x="180.037" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
101 <rect x="195.041" y="210" style="fill:#F9EBE2;" width="15" height="15"/>
102 <rect x="45.007" y="225" style="fill:#F9EBE2;" width="15" height="15"/>
103 <rect x="60.01" y="225" style="fill:#F9EBE2;" width="15" height="15"/>
104 <rect x="75.014" y="225" style="fill:#F9EBE2;" width="15" height="15"/>
105 <rect x="90.017" y="225" style="fill:#F9EBE2;" width="15" height="15"/>
106 <rect x="150.03" y="225" style="fill:#F9EBE2;" width="15" height="15"/>
107 <rect x="165.034" y="225" style="fill:#F9EBE2;" width="15" height="15"/>
108 <rect x="180.037" y="225" style="fill:#F9EBE2;" width="15" height="15"/>
109 <rect x="195.041" y="225" style="fill:#F9EBE2;" width="15" height="15"/>
110 <rect x="60.01" y="240" style="fill:#F9EBE2;" width="15" height="15"/>
111 <rect x="75.014" y="240" style="fill:#F9EBE2;" width="15" height="15"/>
112 <rect x="105.02" y="240" style="fill:#F9EBE2;" width="15" height="15"/>
113 <rect x="120.024" y="240" style="fill:#F9EBE2;" width="15" height="15"/>
114 <rect x="135.027" y="240" style="fill:#F9EBE2;" width="15" height="15"/>
115 <rect x="165.034" y="240" style="fill:#F9EBE2;" width="15" height="15"/>
116 <rect x="180.037" y="240" style="fill:#F9EBE2;" width="15" height="15"/>
117 <rect x="75.014" y="255" style="fill:#F9EBE2;" width="15" height="15"/>
118 <rect x="105.02" y="255" style="fill:#F9EBE2;" width="15" height="15"/>
119 <rect x="120.024" y="255" style="fill:#F9EBE2;" width="15" height="15"/>
120 <rect x="135.027" y="255" style="fill:#F9EBE2;" width="15" height="15"/>
121 <rect x="165.034" y="255" style="fill:#F9EBE2;" width="15" height="15"/>
122 <rect x="105.02" y="270" style="fill:#F9EBE2;" width="15" height="15"/>
123 <rect x="135.027" y="270" style="fill:#F9EBE2;" width="15" height="15"/>
124 </g>
125 <g id="Ceja_izq">
126 <rect x="75.014" y="120" width="15" height="15"/>
127 <rect x="90.017" y="120" width="15" height="15"/>
128 <rect x="60.01" y="135" width="15" height="15"/>
129 </g>
130 <g id="Ceja_der">
131 <rect x="150.03" y="120" width="15" height="15"/>
132 <rect x="165.034" y="120" width="15" height="15"/>
133 <rect x="180.037" y="135" width="15" height="15"/>
134 </g>
135 <rect id="Ojo_izq" x="90.017" y="150" width="15" height="15"/>
136 <rect id="Ojo_der" x="150.03" y="150" width="15" height="15"/>
137 <g id="Pelo">
138 <rect x="75.014" y="0" width="15" height="15"/>
139 <rect x="90.017" y="0" width="15" height="15"/>
140 <rect x="105.02" y="0" width="15" height="15"/>
141 <rect x="120.024" y="0" width="15" height="15"/>
142 <rect x="135.027" y="0" width="15" height="15"/>
143 <rect x="150.03" y="0" width="15" height="15"/>
144 <rect x="165.034" y="0" width="15" height="15"/>
145 <rect x="60.01" y="15" width="15" height="15"/>
146 <rect x="75.014" y="15" width="15" height="15"/>
147 <rect x="90.017" y="15" width="15" height="15"/>
148 <rect x="105.02" y="15" width="15" height="15"/>
149 <rect x="120.024" y="15" width="15" height="15"/>
150 <rect x="135.027" y="15" width="15" height="15"/>
151 <rect x="150.03" y="15" width="15" height="15"/>
152 <rect x="165.034" y="15" width="15" height="15"/>
153 <rect x="180.037" y="15" width="15" height="15"/>
154 <rect x="195.041" y="15" width="15" height="15"/>
155 <rect x="45.007" y="30" width="15" height="15"/>
156 <rect x="60.01" y="30" width="15" height="15"/>
157 <rect x="75.014" y="30" width="15" height="15"/>
158 <rect x="90.017" y="30" width="15" height="15"/>
159 <rect x="105.02" y="30" width="15" height="15"/>
160 <rect x="120.024" y="30" width="15" height="15"/>
161 <rect x="135.027" y="30" width="15" height="15"/>
162 <rect x="150.03" y="30" width="15" height="15"/>
163 <rect x="165.034" y="30" width="15" height="15"/>
164 <rect x="180.037" y="30" width="15" height="15"/>
165 <rect x="195.041" y="30" width="15" height="15"/>
166 <rect x="210.044" y="30" width="15" height="15"/>
167 <rect x="30.003" y="45" width="15" height="15"/>
168 <rect x="45.007" y="45" width="15" height="15"/>
169 <rect x="60.01" y="45" width="15" height="15"/>
170 <rect x="75.014" y="45" width="15" height="15"/>
171 <rect x="90.017" y="45" width="15" height="15"/>
172 <rect x="105.02" y="45" width="15" height="15"/>
173 <rect x="120.024" y="45" width="15" height="15"/>
174 <rect x="135.027" y="45" width="15" height="15"/>
175 <rect x="150.03" y="45" width="15" height="15"/>
176 <rect x="165.034" y="45" width="15" height="15"/>
177 <rect x="195.041" y="45" width="15" height="15"/>
178 <rect x="210.044" y="45" width="15" height="15"/>
179 <rect x="15" y="60" width="15" height="15"/>
180 <rect x="30.003" y="60" width="15" height="15"/>
181 <rect x="45.007" y="60" width="15" height="15"/>
182 <rect x="60.01" y="60" width="15" height="15"/>
183 <rect x="75.014" y="60" width="15" height="15"/>
184 <rect x="90.017" y="60" width="15" height="15"/>
185 <rect x="105.02" y="60" width="15" height="15"/>
186 <rect x="120.024" y="60" width="15" height="15"/>
187 <rect x="135.027" y="60" width="15" height="15"/>
188 <rect x="150.03" y="60" width="15" height="15"/>
189 <rect x="165.034" y="60" width="15" height="15"/>
190 <rect x="180.037" y="60" width="15" height="15"/>
191 <rect x="195.041" y="60" width="15" height="15"/>
192 <rect x="210.044" y="60" width="15" height="15"/>
193 <rect x="225.047" y="60" width="15" height="15"/>
194 <rect x="15" y="75" width="15" height="15"/>
195 <rect x="30.003" y="75" width="15" height="15"/>
196 <rect x="45.007" y="75" width="15" height="15"/>
197 <rect x="60.01" y="75" width="15" height="15"/>
198 <rect x="75.014" y="75" width="15" height="15"/>
199 <rect x="90.017" y="75" width="15" height="15"/>
200 <rect x="105.02" y="75" width="15" height="15"/>
201 <rect x="120.024" y="75" width="15" height="15"/>
202 <rect x="135.027" y="75" width="15" height="15"/>
203 <rect x="180.037" y="75" width="15" height="15"/>
204 <rect x="195.041" y="75" width="15" height="15"/>
205 <rect x="180.037" y="45" width="15" height="15"/>
206 <rect x="210.044" y="75" width="15" height="15"/>
207 <rect x="225.047" y="75" width="15" height="15"/>
208 <rect x="15" y="90" width="15" height="15"/>
209 <rect x="30.003" y="90" width="15" height="15"/>
210 <rect x="45.007" y="90" width="15" height="15"/>
211 <rect x="60.01" y="90" width="15" height="15"/>
212 <rect x="75.014" y="90" width="15" height="15"/>
213 <rect x="90.017" y="90" width="15" height="15"/>
214 <rect x="105.02" y="90" width="15" height="15"/>
215 <rect x="195.041" y="90" width="15" height="15"/>
216 <rect x="210.044" y="90" width="15" height="15"/>
217 <rect x="225.047" y="90" width="15" height="15"/>
218 <rect x="15" y="105" width="15" height="15"/>
219 <rect x="0" y="105" width="15" height="15"/>
220 <rect x="30.003" y="105" width="15" height="15"/>
221 <rect x="45.007" y="105" width="15" height="15"/>
222 <rect x="210.044" y="105" width="15" height="15"/>
223 <rect x="225.047" y="105" width="15" height="15"/>
224 <rect x="15" y="120" width="15" height="15"/>
225 <rect x="30.003" y="120" width="15" height="15"/>
226 <rect x="210.044" y="120" width="15" height="15"/>
227 <rect x="225.047" y="120" width="15" height="15"/>
228 <rect x="15" y="135" width="15" height="15"/>
229 <rect x="30.003" y="135" width="15" height="15"/>
230 <rect x="210.044" y="135" width="15" height="15"/>
231 <rect x="225.047" y="135" width="15" height="15"/>
232 <rect x="30.003" y="150" width="15" height="15"/>
233 <rect x="210.044" y="150" width="15" height="15"/>
234 </g>
235 <g id="Barba">
236 <rect x="15" y="180" width="15" height="15"/>
237 <rect x="225.047" y="180" width="15" height="15"/>
238 <rect x="15" y="195" width="15" height="15"/>
239 <rect x="30.003" y="195" width="15" height="15"/>
240 <rect x="210.044" y="195" width="15" height="15"/>
241 <rect x="225.047" y="195" width="15" height="15"/>
242 <rect x="30.003" y="210" width="15" height="15"/>
243 <rect x="210.044" y="210" width="15" height="15"/>
244 <rect x="30.003" y="225" width="15" height="15"/>
245 <rect x="105.02" y="225" width="15" height="15"/>
246 <rect x="120.024" y="225" width="15" height="15"/>
247 <rect x="135.027" y="225" width="15" height="15"/>
248 <rect x="210.044" y="225" width="15" height="15"/>
249 <rect x="30.003" y="240" width="15" height="15"/>
250 <rect x="45.007" y="240" width="15" height="15"/>
251 <rect x="90.017" y="240" width="15" height="15"/>
252 <rect x="150.03" y="240" width="15" height="15"/>
253 <rect x="195.041" y="240" width="15" height="15"/>
254 <rect x="210.044" y="240" width="15" height="15"/>
255 <rect x="15" y="255" width="15" height="15"/>
256 <rect x="45.007" y="255" width="15" height="15"/>
257 <rect x="60.01" y="255" width="15" height="15"/>
258 <rect x="90.017" y="255" width="15" height="15"/>
259 <rect x="150.03" y="255" width="15" height="15"/>
260 <rect x="180.037" y="255" width="15" height="15"/>
261 <rect x="195.041" y="255" width="15" height="15"/>
262 <rect x="225.047" y="255" width="15" height="15"/>
263 <rect x="45.007" y="270" width="15" height="15"/>
264 <rect x="60.01" y="270" width="15" height="15"/>
265 <rect x="75.014" y="270" width="15" height="15"/>
266 <rect x="90.017" y="270" width="15" height="15"/>
267 <rect x="120.024" y="270" width="15" height="15"/>
268 <rect x="150.03" y="270" width="15" height="15"/>
269 <rect x="165.034" y="270" width="15" height="15"/>
270 <rect x="180.037" y="270" width="15" height="15"/>
271 <rect x="195.041" y="270" width="15" height="15"/>
272 <rect x="30.003" y="285" width="15" height="15"/>
273 <rect x="45.007" y="285" width="15" height="15"/>
274 <rect x="75.014" y="285" width="15" height="15"/>
275 <rect x="90.017" y="285" width="15" height="15"/>
276 <rect x="105.02" y="285" width="15" height="15"/>
277 <rect x="120.024" y="285" width="15" height="15"/>
278 <rect x="135.027" y="285" width="15" height="15"/>
279 <rect x="150.03" y="285" width="15" height="15"/>
280 <rect x="165.034" y="285" width="15" height="15"/>
281 <rect x="195.041" y="285" width="15" height="15"/>
282 <rect x="210.044" y="285" width="15" height="15"/>
283 <rect x="90.017" y="300" width="15" height="15"/>
284 <rect x="105.02" y="300" width="15" height="15"/>
285 <rect x="120.024" y="300" width="15" height="15"/>
286 <rect x="135.027" y="300" width="15" height="15"/>
287 <rect x="150.03" y="300" width="15" height="15"/>
288 <rect x="105.02" y="315" width="15" height="15"/>
289 <rect x="120.024" y="315" width="15" height="15"/>
290 <rect x="135.027" y="315" width="15" height="15"/>
291 </g>
292 </g>
293 </svg>
+0
-18
faraday/server/www/images/fondo_faraday.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 24.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 2882 1440" style="enable-background:new 0 0 2882 1440;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill-rule:evenodd;clip-rule:evenodd;fill:url(#Fill-1_1_);}
6 </style>
7 <g id="Page-1">
8 <g id="Desktop-HD">
9
10 <radialGradient id="Fill-1_1_" cx="1135.5767" cy="1115.7365" r="0.7079" gradientTransform="matrix(-8.9509 -1489.7811 -1467.316 9.0879 1648723 1682416.125)" gradientUnits="userSpaceOnUse">
11 <stop offset="0" style="stop-color:#C7E8FF"/>
12 <stop offset="1" style="stop-color:#23B1E6"/>
13 </radialGradient>
14 <polygon id="Fill-1" class="st0" points="-31.1,1464 2905.6,1464 2905.6,-25.8 -31.1,-25.8 "/>
15 </g>
16 </g>
17 </svg>
faraday/server/www/images/fondofaraday4k.jpg less more
Binary diff not shown
faraday/server/www/images/grafico.png less more
Binary diff not shown
+0
-18
faraday/server/www/images/ico-communication-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#5A5B61;stroke-width:8;stroke-linejoin:bevel;stroke-miterlimit:10;}
6 .st1{fill:#5A5B61;stroke:#5A5B61;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:10;}
7 </style>
8 <g>
9 <path class="st0" d="M130.4,52.8c1.1,0.4,2.2,0.8,3.3,1.3c17.8,7.4,30.1,23.2,30.1,41.4c0,13.6-6.9,25.9-17.8,34.3l9.6,27.4
10 L127.9,139c-5.5,1.6-11.3,2.5-17.4,2.5c-17.6,0-33.1-7.3-42.8-18.6c-0.4-0.4-0.8-0.9-1.1-1.3"/>
11 <path class="st0" d="M70.1,11.2C34.6,11.2,5.9,36,5.9,66.6c0,16.4,8.3,31.2,21.4,41.3l-11.5,33L49.1,119c6.6,2,13.6,3,21,3
12 c35.5,0,64.2-24.8,64.2-55.4S105.6,11.2,70.1,11.2z"/>
13 <circle class="st1" cx="41.1" cy="67.2" r="6"/>
14 <circle class="st1" cx="68.3" cy="67.2" r="6"/>
15 <circle class="st1" cx="95.5" cy="67.2" r="6"/>
16 </g>
17 </svg>
+0
-18
faraday/server/www/images/ico-communication.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-linejoin:bevel;stroke-miterlimit:10;}
6 .st1{fill:#B3B4B5;stroke:#B3B4B5;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:10;}
7 </style>
8 <g>
9 <path class="st0" d="M130.4,52.8c1.1,0.4,2.2,0.8,3.3,1.3c17.8,7.4,30.1,23.2,30.1,41.4c0,13.6-6.9,25.9-17.8,34.3l9.6,27.4
10 L127.9,139c-5.5,1.6-11.3,2.5-17.4,2.5c-17.6,0-33.1-7.3-42.8-18.6c-0.4-0.4-0.8-0.9-1.1-1.3"/>
11 <path class="st0" d="M70.1,11.2C34.6,11.2,5.9,36,5.9,66.6c0,16.4,8.3,31.2,21.4,41.3l-11.5,33L49.1,119c6.6,2,13.6,3,21,3
12 c35.5,0,64.2-24.8,64.2-55.4S105.6,11.2,70.1,11.2z"/>
13 <circle class="st1" cx="41.1" cy="67.2" r="6"/>
14 <circle class="st1" cx="68.3" cy="67.2" r="6"/>
15 <circle class="st1" cx="95.5" cy="67.2" r="6"/>
16 </g>
17 </svg>
+0
-21
faraday/server/www/images/ico-credentials-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#5A5B61;}
6 </style>
7 <g>
8 <path class="st0" d="M161.7,111.5c0,1-1.5,3-4.5,6c-3,3-5,4.5-6,4.5c-0.5,0-1.4-0.5-2.6-1.5c-1.2-1-2.3-2-3.3-3
9 c-1-1-2.2-2.2-3.5-3.6c-1.3-1.4-2.1-2.2-2.2-2.4l-8.8,8.8l20.1,20.1c1.7,1.7,2.6,3.8,2.6,6.2c0,2.6-1.2,5-3.6,7.4
10 c-2.4,2.4-4.8,3.6-7.4,3.6c-2.4,0-4.5-0.9-6.2-2.6L75,93.7c-10.7,8-21.8,11.9-33.3,11.9c-9.9,0-18-3.1-24.2-9.3
11 C11.3,90.1,8.2,82,8.2,72.1c0-9.7,2.9-19.2,8.7-28.5c5.8-9.3,13.3-16.8,22.6-22.6c9.3-5.8,18.8-8.7,28.5-8.7c9.9,0,18,3.1,24.2,9.3
12 c6.2,6.2,9.3,14.3,9.3,24.2c0,11.5-4,22.6-11.9,33.3l32.4,32.4l8.8-8.8c-0.2-0.2-1-0.9-2.4-2.2c-1.4-1.3-2.6-2.5-3.6-3.5
13 c-1-1-2-2.1-3-3.3c-1-1.2-1.5-2.1-1.5-2.6c0-1,1.5-3,4.5-6c3-3,5-4.5,6-4.5c0.8,0,1.5,0.3,2.1,0.9c0.4,0.4,1.8,1.7,4.2,4.1
14 c2.4,2.3,4.9,4.8,7.5,7.2c2.6,2.5,5.2,5.1,7.9,7.8c2.7,2.7,4.9,5.1,6.7,7.1C160.8,109.8,161.7,111,161.7,111.5z M79,59.7
15 c3.4-3.4,5.1-7.5,5.1-12.4c0-4.9-1.7-9-5.1-12.4c-3.4-3.4-7.5-5.1-12.4-5.1c-4.9,0-9,1.7-12.4,5.1c-3.4,3.4-5.1,7.5-5.1,12.4
16 c0,2.6,0.6,5.1,1.7,7.6c-2.5-1.2-5-1.7-7.6-1.7c-4.9,0-9,1.7-12.4,5.1c-3.4,3.4-5.1,7.5-5.1,12.4c0,4.9,1.7,9,5.1,12.4
17 c3.4,3.4,7.5,5.1,12.4,5.1c4.9,0,9-1.7,12.4-5.1c3.4-3.4,5.1-7.5,5.1-12.4c0-2.6-0.6-5.1-1.7-7.6c2.5,1.2,5,1.7,7.6,1.7
18 C71.4,64.8,75.6,63.1,79,59.7z"/>
19 </g>
20 </svg>
+0
-21
faraday/server/www/images/ico-credentials.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#B3B4B5;}
6 </style>
7 <g>
8 <path class="st0" d="M161.7,111.5c0,1-1.5,3-4.5,6c-3,3-5,4.5-6,4.5c-0.5,0-1.4-0.5-2.6-1.5c-1.2-1-2.3-2-3.3-3
9 c-1-1-2.2-2.2-3.5-3.6c-1.3-1.4-2.1-2.2-2.2-2.4l-8.8,8.8l20.1,20.1c1.7,1.7,2.6,3.8,2.6,6.2c0,2.6-1.2,5-3.6,7.4
10 c-2.4,2.4-4.8,3.6-7.4,3.6c-2.4,0-4.5-0.9-6.2-2.6L75,93.7c-10.7,8-21.8,11.9-33.3,11.9c-9.9,0-18-3.1-24.2-9.3
11 C11.3,90.1,8.2,82,8.2,72.1c0-9.7,2.9-19.2,8.7-28.5c5.8-9.3,13.3-16.8,22.6-22.6c9.3-5.8,18.8-8.7,28.5-8.7c9.9,0,18,3.1,24.2,9.3
12 c6.2,6.2,9.3,14.3,9.3,24.2c0,11.5-4,22.6-11.9,33.3l32.4,32.4l8.8-8.8c-0.2-0.2-1-0.9-2.4-2.2c-1.4-1.3-2.6-2.5-3.6-3.5
13 c-1-1-2-2.1-3-3.3c-1-1.2-1.5-2.1-1.5-2.6c0-1,1.5-3,4.5-6c3-3,5-4.5,6-4.5c0.8,0,1.5,0.3,2.1,0.9c0.4,0.4,1.8,1.7,4.2,4.1
14 c2.4,2.3,4.9,4.8,7.5,7.2c2.6,2.5,5.2,5.1,7.9,7.8c2.7,2.7,4.9,5.1,6.7,7.1C160.8,109.8,161.7,111,161.7,111.5z M79,59.7
15 c3.4-3.4,5.1-7.5,5.1-12.4c0-4.9-1.7-9-5.1-12.4c-3.4-3.4-7.5-5.1-12.4-5.1c-4.9,0-9,1.7-12.4,5.1c-3.4,3.4-5.1,7.5-5.1,12.4
16 c0,2.6,0.6,5.1,1.7,7.6c-2.5-1.2-5-1.7-7.6-1.7c-4.9,0-9,1.7-12.4,5.1c-3.4,3.4-5.1,7.5-5.1,12.4c0,4.9,1.7,9,5.1,12.4
17 c3.4,3.4,7.5,5.1,12.4,5.1c4.9,0,9-1.7,12.4-5.1c3.4-3.4,5.1-7.5,5.1-12.4c0-2.6-0.6-5.1-1.7-7.6c2.5,1.2,5,1.7,7.6,1.7
18 C71.4,64.8,75.6,63.1,79,59.7z"/>
19 </g>
20 </svg>
+0
-26
faraday/server/www/images/ico-dashboard-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="-14 16 170 170" style="enable-background:new -14 16 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#5B5C62;stroke-width:8;stroke-linecap:square;stroke-miterlimit:10;}
6 .st1{fill:#5B5C62;stroke:#5B5C62;stroke-width:4;stroke-linejoin:bevel;stroke-miterlimit:10;}
7 .st2{fill:none;stroke:#5B5C62;stroke-width:6;stroke-miterlimit:10;}
8 .st3{fill:#FFFFFF;}
9 </style>
10 <g>
11 <path class="st0" d="M134.7,157.1c8-12.1,12.6-26.6,12.6-42.2c0-42.6-34.5-77.1-77.1-77.1S-6.9,72.3-6.9,114.9
12 c0,15.6,4.6,30.1,12.6,42.2H134.7z"/>
13 <path class="st1" d="M84.8,114.9c0,8.1-6.6,14.7-14.7,14.7s-14.7-6.6-14.7-14.7s14.7-48.7,14.7-48.7S84.8,106.7,84.8,114.9z"/>
14 <line class="st2" x1="70.1" y1="37.7" x2="70.1" y2="55.4"/>
15 <line class="st2" x1="124" y1="60.1" x2="111.5" y2="72.6"/>
16 <line class="st2" x1="146.3" y1="113.9" x2="128.6" y2="113.9"/>
17 <line class="st2" x1="99.2" y1="43.5" x2="95.6" y2="52.1"/>
18 <line class="st2" x1="140.6" y1="85" x2="132" y2="88.5"/>
19 <line class="st2" x1="16.3" y1="60.1" x2="28.8" y2="72.6"/>
20 <line class="st2" x1="-6.1" y1="113.9" x2="11.6" y2="113.9"/>
21 <line class="st2" x1="41.1" y1="43.5" x2="44.7" y2="52.1"/>
22 <line class="st2" x1="-0.3" y1="85" x2="8.3" y2="88.5"/>
23 <circle class="st3" cx="70.1" cy="113.9" r="6.4"/>
24 </g>
25 </svg>
+0
-26
faraday/server/www/images/ico-dashboard.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="-14 16 170 170" style="enable-background:new -14 16 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-linecap:square;stroke-miterlimit:10;}
6 .st1{fill:#B3B4B5;stroke:#B3B4B5;stroke-width:4;stroke-linejoin:bevel;stroke-miterlimit:10;}
7 .st2{fill:none;stroke:#B3B4B5;stroke-width:6;stroke-miterlimit:10;}
8 .st3{fill:#FFFFFF;}
9 </style>
10 <g>
11 <path class="st0" d="M134.7,157.1c8-12.1,12.6-26.6,12.6-42.2c0-42.6-34.5-77.1-77.1-77.1S-6.9,72.3-6.9,114.9
12 c0,15.6,4.6,30.1,12.6,42.2H134.7z"/>
13 <path class="st1" d="M84.8,114.9c0,8.1-6.6,14.7-14.7,14.7s-14.7-6.6-14.7-14.7s14.7-48.7,14.7-48.7S84.8,106.7,84.8,114.9z"/>
14 <line class="st2" x1="70.1" y1="37.7" x2="70.1" y2="55.4"/>
15 <line class="st2" x1="124" y1="60.1" x2="111.5" y2="72.6"/>
16 <line class="st2" x1="146.3" y1="113.9" x2="128.6" y2="113.9"/>
17 <line class="st2" x1="99.2" y1="43.5" x2="95.6" y2="52.1"/>
18 <line class="st2" x1="140.6" y1="85" x2="132" y2="88.5"/>
19 <line class="st2" x1="16.3" y1="60.1" x2="28.8" y2="72.6"/>
20 <line class="st2" x1="-6.1" y1="113.9" x2="11.6" y2="113.9"/>
21 <line class="st2" x1="41.1" y1="43.5" x2="44.7" y2="52.1"/>
22 <line class="st2" x1="-0.3" y1="85" x2="8.3" y2="88.5"/>
23 <circle class="st3" cx="70.1" cy="113.9" r="6.4"/>
24 </g>
25 </svg>
+0
-11
faraday/server/www/images/ico-data-analysis-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#5A5B61;}
6 </style>
7 <g>
8 <path class="st0" d="M162.1,132.7v9.8H6v-117h9.8v107.3H162.1z M132.8,54.6l19.5,68.3H25.5V79l34.1-43.9L103.6,79L132.8,54.6z"/>
9 </g>
10 </svg>
+0
-11
faraday/server/www/images/ico-data-analysis.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#B3B4B5;}
6 </style>
7 <g>
8 <path class="st0" d="M162.1,132.7v9.8H6v-117h9.8v107.3H162.1z M132.8,54.6l19.5,68.3H25.5V79l34.1-43.9L103.6,79L132.8,54.6z"/>
9 </g>
10 </svg>
+0
-26
faraday/server/www/images/ico-executive-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="-14 16 170 170" style="enable-background:new -14 16 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#5B5C62;stroke-width:6;stroke-linecap:square;stroke-miterlimit:10;}
6 .st1{fill:none;stroke:#5B5C62;stroke-width:6;stroke-linejoin:bevel;stroke-miterlimit:10;}
7 .st2{fill:none;stroke:#5B5C62;stroke-width:8;stroke-miterlimit:10;}
8 .st3{fill:#5B5C62;}
9 </style>
10 <g>
11 <line class="st0" x1="33.7" y1="114.6" x2="66.7" y2="114.6"/>
12 <line class="st0" x1="33.7" y1="98.6" x2="66.7" y2="98.6"/>
13 <line class="st0" x1="33.7" y1="82.6" x2="66.7" y2="82.6"/>
14 <line class="st0" x1="33.7" y1="131.6" x2="115.7" y2="131.6"/>
15 <line class="st0" x1="33.7" y1="147.6" x2="54.7" y2="147.6"/>
16 <line class="st1" x1="66.7" y1="147.6" x2="77.7" y2="147.6"/>
17 <path class="st2" d="M25.7,38.1h113.5c6.4,0,11.5,5.1,11.5,11.5v12.5h-114V49.6c0-6.4-5.1-11.5-11.5-11.5l0,0
18 c-6.4,0-11.5,5.1-11.5,11.5v37v29.5v43c0,6.4-5.1,11.5-11.5,11.5l0,0c-6.4,0-11.5-5.1-11.5-11.5v-12.5h23"/>
19 <path class="st2" d="M131.9,62.1v91.1c0,9.6-7.8,17.4-17.4,17.4H1.7"/>
20 <g>
21 <path class="st3" d="M95.9,82.3c-14.3,0-24.8,16.5-13.4,31.6l0,0c15,11.4,31.6,1,31.6-13.4H95.9V82.3L95.9,82.3z"/>
22 <path class="st3" d="M101.5,76.6v18.2l0,0h18.2C119.8,84.8,111.6,76.6,101.5,76.6z"/>
23 </g>
24 </g>
25 </svg>
+0
-26
faraday/server/www/images/ico-executive.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="-14 16 170 170" style="enable-background:new -14 16 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#B3B4B5;stroke-width:6;stroke-linecap:square;stroke-miterlimit:10;}
6 .st1{fill:none;stroke:#B3B4B5;stroke-width:6;stroke-linejoin:bevel;stroke-miterlimit:10;}
7 .st2{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-miterlimit:10;}
8 .st3{fill:#B3B4B5;}
9 </style>
10 <g>
11 <line class="st0" x1="33.7" y1="114.6" x2="66.7" y2="114.6"/>
12 <line class="st0" x1="33.7" y1="98.6" x2="66.7" y2="98.6"/>
13 <line class="st0" x1="33.7" y1="82.6" x2="66.7" y2="82.6"/>
14 <line class="st0" x1="33.7" y1="131.6" x2="115.7" y2="131.6"/>
15 <line class="st0" x1="33.7" y1="147.6" x2="54.7" y2="147.6"/>
16 <line class="st1" x1="66.7" y1="147.6" x2="77.7" y2="147.6"/>
17 <path class="st2" d="M25.7,38.1h113.5c6.4,0,11.5,5.1,11.5,11.5v12.5h-114V49.6c0-6.4-5.1-11.5-11.5-11.5l0,0
18 c-6.4,0-11.5,5.1-11.5,11.5v37v29.5v43c0,6.4-5.1,11.5-11.5,11.5l0,0c-6.4,0-11.5-5.1-11.5-11.5v-12.5h23"/>
19 <path class="st2" d="M131.9,62.1v91.1c0,9.6-7.8,17.4-17.4,17.4H1.7"/>
20 <g>
21 <path class="st3" d="M95.9,82.3c-14.3,0-24.8,16.5-13.4,31.6l0,0c15,11.4,31.6,1,31.6-13.4H95.9V82.3L95.9,82.3z"/>
22 <path class="st3" d="M101.5,76.6v18.2l0,0h18.2C119.8,84.8,111.6,76.6,101.5,76.6z"/>
23 </g>
24 </g>
25 </svg>
faraday/server/www/images/ico-graph.png less more
Binary diff not shown
+0
-21
faraday/server/www/images/ico-hosts-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#5B5C62;stroke-width:8;stroke-linecap:square;stroke-miterlimit:10;}
6 .st1{fill:#5B5C62;stroke:#5B5C62;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:10;}
7 .st2{fill:none;stroke:#5B5C62;stroke-width:10;stroke-miterlimit:10;}
8 </style>
9 <g>
10 <rect x="13.2" y="22" class="st0" width="145.3" height="40.4"/>
11 <circle class="st1" cx="33.4" cy="42.2" r="5.8"/>
12 <line class="st2" x1="52" y1="42.2" x2="143.1" y2="42.2"/>
13 <rect x="13.2" y="61.6" class="st0" width="145.3" height="40.4"/>
14 <circle class="st1" cx="33.4" cy="81.8" r="5.8"/>
15 <line class="st2" x1="52" y1="81.8" x2="143.1" y2="81.8"/>
16 <rect x="13.2" y="101.2" class="st0" width="145.3" height="40.4"/>
17 <circle class="st1" cx="33.4" cy="121.4" r="5.8"/>
18 <line class="st2" x1="52.4" y1="121.4" x2="143.1" y2="121.4"/>
19 </g>
20 </svg>
+0
-21
faraday/server/www/images/ico-hosts.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-linecap:square;stroke-miterlimit:10;}
6 .st1{fill:#B3B4B5;stroke:#B3B4B5;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:10;}
7 .st2{fill:none;stroke:#B3B4B5;stroke-width:10;stroke-miterlimit:10;}
8 </style>
9 <g>
10 <rect x="13.2" y="22" class="st0" width="145.3" height="40.4"/>
11 <circle class="st1" cx="33.4" cy="42.2" r="5.8"/>
12 <line class="st2" x1="52" y1="42.2" x2="143.1" y2="42.2"/>
13 <rect x="13.2" y="61.6" class="st0" width="145.3" height="40.4"/>
14 <circle class="st1" cx="33.4" cy="81.8" r="5.8"/>
15 <line class="st2" x1="52" y1="81.8" x2="143.1" y2="81.8"/>
16 <rect x="13.2" y="101.2" class="st0" width="145.3" height="40.4"/>
17 <circle class="st1" cx="33.4" cy="121.4" r="5.8"/>
18 <line class="st2" x1="52.4" y1="121.4" x2="143.1" y2="121.4"/>
19 </g>
20 </svg>
faraday/server/www/images/ico-settings.png less more
Binary diff not shown
+0
-24
faraday/server/www/images/ico-status-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#5C5D63;stroke-width:8;stroke-linecap:square;stroke-miterlimit:10;}
6 .st1{fill:#5C5D63;}
7 .st2{fill:none;stroke:#5C5D63;stroke-width:6;stroke-linecap:square;stroke-miterlimit:10;}
8 .st3{fill:none;stroke:#5C5D63;stroke-width:8;stroke-miterlimit:10;}
9 </style>
10 <g>
11 <g>
12 <polyline class="st0" points="121.6,34.7 144.6,34.7 144.6,163.7 24.6,163.7 24.6,34.7 47.3,34.7 "/>
13 <rect x="42" y="60.7" class="st1" width="15.3" height="54"/>
14 <rect x="65" y="95.7" class="st1" width="15.3" height="19"/>
15 <rect x="88" y="82.7" class="st1" width="15.3" height="32"/>
16 <rect x="111" y="75" class="st1" width="15.3" height="39.7"/>
17 <line class="st2" x1="46.6" y1="127.7" x2="122.6" y2="127.7"/>
18 <line class="st2" x1="46.6" y1="143.7" x2="65.4" y2="143.7"/>
19 <line class="st2" x1="77.4" y1="143.7" x2="88.4" y2="143.7"/>
20 </g>
21 <path class="st3" d="M118.6,22.7h-16.1c-1-9-8.6-16-17.9-16s-16.9,7-17.9,16H50.6l-4,23h76L118.6,22.7z"/>
22 </g>
23 </svg>
+0
-24
faraday/server/www/images/ico-status.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-linecap:square;stroke-miterlimit:10;}
6 .st1{fill:#B3B4B5;}
7 .st2{fill:none;stroke:#B3B4B5;stroke-width:6;stroke-linecap:square;stroke-miterlimit:10;}
8 .st3{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-miterlimit:10;}
9 </style>
10 <g>
11 <g>
12 <polyline class="st0" points="121.6,34.7 144.6,34.7 144.6,163.7 24.6,163.7 24.6,34.7 47.3,34.7 "/>
13 <rect x="42" y="60.7" class="st1" width="15.3" height="54"/>
14 <rect x="65" y="95.7" class="st1" width="15.3" height="19"/>
15 <rect x="88" y="82.7" class="st1" width="15.3" height="32"/>
16 <rect x="111" y="75" class="st1" width="15.3" height="39.7"/>
17 <line class="st2" x1="46.6" y1="127.7" x2="122.6" y2="127.7"/>
18 <line class="st2" x1="46.6" y1="143.7" x2="65.4" y2="143.7"/>
19 <line class="st2" x1="77.4" y1="143.7" x2="88.4" y2="143.7"/>
20 </g>
21 <path class="st3" d="M118.6,22.7h-16.1c-1-9-8.6-16-17.9-16s-16.9,7-17.9,16H50.6l-4,23h76L118.6,22.7z"/>
22 </g>
23 </svg>
faraday/server/www/images/ico-stopwatch.png less more
Binary diff not shown
+0
-17
faraday/server/www/images/ico-tasks-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#5A5B61;}
6 </style>
7 <g>
8 <path class="st0" d="M162.6,22.2v33.6H5.6V22.2H162.6z M162.6,67v33.6H5.6V67H162.6z M162.6,111.9v33.6H5.6v-33.6H162.6z
9 M16.9,44.6h89.7V33.4H16.9V44.6z M16.9,89.4h89.7V78.2H16.9V89.4z M16.9,134.3h89.7v-11.2H16.9V134.3z M151.8,44.9
10 c1.6-1.6,2.5-3.6,2.5-6c0-2.3-0.8-4.3-2.5-6c-1.6-1.6-3.6-2.5-6-2.5s-4.3,0.8-6,2.5c-1.6,1.6-2.5,3.6-2.5,6c0,2.3,0.8,4.3,2.5,6
11 c1.6,1.6,3.6,2.5,6,2.5S150.1,46.6,151.8,44.9z M151.8,89.8c1.6-1.6,2.5-3.6,2.5-6c0-2.3-0.8-4.3-2.5-6c-1.6-1.6-3.6-2.5-6-2.5
12 s-4.3,0.8-6,2.5c-1.6,1.6-2.5,3.6-2.5,6c0,2.3,0.8,4.3,2.5,6c1.6,1.6,3.6,2.5,6,2.5S150.1,91.4,151.8,89.8z M151.8,134.7
13 c1.6-1.6,2.5-3.6,2.5-6c0-2.3-0.8-4.3-2.5-6c-1.6-1.6-3.6-2.5-6-2.5s-4.3,0.8-6,2.5c-1.6,1.6-2.5,3.6-2.5,6c0,2.3,0.8,4.3,2.5,6
14 c1.6,1.6,3.6,2.5,6,2.5S150.1,136.3,151.8,134.7z"/>
15 </g>
16 </svg>
+0
-17
faraday/server/www/images/ico-tasks.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#B3B4B5;}
6 </style>
7 <g>
8 <path class="st0" d="M162.6,22.2v33.6H5.6V22.2H162.6z M162.6,67v33.6H5.6V67H162.6z M162.6,111.9v33.6H5.6v-33.6H162.6z
9 M16.9,44.6h89.7V33.4H16.9V44.6z M16.9,89.4h89.7V78.2H16.9V89.4z M16.9,134.3h89.7v-11.2H16.9V134.3z M151.8,44.9
10 c1.6-1.6,2.5-3.6,2.5-6c0-2.3-0.8-4.3-2.5-6c-1.6-1.6-3.6-2.5-6-2.5s-4.3,0.8-6,2.5c-1.6,1.6-2.5,3.6-2.5,6c0,2.3,0.8,4.3,2.5,6
11 c1.6,1.6,3.6,2.5,6,2.5S150.1,46.6,151.8,44.9z M151.8,89.8c1.6-1.6,2.5-3.6,2.5-6c0-2.3-0.8-4.3-2.5-6c-1.6-1.6-3.6-2.5-6-2.5
12 s-4.3,0.8-6,2.5c-1.6,1.6-2.5,3.6-2.5,6c0,2.3,0.8,4.3,2.5,6c1.6,1.6,3.6,2.5,6,2.5S150.1,91.4,151.8,89.8z M151.8,134.7
13 c1.6-1.6,2.5-3.6,2.5-6c0-2.3-0.8-4.3-2.5-6c-1.6-1.6-3.6-2.5-6-2.5s-4.3,0.8-6,2.5c-1.6,1.6-2.5,3.6-2.5,6c0,2.3,0.8,4.3,2.5,6
14 c1.6,1.6,3.6,2.5,6,2.5S150.1,136.3,151.8,134.7z"/>
15 </g>
16 </svg>
+0
-20
faraday/server/www/images/ico-users-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#FFFFFF;stroke:#5B5C62;stroke-width:8;stroke-linejoin:bevel;stroke-miterlimit:10;}
6 .st1{fill:none;stroke:#5B5C62;stroke-width:8;stroke-linejoin:bevel;stroke-miterlimit:10;}
7 .st2{fill:#FFFFFF;stroke:#5B5C62;stroke-width:6;stroke-linejoin:bevel;stroke-miterlimit:10;}
8 </style>
9 <g>
10 <path class="st0" d="M57.9,101.3c-27.3,5.2-48,29.2-48,58.1v0.4h151v-0.4c0-29.9-22.2-54.6-51-58.6"/>
11 <path class="st0" d="M69.1,100.3"/>
12 <path class="st1" d="M85.4,110.2L85.4,110.2c-22.1,0-40.1-17.9-40.1-40.1V48.3c0-22.1,17.9-40.1,40.1-40.1l0,0
13 c22.1,0,40.1,17.9,40.1,40.1v21.9C125.5,92.3,107.6,110.2,85.4,110.2z"/>
14 <path class="st2" d="M85.4,8.3L85.4,8.3c-22.1,0-40.1,17.9-40.1,40.1v2.8C51.2,54.3,57.9,56,65,56c15.7,0,29.3-8.6,36.6-21.3
15 c5.2,9.1,13.7,16.1,23.9,19.3v-5.7C125.5,26.2,107.6,8.3,85.4,8.3z"/>
16 <path class="st1" d="M85.4,110.2L85.4,110.2c-22.1,0-40.1-17.9-40.1-40.1V48.3c0-22.1,17.9-40.1,40.1-40.1l0,0
17 c22.1,0,40.1,17.9,40.1,40.1v21.9C125.5,92.3,107.6,110.2,85.4,110.2z"/>
18 </g>
19 </svg>
+0
-20
faraday/server/www/images/ico-users.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#FFFFFF;stroke:#B3B4B5;stroke-width:8;stroke-linejoin:bevel;stroke-miterlimit:10;}
6 .st1{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-linejoin:bevel;stroke-miterlimit:10;}
7 .st2{fill:#FFFFFF;stroke:#B3B4B5;stroke-width:6;stroke-linejoin:bevel;stroke-miterlimit:10;}
8 </style>
9 <g>
10 <path class="st0" d="M57.9,101.3c-27.3,5.2-48,29.2-48,58.1v0.4h151v-0.4c0-29.9-22.2-54.6-51-58.6"/>
11 <path class="st0" d="M69.1,100.3"/>
12 <path class="st1" d="M85.4,110.2L85.4,110.2c-22.1,0-40.1-17.9-40.1-40.1V48.3c0-22.1,17.9-40.1,40.1-40.1l0,0
13 c22.1,0,40.1,17.9,40.1,40.1v21.9C125.5,92.3,107.6,110.2,85.4,110.2z"/>
14 <path class="st2" d="M85.4,8.3L85.4,8.3c-22.1,0-40.1,17.9-40.1,40.1v2.8C51.2,54.3,57.9,56,65,56c15.7,0,29.3-8.6,36.6-21.3
15 c5.2,9.1,13.7,16.1,23.9,19.3v-5.7C125.5,26.2,107.6,8.3,85.4,8.3z"/>
16 <path class="st1" d="M85.4,110.2L85.4,110.2c-22.1,0-40.1-17.9-40.1-40.1V48.3c0-22.1,17.9-40.1,40.1-40.1l0,0
17 c22.1,0,40.1,17.9,40.1,40.1v21.9C125.5,92.3,107.6,110.2,85.4,110.2z"/>
18 </g>
19 </svg>
+0
-20
faraday/server/www/images/ico-vulnerability-templates-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#5A5B61;stroke:#5A5B61;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:10;}
6 </style>
7 <g>
8 <path class="st0" d="M156.6,88.6c1.2,1.2,1.8,2.6,1.8,4.2c0,1.6-0.6,3-1.8,4.2c-1.2,1.2-2.6,1.8-4.2,1.8h-21
9 c0,10.7-2.1,19.7-6.3,27.2l19.5,19.6c1.2,1.2,1.8,2.6,1.8,4.2c0,1.6-0.6,3-1.8,4.2c-1.1,1.2-2.5,1.8-4.2,1.8
10 c-1.7,0-3.1-0.6-4.2-1.8l-18.5-18.4c-0.3,0.3-0.8,0.7-1.4,1.2c-0.6,0.5-1.9,1.4-3.9,2.7c-2,1.3-4,2.4-6.1,3.4
11 c-2.1,1-4.6,1.9-7.7,2.7c-3.1,0.8-6.1,1.2-9.1,1.2V62.9h-12v83.9c-3.2,0-6.4-0.4-9.5-1.3c-3.2-0.8-5.9-1.9-8.1-3.1
12 c-2.3-1.2-4.3-2.4-6.2-3.7c-1.8-1.2-3.2-2.2-4.1-3l-1.4-1.3L31,153.8c-1.2,1.3-2.7,2-4.5,2c-1.5,0-2.8-0.5-4-1.5
13 c-1.2-1.1-1.8-2.5-1.9-4.2c-0.1-1.7,0.4-3.1,1.5-4.4L41,124.5c-3.6-7.1-5.4-15.7-5.4-25.7h-21c-1.6,0-3-0.6-4.2-1.8
14 c-1.2-1.2-1.8-2.6-1.8-4.2c0-1.6,0.6-3,1.8-4.2c1.2-1.2,2.6-1.8,4.2-1.8h21V59.3L19.3,43.1c-1.2-1.2-1.8-2.6-1.8-4.2s0.6-3,1.8-4.2
15 c1.2-1.2,2.6-1.8,4.2-1.8c1.6,0,3,0.6,4.2,1.8L44,50.9h79l16.2-16.2c1.2-1.2,2.6-1.8,4.2-1.8c1.6,0,3,0.6,4.2,1.8
16 c1.2,1.2,1.8,2.6,1.8,4.2s-0.6,3-1.8,4.2l-16.2,16.2v27.5h21C154,86.9,155.4,87.5,156.6,88.6z M113.4,38.9H53.5
17 c0-8.3,2.9-15.4,8.8-21.2C68.1,11.9,75.2,9,83.5,9c8.3,0,15.4,2.9,21.2,8.8S113.4,30.6,113.4,38.9z"/>
18 </g>
19 </svg>
+0
-20
faraday/server/www/images/ico-vulnerability-templates.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#B3B4B5;stroke:#B3B4B5;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:10;}
6 </style>
7 <g>
8 <path class="st0" d="M156.6,88.6c1.2,1.2,1.8,2.6,1.8,4.2c0,1.6-0.6,3-1.8,4.2c-1.2,1.2-2.6,1.8-4.2,1.8h-21
9 c0,10.7-2.1,19.7-6.3,27.2l19.5,19.6c1.2,1.2,1.8,2.6,1.8,4.2c0,1.6-0.6,3-1.8,4.2c-1.1,1.2-2.5,1.8-4.2,1.8
10 c-1.7,0-3.1-0.6-4.2-1.8l-18.5-18.4c-0.3,0.3-0.8,0.7-1.4,1.2c-0.6,0.5-1.9,1.4-3.9,2.7c-2,1.3-4,2.4-6.1,3.4
11 c-2.1,1-4.6,1.9-7.7,2.7c-3.1,0.8-6.1,1.2-9.1,1.2V62.9h-12v83.9c-3.2,0-6.4-0.4-9.5-1.3c-3.2-0.8-5.9-1.9-8.1-3.1
12 c-2.3-1.2-4.3-2.4-6.2-3.7c-1.8-1.2-3.2-2.2-4.1-3l-1.4-1.3L31,153.8c-1.2,1.3-2.7,2-4.5,2c-1.5,0-2.8-0.5-4-1.5
13 c-1.2-1.1-1.8-2.5-1.9-4.2c-0.1-1.7,0.4-3.1,1.5-4.4L41,124.5c-3.6-7.1-5.4-15.7-5.4-25.7h-21c-1.6,0-3-0.6-4.2-1.8
14 c-1.2-1.2-1.8-2.6-1.8-4.2c0-1.6,0.6-3,1.8-4.2c1.2-1.2,2.6-1.8,4.2-1.8h21V59.3L19.3,43.1c-1.2-1.2-1.8-2.6-1.8-4.2s0.6-3,1.8-4.2
15 c1.2-1.2,2.6-1.8,4.2-1.8c1.6,0,3,0.6,4.2,1.8L44,50.9h79l16.2-16.2c1.2-1.2,2.6-1.8,4.2-1.8c1.6,0,3,0.6,4.2,1.8
16 c1.2,1.2,1.8,2.6,1.8,4.2s-0.6,3-1.8,4.2l-16.2,16.2v27.5h21C154,86.9,155.4,87.5,156.6,88.6z M113.4,38.9H53.5
17 c0-8.3,2.9-15.4,8.8-21.2C68.1,11.9,75.2,9,83.5,9c8.3,0,15.4,2.9,21.2,8.8S113.4,30.6,113.4,38.9z"/>
18 </g>
19 </svg>
+0
-16
faraday/server/www/images/ico-web-shell-menu.svg less more
0 <?xml version="1.0" encoding="iso-8859-1"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
4 <g>
5 <path style="fill:none;stroke:#5B5C62;stroke-width:8;stroke-linecap:square;stroke-miterlimit:10;" d="M173.08,157.611H27.081
6 V54.692c0-6.693,5.426-12.119,12.119-12.119h121.762c6.693,0,12.119,5.426,12.119,12.119V157.611z"/>
7 <line style="fill:none;stroke:#5B5C62;stroke-width:8;stroke-miterlimit:10;" x1="27.081" y1="67.208" x2="173.08" y2="67.208"/>
8 <g>
9 <polyline style="fill:none;stroke:#5B5C62;stroke-width:6;stroke-miterlimit:10;" points="58.222,92.638 78.132,112.548
10 58.222,132.458 "/>
11
12 <line style="fill:none;stroke:#5B5C62;stroke-width:6;stroke-miterlimit:10;" x1="97.92" y1="127.251" x2="140.939" y2="127.251"/>
13 </g>
14 </g>
15 </svg>
+0
-16
faraday/server/www/images/ico-web-shell.svg less more
0 <?xml version="1.0" encoding="iso-8859-1"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
4 <g>
5 <path style="fill:none;stroke:#B3B4B5;stroke-width:8;stroke-linecap:square;stroke-miterlimit:10;" d="M173.08,157.611H27.081
6 V54.692c0-6.693,5.426-12.119,12.119-12.119h121.762c6.693,0,12.119,5.426,12.119,12.119V157.611z"/>
7 <line style="fill:none;stroke:#B3B4B5;stroke-width:8;stroke-miterlimit:10;" x1="27.081" y1="67.208" x2="173.08" y2="67.208"/>
8 <g>
9 <polyline style="fill:none;stroke:#B3B4B5;stroke-width:6;stroke-miterlimit:10;" points="58.222,92.638 78.132,112.548
10 58.222,132.458 "/>
11
12 <line style="fill:none;stroke:#B3B4B5;stroke-width:6;stroke-miterlimit:10;" x1="97.92" y1="127.251" x2="140.939" y2="127.251"/>
13 </g>
14 </g>
15 </svg>
+0
-31
faraday/server/www/images/ico-workspace-comparison-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#5A5B61;stroke-width:8;stroke-miterlimit:10;}
6 .st1{fill:none;stroke:#5A5B61;stroke-width:6;stroke-miterlimit:10;}
7 .st2{fill:#FFFFFF;stroke:#5A5B61;stroke-width:8;stroke-miterlimit:10;}
8 </style>
9 <g>
10 <g>
11 <path class="st0" d="M71.5,74L71.5,74c1.9,0,3.5-1.6,3.5-3.5V26.4c0-1.1-0.9-2-2-2H44.6h-4.7c-0.3,0-0.5-0.1-0.7-0.3l-5.9-6.4
12 c-0.2-0.2-0.5-0.3-0.7-0.3H13.4c-1.1,0-2,0.9-2,2v12v38.2c0,2.4,2,4.4,4.4,4.4C15.8,74,71.5,74,71.5,74z"/>
13 <line class="st1" x1="11.4" y1="37.4" x2="75" y2="37.4"/>
14 </g>
15 <g>
16 <path class="st0" d="M154.2,150.9L154.2,150.9c1.9,0,3.5-1.6,3.5-3.5v-44.1c0-1.1-0.9-2-2-2h-28.4h-4.7c-0.3,0-0.5-0.1-0.7-0.3
17 l-5.9-6.4c-0.2-0.2-0.5-0.3-0.7-0.3H96.2c-1.1,0-2,0.9-2,2v12v38.2c0,2.4,2,4.4,4.4,4.4L154.2,150.9L154.2,150.9z"/>
18 <line class="st1" x1="94.2" y1="114.3" x2="157.7" y2="114.3"/>
19 </g>
20 <path class="st2" d="M116.3,69.2"/>
21 <g>
22 <path class="st0" d="M85.6,137.4c-24,0-44.2-16.6-49.6-39"/>
23 <polygon class="st0" points="41.9,98.3 31.3,98.3 36.6,89.3 "/>
24 </g>
25 <g>
26 <path class="st0" d="M83.6,37.4c24,0,44.2,16.6,49.6,39"/>
27 <polygon class="st0" points="127.4,76.5 138,76.5 132.7,85.5 "/>
28 </g>
29 </g>
30 </svg>
+0
-31
faraday/server/www/images/ico-workspace-comparison.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-miterlimit:10;}
6 .st1{fill:none;stroke:#B3B4B5;stroke-width:6;stroke-miterlimit:10;}
7 .st2{fill:#FFFFFF;stroke:#B3B4B5;stroke-width:8;stroke-miterlimit:10;}
8 </style>
9 <g>
10 <g>
11 <path class="st0" d="M71.5,74L71.5,74c1.9,0,3.5-1.6,3.5-3.5V26.4c0-1.1-0.9-2-2-2H44.6h-4.7c-0.3,0-0.5-0.1-0.7-0.3l-5.9-6.4
12 c-0.2-0.2-0.5-0.3-0.7-0.3H13.4c-1.1,0-2,0.9-2,2v12v38.2c0,2.4,2,4.4,4.4,4.4C15.8,74,71.5,74,71.5,74z"/>
13 <line class="st1" x1="11.4" y1="37.4" x2="75" y2="37.4"/>
14 </g>
15 <g>
16 <path class="st0" d="M154.2,150.9L154.2,150.9c1.9,0,3.5-1.6,3.5-3.5v-44.1c0-1.1-0.9-2-2-2h-28.4h-4.7c-0.3,0-0.5-0.1-0.7-0.3
17 l-5.9-6.4c-0.2-0.2-0.5-0.3-0.7-0.3H96.2c-1.1,0-2,0.9-2,2v12v38.2c0,2.4,2,4.4,4.4,4.4L154.2,150.9L154.2,150.9z"/>
18 <line class="st1" x1="94.2" y1="114.3" x2="157.7" y2="114.3"/>
19 </g>
20 <path class="st2" d="M116.3,69.2"/>
21 <g>
22 <path class="st0" d="M85.6,137.4c-24,0-44.2-16.6-49.6-39"/>
23 <polygon class="st0" points="41.9,98.3 31.3,98.3 36.6,89.3 "/>
24 </g>
25 <g>
26 <path class="st0" d="M83.6,37.4c24,0,44.2,16.6,49.6,39"/>
27 <polygon class="st0" points="127.4,76.5 138,76.5 132.7,85.5 "/>
28 </g>
29 </g>
30 </svg>
+0
-20
faraday/server/www/images/ico-workspaces-menu.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#FFFFFF;stroke:#5B5C62;stroke-width:8;stroke-miterlimit:10;}
6 .st1{fill:none;stroke:#5B5C62;stroke-width:8;stroke-miterlimit:10;}
7 .st2{fill:none;stroke:#5B5C62;stroke-width:6;stroke-miterlimit:10;}
8 </style>
9 <g>
10 <path class="st0" d="M145.8,123.7v15.5c0,3.9-3.1,7-7,7l0,0"/>
11 <path class="st1" d="M18.7,61V37c0-2.2,1.8-4,4-4h38.2c0.6,0,1.1,0.2,1.5,0.6l11.8,12.7c0.4,0.4,0.9,0.6,1.5,0.6H85"/>
12 <path class="st1" d="M138.8,146.2"/>
13 <polyline class="st1" points="85.8,60.8 85.8,22 132.4,22 161,49.7 161,123.5 131.7,123.5 "/>
14 <polyline class="st2" points="132.4,22 132.4,51.1 161,51.1 "/>
15 <path class="st1" d="M138.8,146.2c-3.9,0-7-3.1-7-7V65c0-2.2-1.8-4-4-4H85H12.7c-2.2,0-4,1.8-4,4v77.2c0,2.2,1.8,4,4,4H138.8"/>
16 <path class="st2" d="M45.1,70.7v14.8c0,3.9,3.2,7.1,7.1,7.1l0,0c3.9,0,7.1-3.2,7.1-7.1V61c0-6.6-5.3-11.9-11.9-11.9h-1.2
17 c-6.6,0-11.9,5.3-11.9,11.9l0,0"/>
18 </g>
19 </svg>
+0
-20
faraday/server/www/images/ico-workspaces.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#FFFFFF;stroke:#B3B4B5;stroke-width:8;stroke-miterlimit:10;}
6 .st1{fill:none;stroke:#B3B4B5;stroke-width:8;stroke-miterlimit:10;}
7 .st2{fill:none;stroke:#B3B4B5;stroke-width:6;stroke-miterlimit:10;}
8 </style>
9 <g>
10 <path class="st0" d="M145.8,123.7v15.5c0,3.9-3.1,7-7,7l0,0"/>
11 <path class="st1" d="M18.7,61V37c0-2.2,1.8-4,4-4h38.2c0.6,0,1.1,0.2,1.5,0.6l11.8,12.7c0.4,0.4,0.9,0.6,1.5,0.6H85"/>
12 <path class="st1" d="M138.8,146.2"/>
13 <polyline class="st1" points="85.8,60.8 85.8,22 132.4,22 161,49.7 161,123.5 131.7,123.5 "/>
14 <polyline class="st2" points="132.4,22 132.4,51.1 161,51.1 "/>
15 <path class="st1" d="M138.8,146.2c-3.9,0-7-3.1-7-7V65c0-2.2-1.8-4-4-4H85H12.7c-2.2,0-4,1.8-4,4v77.2c0,2.2,1.8,4,4,4H138.8"/>
16 <path class="st2" d="M45.1,70.7v14.8c0,3.9,3.2,7.1,7.1,7.1l0,0c3.9,0,7.1-3.2,7.1-7.1V61c0-6.6-5.3-11.9-11.9-11.9h-1.2
17 c-6.6,0-11.9,5.3-11.9,11.9l0,0"/>
18 </g>
19 </svg>
+0
-3
faraday/server/www/images/icon-gear-thin.svg less more
0 <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd">
1 <path d="M12 8.666c-1.838 0-3.333 1.496-3.333 3.334s1.495 3.333 3.333 3.333 3.333-1.495 3.333-3.333-1.495-3.334-3.333-3.334m0 7.667c-2.39 0-4.333-1.943-4.333-4.333s1.943-4.334 4.333-4.334 4.333 1.944 4.333 4.334c0 2.39-1.943 4.333-4.333 4.333m-1.193 6.667h2.386c.379-1.104.668-2.451 2.107-3.05 1.496-.617 2.666.196 3.635.672l1.686-1.688c-.508-1.047-1.266-2.199-.669-3.641.567-1.369 1.739-1.663 3.048-2.099v-2.388c-1.235-.421-2.471-.708-3.047-2.098-.572-1.38.057-2.395.669-3.643l-1.687-1.686c-1.117.547-2.221 1.257-3.642.668-1.374-.571-1.656-1.734-2.1-3.047h-2.386c-.424 1.231-.704 2.468-2.099 3.046-.365.153-.718.226-1.077.226-.843 0-1.539-.392-2.566-.893l-1.687 1.686c.574 1.175 1.251 2.237.669 3.643-.571 1.375-1.734 1.654-3.047 2.098v2.388c1.226.418 2.468.705 3.047 2.098.581 1.403-.075 2.432-.669 3.643l1.687 1.687c1.45-.725 2.355-1.204 3.642-.669 1.378.572 1.655 1.738 2.1 3.047m3.094 1h-3.803c-.681-1.918-.785-2.713-1.773-3.123-1.005-.419-1.731.132-3.466.952l-2.689-2.689c.873-1.837 1.367-2.465.953-3.465-.412-.991-1.192-1.087-3.123-1.773v-3.804c1.906-.678 2.712-.782 3.123-1.773.411-.991-.071-1.613-.953-3.466l2.689-2.688c1.741.828 2.466 1.365 3.465.953.992-.412 1.082-1.185 1.775-3.124h3.802c.682 1.918.788 2.714 1.774 3.123 1.001.416 1.709-.119 3.467-.952l2.687 2.688c-.878 1.847-1.361 2.477-.952 3.465.411.992 1.192 1.087 3.123 1.774v3.805c-1.906.677-2.713.782-3.124 1.773-.403.975.044 1.561.954 3.464l-2.688 2.689c-1.728-.82-2.467-1.37-3.456-.955-.988.41-1.08 1.146-1.785 3.126"/>
2 </svg>
faraday/server/www/images/icon-list-confirmed.png less more
Binary diff not shown
+0
-11
faraday/server/www/images/icon-list-confirmed.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 15 15" style="enable-background:new 0 0 15 15;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#488BE6;}
6 .st1{fill:#FFFFFF;}
7 </style>
8 <circle id="XMLID_1_" class="st0" cx="7.5" cy="7.5" r="7.5"/>
9 <polygon id="XMLID_2_" class="st1" points="3.9,8.2 6.5,10.8 11.5,5.8 10.3,4.6 6.5,8.4 5,6.9 "/>
10 </svg>
faraday/server/www/images/icon-list-notconfirmed.png less more
Binary diff not shown
+0
-15
faraday/server/www/images/icon-list-notconfirmed.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 15 15" style="enable-background:new 0 0 15 15;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#F8F8F8;stroke:#DEDEDE;stroke-miterlimit:10;}
6 </style>
7 <g id="On">
8 </g>
9 <g id="Off">
10 <g id="XMLID_4_">
11 <circle id="XMLID_6_" class="st0" cx="7.5" cy="7.5" r="7"/>
12 </g>
13 </g>
14 </svg>
+0
-17
faraday/server/www/images/icon-login-password-lock.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 33 33" style="enable-background:new 0 0 33 33;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#D3D3D3;}
6 </style>
7 <path class="st0" d="M24.8,32.7H7.9c-2.8,0-5-2.2-5-5V17.4c0-2.8,2.2-5,5-5h16.9c2.8,0,5,2.2,5,5v10.3
8 C29.8,30.5,27.6,32.7,24.8,32.7z M7.9,15.4c-1.1,0-2,0.9-2,2v10.3c0,1.1,0.9,2,2,2h16.9c1.1,0,2-0.9,2-2V17.4c0-1.1-0.9-2-2-2H7.9z"
9 />
10 <path class="st0" d="M26.5,14.4h-3v-4.3c0-3.9-3.2-7.1-7.1-7.1c-4,0-7.2,3.2-7.2,7.1v4h-3v-4C6.2,4.5,10.7,0,16.3,0
11 C22,0,26.5,4.5,26.5,10.1V14.4z"/>
12 <path class="st0" d="M16,28.1c-1.9,0-3.5-1.7-3.5-3.7s1.6-3.7,3.5-3.7s3.5,1.7,3.5,3.7S18,28.1,16,28.1z M16,23.1
13 c-0.7,0-1.2,0.6-1.2,1.3s0.6,1.3,1.2,1.3c0.7,0,1.2-0.6,1.2-1.3S16.7,23.1,16,23.1z"/>
14 <path class="st0" d="M16.2,23.1L16.2,23.1c-0.7,0-1.3-0.6-1.3-1.2v-2.5c0-0.7,0.6-1.2,1.2-1.2l0,0c0.7,0,1.2,0.6,1.2,1.2v2.5
15 C17.4,22.6,16.9,23.1,16.2,23.1z"/>
16 </svg>
+0
-19
faraday/server/www/images/icon-toolbar-confirmed-off.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 33 33" style="enable-background:new 0 0 33 33;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#FFFFFF;}
6 .st1{fill:#F8F8F8;stroke:#BCBCBC;stroke-width:2;stroke-miterlimit:10;}
7 .st2{fill:#464646;}
8 </style>
9 <g id="Layer_1">
10 </g>
11 <g id="Layer_2">
12 <polygon id="XMLID_5_" class="st0" points="8.8,17.5 14.5,23.2 25.3,12.4 22.7,9.8 14.4,17.9 11.3,14.8 "/>
13 <g id="XMLID_8_">
14 <circle id="XMLID_9_" class="st1" cx="16.5" cy="16.4" r="15.2"/>
15 </g>
16 <polygon id="XMLID_7_" class="st2" points="8.7,17.3 14.4,23.1 25.2,12.3 22.6,9.7 14.3,17.8 11.2,14.7 "/>
17 </g>
18 </svg>
+0
-13
faraday/server/www/images/icon-toolbar-confirmed-on.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 33 33" style="enable-background:new 0 0 33 33;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#488BE6;stroke:#488BE6;stroke-miterlimit:10;}
6 .st1{fill:#FFFFFF;}
7 </style>
8 <g id="XMLID_10_">
9 <circle id="XMLID_11_" class="st0" cx="16.6" cy="16.5" r="15.2"/>
10 </g>
11 <polygon id="XMLID_5_" class="st1" points="8.8,17.5 14.5,23.2 25.3,12.4 22.7,9.8 14.4,17.9 11.3,14.8 "/>
12 </svg>
+0
-18
faraday/server/www/images/icon-toolbar-delete.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 33 33" style="enable-background:new 0 0 33 33;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#363636;}
6 .st1{fill:#353535;}
7 </style>
8 <path id="XMLID_4_" class="st0" d="M21.5,7.3h-2V3.9c0-0.4-0.3-0.7-0.7-0.7h-6.2c-0.4,0-0.7,0.3-0.7,0.7v3.4h-2V3.9
9 c0-1.5,1.2-2.7,2.7-2.7h6.2c1.5,0,2.7,1.2,2.7,2.7V7.3z"/>
10 <path id="XMLID_8_" class="st1" d="M23.3,31.7H8.1c-1.4,0-2.6-1.2-2.6-2.6V10.7h20.4v18.4C25.9,30.5,24.8,31.7,23.3,31.7z M7.5,12.7
11 v16.4c0,0.3,0.3,0.6,0.6,0.6h15.2c0.3,0,0.6-0.3,0.6-0.6V12.7H7.5z"/>
12 <rect id="XMLID_5_" x="9.9" y="11.9" class="st0" width="2" height="18.9"/>
13 <rect id="XMLID_6_" x="14.8" y="11.8" class="st0" width="2" height="19"/>
14 <rect id="XMLID_3_" x="19.5" y="11.9" class="st0" width="2" height="18.8"/>
15 <path id="XMLID_7_" class="st0" d="M27,6.4H4.5C4,6.4,3.6,6.8,3.6,7.3v0.4c0,0.5,0.4,0.9,0.9,0.9H27c0.5,0,0.9-0.4,0.9-0.9V7.3
16 C27.8,6.8,27.4,6.4,27,6.4z"/>
17 </svg>
+0
-20
faraday/server/www/images/icon-toolbar-download.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 33 33" style="enable-background:new 0 0 33 33;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#3F3F3F;}
6 </style>
7 <path id="XMLID_2_" class="st0" d="M17.8,21.7L17.8,21.7c-0.5,0.5-1.4,0.5-1.9,0l-6.4-6.4C9,14.8,9,14,9.5,13.5l0,0
8 c0.5-0.5,1.4-0.5,1.9,0l6.4,6.4C18.3,20.3,18.3,21.2,17.8,21.7z"/>
9 <path id="XMLID_4_" class="st0" d="M4.3,33L4.3,33c-0.8,0-1.5-0.6-1.5-1.4v-9.2c0-0.8,0.7-1.4,1.5-1.4h0c0.8,0,1.5,0.6,1.5,1.4v9.2
10 C5.8,32.4,5.2,33,4.3,33z"/>
11 <path id="XMLID_5_" class="st0" d="M30.4,31.4L30.4,31.4c0,0.8-0.5,1.4-1.2,1.6H4.4c-0.6-0.2-1.2-0.8-1.2-1.6v0
12 c0-0.8,0.5-1.4,1.2-1.4h24.9C29.9,30,30.4,30.6,30.4,31.4z"/>
13 <path id="XMLID_1_" class="st0" d="M16.8,21.6L16.8,21.6c-0.8,0-1.5-0.6-1.5-1.2V1.5c0-0.7,0.7-1.2,1.5-1.2h0c0.8,0,1.5,0.6,1.5,1.2
14 v18.8C18.3,21,17.6,21.6,16.8,21.6z"/>
15 <path id="XMLID_6_" class="st0" d="M28.9,33L28.9,33c-0.8,0-1.5-0.6-1.5-1.4v-9.2c0-0.8,0.7-1.4,1.5-1.4h0c0.8,0,1.5,0.6,1.5,1.4
16 v9.2C30.4,32.4,29.7,33,28.9,33z"/>
17 <path id="XMLID_3_" class="st0" d="M16.1,21.7L16.1,21.7c-0.5-0.5-0.5-1.4,0-1.9l6.4-6.4c0.5-0.5,1.4-0.5,1.9,0l0,0
18 c0.5,0.5,0.5,1.4,0,1.9L18,21.7C17.5,22.2,16.6,22.2,16.1,21.7z"/>
19 </svg>
+0
-19
faraday/server/www/images/icon-toolbar-edit.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 33 33" style="enable-background:new 0 0 33 33;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#363636;}
6 </style>
7 <path id="XMLID_6_" class="st0" d="M13.3,32.5H4.9c-2,0-3.6-1.6-3.6-3.6V4.8c0-2,1.6-3.6,3.6-3.6h10.9l9.4,8.8v7.7h-2.1v-6.8
8 l-8.1-7.6h-10c-0.8,0-1.5,0.7-1.5,1.5v24.1c0,0.8,0.7,1.5,1.5,1.5h8.4V32.5z"/>
9 <path id="XMLID_5_" class="st0" d="M24.4,11.6h-7.5c-2,0-2.7-1.6-2.7-2.7V2.1h2.1v6.8c0,0.6,0.5,0.6,0.6,0.6h7.5V11.6z"/>
10 <path id="XMLID_3_" class="st0" d="M19,31.9c-0.6,0-1.3-0.3-1.7-0.8l-0.5-0.5c-0.4-0.5-0.6-1.1-0.6-1.7c0-0.6,0.3-1.2,0.8-1.6
11 l10.3-9.4c1-0.9,2.4-0.8,3.3,0.2l0.5,0.5c0.4,0.5,0.6,1.1,0.6,1.7s-0.3,1.2-0.8,1.6l-10.3,9.4C20.1,31.7,19.6,31.9,19,31.9z
12 M28.8,19.3c-0.1,0-0.1,0-0.2,0.1l-10.3,9.4c-0.1,0.1-0.1,0.2-0.1,0.2c0,0,0,0.1,0.1,0.2l0.5,0.5c0.1,0.1,0.2,0.1,0.2,0.1
13 c0.1,0,0.1,0,0.2-0.1l10.3-9.4c0.1-0.1,0.1-0.2,0.1-0.2c0,0,0-0.1-0.1-0.2L29,19.4C29,19.4,28.9,19.3,28.8,19.3z"/>
14 <path id="XMLID_4_" class="st0" d="M18.5,31.3l-1.1,1c-0.5,0.5-1.3,0.4-1.8-0.1l-0.1-0.1c-0.5-0.5-0.4-1.3,0.1-1.8l1.1-1
15 c0.5-0.5,1.3-0.4,1.8,0.1l0.1,0.1C19.1,30.1,19,30.9,18.5,31.3z"/>
16 <path id="XMLID_1_" class="st0" d="M29.4,21.1l-1.1,1c-0.5,0.5-1.3,0.4-1.8-0.1L26.4,22c-0.5-0.5-0.4-1.3,0.1-1.8l1.1-1
17 c0.5-0.5,1.3-0.4,1.8,0.1l0.1,0.1C30,19.8,29.9,20.6,29.4,21.1z"/>
18 </svg>
+0
-13
faraday/server/www/images/icon-toolbar-searchbar-loupe.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 33 33" style="enable-background:new 0 0 33 33;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#878787;}
6 </style>
7 <path id="XMLID_4_" class="st0" d="M13.5,26.2c-7,0-12.7-5.7-12.7-12.7c0-7,5.7-12.7,12.7-12.7s12.7,5.7,12.7,12.7
8 C26.2,20.5,20.5,26.2,13.5,26.2z M13.5,3.9c-5.3,0-9.7,4.3-9.7,9.7c0,5.3,4.3,9.7,9.7,9.7s9.7-4.3,9.7-9.7
9 C23.2,8.2,18.8,3.9,13.5,3.9z"/>
10 <path id="XMLID_2_" class="st0" d="M31.8,29.9l-1.7,1.7c-0.5,0.5-1.4,0.5-1.9,0L20,23.2c-0.5-0.5-0.5-1.4,0-1.9l1.7-1.7
11 c0.5-0.5,1.4-0.5,1.9,0l8.4,8.4C32.4,28.6,32.4,29.4,31.8,29.9z"/>
12 </svg>
+0
-30
faraday/server/www/images/icon-toolbar-upload.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 33 33" style="enable-background:new 0 0 33 33;" xml:space="preserve">
4 <g transform="translate(0,-952.36218)">
5 <g>
6 <path d="M16.7,956.6c-2.4,0-4.7,0.9-6.5,2.7c-1.4,1.4-2.2,3.1-2.5,5c-3.5,0.6-6.3,3.6-6.3,7.3c0,4.1,3.3,7.4,7.4,7.4h3.7
7 c0.4,0,0.7-0.3,0.7-0.7s-0.3-0.7-0.7-0.7l0,0H8.9c-3.3,0-6.1-2.8-6.1-6.1c0-3.1,2.4-5.8,5.5-6.1c0.3,0,0.6-0.3,0.6-0.6
8 c0.2-1.7,1-3.3,2.2-4.6c1.5-1.5,3.5-2.3,5.5-2.3s4,0.8,5.5,2.3c1.7,1.7,2.5,4.2,2.2,6.5c0,0.4,0.2,0.7,0.6,0.8H25h0.4
9 c2.9,0,5,2.3,5,5c0,2.9-2.3,5-5,5h-4.8c-0.4,0-0.7,0.3-0.7,0.7s0.3,0.7,0.7,0.7l0,0h4.8c3.5,0,6.5-2.9,6.5-6.5
10 c0-3.4-2.8-6.3-6.2-6.4c0.1-2.5-0.8-5-2.7-6.9C21.4,957.5,19.1,956.6,16.7,956.6z M16.7,966.9c-0.2,0-0.4,0.1-0.5,0.2l-3.7,3.4
11 c-0.3,0.3-0.3,0.7-0.1,1c0.3,0.3,0.7,0.3,1,0l2.6-2.4v10.7c0,0.4,0.3,0.7,0.7,0.7s0.7-0.3,0.7-0.7v-10.7l2.6,2.4
12 c0.3,0.3,0.7,0.2,1,0c0.3-0.3,0.2-0.8-0.1-1l-3.7-3.4C17,966.9,16.9,966.9,16.7,966.9z"/>
13 <path d="M16.6,980.9c-0.6,0-1.1-0.5-1.1-1.1v-9.6l-1.8,1.6c-0.5,0.5-1.1,0.5-1.6,0c-0.4-0.6-0.3-1.2,0.1-1.6l3.7-3.4
14 c0.2-0.2,0.5-0.3,0.8-0.3c0.5,0,0.7,0.2,0.7,0.4l3.6,3.3c0.2,0.1,0.4,0.4,0.4,0.8c0,0.3-0.1,0.6-0.3,0.9c-0.6,0.4-1.2,0.4-1.6,0
15 l-1.8-1.6v9.6C17.8,980.4,17.3,980.9,16.6,980.9z M16.4,968v11.8c0,0.2,0.4,0.2,0.4,0V968l3.4,3.1c0.1,0.1,0.3,0,0.4,0
16 c0,0,0,0,0-0.1c0-0.1,0-0.1-0.1-0.1l-3.8-3.5c0,0,0,0-0.1,0l-3.7,3.4c-0.1,0.1-0.1,0.3,0,0.3c0,0,0.1,0,0.2-0.1L16.4,968z
17 M25.4,979.5h-4.8c-0.6,0-1.1-0.5-1.1-1.1s0.5-1.1,1.1-1.1h4.8c2.6,0,4.6-2,4.6-4.6c0-2.6-2-4.6-4.6-4.6l-0.6,0
18 c-0.6-0.1-0.9-0.6-0.9-1.2c0.3-2.3-0.5-4.6-2.1-6.1c-1.4-1.4-3.2-2.1-5.2-2.1c-2,0-3.8,0.8-5.2,2.1c-1.1,1.1-1.9,2.7-2.1,4.3
19 c0,0.5-0.5,1-1,1c-2.8,0.3-5,2.7-5,5.6c0,3,2.6,5.6,5.6,5.6h3.7c0.6,0,1.1,0.5,1.1,1.1s-0.5,1.1-1.1,1.1H8.9
20 c-4.4,0-7.9-3.5-7.9-7.9c0-3.7,2.7-7,6.3-7.7c0.4-1.9,1.2-3.6,2.6-4.9c1.8-1.8,4.2-2.8,6.8-2.8c2.7,0,5,1,6.6,2.8
21 c1.8,1.8,2.8,4.2,2.8,6.7c3.5,0.3,6.2,3.3,6.2,6.8C32.3,976.4,29.2,979.5,25.4,979.5z M20.6,978.1c-0.1,0-0.2,0.1-0.2,0.2
22 s0.1,0.2,0.2,0.2h4.8c3.3,0,6-2.7,6-6c0-3.2-2.6-5.8-5.7-5.9l-0.5,0l0-0.5c0.1-2.5-0.8-4.8-2.5-6.5c-1.5-1.6-3.6-2.5-5.9-2.5
23 c-2.4,0-4.5,0.9-6.1,2.5c-1.3,1.3-2.1,2.8-2.3,4.7l-0.1,0.3l-0.3,0.1c-3.4,0.5-5.9,3.5-5.9,6.9c0,3.8,3.1,7,7,7h3.7
24 c0.1,0,0.2-0.1,0.2-0.2s-0.1-0.2-0.2-0.2H8.9c-3.6,0-6.6-2.9-6.6-6.6c0-3.4,2.6-6.3,6-6.6c0.1,0,0.1-0.1,0.1-0.1
25 c0.2-1.9,1-3.6,2.3-4.9c1.6-1.6,3.6-2.4,5.9-2.4c2.2,0,4.3,0.9,5.9,2.4c1.8,1.8,2.6,4.3,2.3,6.9c0,0.1,0.1,0.2,0.2,0.2h0.4
26 c3.1,0,5.5,2.4,5.5,5.5c0,3.1-2.4,5.5-5.5,5.5H20.6z"/>
27 </g>
28 </g>
29 </svg>
+0
-14
faraday/server/www/images/icon_terminal.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#757575;}
6 </style>
7 <title>03</title>
8 <g>
9 <path class="st0" d="M88.9,6.3H11.1c-2.6,0-4.7,2.1-4.7,4.7l0,0v77.8c0,2.6,2.1,4.7,4.7,4.7h77.8c2.6,0,4.7-2.1,4.7-4.7V11.1
10 C93.7,8.5,91.5,6.3,88.9,6.3L88.9,6.3z M26.3,66.8l12.5-12.6L26.3,41.8L33,35l15.8,15.9c1.9,1.8,1.9,4.8,0.1,6.7c0,0,0,0-0.1,0.1
11 L32.9,73.5L26.3,66.8z M67.1,73.6H48.5v-9.5H67L67.1,73.6z"/>
12 </g>
13 </svg>
+0
-15
faraday/server/www/images/icon_viewless.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#4F4F4F;}
6 </style>
7 <g>
8 <path class="st0" d="M50.5,4C25.4,4,5,24.4,5,49.5S25.4,95,50.5,95S96,74.6,96,49.5S75.6,4,50.5,4z M50.5,91.1
9 c-23,0-41.6-18.7-41.6-41.6c0-23,18.7-41.6,41.6-41.6c23,0,41.6,18.7,41.6,41.6C92.1,72.5,73.5,91.1,50.5,91.1z"/>
10 <path class="st0" d="M74.7,27.1c-0.7-0.8-2-0.8-2.7-0.1L50.7,47.2L29.4,27c-0.8-0.7-2-0.7-2.7,0.1c-0.7,0.8-0.7,2,0.1,2.7l21.1,20
11 l-21.1,20c-0.8,0.7-0.8,2-0.1,2.7c0.4,0.4,0.9,0.6,1.4,0.6c0.5,0,1-0.2,1.3-0.5l21.3-20.2L72,72.7c0.4,0.4,0.9,0.5,1.3,0.5
12 c0.5,0,1-0.2,1.4-0.6c0.7-0.8,0.7-2-0.1-2.7l-21.1-20l21.1-20C75.4,29.1,75.5,27.8,74.7,27.1z"/>
13 </g>
14 </svg>
+0
-14
faraday/server/www/images/icon_viewmore.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#4F4F4F;}
6 </style>
7 <path class="st0" d="M93.7,26.4H32c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3h61.7c0.7,0,1.3,0.6,1.3,1.3
8 C95,25.9,94.4,26.4,93.7,26.4z M11.4,83C7.9,83,5,80.1,5,76.6c0-3.6,2.9-6.4,6.4-6.4c3.6,0,6.4,2.9,6.4,6.4C17.9,80.1,15,83,11.4,83
9 z M11.4,57.3c-3.5,0-6.4-2.9-6.4-6.4s2.9-6.4,6.4-6.4c3.6,0,6.4,2.9,6.4,6.4S15,57.3,11.4,57.3z M11.4,31.6c-3.5,0-6.4-2.9-6.4-6.4
10 c0-3.6,2.9-6.4,6.4-6.4c3.6,0,6.4,2.9,6.4,6.4C17.9,28.7,15,31.6,11.4,31.6z M32,49.6h47.6c0.7,0,1.3,0.6,1.3,1.3s-0.6,1.3-1.3,1.3
11 H32c-0.7,0-1.3-0.6-1.3-1.3S31.3,49.6,32,49.6z M32,75.3h33.4c0.7,0,1.3,0.6,1.3,1.3c0,0.7-0.6,1.3-1.3,1.3H32
12 c-0.7,0-1.3-0.6-1.3-1.3C30.7,75.9,31.3,75.3,32,75.3z"/>
13 </svg>
faraday/server/www/images/linux.png less more
Binary diff not shown
faraday/server/www/images/loader.gif less more
Binary diff not shown
+0
-10
faraday/server/www/images/logo-faraday-blanco.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 22 26" style="enable-background:new 0 0 22 26;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#FFFFFF;}
6 </style>
7 <polygon id="XMLID_328_" class="st0" points="20.3,7.4 21.4,0 6.8,0 6.4,3.7 3.4,3.7 0,26 6.4,26 6.8,22.9 10,22.9 10.9,16.9
8 17.8,16.9 18.9,10.1 12,10.2 12.4,7.5 "/>
9 </svg>
faraday/server/www/images/logo-faraday.png less more
Binary diff not shown
+0
-10
faraday/server/www/images/logo-faraday.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 170 170" style="enable-background:new 0 0 170 170;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#00a8e1;}
6 </style>
7 <polygon id="XMLID_328_" class="st0" points="144.3,50.2 151.5,3.1 59.2,3.4 56.4,26.5 37.9,26.5 16.1,167.9 56.8,167.8 59.2,147.9
8 79.4,147.8 85.2,110.1 129,110 135.6,67.2 91.8,67.4 94.4,50.4 "/>
9 </svg>
faraday/server/www/images/netdb.png less more
Binary diff not shown
+0
-1
faraday/server/www/images/ok-active.svg less more
0 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" width="16px" height="16px"><path fill="#bae0bd" d="M20,38.5C9.799,38.5,1.5,30.201,1.5,20S9.799,1.5,20,1.5S38.5,9.799,38.5,20S30.201,38.5,20,38.5z"/><path fill="#5e9c76" d="M20,2c9.925,0,18,8.075,18,18s-8.075,18-18,18S2,29.925,2,20S10.075,2,20,2 M20,1 C9.507,1,1,9.507,1,20s8.507,19,19,19s19-8.507,19-19S30.493,1,20,1L20,1z"/><path fill="none" stroke="#fff" stroke-miterlimit="10" stroke-width="2" d="M11 20L17 26 30 13"/></svg>
faraday/server/www/images/osx.png less more
Binary diff not shown
+0
-15
faraday/server/www/images/padlock_closed.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 39 46.9" style="enable-background:new 0 0 39 46.9;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#DEF1FE;}
6 .st1{fill:none;stroke:#1C87C3;stroke-width:1.6;stroke-linecap:round;stroke-miterlimit:10;}
7 .st2{fill:#1C87C3;}
8 </style>
9 <rect x="1.7" y="17.9" class="st0" width="36" height="28"/>
10 <path class="st1" d="M3.7,45.9c-1.1,0-2-0.9-2-2v-24c0-1.1,0.9-2,2-2h32c1.1,0,2,0.9,2,2v24c0,1.1-0.9,2-2,2H3.7z"/>
11 <path class="st1" d="M30.7,17.6c0,0,0-3.8,0-4.5c0-6.2-4.8-10.7-11-10.7c-6.1,0-10.9,4.4-10.9,10.7c0.1,0.7,0,3.3,0,4.8"/>
12 <path class="st2" d="M22.7,29.9c0-1.7-1.3-3-3-3s-3,1.3-3,3c0,0.9,0.4,1.7,1,2.2v2.8c0,1.1,0.9,2,2,2s2-0.9,2-2v-2.8
13 C22.3,31.6,22.7,30.8,22.7,29.9z"/>
14 </svg>
+0
-15
faraday/server/www/images/padlock_open.svg less more
0 <?xml version="1.0" encoding="utf-8"?>
1 <!-- Generator: Adobe Illustrator 24.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
2 <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3 viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
4 <style type="text/css">
5 .st0{fill:#DEF1FE;}
6 .st1{fill:none;stroke:#1C87C3;stroke-width:1.6;stroke-linecap:round;stroke-miterlimit:10;}
7 .st2{fill:#1C87C3;}
8 </style>
9 <rect x="7" y="21" class="st0" width="36" height="28"/>
10 <path class="st1" d="M9,49c-1.1,0-2-0.9-2-2V23c0-1.1,0.9-2,2-2h32c1.1,0,2,0.9,2,2v24c0,1.1-0.9,2-2,2H9z M34.6,13.1
11 c0,0-1.1-3.6-1.3-4.3c-1.8-5.8-8-9.1-13.8-7.3s-9.1,8-7.3,13.8C12.6,16.4,14,21,14,21"/>
12 <path class="st2" d="M28,33c0-1.7-1.3-3-3-3s-3,1.3-3,3c0,0.9,0.4,1.7,1,2.2V38c0,1.1,0.9,2,2,2s2-0.9,2-2v-2.8
13 C27.6,34.7,28,33.9,28,33z"/>
14 </svg>
faraday/server/www/images/router.png less more
Binary diff not shown
faraday/server/www/images/shodan.png less more
Binary diff not shown
faraday/server/www/images/windows.png less more
Binary diff not shown
faraday/server/www/images/zoom.png less more
Binary diff not shown
+0
-222
faraday/server/www/index.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3 <!DOCTYPE html>
4 <!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
5 <!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
6 <!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
7 <!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
8 <!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js" ng-app="faradayApp"> <!--<![endif]-->
9 <head>
10 <meta charset="utf-8"/>
11 <!--[if IE]><![endif]-->
12 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
13 <title ng-bind="title + 'Faraday'"></title>
14 <meta name="description" content=""/>
15 <meta name="keywords" content=""/>
16 <meta name="author" content=""/>
17
18 <link rel="apple-touch-icon" sizes="57x57" href="apple-icon-57x57.png">
19 <link rel="apple-touch-icon" sizes="60x60" href="apple-icon-60x60.png">
20 <link rel="apple-touch-icon" sizes="72x72" href="apple-icon-72x72.png">
21 <link rel="apple-touch-icon" sizes="76x76" href="apple-icon-76x76.png">
22 <link rel="apple-touch-icon" sizes="114x114" href="apple-icon-114x114.png">
23 <link rel="apple-touch-icon" sizes="120x120" href="apple-icon-120x120.png">
24 <link rel="apple-touch-icon" sizes="144x144" href="apple-icon-144x144.png">
25 <link rel="apple-touch-icon" sizes="152x152" href="apple-icon-152x152.png">
26 <link rel="apple-touch-icon" sizes="180x180" href="apple-icon-180x180.png">
27 <link rel="icon" type="image/png" sizes="192x192" href="android-icon-192x192.png">
28 <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
29 <link rel="icon" type="image/png" sizes="96x96" href="favicon-96x96.png">
30 <link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
31 <link rel="manifest" href="manifest.json">
32 <meta name="msapplication-TileColor" content="#ffffff">
33 <meta name="msapplication-TileImage" content="/ms-icon-144x144.png">
34 <meta name="theme-color" content="#ffffff">
35
36 <!-- CSS -->
37 <link rel="stylesheet" type="text/css" href="script/anguilar-ui-notification.min.css" />
38 <link rel="stylesheet" type="text/css" href="script/font.opensans.css" />
39 <link rel="stylesheet" type="text/css" href="normalize.css" />
40 <link rel="stylesheet" type="text/css" href="estilos.css" />
41 <link rel="stylesheet" type="text/css" href="styles/material-input.css" />
42 <link rel="stylesheet" type="text/css" href="script/animate.css" />
43 <link rel="stylesheet" href="script/bootstrap.min.css">
44 <link rel="stylesheet" type="text/css" href="styles/font-awesome.css" />
45 <link rel="stylesheet" type="text/css" href="styles/angular-hotkeys.css" />
46 <link rel="stylesheet" type="text/css" href="script/angular-chart.css" />
47 <link rel="stylesheet" type="text/css" href="script/ui-grid.css" />
48 <!-- Custom css will have priority -->
49 <link rel="stylesheet" type="text/css" href="estilos-v3.css" />
50 <link rel="stylesheet" type="text/css" href="dashboard-v3.css" />
51 <link rel="stylesheet" type="text/css" href="header.css" />
52 <link rel="stylesheet" type="text/css" href="scripts/statusReport/styles/status.css" />
53 <link rel="stylesheet" type="text/css" href="table-v3.css" />
54
55 <!--table resize-->
56 <link rel="stylesheet" type="text/css" href="script/angular-table-resize.css" />
57
58 <!-- Icons -->
59 <link href="favicon.ico" rel="shortcut icon">
60 <link href="favicon.ico" type="image/vnd.microsoft.icon" rel="icon" />
61 <link href="images/site_preview.jpg" rel="image_src" />
62
63 <!-- Scripts -->
64 <script type="text/javascript" src="script/mousetrap.min.js"></script>
65 <script type="text/javascript" src="script/jquery-1.9.1.min.js"></script>
66 <script type="text/javascript" src="script/bootstrap.min.js"></script>
67 <script type="text/javascript" src="script/angular.min.js"></script>
68 <script type="text/javascript" src="script/angular-cookies.min.js"></script>
69 <script type="text/javascript" src="script/angular-hotkeys.js"></script>
70 <script type="text/javascript" src="script/angular-route.min.js"></script>
71 <script type="text/javascript" src="script/angular-selection-model.min.js"></script>
72 <script type="text/javascript" src="script/angular-file-upload-shim.min.js"></script><!-- compatibility with older browsers -->
73 <script type="text/javascript" src="script/angular-file-upload.min.js"></script>
74 <script type="text/javascript" src="script/angular-file-upload-lib.min.js"></script>
75 <script type="text/javascript" src="script/ui-bootstrap-tpls-0.14.1.min.js"></script>
76 <script type="text/javascript" src="script/cryptojs-sha1.js"></script>
77 <script type="text/javascript" src="script/sanitize.js"></script>
78 <script type="text/javascript" src="script/showdown.min.js"></script>
79 <script type="text/javascript" src="script/showdown-table.min.js"></script>
80 <script type="text/javascript" src="script/angular-ui-notification.min.js"></script>
81 <script type="text/javascript" src="script/angular-ui.min.js"></script>
82 <script type="text/javascript" src="script/angular-clipboard.min.js"></script>
83 <!-- angular chart -->
84 <script type="text/javascript" src="script/Chart.min.js"></script>
85 <script type="text/javascript" src="script/angular-chart.min.js"></script>
86 <!-- ui-grid -->
87 <script type="text/javascript" src="script/ui-grid.min.js"></script>
88 <!-- angular moment -->
89 <script type="text/javascript" src="script/moment.min.js"></script>
90 <script type="text/javascript" src="script/angular-moment.min.js"></script>
91 <script type="text/javascript" src="script/papaparse.min.js"></script>
92 <script type="text/javascript" src="script/oui.web.min.js"></script>
93 <script type="text/javascript" src="script/angular-drag-and-drop-lists.min.js"></script>
94
95 <!--table resizable-->
96 <script type="text/javascript" src="script/angular-table-resize.min.js"></script>
97 </head>
98
99 <body ng-controller="loginBackgroundCtrl" ng-class="{'login': isLogin}">
100 <div id="cont">
101 <div class="wrapper" ng-controller="indexCtrl">
102 <div ng-view></div>
103 </div><!--!/#wrapper -->
104 </div><!--!/#container -->
105
106 <script type="text/javascript" src="scripts/app.js"></script>
107 <script type="text/javascript" src="scripts/attachments/providers/attachments.js"></script>
108 <script type="text/javascript" src="scripts/commons/directives/contenteditable.js"></script>
109 <script type="text/javascript" src="scripts/commons/directives/osintLink.js"></script>
110 <script type="text/javascript" src="scripts/commons/directives/file.js"></script>
111 <script type="text/javascript" src="scripts/commons/directives/fileModel.js"></script>
112 <script type="text/javascript" src="scripts/commons/directives/angular-simple-pagination.js"></script>
113 <script type="text/javascript" src="scripts/commons/controllers/modal.js"></script>
114 <script type="text/javascript" src="scripts/commons/controllers/headerCtrl.js"></script>
115 <script type="text/javascript" src="scripts/commons/controllers/commercialCtrl.js"></script>
116 <script type="text/javascript" src="scripts/commons/controllers/homeCtrl.js"></script>
117 <script type="text/javascript" src="scripts/commons/providers/commons.js"></script>
118 <script type="text/javascript" src="scripts/commons/providers/server.js"></script>
119 <script type="text/javascript" src="scripts/commons/filters/decodeURIComponent.js"></script>
120 <script type="text/javascript" src="scripts/commons/filters/encodeURIComponent.js"></script>
121 <script type="text/javascript" src="scripts/commons/filters/getByProperty.js"></script>
122 <script type="text/javascript" src="scripts/commons/filters/orderObjectBy.js"></script>
123 <script type="text/javascript" src="scripts/commons/filters/startFrom.js"></script>
124 <script type="text/javascript" src="scripts/commons/filters/markdown.js"></script>
125 <script type="text/javascript" src="scripts/commons/filters/integer.js"></script>
126 <script type="text/javascript" src="scripts/commons/filters/removeLinebreaks.js"></script>
127 <script type="text/javascript" src="scripts/config/services/config.js"></script>
128 <script type="text/javascript" src="scripts/csv/providers/csv.js"></script>
129 <script type="text/javascript" src="scripts/fileExporter/directives/download.js"></script>
130 <script type="text/javascript" src="scripts/fileExporter/providers/blob.js"></script>
131 <script type="text/javascript" src="scripts/fileExporter/providers/click.js"></script>
132 <script type="text/javascript" src="scripts/hosts/controllers/host.js"></script>
133 <script type="text/javascript" src="scripts/hosts/controllers/new.js"></script>
134 <script type="text/javascript" src="scripts/hosts/controllers/hosts.js"></script>
135 <script type="text/javascript" src="scripts/hosts/controllers/hostsModalEdit.js"></script>
136 <script type="text/javascript" src="scripts/hosts/controllers/hostsModalNew.js"></script>
137 <script type="text/javascript" src="scripts/hosts/controllers/upload.js"></script>
138 <script type="text/javascript" src="scripts/hosts/providers/host.js"></script>
139 <script type="text/javascript" src="scripts/hosts/providers/hosts.js"></script>
140 <script type="text/javascript" src="scripts/index/controllers/indexCtrl.js"></script>
141 <script type="text/javascript" src="scripts/index/providers/index.js"></script>
142 <script type="text/javascript" src="scripts/licenses/controllers/licenses.js"></script>
143 <script type="text/javascript" src="scripts/licenses/controllers/modalEdit.js"></script>
144 <script type="text/javascript" src="scripts/licenses/controllers/modalNew.js"></script>
145 <script type="text/javascript" src="scripts/licenses/providers/license.js"></script>
146 <script type="text/javascript" src="scripts/licenses/providers/licenses.js"></script>
147 <script type="text/javascript" src="scripts/navigation/controllers/navigationCtrl.js"></script>
148 <script type="text/javascript" src="scripts/notes/providers/notes.js"></script>
149 <script type="text/javascript" src="scripts/services/controllers/serviceModalNew.js"></script>
150 <script type="text/javascript" src="scripts/services/controllers/serviceModalEdit.js"></script>
151 <script type="text/javascript" src="scripts/services/providers/services.js"></script>
152 <script type="text/javascript" src="scripts/services/providers/service.js"></script>
153 <script type="text/javascript" src="scripts/statusReport/controllers/statusReport.js"></script>
154 <script type="text/javascript" src="scripts/statusReport/controllers/modalEdit.js"></script>
155 <script type="text/javascript" src="scripts/statusReport/controllers/modalNew.js"></script>
156 <script type="text/javascript" src="scripts/statusReport/directives/textCollapse.js"></script>
157 <script type="text/javascript" src="scripts/statusReport/directives/appendSearchParam.js"></script>
158 <script type="text/javascript" src="scripts/statusReport/directives/autofocus.js"></script>
159 <script type="text/javascript" src="scripts/statusReport/directives/customField.js"></script>
160 <script type="text/javascript" src="scripts/statusReport/directives/customFieldPrev.js"></script>
161 <script type="text/javascript" src="scripts/statusReport/directives/checkCustomType.js"></script>
162 <script type="text/javascript" src="scripts/statusReport/providers/target.js"></script>
163 <script type="text/javascript" src="scripts/statusReport/providers/reference.js"></script>
164 <script type="text/javascript" src="scripts/statusReport/providers/logical.js"></script>
165 <script type="text/javascript" src="scripts/statusReport/providers/parser.js"></script>
166 <script type="text/javascript" src="scripts/statusReport/providers/ui-common.js"></script>
167 <script type="text/javascript" src="scripts/vulns/providers/vuln.js"></script>
168 <script type="text/javascript" src="scripts/vulns/providers/vulns.js"></script>
169 <script type="text/javascript" src="scripts/vulns/providers/web.js"></script>
170 <script type="text/javascript" src="scripts/workspaces/controllers/workspaces.js"></script>
171 <script type="text/javascript" src="scripts/workspaces/controllers/workspacesModalEdit.js"></script>
172 <script type="text/javascript" src="scripts/workspaces/controllers/workspacesModalNew.js"></script>
173 <script type="text/javascript" src="scripts/workspaces/providers/workspaces.js"></script>
174 <script type="text/javascript" src="scripts/auth/controllers/login.js"></script>
175 <script type="text/javascript" src="scripts/auth/controllers/resetPassword.js"></script>
176 <script type="text/javascript" src="scripts/auth/controllers/forgotPassword.js"></script>
177 <script type="text/javascript" src="scripts/auth/directives/compareTo.js"></script>
178 <script type="text/javascript" src="scripts/auth/services/account.js"></script>
179 <script type="text/javascript" src="scripts/auth/services/login.js"></script>
180 <script type="text/javascript" src="scripts/auth/services/interceptor.js"></script>
181 <script type="text/javascript" src="scripts/dashboard/controllers/commandsCtrl.js"></script>
182 <script type="text/javascript" src="scripts/dashboard/controllers/compoundCtrl.js"></script>
183 <script type="text/javascript" src="scripts/dashboard/controllers/dashboard.js"></script>
184 <script type="text/javascript" src="scripts/dashboard/controllers/lastVulnsCtrl.js"></script>
185 <script type="text/javascript" src="scripts/dashboard/controllers/topHostsCtrl.js"></script>
186 <script type="text/javascript" src="scripts/dashboard/controllers/topServicesCtrl.js"></script>
187 <script type="text/javascript" src="scripts/dashboard/controllers/treemapModalCtrl.js"></script>
188 <script type="text/javascript" src="scripts/dashboard/controllers/servicesCtrl.js"></script>
189 <script type="text/javascript" src="scripts/dashboard/controllers/summarizedCtrl.js"></script>
190 <script type="text/javascript" src="scripts/dashboard/controllers/summarizedCtrlServicesModal.js"></script>
191 <script type="text/javascript" src="scripts/dashboard/controllers/summarizedCtrlHostsModal.js"></script>
192 <script type="text/javascript" src="scripts/dashboard/controllers/vulnsByPriceCtrl.js"></script>
193 <script type="text/javascript" src="scripts/dashboard/controllers/vulnsBySeverityCtrl.js"></script>
194 <script type="text/javascript" src="scripts/dashboard/controllers/vulnsPiechartCtrl.js"></script>
195 <script type="text/javascript" src="scripts/dashboard/controllers/vulnsByStatusCtrl.js"></script>
196 <script type="text/javascript" src="scripts/dashboard/controllers/workspaceProgressCtrl.js"></script>
197 <script type="text/javascript" src="scripts/dashboard/controllers/activityFeedCtrl.js"></script>
198 <script type="text/javascript" src="scripts/dashboard/providers/dashboard.js"></script>
199 <script type="text/javascript" src="scripts/d3/providers/d3.js"></script>
200 <script type="text/javascript" src="scripts/d3/directives/treemap.js"></script>
201 <script type="text/javascript" src="scripts/d3/directives/bar.js"></script>
202 <script type="text/javascript" src="scripts/d3/directives/cake.js"></script>
203 <script type="text/javascript" src="scripts/d3/directives/stackedbar.js"></script>
204 <script type="text/javascript" src="scripts/credentials/providers/credential.js"></script>
205 <script type="text/javascript" src="scripts/credentials/providers/targetCred.js"></script>
206 <script type="text/javascript" src="scripts/credentials/controllers/credentials.js"></script>
207 <script type="text/javascript" src="scripts/credentials/controllers/modalNewEditCredentialCtrl.js"></script>
208 <script type="text/javascript" src="scripts/vulndb/controllers/vulnModels.js"></script>
209 <script type="text/javascript" src="scripts/vulndb/controllers/modalUpload.js"></script>
210 <script type="text/javascript" src="scripts/vulndb/controllers/modalEdit.js"></script>
211 <script type="text/javascript" src="scripts/vulndb/controllers/modalNew.js"></script>
212 <script type="text/javascript" src="scripts/vulndb/providers/vulnModel.js"></script>
213 <script type="text/javascript" src="scripts/vulndb/providers/vulnModels.js"></script>
214 <script type="text/javascript" src="scripts/vulndb/directives/customField.js"></script>
215 <script type="text/javascript" src="scripts/admin/admin.js"></script>
216 <script type="text/javascript" src="scripts/admin/customFields/controllers/customFields.js"></script>
217 <script type="text/javascript" src="scripts/admin/customFields/providers/customFields.js"></script>
218 <script type="text/javascript" src="scripts/admin/agents/controllers/agents.js"></script>
219 <script type="text/javascript" src="scripts/admin/agents/providers/agents.js"></script>
220 </body>
221 </html>
+0
-41
faraday/server/www/manifest.json less more
0 {
1 "name": "App",
2 "icons": [
3 {
4 "src": "\/android-icon-36x36.png",
5 "sizes": "36x36",
6 "type": "image\/png",
7 "density": "0.75"
8 },
9 {
10 "src": "\/android-icon-48x48.png",
11 "sizes": "48x48",
12 "type": "image\/png",
13 "density": "1.0"
14 },
15 {
16 "src": "\/android-icon-72x72.png",
17 "sizes": "72x72",
18 "type": "image\/png",
19 "density": "1.5"
20 },
21 {
22 "src": "\/android-icon-96x96.png",
23 "sizes": "96x96",
24 "type": "image\/png",
25 "density": "2.0"
26 },
27 {
28 "src": "\/android-icon-144x144.png",
29 "sizes": "144x144",
30 "type": "image\/png",
31 "density": "3.0"
32 },
33 {
34 "src": "\/android-icon-192x192.png",
35 "sizes": "192x192",
36 "type": "image\/png",
37 "density": "4.0"
38 }
39 ]
40 }
faraday/server/www/ms-icon-144x144.png less more
Binary diff not shown
faraday/server/www/ms-icon-150x150.png less more
Binary diff not shown
faraday/server/www/ms-icon-310x310.png less more
Binary diff not shown
faraday/server/www/ms-icon-70x70.png less more
Binary diff not shown
+0
-427
faraday/server/www/normalize.css less more
0 /*! normalize.css v3.0.2 | MIT License | git.io/normalize */
1
2 /**
3 * 1. Set default font family to sans-serif.
4 * 2. Prevent iOS text size adjust after orientation change, without disabling
5 * user zoom.
6 */
7
8 html {
9 font-family: sans-serif; /* 1 */
10 -ms-text-size-adjust: 100%; /* 2 */
11 -webkit-text-size-adjust: 100%; /* 2 */
12 }
13
14 /**
15 * Remove default margin.
16 */
17
18 body {
19 margin: 0;
20 }
21
22 /* HTML5 display definitions
23 ========================================================================== */
24
25 /**
26 * Correct `block` display not defined for any HTML5 element in IE 8/9.
27 * Correct `block` display not defined for `details` or `summary` in IE 10/11
28 * and Firefox.
29 * Correct `block` display not defined for `main` in IE 11.
30 */
31
32 article,
33 aside,
34 details,
35 figcaption,
36 figure,
37 footer,
38 header,
39 hgroup,
40 main,
41 menu,
42 nav,
43 section,
44 summary {
45 display: block;
46 }
47
48 /**
49 * 1. Correct `inline-block` display not defined in IE 8/9.
50 * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
51 */
52
53 audio,
54 canvas,
55 progress,
56 video {
57 display: inline-block; /* 1 */
58 vertical-align: baseline; /* 2 */
59 }
60
61 /**
62 * Prevent modern browsers from displaying `audio` without controls.
63 * Remove excess height in iOS 5 devices.
64 */
65
66 audio:not([controls]) {
67 display: none;
68 height: 0;
69 }
70
71 /**
72 * Address `[hidden]` styling not present in IE 8/9/10.
73 * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
74 */
75
76 [hidden],
77 template {
78 display: none;
79 }
80
81 /* Links
82 ========================================================================== */
83
84 /**
85 * Remove the gray background color from active links in IE 10.
86 */
87
88 a {
89 background-color: transparent;
90 }
91
92 /**
93 * Improve readability when focused and also mouse hovered in all browsers.
94 */
95
96 a:active,
97 a:hover {
98 outline: 0;
99 }
100
101 /* Text-level semantics
102 ========================================================================== */
103
104 /**
105 * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
106 */
107
108 abbr[title] {
109 border-bottom: 1px dotted;
110 }
111
112 /**
113 * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
114 */
115
116 b,
117 strong {
118 font-weight: bold;
119 }
120
121 /**
122 * Address styling not present in Safari and Chrome.
123 */
124
125 dfn {
126 font-style: italic;
127 }
128
129 /**
130 * Address variable `h1` font-size and margin within `section` and `article`
131 * contexts in Firefox 4+, Safari, and Chrome.
132 */
133
134 h1 {
135 font-size: 2em;
136 margin: 0.67em 0;
137 }
138
139 /**
140 * Address styling not present in IE 8/9.
141 */
142
143 mark {
144 background: #ff0;
145 color: #000;
146 }
147
148 /**
149 * Address inconsistent and variable font size in all browsers.
150 */
151
152 small {
153 font-size: 80%;
154 }
155
156 /**
157 * Prevent `sub` and `sup` affecting `line-height` in all browsers.
158 */
159
160 sub,
161 sup {
162 font-size: 75%;
163 line-height: 0;
164 position: relative;
165 vertical-align: baseline;
166 }
167
168 sup {
169 top: -0.5em;
170 }
171
172 sub {
173 bottom: -0.25em;
174 }
175
176 /* Embedded content
177 ========================================================================== */
178
179 /**
180 * Remove border when inside `a` element in IE 8/9/10.
181 */
182
183 img {
184 border: 0;
185 }
186
187 /**
188 * Correct overflow not hidden in IE 9/10/11.
189 */
190
191 svg:not(:root) {
192 overflow: hidden;
193 }
194
195 /* Grouping content
196 ========================================================================== */
197
198 /**
199 * Address margin not present in IE 8/9 and Safari.
200 */
201
202 figure {
203 margin: 1em 40px;
204 }
205
206 /**
207 * Address differences between Firefox and other browsers.
208 */
209
210 hr {
211 -moz-box-sizing: content-box;
212 box-sizing: content-box;
213 height: 0;
214 }
215
216 /**
217 * Contain overflow in all browsers.
218 */
219
220 pre {
221 overflow: auto;
222 }
223
224 /**
225 * Address odd `em`-unit font size rendering in all browsers.
226 */
227
228 code,
229 kbd,
230 pre,
231 samp {
232 font-family: monospace, monospace;
233 font-size: 1em;
234 }
235
236 /* Forms
237 ========================================================================== */
238
239 /**
240 * Known limitation: by default, Chrome and Safari on OS X allow very limited
241 * styling of `select`, unless a `border` property is set.
242 */
243
244 /**
245 * 1. Correct color not being inherited.
246 * Known issue: affects color of disabled elements.
247 * 2. Correct font properties not being inherited.
248 * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
249 */
250
251 button,
252 input,
253 optgroup,
254 select,
255 textarea {
256 color: inherit; /* 1 */
257 font: inherit; /* 2 */
258 margin: 0; /* 3 */
259 }
260
261 /**
262 * Address `overflow` set to `hidden` in IE 8/9/10/11.
263 */
264
265 button {
266 overflow: visible;
267 }
268
269 /**
270 * Address inconsistent `text-transform` inheritance for `button` and `select`.
271 * All other form control elements do not inherit `text-transform` values.
272 * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
273 * Correct `select` style inheritance in Firefox.
274 */
275
276 button,
277 select {
278 text-transform: none;
279 }
280
281 /**
282 * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
283 * and `video` controls.
284 * 2. Correct inability to style clickable `input` types in iOS.
285 * 3. Improve usability and consistency of cursor style between image-type
286 * `input` and others.
287 */
288
289 button,
290 html input[type="button"], /* 1 */
291 input[type="reset"],
292 input[type="submit"] {
293 -webkit-appearance: button; /* 2 */
294 cursor: pointer; /* 3 */
295 }
296
297 /**
298 * Re-set default cursor for disabled elements.
299 */
300
301 button[disabled],
302 html input[disabled] {
303 cursor: default;
304 }
305
306 /**
307 * Remove inner padding and border in Firefox 4+.
308 */
309
310 button::-moz-focus-inner,
311 input::-moz-focus-inner {
312 border: 0;
313 padding: 0;
314 }
315
316 /**
317 * Address Firefox 4+ setting `line-height` on `input` using `!important` in
318 * the UA stylesheet.
319 */
320
321 input {
322 line-height: normal;
323 }
324
325 /**
326 * It's recommended that you don't attempt to style these elements.
327 * Firefox's implementation doesn't respect box-sizing, padding, or width.
328 *
329 * 1. Address box sizing set to `content-box` in IE 8/9/10.
330 * 2. Remove excess padding in IE 8/9/10.
331 */
332
333 input[type="checkbox"],
334 input[type="radio"] {
335 box-sizing: border-box; /* 1 */
336 padding: 0; /* 2 */
337 }
338
339 /**
340 * Fix the cursor style for Chrome's increment/decrement buttons. For certain
341 * `font-size` values of the `input`, it causes the cursor style of the
342 * decrement button to change from `default` to `text`.
343 */
344
345 input[type="number"]::-webkit-inner-spin-button,
346 input[type="number"]::-webkit-outer-spin-button {
347 height: auto;
348 }
349
350 /**
351 * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
352 * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
353 * (include `-moz` to future-proof).
354 */
355
356 input[type="search"] {
357 -webkit-appearance: textfield; /* 1 */
358 -moz-box-sizing: content-box;
359 -webkit-box-sizing: content-box; /* 2 */
360 box-sizing: content-box;
361 }
362
363 /**
364 * Remove inner padding and search cancel button in Safari and Chrome on OS X.
365 * Safari (but not Chrome) clips the cancel button when the search input has
366 * padding (and `textfield` appearance).
367 */
368
369 input[type="search"]::-webkit-search-cancel-button,
370 input[type="search"]::-webkit-search-decoration {
371 -webkit-appearance: none;
372 }
373
374 /**
375 * Define consistent border, margin, and padding.
376 */
377
378 fieldset {
379 border: 1px solid #c0c0c0;
380 margin: 0 2px;
381 padding: 0.35em 0.625em 0.75em;
382 }
383
384 /**
385 * 1. Correct `color` not being inherited in IE 8/9/10/11.
386 * 2. Remove padding so people aren't caught out if they zero out fieldsets.
387 */
388
389 legend {
390 border: 0; /* 1 */
391 padding: 0; /* 2 */
392 }
393
394 /**
395 * Remove default vertical scrollbar in IE 8/9/10/11.
396 */
397
398 textarea {
399 overflow: auto;
400 }
401
402 /**
403 * Don't inherit the `font-weight` (applied by a rule above).
404 * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
405 */
406
407 optgroup {
408 font-weight: bold;
409 }
410
411 /* Tables
412 ========================================================================== */
413
414 /**
415 * Remove most spacing between table cells.
416 */
417
418 table {
419 border-collapse: collapse;
420 border-spacing: 0;
421 }
422
423 td,
424 th {
425 padding: 0;
426 }
+0
-3331
faraday/server/www/script/Chart.js less more
0 /*!
1 * Chart.js
2 * http://chartjs.org/
3 * Version: 1.0.1-beta.3
4 *
5 * Copyright 2014 Nick Downie
6 * Released under the MIT license
7 * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
8 */
9
10
11 (function(){
12
13 "use strict";
14
15 //Declare root variable - window in the browser, global on the server
16 var root = this,
17 previous = root.Chart;
18
19 //Occupy the global variable of Chart, and create a simple base class
20 var Chart = function(context){
21 var chart = this;
22 this.canvas = context.canvas;
23
24 this.ctx = context;
25
26 //Variables global to the chart
27 var width = this.width = context.canvas.width;
28 var height = this.height = context.canvas.height;
29 this.aspectRatio = this.width / this.height;
30 //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
31 helpers.retinaScale(this);
32
33 return this;
34 };
35 //Globally expose the defaults to allow for user updating/changing
36 Chart.defaults = {
37 global: {
38 // Boolean - Whether to animate the chart
39 animation: true,
40
41 // Number - Number of animation steps
42 animationSteps: 60,
43
44 // String - Animation easing effect
45 animationEasing: "easeOutQuart",
46
47 // Boolean - If we should show the scale at all
48 showScale: true,
49
50 // Boolean - If we want to override with a hard coded scale
51 scaleOverride: false,
52
53 // ** Required if scaleOverride is true **
54 // Number - The number of steps in a hard coded scale
55 scaleSteps: null,
56 // Number - The value jump in the hard coded scale
57 scaleStepWidth: null,
58 // Number - The scale starting value
59 scaleStartValue: null,
60
61 // String - Colour of the scale line
62 scaleLineColor: "rgba(0,0,0,.1)",
63
64 // Number - Pixel width of the scale line
65 scaleLineWidth: 1,
66
67 // Boolean - Whether to show labels on the scale
68 scaleShowLabels: true,
69
70 // Boolean or a positive integer denoting number of labels to be shown on x axis
71 showXLabels: true,
72
73 // Interpolated JS string - can access value
74 scaleLabel: "<%=value%>",
75
76 // Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there
77 scaleIntegersOnly: true,
78
79 // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
80 scaleBeginAtZero: false,
81
82 // String - Scale label font declaration for the scale label
83 scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
84
85 // Number - Scale label font size in pixels
86 scaleFontSize: 12,
87
88 // String - Scale label font weight style
89 scaleFontStyle: "normal",
90
91 // String - Scale label font colour
92 scaleFontColor: "#666",
93
94 // Boolean - whether or not the chart should be responsive and resize when the browser does.
95 responsive: false,
96
97 // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
98 maintainAspectRatio: true,
99
100 // Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
101 showTooltips: true,
102
103 // Array - Array of string names to attach tooltip events
104 tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
105
106 // String - Tooltip background colour
107 tooltipFillColor: "rgba(0,0,0,0.8)",
108
109 // String - Tooltip label font declaration for the scale label
110 tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
111
112 // Number - Tooltip label font size in pixels
113 tooltipFontSize: 14,
114
115 // String - Tooltip font weight style
116 tooltipFontStyle: "normal",
117
118 // String - Tooltip label font colour
119 tooltipFontColor: "#fff",
120
121 // String - Tooltip title font declaration for the scale label
122 tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
123
124 // Number - Tooltip title font size in pixels
125 tooltipTitleFontSize: 14,
126
127 // String - Tooltip title font weight style
128 tooltipTitleFontStyle: "bold",
129
130 // String - Tooltip title font colour
131 tooltipTitleFontColor: "#fff",
132
133 // Number - pixel width of padding around tooltip text
134 tooltipYPadding: 6,
135
136 // Number - pixel width of padding around tooltip text
137 tooltipXPadding: 6,
138
139 // Number - Size of the caret on the tooltip
140 tooltipCaretSize: 8,
141
142 // Number - Pixel radius of the tooltip border
143 tooltipCornerRadius: 6,
144
145 // Number - Pixel offset from point x to tooltip edge
146 tooltipXOffset: 10,
147
148 // String - Template string for single tooltips
149 tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
150
151 // String - Template string for single tooltips
152 multiTooltipTemplate: "<%= value %>",
153
154 // String - Colour behind the legend colour block
155 multiTooltipKeyBackground: '#fff',
156
157 // Function - Will fire on animation progression.
158 onAnimationProgress: function(){},
159
160 // Function - Will fire on animation completion.
161 onAnimationComplete: function(){}
162
163 }
164 };
165
166 //Create a dictionary of chart types, to allow for extension of existing types
167 Chart.types = {};
168
169 //Global Chart helpers object for utility methods and classes
170 var helpers = Chart.helpers = {};
171
172 //-- Basic js utility methods
173 var each = helpers.each = function(loopable,callback,self){
174 var additionalArgs = Array.prototype.slice.call(arguments, 3);
175 // Check to see if null or undefined firstly.
176 if (loopable){
177 if (loopable.length === +loopable.length){
178 var i;
179 for (i=0; i<loopable.length; i++){
180 callback.apply(self,[loopable[i], i].concat(additionalArgs));
181 }
182 }
183 else{
184 for (var item in loopable){
185 callback.apply(self,[loopable[item],item].concat(additionalArgs));
186 }
187 }
188 }
189 },
190 clone = helpers.clone = function(obj){
191 var objClone = {};
192 each(obj,function(value,key){
193 if (obj.hasOwnProperty(key)) objClone[key] = value;
194 });
195 return objClone;
196 },
197 extend = helpers.extend = function(base){
198 each(Array.prototype.slice.call(arguments,1), function(extensionObject) {
199 each(extensionObject,function(value,key){
200 if (extensionObject.hasOwnProperty(key)) base[key] = value;
201 });
202 });
203 return base;
204 },
205 merge = helpers.merge = function(base,master){
206 //Merge properties in left object over to a shallow clone of object right.
207 var args = Array.prototype.slice.call(arguments,0);
208 args.unshift({});
209 return extend.apply(null, args);
210 },
211 indexOf = helpers.indexOf = function(arrayToSearch, item){
212 if (Array.prototype.indexOf) {
213 return arrayToSearch.indexOf(item);
214 }
215 else{
216 for (var i = 0; i < arrayToSearch.length; i++) {
217 if (arrayToSearch[i] === item) return i;
218 }
219 return -1;
220 }
221 },
222 inherits = helpers.inherits = function(extensions){
223 //Basic javascript inheritance based on the model created in Backbone.js
224 var parent = this;
225 var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function(){ return parent.apply(this, arguments); };
226
227 var Surrogate = function(){ this.constructor = ChartElement;};
228 Surrogate.prototype = parent.prototype;
229 ChartElement.prototype = new Surrogate();
230
231 ChartElement.extend = inherits;
232
233 if (extensions) extend(ChartElement.prototype, extensions);
234
235 ChartElement.__super__ = parent.prototype;
236
237 return ChartElement;
238 },
239 noop = helpers.noop = function(){},
240 uid = helpers.uid = (function(){
241 var id=0;
242 return function(){
243 return "chart-" + id++;
244 };
245 })(),
246 warn = helpers.warn = function(str){
247 //Method for warning of errors
248 if (window.console && typeof window.console.warn == "function") console.warn(str);
249 },
250 amd = helpers.amd = (typeof root.define == 'function' && root.define.amd),
251 //-- Math methods
252 isNumber = helpers.isNumber = function(n){
253 return !isNaN(parseFloat(n)) && isFinite(n);
254 },
255 max = helpers.max = function(array){
256 return Math.max.apply( Math, array );
257 },
258 min = helpers.min = function(array){
259 return Math.min.apply( Math, array );
260 },
261 cap = helpers.cap = function(valueToCap,maxValue,minValue){
262 if(isNumber(maxValue)) {
263 if( valueToCap > maxValue ) {
264 return maxValue;
265 }
266 }
267 else if(isNumber(minValue)){
268 if ( valueToCap < minValue ){
269 return minValue;
270 }
271 }
272 return valueToCap;
273 },
274 getDecimalPlaces = helpers.getDecimalPlaces = function(num){
275 if (num%1!==0 && isNumber(num)){
276 return num.toString().split(".")[1].length;
277 }
278 else {
279 return 0;
280 }
281 },
282 toRadians = helpers.radians = function(degrees){
283 return degrees * (Math.PI/180);
284 },
285 // Gets the angle from vertical upright to the point about a centre.
286 getAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){
287 var distanceFromXCenter = anglePoint.x - centrePoint.x,
288 distanceFromYCenter = anglePoint.y - centrePoint.y,
289 radialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
290
291
292 var angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter);
293
294 //If the segment is in the top left quadrant, we need to add another rotation to the angle
295 if (distanceFromXCenter < 0 && distanceFromYCenter < 0){
296 angle += Math.PI*2;
297 }
298
299 return {
300 angle: angle,
301 distance: radialDistanceFromCenter
302 };
303 },
304 aliasPixel = helpers.aliasPixel = function(pixelWidth){
305 return (pixelWidth % 2 === 0) ? 0 : 0.5;
306 },
307 splineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){
308 //Props to Rob Spencer at scaled innovation for his post on splining between points
309 //http://scaledinnovation.com/analytics/splines/aboutSplines.html
310 var d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)),
311 d12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)),
312 fa=t*d01/(d01+d12),// scaling factor for triangle Ta
313 fb=t*d12/(d01+d12);
314 return {
315 inner : {
316 x : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x),
317 y : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y)
318 },
319 outer : {
320 x: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x),
321 y : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y)
322 }
323 };
324 },
325 calculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){
326 return Math.floor(Math.log(val) / Math.LN10);
327 },
328 calculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){
329
330 //Set a minimum step of two - a point at the top of the graph, and a point at the base
331 var minSteps = 2,
332 maxSteps = Math.floor(drawingSize/(textSize * 1.5)),
333 skipFitting = (minSteps >= maxSteps);
334
335 var maxValue = max(valuesArray),
336 minValue = min(valuesArray);
337
338 // We need some degree of seperation here to calculate the scales if all the values are the same
339 // Adding/minusing 0.5 will give us a range of 1.
340 if (maxValue === minValue){
341 maxValue += 0.5;
342 // So we don't end up with a graph with a negative start value if we've said always start from zero
343 if (minValue >= 0.5 && !startFromZero){
344 minValue -= 0.5;
345 }
346 else{
347 // Make up a whole number above the values
348 maxValue += 0.5;
349 }
350 }
351
352 var valueRange = Math.abs(maxValue - minValue),
353 rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange),
354 graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
355 graphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
356 graphRange = graphMax - graphMin,
357 stepValue = Math.pow(10, rangeOrderOfMagnitude),
358 numberOfSteps = Math.round(graphRange / stepValue);
359
360 //If we have more space on the graph we'll use it to give more definition to the data
361 while((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) {
362 if(numberOfSteps > maxSteps){
363 stepValue *=2;
364 numberOfSteps = Math.round(graphRange/stepValue);
365 // Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps.
366 if (numberOfSteps % 1 !== 0){
367 skipFitting = true;
368 }
369 }
370 //We can fit in double the amount of scale points on the scale
371 else{
372 //If user has declared ints only, and the step value isn't a decimal
373 if (integersOnly && rangeOrderOfMagnitude >= 0){
374 //If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float
375 if(stepValue/2 % 1 === 0){
376 stepValue /=2;
377 numberOfSteps = Math.round(graphRange/stepValue);
378 }
379 //If it would make it a float break out of the loop
380 else{
381 break;
382 }
383 }
384 //If the scale doesn't have to be an int, make the scale more granular anyway.
385 else{
386 stepValue /=2;
387 numberOfSteps = Math.round(graphRange/stepValue);
388 }
389
390 }
391 }
392
393 if (skipFitting){
394 numberOfSteps = minSteps;
395 stepValue = graphRange / numberOfSteps;
396 }
397
398 return {
399 steps : numberOfSteps,
400 stepValue : stepValue,
401 min : graphMin,
402 max : graphMin + (numberOfSteps * stepValue)
403 };
404
405 },
406 /* jshint ignore:start */
407 // Blows up jshint errors based on the new Function constructor
408 //Templating methods
409 //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
410 template = helpers.template = function(templateString, valuesObject){
411 // If templateString is function rather than string-template - call the function for valuesObject
412 if(templateString instanceof Function)
413 {
414 return templateString(valuesObject);
415 }
416
417 var cache = {};
418 function tmpl(str, data){
419 // Figure out if we're getting a template, or if we need to
420 // load the template - and be sure to cache the result.
421 var fn = !/\W/.test(str) ?
422 cache[str] = cache[str] :
423
424 // Generate a reusable function that will serve as a template
425 // generator (and which will be cached).
426 new Function("obj",
427 "var p=[],print=function(){p.push.apply(p,arguments);};" +
428
429 // Introduce the data as local variables using with(){}
430 "with(obj){p.push('" +
431
432 // Convert the template into pure JavaScript
433 str
434 .replace(/[\r\t\n]/g, " ")
435 .split("<%").join("\t")
436 .replace(/((^|%>)[^\t]*)'/g, "$1\r")
437 .replace(/\t=(.*?)%>/g, "',$1,'")
438 .split("\t").join("');")
439 .split("%>").join("p.push('")
440 .split("\r").join("\\'") +
441 "');}return p.join('');"
442 );
443
444 // Provide some basic currying to the user
445 return data ? fn( data ) : fn;
446 }
447 return tmpl(templateString,valuesObject);
448 },
449 /* jshint ignore:end */
450 generateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){
451 var labelsArray = new Array(numberOfSteps);
452 if (labelTemplateString){
453 each(labelsArray,function(val,index){
454 labelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))});
455 });
456 }
457 return labelsArray;
458 },
459 //--Animation methods
460 //Easing functions adapted from Robert Penner's easing equations
461 //http://www.robertpenner.com/easing/
462 easingEffects = helpers.easingEffects = {
463 linear: function (t) {
464 return t;
465 },
466 easeInQuad: function (t) {
467 return t * t;
468 },
469 easeOutQuad: function (t) {
470 return -1 * t * (t - 2);
471 },
472 easeInOutQuad: function (t) {
473 if ((t /= 1 / 2) < 1) return 1 / 2 * t * t;
474 return -1 / 2 * ((--t) * (t - 2) - 1);
475 },
476 easeInCubic: function (t) {
477 return t * t * t;
478 },
479 easeOutCubic: function (t) {
480 return 1 * ((t = t / 1 - 1) * t * t + 1);
481 },
482 easeInOutCubic: function (t) {
483 if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;
484 return 1 / 2 * ((t -= 2) * t * t + 2);
485 },
486 easeInQuart: function (t) {
487 return t * t * t * t;
488 },
489 easeOutQuart: function (t) {
490 return -1 * ((t = t / 1 - 1) * t * t * t - 1);
491 },
492 easeInOutQuart: function (t) {
493 if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;
494 return -1 / 2 * ((t -= 2) * t * t * t - 2);
495 },
496 easeInQuint: function (t) {
497 return 1 * (t /= 1) * t * t * t * t;
498 },
499 easeOutQuint: function (t) {
500 return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
501 },
502 easeInOutQuint: function (t) {
503 if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;
504 return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
505 },
506 easeInSine: function (t) {
507 return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
508 },
509 easeOutSine: function (t) {
510 return 1 * Math.sin(t / 1 * (Math.PI / 2));
511 },
512 easeInOutSine: function (t) {
513 return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
514 },
515 easeInExpo: function (t) {
516 return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
517 },
518 easeOutExpo: function (t) {
519 return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
520 },
521 easeInOutExpo: function (t) {
522 if (t === 0) return 0;
523 if (t === 1) return 1;
524 if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));
525 return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
526 },
527 easeInCirc: function (t) {
528 if (t >= 1) return t;
529 return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
530 },
531 easeOutCirc: function (t) {
532 return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
533 },
534 easeInOutCirc: function (t) {
535 if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
536 return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
537 },
538 easeInElastic: function (t) {
539 var s = 1.70158;
540 var p = 0;
541 var a = 1;
542 if (t === 0) return 0;
543 if ((t /= 1) == 1) return 1;
544 if (!p) p = 1 * 0.3;
545 if (a < Math.abs(1)) {
546 a = 1;
547 s = p / 4;
548 } else s = p / (2 * Math.PI) * Math.asin(1 / a);
549 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
550 },
551 easeOutElastic: function (t) {
552 var s = 1.70158;
553 var p = 0;
554 var a = 1;
555 if (t === 0) return 0;
556 if ((t /= 1) == 1) return 1;
557 if (!p) p = 1 * 0.3;
558 if (a < Math.abs(1)) {
559 a = 1;
560 s = p / 4;
561 } else s = p / (2 * Math.PI) * Math.asin(1 / a);
562 return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
563 },
564 easeInOutElastic: function (t) {
565 var s = 1.70158;
566 var p = 0;
567 var a = 1;
568 if (t === 0) return 0;
569 if ((t /= 1 / 2) == 2) return 1;
570 if (!p) p = 1 * (0.3 * 1.5);
571 if (a < Math.abs(1)) {
572 a = 1;
573 s = p / 4;
574 } else s = p / (2 * Math.PI) * Math.asin(1 / a);
575 if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
576 return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
577 },
578 easeInBack: function (t) {
579 var s = 1.70158;
580 return 1 * (t /= 1) * t * ((s + 1) * t - s);
581 },
582 easeOutBack: function (t) {
583 var s = 1.70158;
584 return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
585 },
586 easeInOutBack: function (t) {
587 var s = 1.70158;
588 if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
589 return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
590 },
591 easeInBounce: function (t) {
592 return 1 - easingEffects.easeOutBounce(1 - t);
593 },
594 easeOutBounce: function (t) {
595 if ((t /= 1) < (1 / 2.75)) {
596 return 1 * (7.5625 * t * t);
597 } else if (t < (2 / 2.75)) {
598 return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
599 } else if (t < (2.5 / 2.75)) {
600 return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
601 } else {
602 return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
603 }
604 },
605 easeInOutBounce: function (t) {
606 if (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5;
607 return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
608 }
609 },
610 //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
611 requestAnimFrame = helpers.requestAnimFrame = (function(){
612 return window.requestAnimationFrame ||
613 window.webkitRequestAnimationFrame ||
614 window.mozRequestAnimationFrame ||
615 window.oRequestAnimationFrame ||
616 window.msRequestAnimationFrame ||
617 function(callback) {
618 return window.setTimeout(callback, 1000 / 60);
619 };
620 })(),
621 cancelAnimFrame = helpers.cancelAnimFrame = (function(){
622 return window.cancelAnimationFrame ||
623 window.webkitCancelAnimationFrame ||
624 window.mozCancelAnimationFrame ||
625 window.oCancelAnimationFrame ||
626 window.msCancelAnimationFrame ||
627 function(callback) {
628 return window.clearTimeout(callback, 1000 / 60);
629 };
630 })(),
631 animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){
632
633 var currentStep = 0,
634 easingFunction = easingEffects[easingString] || easingEffects.linear;
635
636 var animationFrame = function(){
637 currentStep++;
638 var stepDecimal = currentStep/totalSteps;
639 var easeDecimal = easingFunction(stepDecimal);
640
641 callback.call(chartInstance,easeDecimal,stepDecimal, currentStep);
642 onProgress.call(chartInstance,easeDecimal,stepDecimal);
643 if (currentStep < totalSteps){
644 chartInstance.animationFrame = requestAnimFrame(animationFrame);
645 } else{
646 onComplete.apply(chartInstance);
647 }
648 };
649 requestAnimFrame(animationFrame);
650 },
651 //-- DOM methods
652 getRelativePosition = helpers.getRelativePosition = function(evt){
653 var mouseX, mouseY;
654 var e = evt.originalEvent || evt,
655 canvas = evt.currentTarget || evt.srcElement,
656 boundingRect = canvas.getBoundingClientRect();
657
658 if (e.touches){
659 mouseX = e.touches[0].clientX - boundingRect.left;
660 mouseY = e.touches[0].clientY - boundingRect.top;
661
662 }
663 else{
664 mouseX = e.clientX - boundingRect.left;
665 mouseY = e.clientY - boundingRect.top;
666 }
667
668 return {
669 x : mouseX,
670 y : mouseY
671 };
672
673 },
674 addEvent = helpers.addEvent = function(node,eventType,method){
675 if (node.addEventListener){
676 node.addEventListener(eventType,method);
677 } else if (node.attachEvent){
678 node.attachEvent("on"+eventType, method);
679 } else {
680 node["on"+eventType] = method;
681 }
682 },
683 removeEvent = helpers.removeEvent = function(node, eventType, handler){
684 if (node.removeEventListener){
685 node.removeEventListener(eventType, handler, false);
686 } else if (node.detachEvent){
687 node.detachEvent("on"+eventType,handler);
688 } else{
689 node["on" + eventType] = noop;
690 }
691 },
692 bindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){
693 // Create the events object if it's not already present
694 if (!chartInstance.events) chartInstance.events = {};
695
696 each(arrayOfEvents,function(eventName){
697 chartInstance.events[eventName] = function(){
698 handler.apply(chartInstance, arguments);
699 };
700 addEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]);
701 });
702 },
703 unbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) {
704 each(arrayOfEvents, function(handler,eventName){
705 removeEvent(chartInstance.chart.canvas, eventName, handler);
706 });
707 },
708 getMaximumWidth = helpers.getMaximumWidth = function(domNode){
709 var container = domNode.parentNode;
710 // TODO = check cross browser stuff with this.
711 return container.clientWidth;
712 },
713 getMaximumHeight = helpers.getMaximumHeight = function(domNode){
714 var container = domNode.parentNode;
715 // TODO = check cross browser stuff with this.
716 return container.clientHeight;
717 },
718 getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support
719 retinaScale = helpers.retinaScale = function(chart){
720 var ctx = chart.ctx,
721 width = chart.canvas.width,
722 height = chart.canvas.height;
723 //console.log(width + " x " + height);
724 if (window.devicePixelRatio) {
725 ctx.canvas.style.width = width + "px";
726 ctx.canvas.style.height = height + "px";
727 ctx.canvas.height = height * window.devicePixelRatio;
728 ctx.canvas.width = width * window.devicePixelRatio;
729 ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
730 }
731 },
732 //-- Canvas methods
733 clear = helpers.clear = function(chart){
734 chart.ctx.clearRect(0,0,chart.width,chart.height);
735 },
736 fontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){
737 return fontStyle + " " + pixelSize+"px " + fontFamily;
738 },
739 longestText = helpers.longestText = function(ctx,font,arrayOfStrings){
740 ctx.font = font;
741 var longest = 0;
742 each(arrayOfStrings,function(string){
743 var textWidth = ctx.measureText(string).width;
744 longest = (textWidth > longest) ? textWidth : longest;
745 });
746 return longest;
747 },
748 drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){
749 ctx.beginPath();
750 ctx.moveTo(x + radius, y);
751 ctx.lineTo(x + width - radius, y);
752 ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
753 ctx.lineTo(x + width, y + height - radius);
754 ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
755 ctx.lineTo(x + radius, y + height);
756 ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
757 ctx.lineTo(x, y + radius);
758 ctx.quadraticCurveTo(x, y, x + radius, y);
759 ctx.closePath();
760 };
761
762
763 //Store a reference to each instance - allowing us to globally resize chart instances on window resize.
764 //Destroy method on the chart will remove the instance of the chart from this reference.
765 Chart.instances = {};
766
767 Chart.Type = function(data,options,chart){
768 this.options = options;
769 this.chart = chart;
770 this.id = uid();
771 //Add the chart instance to the global namespace
772 Chart.instances[this.id] = this;
773
774 // Initialize is always called when a chart type is created
775 // By default it is a no op, but it should be extended
776 if (options.responsive){
777 this.resize();
778 }
779 this.initialize.call(this,data);
780 };
781
782 //Core methods that'll be a part of every chart type
783 extend(Chart.Type.prototype,{
784 initialize : function(){return this;},
785 clear : function(){
786 clear(this.chart);
787 return this;
788 },
789 stop : function(){
790 // Stops any current animation loop occuring
791 helpers.cancelAnimFrame.call(root, this.animationFrame);
792 return this;
793 },
794 resize : function(callback){
795 this.stop();
796 var canvas = this.chart.canvas,
797 newWidth = getMaximumWidth(this.chart.canvas),
798 newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
799
800 canvas.width = this.chart.width = newWidth;
801 canvas.height = this.chart.height = newHeight;
802
803 retinaScale(this.chart);
804
805 if (typeof callback === "function"){
806 callback.apply(this, Array.prototype.slice.call(arguments, 1));
807 }
808 return this;
809 },
810 reflow : noop,
811 render : function(reflow){
812 if (reflow){
813 this.reflow();
814 }
815 if (this.options.animation && !reflow){
816 helpers.animationLoop(
817 this.draw,
818 this.options.animationSteps,
819 this.options.animationEasing,
820 this.options.onAnimationProgress,
821 this.options.onAnimationComplete,
822 this
823 );
824 }
825 else{
826 this.draw();
827 this.options.onAnimationComplete.call(this);
828 }
829 return this;
830 },
831 generateLegend : function(){
832 return template(this.options.legendTemplate,this);
833 },
834 destroy : function(){
835 this.clear();
836 unbindEvents(this, this.events);
837 delete Chart.instances[this.id];
838 },
839 showTooltip : function(ChartElements, forceRedraw){
840 // Only redraw the chart if we've actually changed what we're hovering on.
841 if (typeof this.activeElements === 'undefined') this.activeElements = [];
842
843 var isChanged = (function(Elements){
844 var changed = false;
845
846 if (Elements.length !== this.activeElements.length){
847 changed = true;
848 return changed;
849 }
850
851 each(Elements, function(element, index){
852 if (element !== this.activeElements[index]){
853 changed = true;
854 }
855 }, this);
856 return changed;
857 }).call(this, ChartElements);
858
859 if (!isChanged && !forceRedraw){
860 return;
861 }
862 else{
863 this.activeElements = ChartElements;
864 }
865 this.draw();
866 if (ChartElements.length > 0){
867 // If we have multiple datasets, show a MultiTooltip for all of the data points at that index
868 if (this.datasets && this.datasets.length > 1) {
869 var dataArray,
870 dataIndex;
871
872 for (var i = this.datasets.length - 1; i >= 0; i--) {
873 dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
874 dataIndex = indexOf(dataArray, ChartElements[0]);
875 if (dataIndex !== -1){
876 break;
877 }
878 }
879 var tooltipLabels = [],
880 tooltipColors = [],
881 medianPosition = (function(index) {
882
883 // Get all the points at that particular index
884 var Elements = [],
885 dataCollection,
886 xPositions = [],
887 yPositions = [],
888 xMax,
889 yMax,
890 xMin,
891 yMin;
892 helpers.each(this.datasets, function(dataset){
893 dataCollection = dataset.points || dataset.bars || dataset.segments;
894 if (dataCollection[dataIndex]){
895 Elements.push(dataCollection[dataIndex]);
896 }
897 });
898
899 helpers.each(Elements, function(element) {
900 xPositions.push(element.x);
901 yPositions.push(element.y);
902
903
904 //Include any colour information about the element
905 tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
906 tooltipColors.push({
907 fill: element._saved.fillColor || element.fillColor,
908 stroke: element._saved.strokeColor || element.strokeColor
909 });
910
911 }, this);
912
913 yMin = min(yPositions);
914 yMax = max(yPositions);
915
916 xMin = min(xPositions);
917 xMax = max(xPositions);
918
919 return {
920 x: (xMin > this.chart.width/2) ? xMin : xMax,
921 y: (yMin + yMax)/2
922 };
923 }).call(this, dataIndex);
924
925 new Chart.MultiTooltip({
926 x: medianPosition.x,
927 y: medianPosition.y,
928 xPadding: this.options.tooltipXPadding,
929 yPadding: this.options.tooltipYPadding,
930 xOffset: this.options.tooltipXOffset,
931 fillColor: this.options.tooltipFillColor,
932 textColor: this.options.tooltipFontColor,
933 fontFamily: this.options.tooltipFontFamily,
934 fontStyle: this.options.tooltipFontStyle,
935 fontSize: this.options.tooltipFontSize,
936 titleTextColor: this.options.tooltipTitleFontColor,
937 titleFontFamily: this.options.tooltipTitleFontFamily,
938 titleFontStyle: this.options.tooltipTitleFontStyle,
939 titleFontSize: this.options.tooltipTitleFontSize,
940 cornerRadius: this.options.tooltipCornerRadius,
941 labels: tooltipLabels,
942 legendColors: tooltipColors,
943 legendColorBackground : this.options.multiTooltipKeyBackground,
944 title: ChartElements[0].label,
945 chart: this.chart,
946 ctx: this.chart.ctx
947 }).draw();
948
949 } else {
950 each(ChartElements, function(Element) {
951 var tooltipPosition = Element.tooltipPosition();
952 new Chart.Tooltip({
953 x: Math.round(tooltipPosition.x),
954 y: Math.round(tooltipPosition.y),
955 xPadding: this.options.tooltipXPadding,
956 yPadding: this.options.tooltipYPadding,
957 fillColor: this.options.tooltipFillColor,
958 textColor: this.options.tooltipFontColor,
959 fontFamily: this.options.tooltipFontFamily,
960 fontStyle: this.options.tooltipFontStyle,
961 fontSize: this.options.tooltipFontSize,
962 caretHeight: this.options.tooltipCaretSize,
963 cornerRadius: this.options.tooltipCornerRadius,
964 text: template(this.options.tooltipTemplate, Element),
965 chart: this.chart
966 }).draw();
967 }, this);
968 }
969 }
970 return this;
971 },
972 toBase64Image : function(){
973 return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
974 }
975 });
976
977 Chart.Type.extend = function(extensions){
978
979 var parent = this;
980
981 var ChartType = function(){
982 return parent.apply(this,arguments);
983 };
984
985 //Copy the prototype object of the this class
986 ChartType.prototype = clone(parent.prototype);
987 //Now overwrite some of the properties in the base class with the new extensions
988 extend(ChartType.prototype, extensions);
989
990 ChartType.extend = Chart.Type.extend;
991
992 if (extensions.name || parent.prototype.name){
993
994 var chartName = extensions.name || parent.prototype.name;
995 //Assign any potential default values of the new chart type
996
997 //If none are defined, we'll use a clone of the chart type this is being extended from.
998 //I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart
999 //doesn't define some defaults of their own.
1000
1001 var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};
1002
1003 Chart.defaults[chartName] = extend(baseDefaults,extensions.defaults);
1004
1005 Chart.types[chartName] = ChartType;
1006
1007 //Register this new chart type in the Chart prototype
1008 Chart.prototype[chartName] = function(data,options){
1009 var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});
1010 return new ChartType(data,config,this);
1011 };
1012 } else{
1013 warn("Name not provided for this chart, so it hasn't been registered");
1014 }
1015 return parent;
1016 };
1017
1018 Chart.Element = function(configuration){
1019 extend(this,configuration);
1020 this.initialize.apply(this,arguments);
1021 this.save();
1022 };
1023 extend(Chart.Element.prototype,{
1024 initialize : function(){},
1025 restore : function(props){
1026 if (!props){
1027 extend(this,this._saved);
1028 } else {
1029 each(props,function(key){
1030 this[key] = this._saved[key];
1031 },this);
1032 }
1033 return this;
1034 },
1035 save : function(){
1036 this._saved = clone(this);
1037 delete this._saved._saved;
1038 return this;
1039 },
1040 update : function(newProps){
1041 each(newProps,function(value,key){
1042 this._saved[key] = this[key];
1043 this[key] = value;
1044 },this);
1045 return this;
1046 },
1047 transition : function(props,ease){
1048 each(props,function(value,key){
1049 this[key] = ((value - this._saved[key]) * ease) + this._saved[key];
1050 },this);
1051 return this;
1052 },
1053 tooltipPosition : function(){
1054 return {
1055 x : this.x,
1056 y : this.y
1057 };
1058 }
1059 });
1060
1061 Chart.Element.extend = inherits;
1062
1063
1064 Chart.Point = Chart.Element.extend({
1065 display: true,
1066 inRange: function(chartX,chartY){
1067 var hitDetectionRange = this.hitDetectionRadius + this.radius;
1068 return ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2));
1069 },
1070 draw : function(){
1071 if (this.display){
1072 var ctx = this.ctx;
1073 ctx.beginPath();
1074
1075 ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
1076 ctx.closePath();
1077
1078 ctx.strokeStyle = this.strokeColor;
1079 ctx.lineWidth = this.strokeWidth;
1080
1081 ctx.fillStyle = this.fillColor;
1082
1083 ctx.fill();
1084 ctx.stroke();
1085 }
1086
1087
1088 //Quick debug for bezier curve splining
1089 //Highlights control points and the line between them.
1090 //Handy for dev - stripped in the min version.
1091
1092 // ctx.save();
1093 // ctx.fillStyle = "black";
1094 // ctx.strokeStyle = "black"
1095 // ctx.beginPath();
1096 // ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2);
1097 // ctx.fill();
1098
1099 // ctx.beginPath();
1100 // ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2);
1101 // ctx.fill();
1102
1103 // ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);
1104 // ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);
1105 // ctx.stroke();
1106
1107 // ctx.restore();
1108
1109
1110
1111 }
1112 });
1113
1114 Chart.Arc = Chart.Element.extend({
1115 inRange : function(chartX,chartY){
1116
1117 var pointRelativePosition = helpers.getAngleFromPoint(this, {
1118 x: chartX,
1119 y: chartY
1120 });
1121
1122 //Check if within the range of the open/close angle
1123 var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),
1124 withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);
1125
1126 return (betweenAngles && withinRadius);
1127 //Ensure within the outside of the arc centre, but inside arc outer
1128 },
1129 tooltipPosition : function(){
1130 var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),
1131 rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;
1132 return {
1133 x : this.x + (Math.cos(centreAngle) * rangeFromCentre),
1134 y : this.y + (Math.sin(centreAngle) * rangeFromCentre)
1135 };
1136 },
1137 draw : function(animationPercent){
1138
1139 var easingDecimal = animationPercent || 1;
1140
1141 var ctx = this.ctx;
1142
1143 ctx.beginPath();
1144
1145 ctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle);
1146
1147 ctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true);
1148
1149 ctx.closePath();
1150 ctx.strokeStyle = this.strokeColor;
1151 ctx.lineWidth = this.strokeWidth;
1152
1153 ctx.fillStyle = this.fillColor;
1154
1155 ctx.fill();
1156 ctx.lineJoin = 'bevel';
1157
1158 if (this.showStroke){
1159 ctx.stroke();
1160 }
1161 }
1162 });
1163
1164 Chart.Rectangle = Chart.Element.extend({
1165 draw : function(){
1166 var ctx = this.ctx,
1167 halfWidth = this.width/2,
1168 leftX = this.x - halfWidth,
1169 rightX = this.x + halfWidth,
1170 top = this.base - (this.base - this.y),
1171 halfStroke = this.strokeWidth / 2;
1172
1173 // Canvas doesn't allow us to stroke inside the width so we can
1174 // adjust the sizes to fit if we're setting a stroke on the line
1175 if (this.showStroke){
1176 leftX += halfStroke;
1177 rightX -= halfStroke;
1178 top += halfStroke;
1179 }
1180
1181 ctx.beginPath();
1182
1183 ctx.fillStyle = this.fillColor;
1184 ctx.strokeStyle = this.strokeColor;
1185 ctx.lineWidth = this.strokeWidth;
1186
1187 // It'd be nice to keep this class totally generic to any rectangle
1188 // and simply specify which border to miss out.
1189 ctx.moveTo(leftX, this.base);
1190 ctx.lineTo(leftX, top);
1191 ctx.lineTo(rightX, top);
1192 ctx.lineTo(rightX, this.base);
1193 ctx.fill();
1194 if (this.showStroke){
1195 ctx.stroke();
1196 }
1197 },
1198 height : function(){
1199 return this.base - this.y;
1200 },
1201 inRange : function(chartX,chartY){
1202 return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);
1203 }
1204 });
1205
1206 Chart.Tooltip = Chart.Element.extend({
1207 draw : function(){
1208
1209 var ctx = this.chart.ctx;
1210
1211 ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1212
1213 this.xAlign = "center";
1214 this.yAlign = "above";
1215
1216 //Distance between the actual element.y position and the start of the tooltip caret
1217 var caretPadding = 2;
1218
1219 var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
1220 tooltipRectHeight = this.fontSize + 2*this.yPadding,
1221 tooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding;
1222
1223 if (this.x + tooltipWidth/2 >this.chart.width){
1224 this.xAlign = "left";
1225 } else if (this.x - tooltipWidth/2 < 0){
1226 this.xAlign = "right";
1227 }
1228
1229 if (this.y - tooltipHeight < 0){
1230 this.yAlign = "below";
1231 }
1232
1233
1234 var tooltipX = this.x - tooltipWidth/2,
1235 tooltipY = this.y - tooltipHeight;
1236
1237 ctx.fillStyle = this.fillColor;
1238
1239 switch(this.yAlign)
1240 {
1241 case "above":
1242 //Draw a caret above the x/y
1243 ctx.beginPath();
1244 ctx.moveTo(this.x,this.y - caretPadding);
1245 ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
1246 ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
1247 ctx.closePath();
1248 ctx.fill();
1249 break;
1250 case "below":
1251 tooltipY = this.y + caretPadding + this.caretHeight;
1252 //Draw a caret below the x/y
1253 ctx.beginPath();
1254 ctx.moveTo(this.x, this.y + caretPadding);
1255 ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
1256 ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
1257 ctx.closePath();
1258 ctx.fill();
1259 break;
1260 }
1261
1262 switch(this.xAlign)
1263 {
1264 case "left":
1265 tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
1266 break;
1267 case "right":
1268 tooltipX = this.x - (this.cornerRadius + this.caretHeight);
1269 break;
1270 }
1271
1272 drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
1273
1274 ctx.fill();
1275
1276 ctx.fillStyle = this.textColor;
1277 ctx.textAlign = "center";
1278 ctx.textBaseline = "middle";
1279 ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
1280 }
1281 });
1282
1283 Chart.MultiTooltip = Chart.Element.extend({
1284 initialize : function(){
1285 this.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1286
1287 this.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily);
1288
1289 this.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5;
1290
1291 this.ctx.font = this.titleFont;
1292
1293 var titleWidth = this.ctx.measureText(this.title).width,
1294 //Label has a legend square as well so account for this.
1295 labelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3,
1296 longestTextWidth = max([labelWidth,titleWidth]);
1297
1298 this.width = longestTextWidth + (this.xPadding*2);
1299
1300
1301 var halfHeight = this.height/2;
1302
1303 //Check to ensure the height will fit on the canvas
1304 //The three is to buffer form the very
1305 if (this.y - halfHeight < 0 ){
1306 this.y = halfHeight;
1307 } else if (this.y + halfHeight > this.chart.height){
1308 this.y = this.chart.height - halfHeight;
1309 }
1310
1311 //Decide whether to align left or right based on position on canvas
1312 if (this.x > this.chart.width/2){
1313 this.x -= this.xOffset + this.width;
1314 } else {
1315 this.x += this.xOffset;
1316 }
1317
1318
1319 },
1320 getLineHeight : function(index){
1321 var baseLineHeight = this.y - (this.height/2) + this.yPadding,
1322 afterTitleIndex = index-1;
1323
1324 //If the index is zero, we're getting the title
1325 if (index === 0){
1326 return baseLineHeight + this.titleFontSize/2;
1327 } else{
1328 return baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5;
1329 }
1330
1331 },
1332 draw : function(){
1333 drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
1334 var ctx = this.ctx;
1335 ctx.fillStyle = this.fillColor;
1336 ctx.fill();
1337 ctx.closePath();
1338
1339 ctx.textAlign = "left";
1340 ctx.textBaseline = "middle";
1341 ctx.fillStyle = this.titleTextColor;
1342 ctx.font = this.titleFont;
1343
1344 ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
1345
1346 ctx.font = this.font;
1347 helpers.each(this.labels,function(label,index){
1348 ctx.fillStyle = this.textColor;
1349 ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
1350
1351 //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
1352 //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1353 //Instead we'll make a white filled block to put the legendColour palette over.
1354
1355 ctx.fillStyle = this.legendColorBackground;
1356 ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1357
1358 ctx.fillStyle = this.legendColors[index].fill;
1359 ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
1360
1361
1362 },this);
1363 }
1364 });
1365
1366 Chart.Scale = Chart.Element.extend({
1367 initialize : function(){
1368 this.fit();
1369 },
1370 buildYLabels : function(){
1371 this.yLabels = [];
1372
1373 var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
1374
1375 for (var i=0; i<=this.steps; i++){
1376 this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
1377 }
1378 this.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0;
1379 },
1380 addXLabel : function(label){
1381 this.xLabels.push(label);
1382 this.valuesCount++;
1383 this.fit();
1384 },
1385 removeXLabel : function(){
1386 this.xLabels.shift();
1387 this.valuesCount--;
1388 this.fit();
1389 },
1390 // Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use
1391 fit: function(){
1392 // First we need the width of the yLabels, assuming the xLabels aren't rotated
1393
1394 // To do that we need the base line at the top and base of the chart, assuming there is no x label rotation
1395 this.startPoint = (this.display) ? this.fontSize : 0;
1396 this.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels
1397
1398 // Apply padding settings to the start and end point.
1399 this.startPoint += this.padding;
1400 this.endPoint -= this.padding;
1401
1402 // Cache the starting height, so can determine if we need to recalculate the scale yAxis
1403 var cachedHeight = this.endPoint - this.startPoint,
1404 cachedYLabelWidth;
1405
1406 // Build the current yLabels so we have an idea of what size they'll be to start
1407 /*
1408 * This sets what is returned from calculateScaleRange as static properties of this class:
1409 *
1410 this.steps;
1411 this.stepValue;
1412 this.min;
1413 this.max;
1414 *
1415 */
1416 this.calculateYRange(cachedHeight);
1417
1418 // With these properties set we can now build the array of yLabels
1419 // and also the width of the largest yLabel
1420 this.buildYLabels();
1421
1422 this.calculateXLabelRotation();
1423
1424 while((cachedHeight > this.endPoint - this.startPoint)){
1425 cachedHeight = this.endPoint - this.startPoint;
1426 cachedYLabelWidth = this.yLabelWidth;
1427
1428 this.calculateYRange(cachedHeight);
1429 this.buildYLabels();
1430
1431 // Only go through the xLabel loop again if the yLabel width has changed
1432 if (cachedYLabelWidth < this.yLabelWidth){
1433 this.calculateXLabelRotation();
1434 }
1435 }
1436
1437 },
1438 calculateXLabelRotation : function(){
1439 //Get the width of each grid by calculating the difference
1440 //between x offsets between 0 and 1.
1441
1442 this.ctx.font = this.font;
1443
1444 var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
1445 lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
1446 firstRotated,
1447 lastRotated;
1448
1449
1450 this.xScalePaddingRight = lastWidth/2 + 3;
1451 this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10;
1452
1453 this.xLabelRotation = 0;
1454 if (this.display){
1455 var originalLabelWidth = longestText(this.ctx,this.font,this.xLabels),
1456 cosRotation,
1457 firstRotatedWidth;
1458 this.xLabelWidth = originalLabelWidth;
1459 //Allow 3 pixels x2 padding either side for label readability
1460 var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
1461
1462 //Max label rotate should be 90 - also act as a loop counter
1463 while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){
1464 cosRotation = Math.cos(toRadians(this.xLabelRotation));
1465
1466 firstRotated = cosRotation * firstWidth;
1467 lastRotated = cosRotation * lastWidth;
1468
1469 // We're right aligning the text now.
1470 if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){
1471 this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
1472 }
1473 this.xScalePaddingRight = this.fontSize/2;
1474
1475
1476 this.xLabelRotation++;
1477 this.xLabelWidth = cosRotation * originalLabelWidth;
1478
1479 }
1480 if (this.xLabelRotation > 0){
1481 this.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3;
1482 }
1483 }
1484 else{
1485 this.xLabelWidth = 0;
1486 this.xScalePaddingRight = this.padding;
1487 this.xScalePaddingLeft = this.padding;
1488 }
1489
1490 },
1491 // Needs to be overidden in each Chart type
1492 // Otherwise we need to pass all the data into the scale class
1493 calculateYRange: noop,
1494 drawingArea: function(){
1495 return this.startPoint - this.endPoint;
1496 },
1497 calculateY : function(value){
1498 var scalingFactor = this.drawingArea() / (this.min - this.max);
1499 return this.endPoint - (scalingFactor * (value - this.min));
1500 },
1501 calculateX : function(index){
1502 var isRotated = (this.xLabelRotation > 0),
1503 // innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,
1504 innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),
1505 valueWidth = innerWidth/(this.valuesCount - ((this.offsetGridLines) ? 0 : 1)),
1506 valueOffset = (valueWidth * index) + this.xScalePaddingLeft;
1507
1508 if (this.offsetGridLines){
1509 valueOffset += (valueWidth/2);
1510 }
1511
1512 return Math.round(valueOffset);
1513 },
1514 update : function(newProps){
1515 helpers.extend(this, newProps);
1516 this.fit();
1517 },
1518 draw : function(){
1519 var ctx = this.ctx,
1520 yLabelGap = (this.endPoint - this.startPoint) / this.steps,
1521 xStart = Math.round(this.xScalePaddingLeft);
1522 if (this.display){
1523 ctx.fillStyle = this.textColor;
1524 ctx.font = this.font;
1525 each(this.yLabels,function(labelString,index){
1526 var yLabelCenter = this.endPoint - (yLabelGap * index),
1527 linePositionY = Math.round(yLabelCenter);
1528
1529 ctx.textAlign = "right";
1530 ctx.textBaseline = "middle";
1531 if (this.showLabels){
1532 ctx.fillText(labelString,xStart - 10,yLabelCenter);
1533 }
1534 ctx.beginPath();
1535 if (index > 0){
1536 // This is a grid line in the centre, so drop that
1537 ctx.lineWidth = this.gridLineWidth;
1538 ctx.strokeStyle = this.gridLineColor;
1539 } else {
1540 // This is the first line on the scale
1541 ctx.lineWidth = this.lineWidth;
1542 ctx.strokeStyle = this.lineColor;
1543 }
1544
1545 linePositionY += helpers.aliasPixel(ctx.lineWidth);
1546
1547 ctx.moveTo(xStart, linePositionY);
1548 ctx.lineTo(this.width, linePositionY);
1549 ctx.stroke();
1550 ctx.closePath();
1551
1552 ctx.lineWidth = this.lineWidth;
1553 ctx.strokeStyle = this.lineColor;
1554 ctx.beginPath();
1555 ctx.moveTo(xStart - 5, linePositionY);
1556 ctx.lineTo(xStart, linePositionY);
1557 ctx.stroke();
1558 ctx.closePath();
1559
1560 },this);
1561
1562 // xLabelsSkipper is a number which if gives 0 as remainder [ indexof(xLabel)/xLabelsSkipper ], we print xLabels, otherwise, we skip it
1563 // if number then divide and determine | else, if true, print all labels, else we never print
1564 this.xLabelsSkipper = isNumber(this.showXLabels) ? Math.ceil(this.xLabels.length/this.showXLabels) : (this.showXLabels === true) ? 1 : this.xLabels.length+1;
1565 each(this.xLabels,function(label,index){
1566 var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
1567 // Check to see if line/bar here and decide where to place the line
1568 linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
1569 isRotated = (this.xLabelRotation > 0);
1570
1571 ctx.beginPath();
1572
1573 if (index > 0){
1574 // This is a grid line in the centre, so drop that
1575 ctx.lineWidth = this.gridLineWidth;
1576 ctx.strokeStyle = this.gridLineColor;
1577 } else {
1578 // This is the first line on the scale
1579 ctx.lineWidth = this.lineWidth;
1580 ctx.strokeStyle = this.lineColor;
1581 }
1582 ctx.moveTo(linePos,this.endPoint);
1583 ctx.lineTo(linePos,this.startPoint - 3);
1584 ctx.stroke();
1585 ctx.closePath();
1586
1587
1588 ctx.lineWidth = this.lineWidth;
1589 ctx.strokeStyle = this.lineColor;
1590
1591
1592 // Small lines at the bottom of the base grid line
1593 ctx.beginPath();
1594 ctx.moveTo(linePos,this.endPoint);
1595 ctx.lineTo(linePos,this.endPoint + 5);
1596 ctx.stroke();
1597 ctx.closePath();
1598
1599 ctx.save();
1600 ctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8);
1601 ctx.rotate(toRadians(this.xLabelRotation)*-1);
1602 ctx.font = this.font;
1603 ctx.textAlign = (isRotated) ? "right" : "center";
1604 ctx.textBaseline = (isRotated) ? "middle" : "top";
1605 if(index % this.xLabelsSkipper === 0) {
1606 ctx.fillText(label, 0, 0);
1607 }
1608 ctx.restore();
1609 },this);
1610
1611 }
1612 }
1613
1614 });
1615
1616 Chart.RadialScale = Chart.Element.extend({
1617 initialize: function(){
1618 this.size = min([this.height, this.width]);
1619 this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
1620 },
1621 calculateCenterOffset: function(value){
1622 // Take into account half font size + the yPadding of the top value
1623 var scalingFactor = this.drawingArea / (this.max - this.min);
1624
1625 return (value - this.min) * scalingFactor;
1626 },
1627 update : function(){
1628 if (!this.lineArc){
1629 this.setScaleSize();
1630 } else {
1631 this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
1632 }
1633 this.buildYLabels();
1634 },
1635 buildYLabels: function(){
1636 this.yLabels = [];
1637
1638 var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
1639
1640 for (var i=0; i<=this.steps; i++){
1641 this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
1642 }
1643 },
1644 getCircumference : function(){
1645 return ((Math.PI*2) / this.valuesCount);
1646 },
1647 setScaleSize: function(){
1648 /*
1649 * Right, this is really confusing and there is a lot of maths going on here
1650 * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
1651 *
1652 * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
1653 *
1654 * Solution:
1655 *
1656 * We assume the radius of the polygon is half the size of the canvas at first
1657 * at each index we check if the text overlaps.
1658 *
1659 * Where it does, we store that angle and that index.
1660 *
1661 * After finding the largest index and angle we calculate how much we need to remove
1662 * from the shape radius to move the point inwards by that x.
1663 *
1664 * We average the left and right distances to get the maximum shape radius that can fit in the box
1665 * along with labels.
1666 *
1667 * Once we have that, we can find the centre point for the chart, by taking the x text protrusion
1668 * on each side, removing that from the size, halving it and adding the left x protrusion width.
1669 *
1670 * This will mean we have a shape fitted to the canvas, as large as it can be with the labels
1671 * and position it in the most space efficient manner
1672 *
1673 * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
1674 */
1675
1676
1677 // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
1678 // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
1679 var largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]),
1680 pointPosition,
1681 i,
1682 textWidth,
1683 halfTextWidth,
1684 furthestRight = this.width,
1685 furthestRightIndex,
1686 furthestRightAngle,
1687 furthestLeft = 0,
1688 furthestLeftIndex,
1689 furthestLeftAngle,
1690 xProtrusionLeft,
1691 xProtrusionRight,
1692 radiusReductionRight,
1693 radiusReductionLeft,
1694 maxWidthRadius;
1695 this.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
1696 for (i=0;i<this.valuesCount;i++){
1697 // 5px to space the text slightly out - similar to what we do in the draw function.
1698 pointPosition = this.getPointPosition(i, largestPossibleRadius);
1699 textWidth = this.ctx.measureText(template(this.templateString, { value: this.labels[i] })).width + 5;
1700 if (i === 0 || i === this.valuesCount/2){
1701 // If we're at index zero, or exactly the middle, we're at exactly the top/bottom
1702 // of the radar chart, so text will be aligned centrally, so we'll half it and compare
1703 // w/left and right text sizes
1704 halfTextWidth = textWidth/2;
1705 if (pointPosition.x + halfTextWidth > furthestRight) {
1706 furthestRight = pointPosition.x + halfTextWidth;
1707 furthestRightIndex = i;
1708 }
1709 if (pointPosition.x - halfTextWidth < furthestLeft) {
1710 furthestLeft = pointPosition.x - halfTextWidth;
1711 furthestLeftIndex = i;
1712 }
1713 }
1714 else if (i < this.valuesCount/2) {
1715 // Less than half the values means we'll left align the text
1716 if (pointPosition.x + textWidth > furthestRight) {
1717 furthestRight = pointPosition.x + textWidth;
1718 furthestRightIndex = i;
1719 }
1720 }
1721 else if (i > this.valuesCount/2){
1722 // More than half the values means we'll right align the text
1723 if (pointPosition.x - textWidth < furthestLeft) {
1724 furthestLeft = pointPosition.x - textWidth;
1725 furthestLeftIndex = i;
1726 }
1727 }
1728 }
1729
1730 xProtrusionLeft = furthestLeft;
1731
1732 xProtrusionRight = Math.ceil(furthestRight - this.width);
1733
1734 furthestRightAngle = this.getIndexAngle(furthestRightIndex);
1735
1736 furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
1737
1738 radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2);
1739
1740 radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2);
1741
1742 // Ensure we actually need to reduce the size of the chart
1743 radiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
1744 radiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
1745
1746 this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2;
1747
1748 //this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])
1749 this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
1750
1751 },
1752 setCenterPoint: function(leftMovement, rightMovement){
1753
1754 var maxRight = this.width - rightMovement - this.drawingArea,
1755 maxLeft = leftMovement + this.drawingArea;
1756
1757 this.xCenter = (maxLeft + maxRight)/2;
1758 // Always vertically in the centre as the text height doesn't change
1759 this.yCenter = (this.height/2);
1760 },
1761
1762 getIndexAngle : function(index){
1763 var angleMultiplier = (Math.PI * 2) / this.valuesCount;
1764 // Start from the top instead of right, so remove a quarter of the circle
1765
1766 return index * angleMultiplier - (Math.PI/2);
1767 },
1768 getPointPosition : function(index, distanceFromCenter){
1769 var thisAngle = this.getIndexAngle(index);
1770 return {
1771 x : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,
1772 y : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter
1773 };
1774 },
1775 draw: function(){
1776 if (this.display){
1777 var ctx = this.ctx;
1778 each(this.yLabels, function(label, index){
1779 // Don't draw a centre value
1780 if (index > 0){
1781 var yCenterOffset = index * (this.drawingArea/this.steps),
1782 yHeight = this.yCenter - yCenterOffset,
1783 pointPosition;
1784
1785 // Draw circular lines around the scale
1786 if (this.lineWidth > 0){
1787 ctx.strokeStyle = this.lineColor;
1788 ctx.lineWidth = this.lineWidth;
1789
1790 if(this.lineArc){
1791 ctx.beginPath();
1792 ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2);
1793 ctx.closePath();
1794 ctx.stroke();
1795 } else{
1796 ctx.beginPath();
1797 for (var i=0;i<this.valuesCount;i++)
1798 {
1799 pointPosition = this.getPointPosition(i, this.calculateCenterOffset(this.min + (index * this.stepValue)));
1800 if (i === 0){
1801 ctx.moveTo(pointPosition.x, pointPosition.y);
1802 } else {
1803 ctx.lineTo(pointPosition.x, pointPosition.y);
1804 }
1805 }
1806 ctx.closePath();
1807 ctx.stroke();
1808 }
1809 }
1810 if(this.showLabels){
1811 ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
1812 if (this.showLabelBackdrop){
1813 var labelWidth = ctx.measureText(label).width;
1814 ctx.fillStyle = this.backdropColor;
1815 ctx.fillRect(
1816 this.xCenter - labelWidth/2 - this.backdropPaddingX,
1817 yHeight - this.fontSize/2 - this.backdropPaddingY,
1818 labelWidth + this.backdropPaddingX*2,
1819 this.fontSize + this.backdropPaddingY*2
1820 );
1821 }
1822 ctx.textAlign = 'center';
1823 ctx.textBaseline = "middle";
1824 ctx.fillStyle = this.fontColor;
1825 ctx.fillText(label, this.xCenter, yHeight);
1826 }
1827 }
1828 }, this);
1829
1830 if (!this.lineArc){
1831 ctx.lineWidth = this.angleLineWidth;
1832 ctx.strokeStyle = this.angleLineColor;
1833 for (var i = this.valuesCount - 1; i >= 0; i--) {
1834 if (this.angleLineWidth > 0){
1835 var outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max));
1836 ctx.beginPath();
1837 ctx.moveTo(this.xCenter, this.yCenter);
1838 ctx.lineTo(outerPosition.x, outerPosition.y);
1839 ctx.stroke();
1840 ctx.closePath();
1841 }
1842 // Extra 3px out for some label spacing
1843 var pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5);
1844 ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
1845 ctx.fillStyle = this.pointLabelFontColor;
1846
1847 var labelsCount = this.labels.length,
1848 halfLabelsCount = this.labels.length/2,
1849 quarterLabelsCount = halfLabelsCount/2,
1850 upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
1851 exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
1852 if (i === 0){
1853 ctx.textAlign = 'center';
1854 } else if(i === halfLabelsCount){
1855 ctx.textAlign = 'center';
1856 } else if (i < halfLabelsCount){
1857 ctx.textAlign = 'left';
1858 } else {
1859 ctx.textAlign = 'right';
1860 }
1861
1862 // Set the correct text baseline based on outer positioning
1863 if (exactQuarter){
1864 ctx.textBaseline = 'middle';
1865 } else if (upperHalf){
1866 ctx.textBaseline = 'bottom';
1867 } else {
1868 ctx.textBaseline = 'top';
1869 }
1870
1871 ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);
1872 }
1873 }
1874 }
1875 }
1876 });
1877
1878 // Attach global event to resize each chart instance when the browser resizes
1879 helpers.addEvent(window, "resize", (function(){
1880 // Basic debounce of resize function so it doesn't hurt performance when resizing browser.
1881 var timeout;
1882 return function(){
1883 clearTimeout(timeout);
1884 timeout = setTimeout(function(){
1885 each(Chart.instances,function(instance){
1886 // If the responsive flag is set in the chart instance config
1887 // Cascade the resize event down to the chart.
1888 if (instance.options.responsive){
1889 instance.resize(instance.render, true);
1890 }
1891 });
1892 }, 50);
1893 };
1894 })());
1895
1896
1897 if (amd) {
1898 define(function(){
1899 return Chart;
1900 });
1901 } else if (typeof module === 'object' && module.exports) {
1902 module.exports = Chart;
1903 }
1904
1905 root.Chart = Chart;
1906
1907 Chart.noConflict = function(){
1908 root.Chart = previous;
1909 return Chart;
1910 };
1911
1912 }).call(this);
1913
1914 (function(){
1915 "use strict";
1916
1917 var root = this,
1918 Chart = root.Chart,
1919 helpers = Chart.helpers;
1920
1921
1922 var defaultConfig = {
1923 //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
1924 scaleBeginAtZero : true,
1925
1926 //Boolean - Whether grid lines are shown across the chart
1927 scaleShowGridLines : true,
1928
1929 //String - Colour of the grid lines
1930 scaleGridLineColor : "rgba(0,0,0,.05)",
1931
1932 //Number - Width of the grid lines
1933 scaleGridLineWidth : 1,
1934
1935 //Boolean - If there is a stroke on each bar
1936 barShowStroke : true,
1937
1938 //Number - Pixel width of the bar stroke
1939 barStrokeWidth : 2,
1940
1941 //Number - Spacing between each of the X value sets
1942 barValueSpacing : 5,
1943
1944 //Number - Spacing between data sets within X values
1945 barDatasetSpacing : 1,
1946
1947 //String - A legend template
1948 legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
1949
1950 };
1951
1952
1953 Chart.Type.extend({
1954 name: "Bar",
1955 defaults : defaultConfig,
1956 initialize: function(data){
1957
1958 //Expose options as a scope variable here so we can access it in the ScaleClass
1959 var options = this.options;
1960
1961 this.ScaleClass = Chart.Scale.extend({
1962 offsetGridLines : true,
1963 calculateBarX : function(datasetCount, datasetIndex, barIndex){
1964 //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
1965 var xWidth = this.calculateBaseWidth(),
1966 xAbsolute = this.calculateX(barIndex) - (xWidth/2),
1967 barWidth = this.calculateBarWidth(datasetCount);
1968
1969 return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
1970 },
1971 calculateBaseWidth : function(){
1972 return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
1973 },
1974 calculateBarWidth : function(datasetCount){
1975 //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
1976 var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
1977
1978 return (baseWidth / datasetCount);
1979 }
1980 });
1981
1982 this.datasets = [];
1983
1984 //Set up tooltip events on the chart
1985 if (this.options.showTooltips){
1986 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
1987 var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
1988
1989 this.eachBars(function(bar){
1990 bar.restore(['fillColor', 'strokeColor']);
1991 });
1992 helpers.each(activeBars, function(activeBar){
1993 activeBar.fillColor = activeBar.highlightFill;
1994 activeBar.strokeColor = activeBar.highlightStroke;
1995 });
1996 this.showTooltip(activeBars);
1997 });
1998 }
1999
2000 //Declare the extension of the default point, to cater for the options passed in to the constructor
2001 this.BarClass = Chart.Rectangle.extend({
2002 strokeWidth : this.options.barStrokeWidth,
2003 showStroke : this.options.barShowStroke,
2004 ctx : this.chart.ctx
2005 });
2006
2007 //Iterate through each of the datasets, and build this into a property of the chart
2008 helpers.each(data.datasets,function(dataset,datasetIndex){
2009
2010 var datasetObject = {
2011 label : dataset.label || null,
2012 fillColor : dataset.fillColor,
2013 strokeColor : dataset.strokeColor,
2014 bars : []
2015 };
2016
2017 this.datasets.push(datasetObject);
2018
2019 helpers.each(dataset.data,function(dataPoint,index){
2020 if (helpers.isNumber(dataPoint)){
2021 //Add a new point for each piece of data, passing any required data to draw.
2022 datasetObject.bars.push(new this.BarClass({
2023 value : dataPoint,
2024 label : data.labels[index],
2025 datasetLabel: dataset.label,
2026 strokeColor : dataset.strokeColor,
2027 fillColor : dataset.fillColor,
2028 highlightFill : dataset.highlightFill || dataset.fillColor,
2029 highlightStroke : dataset.highlightStroke || dataset.strokeColor
2030 }));
2031 }
2032 },this);
2033
2034 },this);
2035
2036 this.buildScale(data.labels);
2037
2038 this.BarClass.prototype.base = this.scale.endPoint;
2039
2040 this.eachBars(function(bar, index, datasetIndex){
2041 helpers.extend(bar, {
2042 width : this.scale.calculateBarWidth(this.datasets.length),
2043 x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
2044 y: this.scale.endPoint
2045 });
2046 bar.save();
2047 }, this);
2048
2049 this.render();
2050 },
2051 update : function(){
2052 this.scale.update();
2053 // Reset any highlight colours before updating.
2054 helpers.each(this.activeElements, function(activeElement){
2055 activeElement.restore(['fillColor', 'strokeColor']);
2056 });
2057
2058 this.eachBars(function(bar){
2059 bar.save();
2060 });
2061 this.render();
2062 },
2063 eachBars : function(callback){
2064 helpers.each(this.datasets,function(dataset, datasetIndex){
2065 helpers.each(dataset.bars, callback, this, datasetIndex);
2066 },this);
2067 },
2068 getBarsAtEvent : function(e){
2069 var barsArray = [],
2070 eventPosition = helpers.getRelativePosition(e),
2071 datasetIterator = function(dataset){
2072 barsArray.push(dataset.bars[barIndex]);
2073 },
2074 barIndex;
2075
2076 for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
2077 for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
2078 if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
2079 helpers.each(this.datasets, datasetIterator);
2080 return barsArray;
2081 }
2082 }
2083 }
2084
2085 return barsArray;
2086 },
2087 buildScale : function(labels){
2088 var self = this;
2089
2090 var dataTotal = function(){
2091 var values = [];
2092 self.eachBars(function(bar){
2093 values.push(bar.value);
2094 });
2095 return values;
2096 };
2097
2098 var scaleOptions = {
2099 templateString : this.options.scaleLabel,
2100 height : this.chart.height,
2101 width : this.chart.width,
2102 ctx : this.chart.ctx,
2103 textColor : this.options.scaleFontColor,
2104 fontSize : this.options.scaleFontSize,
2105 fontStyle : this.options.scaleFontStyle,
2106 fontFamily : this.options.scaleFontFamily,
2107 valuesCount : labels.length,
2108 beginAtZero : this.options.scaleBeginAtZero,
2109 integersOnly : this.options.scaleIntegersOnly,
2110 calculateYRange: function(currentHeight){
2111 var updatedRanges = helpers.calculateScaleRange(
2112 dataTotal(),
2113 currentHeight,
2114 this.fontSize,
2115 this.beginAtZero,
2116 this.integersOnly
2117 );
2118 helpers.extend(this, updatedRanges);
2119 },
2120 xLabels : labels,
2121 showXLabels: (this.options.showXLabels) ? this.options.showXLabels : true,
2122 font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
2123 lineWidth : this.options.scaleLineWidth,
2124 lineColor : this.options.scaleLineColor,
2125 gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
2126 gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
2127 padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
2128 showLabels : this.options.scaleShowLabels,
2129 display : this.options.showScale
2130 };
2131
2132 if (this.options.scaleOverride){
2133 helpers.extend(scaleOptions, {
2134 calculateYRange: helpers.noop,
2135 steps: this.options.scaleSteps,
2136 stepValue: this.options.scaleStepWidth,
2137 min: this.options.scaleStartValue,
2138 max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
2139 });
2140 }
2141
2142 this.scale = new this.ScaleClass(scaleOptions);
2143 },
2144 addData : function(valuesArray,label){
2145 //Map the values array for each of the datasets
2146 helpers.each(valuesArray,function(value,datasetIndex){
2147 if (helpers.isNumber(value)){
2148 //Add a new point for each piece of data, passing any required data to draw.
2149 this.datasets[datasetIndex].bars.push(new this.BarClass({
2150 value : value,
2151 label : label,
2152 x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
2153 y: this.scale.endPoint,
2154 width : this.scale.calculateBarWidth(this.datasets.length),
2155 base : this.scale.endPoint,
2156 strokeColor : this.datasets[datasetIndex].strokeColor,
2157 fillColor : this.datasets[datasetIndex].fillColor
2158 }));
2159 }
2160 },this);
2161
2162 this.scale.addXLabel(label);
2163 //Then re-render the chart.
2164 this.update();
2165 },
2166 removeData : function(){
2167 this.scale.removeXLabel();
2168 //Then re-render the chart.
2169 helpers.each(this.datasets,function(dataset){
2170 dataset.bars.shift();
2171 },this);
2172 this.update();
2173 },
2174 reflow : function(){
2175 helpers.extend(this.BarClass.prototype,{
2176 y: this.scale.endPoint,
2177 base : this.scale.endPoint
2178 });
2179 var newScaleProps = helpers.extend({
2180 height : this.chart.height,
2181 width : this.chart.width
2182 });
2183 this.scale.update(newScaleProps);
2184 },
2185 draw : function(ease){
2186 var easingDecimal = ease || 1;
2187 this.clear();
2188
2189 var ctx = this.chart.ctx;
2190
2191 this.scale.draw(easingDecimal);
2192
2193 //Draw all the bars for each dataset
2194 helpers.each(this.datasets,function(dataset,datasetIndex){
2195 helpers.each(dataset.bars,function(bar,index){
2196 bar.base = this.scale.endPoint;
2197 //Transition then draw
2198 bar.transition({
2199 x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
2200 y : this.scale.calculateY(bar.value),
2201 width : this.scale.calculateBarWidth(this.datasets.length)
2202 }, easingDecimal).draw();
2203 },this);
2204
2205 },this);
2206 }
2207 });
2208
2209
2210 }).call(this);
2211 (function(){
2212 "use strict";
2213
2214 var root = this,
2215 Chart = root.Chart,
2216 //Cache a local reference to Chart.helpers
2217 helpers = Chart.helpers;
2218
2219 var defaultConfig = {
2220 //Boolean - Whether we should show a stroke on each segment
2221 segmentShowStroke : true,
2222
2223 //String - The colour of each segment stroke
2224 segmentStrokeColor : "#fff",
2225
2226 //Number - The width of each segment stroke
2227 segmentStrokeWidth : 2,
2228
2229 //The percentage of the chart that we cut out of the middle.
2230 percentageInnerCutout : 50,
2231
2232 //Number - Amount of animation steps
2233 animationSteps : 100,
2234
2235 //String - Animation easing effect
2236 animationEasing : "easeOutBounce",
2237
2238 //Boolean - Whether we animate the rotation of the Doughnut
2239 animateRotate : true,
2240
2241 //Boolean - Whether we animate scaling the Doughnut from the centre
2242 animateScale : false,
2243
2244 //String - A legend template
2245 legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
2246
2247 };
2248
2249
2250 Chart.Type.extend({
2251 //Passing in a name registers this chart in the Chart namespace
2252 name: "Doughnut",
2253 //Providing a defaults will also register the deafults in the chart namespace
2254 defaults : defaultConfig,
2255 //Initialize is fired when the chart is initialized - Data is passed in as a parameter
2256 //Config is automatically merged by the core of Chart.js, and is available at this.options
2257 initialize: function(data){
2258
2259 //Declare segments as a static property to prevent inheriting across the Chart type prototype
2260 this.segments = [];
2261 this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
2262
2263 this.SegmentArc = Chart.Arc.extend({
2264 ctx : this.chart.ctx,
2265 x : this.chart.width/2,
2266 y : this.chart.height/2
2267 });
2268
2269 //Set up tooltip events on the chart
2270 if (this.options.showTooltips){
2271 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
2272 var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
2273
2274 helpers.each(this.segments,function(segment){
2275 segment.restore(["fillColor"]);
2276 });
2277 helpers.each(activeSegments,function(activeSegment){
2278 activeSegment.fillColor = activeSegment.highlightColor;
2279 });
2280 this.showTooltip(activeSegments);
2281 });
2282 }
2283 this.calculateTotal(data);
2284
2285 helpers.each(data,function(datapoint, index){
2286 this.addData(datapoint, index, true);
2287 },this);
2288
2289 this.render();
2290 },
2291 getSegmentsAtEvent : function(e){
2292 var segmentsArray = [];
2293
2294 var location = helpers.getRelativePosition(e);
2295
2296 helpers.each(this.segments,function(segment){
2297 if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
2298 },this);
2299 return segmentsArray;
2300 },
2301 addData : function(segment, atIndex, silent){
2302 var index = atIndex || this.segments.length;
2303 this.segments.splice(index, 0, new this.SegmentArc({
2304 value : segment.value,
2305 outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
2306 innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
2307 fillColor : segment.color,
2308 highlightColor : segment.highlight || segment.color,
2309 showStroke : this.options.segmentShowStroke,
2310 strokeWidth : this.options.segmentStrokeWidth,
2311 strokeColor : this.options.segmentStrokeColor,
2312 startAngle : Math.PI * 1.5,
2313 circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
2314 label : segment.label
2315 }));
2316 if (!silent){
2317 this.reflow();
2318 this.update();
2319 }
2320 },
2321 calculateCircumference : function(value){
2322 return (Math.PI*2)*(value / this.total);
2323 },
2324 calculateTotal : function(data){
2325 this.total = 0;
2326 helpers.each(data,function(segment){
2327 this.total += segment.value;
2328 },this);
2329 },
2330 update : function(){
2331 this.calculateTotal(this.segments);
2332
2333 // Reset any highlight colours before updating.
2334 helpers.each(this.activeElements, function(activeElement){
2335 activeElement.restore(['fillColor']);
2336 });
2337
2338 helpers.each(this.segments,function(segment){
2339 segment.save();
2340 });
2341 this.render();
2342 },
2343
2344 removeData: function(atIndex){
2345 var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
2346 this.segments.splice(indexToDelete, 1);
2347 this.reflow();
2348 this.update();
2349 },
2350
2351 reflow : function(){
2352 helpers.extend(this.SegmentArc.prototype,{
2353 x : this.chart.width/2,
2354 y : this.chart.height/2
2355 });
2356 this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
2357 helpers.each(this.segments, function(segment){
2358 segment.update({
2359 outerRadius : this.outerRadius,
2360 innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
2361 });
2362 }, this);
2363 },
2364 draw : function(easeDecimal){
2365 var animDecimal = (easeDecimal) ? easeDecimal : 1;
2366 this.clear();
2367 helpers.each(this.segments,function(segment,index){
2368 segment.transition({
2369 circumference : this.calculateCircumference(segment.value),
2370 outerRadius : this.outerRadius,
2371 innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
2372 },animDecimal);
2373
2374 segment.endAngle = segment.startAngle + segment.circumference;
2375
2376 segment.draw();
2377 if (index === 0){
2378 segment.startAngle = Math.PI * 1.5;
2379 }
2380 //Check to see if it's the last segment, if not get the next and update the start angle
2381 if (index < this.segments.length-1){
2382 this.segments[index+1].startAngle = segment.endAngle;
2383 }
2384 },this);
2385
2386 }
2387 });
2388
2389 Chart.types.Doughnut.extend({
2390 name : "Pie",
2391 defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
2392 });
2393
2394 }).call(this);
2395 (function(){
2396 "use strict";
2397
2398 var root = this,
2399 Chart = root.Chart,
2400 helpers = Chart.helpers;
2401
2402 var defaultConfig = {
2403
2404 ///Boolean - Whether grid lines are shown across the chart
2405 scaleShowGridLines : true,
2406
2407 //String - Colour of the grid lines
2408 scaleGridLineColor : "rgba(0,0,0,.05)",
2409
2410 //Number - Width of the grid lines
2411 scaleGridLineWidth : 1,
2412
2413 //Boolean - Whether the line is curved between points
2414 bezierCurve : true,
2415
2416 //Number - Tension of the bezier curve between points
2417 bezierCurveTension : 0.4,
2418
2419 //Boolean - Whether to show a dot for each point
2420 pointDot : true,
2421
2422 //Number - Radius of each point dot in pixels
2423 pointDotRadius : 4,
2424
2425 //Number - Pixel width of point dot stroke
2426 pointDotStrokeWidth : 1,
2427
2428 //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
2429 pointHitDetectionRadius : 20,
2430
2431 //Boolean - Whether to show a stroke for datasets
2432 datasetStroke : true,
2433
2434 //Number - Pixel width of dataset stroke
2435 datasetStrokeWidth : 2,
2436
2437 //Boolean - Whether to fill the dataset with a colour
2438 datasetFill : true,
2439
2440 //String - A legend template
2441 legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
2442
2443 };
2444
2445
2446 Chart.Type.extend({
2447 name: "Line",
2448 defaults : defaultConfig,
2449 initialize: function(data){
2450 //Declare the extension of the default point, to cater for the options passed in to the constructor
2451 this.PointClass = Chart.Point.extend({
2452 strokeWidth : this.options.pointDotStrokeWidth,
2453 radius : this.options.pointDotRadius,
2454 display: this.options.pointDot,
2455 hitDetectionRadius : this.options.pointHitDetectionRadius,
2456 ctx : this.chart.ctx,
2457 inRange : function(mouseX){
2458 return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));
2459 }
2460 });
2461
2462 this.datasets = [];
2463
2464 //Set up tooltip events on the chart
2465 if (this.options.showTooltips){
2466 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
2467 var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
2468 this.eachPoints(function(point){
2469 point.restore(['fillColor', 'strokeColor']);
2470 });
2471 helpers.each(activePoints, function(activePoint){
2472 activePoint.fillColor = activePoint.highlightFill;
2473 activePoint.strokeColor = activePoint.highlightStroke;
2474 });
2475 this.showTooltip(activePoints);
2476 });
2477 }
2478
2479 //Iterate through each of the datasets, and build this into a property of the chart
2480 helpers.each(data.datasets,function(dataset){
2481
2482 var datasetObject = {
2483 label : dataset.label || null,
2484 fillColor : dataset.fillColor,
2485 strokeColor : dataset.strokeColor,
2486 pointColor : dataset.pointColor,
2487 pointStrokeColor : dataset.pointStrokeColor,
2488 points : []
2489 };
2490
2491 this.datasets.push(datasetObject);
2492
2493
2494 helpers.each(dataset.data,function(dataPoint,index){
2495 //Best way to do this? or in draw sequence...?
2496 if (helpers.isNumber(dataPoint)){
2497 //Add a new point for each piece of data, passing any required data to draw.
2498 datasetObject.points.push(new this.PointClass({
2499 value : dataPoint,
2500 label : data.labels[index],
2501 datasetLabel: dataset.label,
2502 strokeColor : dataset.pointStrokeColor,
2503 fillColor : dataset.pointColor,
2504 highlightFill : dataset.pointHighlightFill || dataset.pointColor,
2505 highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
2506 }));
2507 }
2508 },this);
2509
2510 this.buildScale(data.labels);
2511
2512
2513 this.eachPoints(function(point, index){
2514 helpers.extend(point, {
2515 x: this.scale.calculateX(index),
2516 y: this.scale.endPoint
2517 });
2518 point.save();
2519 }, this);
2520
2521 },this);
2522
2523
2524 this.render();
2525 },
2526 update : function(){
2527 this.scale.update();
2528 // Reset any highlight colours before updating.
2529 helpers.each(this.activeElements, function(activeElement){
2530 activeElement.restore(['fillColor', 'strokeColor']);
2531 });
2532 this.eachPoints(function(point){
2533 point.save();
2534 });
2535 this.render();
2536 },
2537 eachPoints : function(callback){
2538 helpers.each(this.datasets,function(dataset){
2539 helpers.each(dataset.points,callback,this);
2540 },this);
2541 },
2542 getPointsAtEvent : function(e){
2543 var pointsArray = [],
2544 eventPosition = helpers.getRelativePosition(e);
2545 helpers.each(this.datasets,function(dataset){
2546 helpers.each(dataset.points,function(point){
2547 if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);
2548 });
2549 },this);
2550 return pointsArray;
2551 },
2552 buildScale : function(labels){
2553 var self = this;
2554
2555 var dataTotal = function(){
2556 var values = [];
2557 self.eachPoints(function(point){
2558 values.push(point.value);
2559 });
2560
2561 return values;
2562 };
2563
2564 var scaleOptions = {
2565 templateString : this.options.scaleLabel,
2566 height : this.chart.height,
2567 width : this.chart.width,
2568 ctx : this.chart.ctx,
2569 textColor : this.options.scaleFontColor,
2570 fontSize : this.options.scaleFontSize,
2571 fontStyle : this.options.scaleFontStyle,
2572 fontFamily : this.options.scaleFontFamily,
2573 valuesCount : labels.length,
2574 beginAtZero : this.options.scaleBeginAtZero,
2575 integersOnly : this.options.scaleIntegersOnly,
2576 calculateYRange : function(currentHeight){
2577 var updatedRanges = helpers.calculateScaleRange(
2578 dataTotal(),
2579 currentHeight,
2580 this.fontSize,
2581 this.beginAtZero,
2582 this.integersOnly
2583 );
2584 helpers.extend(this, updatedRanges);
2585 },
2586 xLabels : labels,
2587 showXLabels: (this.options.showXLabels) ? this.options.showXLabels : true,
2588 font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
2589 lineWidth : this.options.scaleLineWidth,
2590 lineColor : this.options.scaleLineColor,
2591 gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
2592 gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
2593 padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
2594 showLabels : this.options.scaleShowLabels,
2595 display : this.options.showScale
2596 };
2597
2598 if (this.options.scaleOverride){
2599 helpers.extend(scaleOptions, {
2600 calculateYRange: helpers.noop,
2601 steps: this.options.scaleSteps,
2602 stepValue: this.options.scaleStepWidth,
2603 min: this.options.scaleStartValue,
2604 max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
2605 });
2606 }
2607
2608
2609 this.scale = new Chart.Scale(scaleOptions);
2610 },
2611 addData : function(valuesArray,label){
2612 //Map the values array for each of the datasets
2613
2614 helpers.each(valuesArray,function(value,datasetIndex){
2615 if (helpers.isNumber(value)){
2616 //Add a new point for each piece of data, passing any required data to draw.
2617 this.datasets[datasetIndex].points.push(new this.PointClass({
2618 value : value,
2619 label : label,
2620 x: this.scale.calculateX(this.scale.valuesCount+1),
2621 y: this.scale.endPoint,
2622 strokeColor : this.datasets[datasetIndex].pointStrokeColor,
2623 fillColor : this.datasets[datasetIndex].pointColor
2624 }));
2625 }
2626 },this);
2627
2628 this.scale.addXLabel(label);
2629 //Then re-render the chart.
2630 this.update();
2631 },
2632 removeData : function(){
2633 this.scale.removeXLabel();
2634 //Then re-render the chart.
2635 helpers.each(this.datasets,function(dataset){
2636 dataset.points.shift();
2637 },this);
2638 this.update();
2639 },
2640 reflow : function(){
2641 var newScaleProps = helpers.extend({
2642 height : this.chart.height,
2643 width : this.chart.width
2644 });
2645 this.scale.update(newScaleProps);
2646 },
2647 draw : function(ease){
2648 var easingDecimal = ease || 1;
2649 this.clear();
2650
2651 var ctx = this.chart.ctx;
2652
2653 this.scale.draw(easingDecimal);
2654
2655
2656 helpers.each(this.datasets,function(dataset){
2657
2658 //Transition each point first so that the line and point drawing isn't out of sync
2659 //We can use this extra loop to calculate the control points of this dataset also in this loop
2660
2661 helpers.each(dataset.points,function(point,index){
2662 point.transition({
2663 y : this.scale.calculateY(point.value),
2664 x : this.scale.calculateX(index)
2665 }, easingDecimal);
2666
2667 },this);
2668
2669
2670 // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
2671 // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
2672 if (this.options.bezierCurve){
2673 helpers.each(dataset.points,function(point,index){
2674 //If we're at the start or end, we don't have a previous/next point
2675 //By setting the tension to 0 here, the curve will transition to straight at the end
2676 if (index === 0){
2677 point.controlPoints = helpers.splineCurve(point,point,dataset.points[index+1],0);
2678 }
2679 else if (index >= dataset.points.length-1){
2680 point.controlPoints = helpers.splineCurve(dataset.points[index-1],point,point,0);
2681 }
2682 else{
2683 point.controlPoints = helpers.splineCurve(dataset.points[index-1],point,dataset.points[index+1],this.options.bezierCurveTension);
2684 }
2685 },this);
2686 }
2687
2688
2689 //Draw the line between all the points
2690 ctx.lineWidth = this.options.datasetStrokeWidth;
2691 ctx.strokeStyle = dataset.strokeColor;
2692 ctx.beginPath();
2693 helpers.each(dataset.points,function(point,index){
2694 if (index>0){
2695 if(this.options.bezierCurve){
2696 ctx.bezierCurveTo(
2697 dataset.points[index-1].controlPoints.outer.x,
2698 dataset.points[index-1].controlPoints.outer.y,
2699 point.controlPoints.inner.x,
2700 point.controlPoints.inner.y,
2701 point.x,
2702 point.y
2703 );
2704 }
2705 else{
2706 ctx.lineTo(point.x,point.y);
2707 }
2708
2709 }
2710 else{
2711 ctx.moveTo(point.x,point.y);
2712 }
2713 },this);
2714 ctx.stroke();
2715
2716
2717 if (this.options.datasetFill){
2718 //Round off the line by going to the base of the chart, back to the start, then fill.
2719 ctx.lineTo(dataset.points[dataset.points.length-1].x, this.scale.endPoint);
2720 ctx.lineTo(this.scale.calculateX(0), this.scale.endPoint);
2721 ctx.fillStyle = dataset.fillColor;
2722 ctx.closePath();
2723 ctx.fill();
2724 }
2725
2726 //Now draw the points over the line
2727 //A little inefficient double looping, but better than the line
2728 //lagging behind the point positions
2729 helpers.each(dataset.points,function(point){
2730 point.draw();
2731 });
2732
2733 },this);
2734 }
2735 });
2736
2737
2738 }).call(this);
2739 (function(){
2740 "use strict";
2741
2742 var root = this,
2743 Chart = root.Chart,
2744 //Cache a local reference to Chart.helpers
2745 helpers = Chart.helpers;
2746
2747 var defaultConfig = {
2748 //Boolean - Show a backdrop to the scale label
2749 scaleShowLabelBackdrop : true,
2750
2751 //String - The colour of the label backdrop
2752 scaleBackdropColor : "rgba(255,255,255,0.75)",
2753
2754 // Boolean - Whether the scale should begin at zero
2755 scaleBeginAtZero : true,
2756
2757 //Number - The backdrop padding above & below the label in pixels
2758 scaleBackdropPaddingY : 2,
2759
2760 //Number - The backdrop padding to the side of the label in pixels
2761 scaleBackdropPaddingX : 2,
2762
2763 //Boolean - Show line for each value in the scale
2764 scaleShowLine : true,
2765
2766 //Boolean - Stroke a line around each segment in the chart
2767 segmentShowStroke : true,
2768
2769 //String - The colour of the stroke on each segement.
2770 segmentStrokeColor : "#fff",
2771
2772 //Number - The width of the stroke value in pixels
2773 segmentStrokeWidth : 2,
2774
2775 //Number - Amount of animation steps
2776 animationSteps : 100,
2777
2778 //String - Animation easing effect.
2779 animationEasing : "easeOutBounce",
2780
2781 //Boolean - Whether to animate the rotation of the chart
2782 animateRotate : true,
2783
2784 //Boolean - Whether to animate scaling the chart from the centre
2785 animateScale : false,
2786
2787 //String - A legend template
2788 legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
2789 };
2790
2791
2792 Chart.Type.extend({
2793 //Passing in a name registers this chart in the Chart namespace
2794 name: "PolarArea",
2795 //Providing a defaults will also register the deafults in the chart namespace
2796 defaults : defaultConfig,
2797 //Initialize is fired when the chart is initialized - Data is passed in as a parameter
2798 //Config is automatically merged by the core of Chart.js, and is available at this.options
2799 initialize: function(data){
2800 this.segments = [];
2801 //Declare segment class as a chart instance specific class, so it can share props for this instance
2802 this.SegmentArc = Chart.Arc.extend({
2803 showStroke : this.options.segmentShowStroke,
2804 strokeWidth : this.options.segmentStrokeWidth,
2805 strokeColor : this.options.segmentStrokeColor,
2806 ctx : this.chart.ctx,
2807 innerRadius : 0,
2808 x : this.chart.width/2,
2809 y : this.chart.height/2
2810 });
2811 this.scale = new Chart.RadialScale({
2812 display: this.options.showScale,
2813 fontStyle: this.options.scaleFontStyle,
2814 fontSize: this.options.scaleFontSize,
2815 fontFamily: this.options.scaleFontFamily,
2816 fontColor: this.options.scaleFontColor,
2817 showLabels: this.options.scaleShowLabels,
2818 showLabelBackdrop: this.options.scaleShowLabelBackdrop,
2819 backdropColor: this.options.scaleBackdropColor,
2820 backdropPaddingY : this.options.scaleBackdropPaddingY,
2821 backdropPaddingX: this.options.scaleBackdropPaddingX,
2822 lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
2823 lineColor: this.options.scaleLineColor,
2824 lineArc: true,
2825 width: this.chart.width,
2826 height: this.chart.height,
2827 xCenter: this.chart.width/2,
2828 yCenter: this.chart.height/2,
2829 ctx : this.chart.ctx,
2830 templateString: this.options.scaleLabel,
2831 valuesCount: data.length
2832 });
2833
2834 this.updateScaleRange(data);
2835
2836 this.scale.update();
2837
2838 helpers.each(data,function(segment,index){
2839 this.addData(segment,index,true);
2840 },this);
2841
2842 //Set up tooltip events on the chart
2843 if (this.options.showTooltips){
2844 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
2845 var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
2846 helpers.each(this.segments,function(segment){
2847 segment.restore(["fillColor"]);
2848 });
2849 helpers.each(activeSegments,function(activeSegment){
2850 activeSegment.fillColor = activeSegment.highlightColor;
2851 });
2852 this.showTooltip(activeSegments);
2853 });
2854 }
2855
2856 this.render();
2857 },
2858 getSegmentsAtEvent : function(e){
2859 var segmentsArray = [];
2860
2861 var location = helpers.getRelativePosition(e);
2862
2863 helpers.each(this.segments,function(segment){
2864 if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
2865 },this);
2866 return segmentsArray;
2867 },
2868 addData : function(segment, atIndex, silent){
2869 var index = atIndex || this.segments.length;
2870
2871 this.segments.splice(index, 0, new this.SegmentArc({
2872 fillColor: segment.color,
2873 highlightColor: segment.highlight || segment.color,
2874 label: segment.label,
2875 value: segment.value,
2876 outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
2877 circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
2878 startAngle: Math.PI * 1.5
2879 }));
2880 if (!silent){
2881 this.reflow();
2882 this.update();
2883 }
2884 },
2885 removeData: function(atIndex){
2886 var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
2887 this.segments.splice(indexToDelete, 1);
2888 this.reflow();
2889 this.update();
2890 },
2891 calculateTotal: function(data){
2892 this.total = 0;
2893 helpers.each(data,function(segment){
2894 this.total += segment.value;
2895 },this);
2896 this.scale.valuesCount = this.segments.length;
2897 },
2898 updateScaleRange: function(datapoints){
2899 var valuesArray = [];
2900 helpers.each(datapoints,function(segment){
2901 valuesArray.push(segment.value);
2902 });
2903
2904 var scaleSizes = (this.options.scaleOverride) ?
2905 {
2906 steps: this.options.scaleSteps,
2907 stepValue: this.options.scaleStepWidth,
2908 min: this.options.scaleStartValue,
2909 max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
2910 } :
2911 helpers.calculateScaleRange(
2912 valuesArray,
2913 helpers.min([this.chart.width, this.chart.height])/2,
2914 this.options.scaleFontSize,
2915 this.options.scaleBeginAtZero,
2916 this.options.scaleIntegersOnly
2917 );
2918
2919 helpers.extend(
2920 this.scale,
2921 scaleSizes,
2922 {
2923 size: helpers.min([this.chart.width, this.chart.height]),
2924 xCenter: this.chart.width/2,
2925 yCenter: this.chart.height/2
2926 }
2927 );
2928
2929 },
2930 update : function(){
2931 this.calculateTotal(this.segments);
2932
2933 helpers.each(this.segments,function(segment){
2934 segment.save();
2935 });
2936 this.render();
2937 },
2938 reflow : function(){
2939 helpers.extend(this.SegmentArc.prototype,{
2940 x : this.chart.width/2,
2941 y : this.chart.height/2
2942 });
2943 this.updateScaleRange(this.segments);
2944 this.scale.update();
2945
2946 helpers.extend(this.scale,{
2947 xCenter: this.chart.width/2,
2948 yCenter: this.chart.height/2
2949 });
2950
2951 helpers.each(this.segments, function(segment){
2952 segment.update({
2953 outerRadius : this.scale.calculateCenterOffset(segment.value)
2954 });
2955 }, this);
2956
2957 },
2958 draw : function(ease){
2959 var easingDecimal = ease || 1;
2960 //Clear & draw the canvas
2961 this.clear();
2962 helpers.each(this.segments,function(segment, index){
2963 segment.transition({
2964 circumference : this.scale.getCircumference(),
2965 outerRadius : this.scale.calculateCenterOffset(segment.value)
2966 },easingDecimal);
2967
2968 segment.endAngle = segment.startAngle + segment.circumference;
2969
2970 // If we've removed the first segment we need to set the first one to
2971 // start at the top.
2972 if (index === 0){
2973 segment.startAngle = Math.PI * 1.5;
2974 }
2975
2976 //Check to see if it's the last segment, if not get the next and update the start angle
2977 if (index < this.segments.length - 1){
2978 this.segments[index+1].startAngle = segment.endAngle;
2979 }
2980 segment.draw();
2981 }, this);
2982 this.scale.draw();
2983 }
2984 });
2985
2986 }).call(this);
2987 (function(){
2988 "use strict";
2989
2990 var root = this,
2991 Chart = root.Chart,
2992 helpers = Chart.helpers;
2993
2994
2995
2996 Chart.Type.extend({
2997 name: "Radar",
2998 defaults:{
2999 //Boolean - Whether to show lines for each scale point
3000 scaleShowLine : true,
3001
3002 //Boolean - Whether we show the angle lines out of the radar
3003 angleShowLineOut : true,
3004
3005 //Boolean - Whether to show labels on the scale
3006 scaleShowLabels : false,
3007
3008 // Boolean - Whether the scale should begin at zero
3009 scaleBeginAtZero : true,
3010
3011 //String - Colour of the angle line
3012 angleLineColor : "rgba(0,0,0,.1)",
3013
3014 //Number - Pixel width of the angle line
3015 angleLineWidth : 1,
3016
3017 //String - Point label font declaration
3018 pointLabelFontFamily : "'Arial'",
3019
3020 //String - Point label font weight
3021 pointLabelFontStyle : "normal",
3022
3023 //Number - Point label font size in pixels
3024 pointLabelFontSize : 10,
3025
3026 //String - Point label font colour
3027 pointLabelFontColor : "#666",
3028
3029 //Boolean - Whether to show a dot for each point
3030 pointDot : true,
3031
3032 //Number - Radius of each point dot in pixels
3033 pointDotRadius : 3,
3034
3035 //Number - Pixel width of point dot stroke
3036 pointDotStrokeWidth : 1,
3037
3038 //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
3039 pointHitDetectionRadius : 20,
3040
3041 //Boolean - Whether to show a stroke for datasets
3042 datasetStroke : true,
3043
3044 //Number - Pixel width of dataset stroke
3045 datasetStrokeWidth : 2,
3046
3047 //Boolean - Whether to fill the dataset with a colour
3048 datasetFill : true,
3049
3050 //String - A legend template
3051 legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
3052
3053 },
3054
3055 initialize: function(data){
3056 this.PointClass = Chart.Point.extend({
3057 strokeWidth : this.options.pointDotStrokeWidth,
3058 radius : this.options.pointDotRadius,
3059 display: this.options.pointDot,
3060 hitDetectionRadius : this.options.pointHitDetectionRadius,
3061 ctx : this.chart.ctx
3062 });
3063
3064 this.datasets = [];
3065
3066 this.buildScale(data);
3067
3068 //Set up tooltip events on the chart
3069 if (this.options.showTooltips){
3070 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
3071 var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
3072
3073 this.eachPoints(function(point){
3074 point.restore(['fillColor', 'strokeColor']);
3075 });
3076 helpers.each(activePointsCollection, function(activePoint){
3077 activePoint.fillColor = activePoint.highlightFill;
3078 activePoint.strokeColor = activePoint.highlightStroke;
3079 });
3080
3081 this.showTooltip(activePointsCollection);
3082 });
3083 }
3084
3085 //Iterate through each of the datasets, and build this into a property of the chart
3086 helpers.each(data.datasets,function(dataset){
3087
3088 var datasetObject = {
3089 label: dataset.label || null,
3090 fillColor : dataset.fillColor,
3091 strokeColor : dataset.strokeColor,
3092 pointColor : dataset.pointColor,
3093 pointStrokeColor : dataset.pointStrokeColor,
3094 points : []
3095 };
3096
3097 this.datasets.push(datasetObject);
3098
3099 helpers.each(dataset.data,function(dataPoint,index){
3100 //Best way to do this? or in draw sequence...?
3101 if (helpers.isNumber(dataPoint)){
3102 //Add a new point for each piece of data, passing any required data to draw.
3103 var pointPosition;
3104 if (!this.scale.animation){
3105 pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
3106 }
3107 datasetObject.points.push(new this.PointClass({
3108 value : dataPoint,
3109 label : data.labels[index],
3110 datasetLabel: dataset.label,
3111 x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
3112 y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
3113 strokeColor : dataset.pointStrokeColor,
3114 fillColor : dataset.pointColor,
3115 highlightFill : dataset.pointHighlightFill || dataset.pointColor,
3116 highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
3117 }));
3118 }
3119 },this);
3120
3121 },this);
3122
3123 this.render();
3124 },
3125 eachPoints : function(callback){
3126 helpers.each(this.datasets,function(dataset){
3127 helpers.each(dataset.points,callback,this);
3128 },this);
3129 },
3130
3131 getPointsAtEvent : function(evt){
3132 var mousePosition = helpers.getRelativePosition(evt),
3133 fromCenter = helpers.getAngleFromPoint({
3134 x: this.scale.xCenter,
3135 y: this.scale.yCenter
3136 }, mousePosition);
3137
3138 var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
3139 pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
3140 activePointsCollection = [];
3141
3142 // If we're at the top, make the pointIndex 0 to get the first of the array.
3143 if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
3144 pointIndex = 0;
3145 }
3146
3147 if (fromCenter.distance <= this.scale.drawingArea){
3148 helpers.each(this.datasets, function(dataset){
3149 activePointsCollection.push(dataset.points[pointIndex]);
3150 });
3151 }
3152
3153 return activePointsCollection;
3154 },
3155
3156 buildScale : function(data){
3157 this.scale = new Chart.RadialScale({
3158 display: this.options.showScale,
3159 fontStyle: this.options.scaleFontStyle,
3160 fontSize: this.options.scaleFontSize,
3161 fontFamily: this.options.scaleFontFamily,
3162 fontColor: this.options.scaleFontColor,
3163 showLabels: this.options.scaleShowLabels,
3164 showLabelBackdrop: this.options.scaleShowLabelBackdrop,
3165 backdropColor: this.options.scaleBackdropColor,
3166 backdropPaddingY : this.options.scaleBackdropPaddingY,
3167 backdropPaddingX: this.options.scaleBackdropPaddingX,
3168 lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
3169 lineColor: this.options.scaleLineColor,
3170 angleLineColor : this.options.angleLineColor,
3171 angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
3172 // Point labels at the edge of each line
3173 pointLabelFontColor : this.options.pointLabelFontColor,
3174 pointLabelFontSize : this.options.pointLabelFontSize,
3175 pointLabelFontFamily : this.options.pointLabelFontFamily,
3176 pointLabelFontStyle : this.options.pointLabelFontStyle,
3177 height : this.chart.height,
3178 width: this.chart.width,
3179 xCenter: this.chart.width/2,
3180 yCenter: this.chart.height/2,
3181 ctx : this.chart.ctx,
3182 templateString: this.options.scaleLabel,
3183 labels: data.labels,
3184 valuesCount: data.datasets[0].data.length
3185 });
3186
3187 this.scale.setScaleSize();
3188 this.updateScaleRange(data.datasets);
3189 this.scale.buildYLabels();
3190 },
3191 updateScaleRange: function(datasets){
3192 var valuesArray = (function(){
3193 var totalDataArray = [];
3194 helpers.each(datasets,function(dataset){
3195 if (dataset.data){
3196 totalDataArray = totalDataArray.concat(dataset.data);
3197 }
3198 else {
3199 helpers.each(dataset.points, function(point){
3200 totalDataArray.push(point.value);
3201 });
3202 }
3203 });
3204 return totalDataArray;
3205 })();
3206
3207
3208 var scaleSizes = (this.options.scaleOverride) ?
3209 {
3210 steps: this.options.scaleSteps,
3211 stepValue: this.options.scaleStepWidth,
3212 min: this.options.scaleStartValue,
3213 max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
3214 } :
3215 helpers.calculateScaleRange(
3216 valuesArray,
3217 helpers.min([this.chart.width, this.chart.height])/2,
3218 this.options.scaleFontSize,
3219 this.options.scaleBeginAtZero,
3220 this.options.scaleIntegersOnly
3221 );
3222
3223 helpers.extend(
3224 this.scale,
3225 scaleSizes
3226 );
3227
3228 },
3229 addData : function(valuesArray,label){
3230 //Map the values array for each of the datasets
3231 this.scale.valuesCount++;
3232 helpers.each(valuesArray,function(value,datasetIndex){
3233 if (helpers.isNumber(value)){
3234 var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
3235 this.datasets[datasetIndex].points.push(new this.PointClass({
3236 value : value,
3237 label : label,
3238 x: pointPosition.x,
3239 y: pointPosition.y,
3240 strokeColor : this.datasets[datasetIndex].pointStrokeColor,
3241 fillColor : this.datasets[datasetIndex].pointColor
3242 }));
3243 }
3244 },this);
3245
3246 this.scale.labels.push(label);
3247
3248 this.reflow();
3249
3250 this.update();
3251 },
3252 removeData : function(){
3253 this.scale.valuesCount--;
3254 this.scale.labels.shift();
3255 helpers.each(this.datasets,function(dataset){
3256 dataset.points.shift();
3257 },this);
3258 this.reflow();
3259 this.update();
3260 },
3261 update : function(){
3262 this.eachPoints(function(point){
3263 point.save();
3264 });
3265 this.reflow();
3266 this.render();
3267 },
3268 reflow: function(){
3269 helpers.extend(this.scale, {
3270 width : this.chart.width,
3271 height: this.chart.height,
3272 size : helpers.min([this.chart.width, this.chart.height]),
3273 xCenter: this.chart.width/2,
3274 yCenter: this.chart.height/2
3275 });
3276 this.updateScaleRange(this.datasets);
3277 this.scale.setScaleSize();
3278 this.scale.buildYLabels();
3279 },
3280 draw : function(ease){
3281 var easeDecimal = ease || 1,
3282 ctx = this.chart.ctx;
3283 this.clear();
3284 this.scale.draw();
3285
3286 helpers.each(this.datasets,function(dataset){
3287
3288 //Transition each point first so that the line and point drawing isn't out of sync
3289 helpers.each(dataset.points,function(point,index){
3290 point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
3291 },this);
3292
3293
3294
3295 //Draw the line between all the points
3296 ctx.lineWidth = this.options.datasetStrokeWidth;
3297 ctx.strokeStyle = dataset.strokeColor;
3298 ctx.beginPath();
3299 helpers.each(dataset.points,function(point,index){
3300 if (index === 0){
3301 ctx.moveTo(point.x,point.y);
3302 }
3303 else{
3304 ctx.lineTo(point.x,point.y);
3305 }
3306 },this);
3307 ctx.closePath();
3308 ctx.stroke();
3309
3310 ctx.fillStyle = dataset.fillColor;
3311 ctx.fill();
3312
3313 //Now draw the points over the line
3314 //A little inefficient double looping, but better than the line
3315 //lagging behind the point positions
3316 helpers.each(dataset.points,function(point){
3317 point.draw();
3318 });
3319
3320 },this);
3321
3322 }
3323
3324 });
3325
3326
3327
3328
3329
3330 }).call(this);
+0
-11
faraday/server/www/script/Chart.min.js less more
0 /*!
1 * Chart.js
2 * http://chartjs.org/
3 * Version: 1.0.1-beta.3
4 *
5 * Copyright 2014 Nick Downie
6 * Released under the MIT license
7 * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
8 */
9 (function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;this.width=t.canvas.width,this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n<t.length;n++)i.apply(e,[t[n],n].concat(s))}else for(var o in t)i.apply(e,[t[o],o].concat(s))},o=s.clone=function(t){var i={};return n(t,function(e,s){t.hasOwnProperty(s)&&(i[s]=e)}),i},a=s.extend=function(t){return n(Array.prototype.slice.call(arguments,1),function(i){n(i,function(e,s){i.hasOwnProperty(s)&&(t[s]=e)})}),t},h=s.merge=function(){var t=Array.prototype.slice.call(arguments,0);return t.unshift({}),a.apply(null,t)},l=s.indexOf=function(t,i){if(Array.prototype.indexOf)return t.indexOf(i);for(var e=0;e<t.length;e++)if(t[e]===i)return e;return-1},r=s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e},c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof t.define&&t.define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),x=s.radians=function(t){return t*(Math.PI/180)},S=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),C=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),y=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=C(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),x=Math.round(f/v);(x>a||a>2*x)&&!h;)if(x>a)v*=2,x=Math.round(f/v),x%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,x=Math.round(f/v)}else v/=2,x=Math.round(f/v);return h&&(x=o,v=f/x),{steps:x,stepValue:v,min:p,max:p+x*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),b=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=y(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),-(s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)))},easeOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),s*Math.pow(2,-10*t)*Math.sin(2*(1*t-i)*Math.PI/e)+1)},easeInOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:2==(t/=.5)?1:(e||(e=.3*1.5),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),1>t?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-b.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*b.easeInBounce(2*t):.5*b.easeOutBounce(2*t-1)+.5}}),w=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=(s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),s.animationLoop=function(t,i,e,s,n,o){var a=0,h=b[e]||b.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=w(l):n.apply(o)};w(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),L=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},k=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},P(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){L(t.chart.canvas,e,i)})}),F=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},R=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),T=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},M=s.fontString=function(t,i,e){return i+" "+t+"px "+e},W=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},z=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return T(this.chart),this},stop:function(){return s.cancelAnimFrame.call(t,this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=F(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:R(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return y(this.options.legendTemplate,this)},destroy:function(){this.clear(),k(this,this.events),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:y(this.options.tooltipTemplate,t),chart:this.chart}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)<Math.pow(e,2)},draw:function(){if(this.display){var t=this.ctx;t.beginPath(),t.arc(this.x,this.y,this.radius,0,2*Math.PI),t.closePath(),t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.fillStyle=this.fillColor,t.fill(),t.stroke()}}}),e.Arc=e.Element.extend({inRange:function(t,i){var e=s.getAngleFromPoint(this,{x:t,y:i}),n=e.angle>=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;switch(t.fillStyle=this.fillColor,this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}z(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=M(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=W(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){z(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(y(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?W(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),t<this.yLabelWidth&&this.calculateXLabelRotation()},calculateXLabelRotation:function(){this.ctx.font=this.font;var t,i,e=this.ctx.measureText(this.xLabels[0]).width,s=this.ctx.measureText(this.xLabels[this.xLabels.length-1]).width;if(this.xScalePaddingRight=s/2+3,this.xScalePaddingLeft=e/2>this.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=W(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(x(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(x(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/(this.valuesCount-(this.offsetGridLines?0:1)),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a);t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+S(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+S(this.lineWidth),o=this.xLabelRotation>0;t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*x(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(y(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;i<this.valuesCount;i++)t=this.getPointPosition(i,d),e=this.ctx.measureText(y(this.templateString,{value:this.labels[i]})).width+5,0===i||i===this.valuesCount/2?(s=e/2,t.x+s>p&&(p=t.x+s,n=i),t.x-s<g&&(g=t.x-s,a=i)):i<this.valuesCount/2?t.x+e>p&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e<g&&(g=t.x-e,a=i);l=g,r=Math.ceil(p-this.width),o=this.getIndexAngle(n),h=this.getIndexAngle(a),c=r/Math.sin(o+Math.PI/2),u=l/Math.sin(h+Math.PI/2),c=f(c)?c:0,u=f(u)?u:0,this.drawingArea=d-(u+c)/2,this.setCenterPoint(u,c)},setCenterPoint:function(t,i){var e=this.width-i-this.drawingArea,s=t+this.drawingArea;this.xCenter=(s+e)/2,this.yCenter=this.height/2},getIndexAngle:function(t){var i=2*Math.PI/this.valuesCount;return t*i-Math.PI/2},getPointPosition:function(t,i){var e=this.getIndexAngle(t);return{x:Math.cos(e)*i+this.xCenter,y:Math.sin(e)*i+this.yCenter}},draw:function(){if(this.display){var t=this.ctx;if(n(this.yLabels,function(i,e){if(e>0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a<this.valuesCount;a++)s=this.getPointPosition(a,this.calculateCenterOffset(this.min+e*this.stepValue)),0===a?t.moveTo(s.x,s.y):t.lineTo(s.x,s.y);t.closePath(),t.stroke()}if(this.showLabels){if(t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.showLabelBackdrop){var h=t.measureText(i).width;t.fillStyle=this.backdropColor,t.fillRect(this.xCenter-h/2-this.backdropPaddingX,o-this.fontSize/2-this.backdropPaddingY,h+2*this.backdropPaddingX,this.fontSize+2*this.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.fontColor,t.fillText(i,this.xCenter,o)}}},this),!this.lineArc){t.lineWidth=this.angleLineWidth,t.strokeStyle=this.angleLineColor;for(var i=this.valuesCount-1;i>=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].fillColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(n,o){e.isNumber(n)&&s.bars.push(new this.BarClass({value:n,label:t.labels[o],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<this.datasets.length;a++)for(i=0;i<this.datasets[a].bars.length;i++)if(this.datasets[a].bars[i].inRange(n.x,n.y))return e.each(this.datasets,o),s;return s},buildScale:function(t){var i=this,s=function(){var t=[];return i.eachBars(function(i){t.push(i.value)}),t},n={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(s(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.barShowStroke?this.options.barStrokeWidth:0,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(n,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new this.ScaleClass(n)},addData:function(t,i){e.each(t,function(t,s){e.isNumber(t)&&this.datasets[s].bars.push(new this.BarClass({value:t,label:i,x:this.scale.calculateBarX(this.datasets.length,s,this.scale.valuesCount+1),y:this.scale.endPoint,width:this.scale.calculateBarWidth(this.datasets.length),base:this.scale.endPoint,strokeColor:this.datasets[s].strokeColor,fillColor:this.datasets[s].fillColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){e.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t,s){e.each(t.bars,function(t,e){t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,s,e),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},i).draw()},this)},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];
10 e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(t/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle)},this)}}),i.types.Doughnut.extend({name:"Pie",defaults:e.merge(s,{percentageInnerCutout:0})})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,bezierCurve:!0,bezierCurveTension:.4,pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)<Math.pow(this.radius+this.hitDetectionRadius,2)}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(n,o){e.isNumber(n)&&s.points.push(new this.PointClass({value:n,label:t.labels[o],datasetLabel:i.label,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this),this.buildScale(t.labels),this.eachPoints(function(t,i){e.extend(t,{x:this.scale.calculateX(i),y:this.scale.endPoint}),t.save()},this)},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachPoints(function(t){t.save()}),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.datasets,function(t){e.each(t.points,function(t){t.inRange(s.x,s.y)&&i.push(t)})},this),i},buildScale:function(t){var s=this,n=function(){var t=[];return s.eachPoints(function(i){t.push(i.value)}),t},o={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(n(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.pointDotRadius+this.options.pointDotStrokeWidth,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(o,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new i.Scale(o)},addData:function(t,i){e.each(t,function(t,s){e.isNumber(t)&&this.datasets[s].points.push(new this.PointClass({value:t,label:i,x:this.scale.calculateX(this.scale.valuesCount+1),y:this.scale.endPoint,strokeColor:this.datasets[s].pointStrokeColor,fillColor:this.datasets[s].pointColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.points.shift()},this),this.update()},reflow:function(){var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();var s=this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.transition({y:this.scale.calculateY(t.value),x:this.scale.calculateX(e)},i)},this),this.options.bezierCurve&&e.each(t.points,function(i,s){i.controlPoints=0===s?e.splineCurve(i,i,t.points[s+1],0):s>=t.points.length-1?e.splineCurve(t.points[s-1],i,i,0):e.splineCurve(t.points[s-1],i,t.points[s+1],this.options.bezierCurveTension)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(i,e){e>0?this.options.bezierCurve?s.bezierCurveTo(t.points[e-1].controlPoints.outer.x,t.points[e-1].controlPoints.outer.y,i.controlPoints.inner.x,i.controlPoints.inner.y,i.x,i.y):s.lineTo(i.x,i.y):s.moveTo(i.x,i.y)},this),s.stroke(),this.options.datasetFill&&(s.lineTo(t.points[t.points.length-1].x,this.scale.endPoint),s.lineTo(this.scale.calculateX(0),this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(t.points,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle),t.draw()},this),this.scale.draw()}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers;i.Type.extend({name:"Radar",defaults:{scaleShowLine:!0,angleShowLineOut:!0,scaleShowLabels:!1,scaleBeginAtZero:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:10,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(n,o){if(e.isNumber(n)){var a;this.scale.animation||(a=this.scale.getPointPosition(o,this.scale.calculateCenterOffset(n))),s.points.push(new this.PointClass({value:n,label:t.labels[o],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:a.x,y:this.options.animation?this.scale.yCenter:a.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))}},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,s){if(e.isNumber(t)){var n=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[s].points.push(new this.PointClass({value:t,label:i,x:n.x,y:n.y,strokeColor:this.datasets[s].pointStrokeColor,fillColor:this.datasets[s].pointColor}))}},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.draw()})},this)}})}.call(this);
+0
-8
faraday/server/www/script/anguilar-ui-notification.min.css less more
0 /**
1 * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
2 * @author Alex_Crack
3 * @version v0.2.0
4 * @link https://github.com/alexcrack/angular-ui-notification
5 * @license MIT
6 */
7 .ui-notification{position:fixed;z-index:9999;width:300px;-webkit-transition:all ease .5s;-o-transition:all ease .5s;transition:all ease .5s;color:#fff;border-radius:0;background:#337ab7;box-shadow:5px 5px 10px rgba(0,0,0,.3)}.ui-notification.clickable{cursor:pointer}.ui-notification.clickable:hover{opacity:.7}.ui-notification.killed{-webkit-transition:opacity ease 1s;-o-transition:opacity ease 1s;transition:opacity ease 1s;opacity:0}.ui-notification>h3{font-size:14px;font-weight:700;display:block;margin:10px 10px 0;padding:0 0 5px;text-align:left;border-bottom:1px solid rgba(255,255,255,.3)}.ui-notification a{color:#fff}.ui-notification a:hover{text-decoration:underline}.ui-notification>.message{margin:10px}.ui-notification.warning{color:#fff;background:#f0ad4e}.ui-notification.error{color:#fff;background:#d9534f}.ui-notification.success{color:#fff;background:#5cb85c}.ui-notification.info{color:#fff;background:#5bc0de}
+0
-2
faraday/server/www/script/angular-chart.css less more
0 .chart-legend,.bar-legend,.line-legend,.pie-legend,.radar-legend,.polararea-legend,.doughnut-legend{list-style-type:none;margin-top:5px;text-align:center;-webkit-padding-start:0;-moz-padding-start:0;padding-left:0}.chart-legend li,.bar-legend li,.line-legend li,.pie-legend li,.radar-legend li,.polararea-legend li,.doughnut-legend li{display:inline-block;white-space:nowrap;position:relative;margin-bottom:4px;border-radius:5px;padding:2px 8px 2px 28px;font-size:smaller;cursor:default}.chart-legend li span,.bar-legend li span,.line-legend li span,.pie-legend li span,.radar-legend li span,.polararea-legend li span,.doughnut-legend li span{display:block;position:absolute;left:0;top:0;width:20px;height:20px;border-radius:5px}
1 /*# sourceMappingURL=angular-chart.css.map */
+0
-1
faraday/server/www/script/angular-chart.css.map less more
0 {"version":3,"sources":["angular-chart.less"],"names":[],"mappings":"AAAA;AAAe;AAAa;AAAc;AAAa;AAAe;AAAmB;EACvF,qBAAA;EACA,eAAA;EACA,kBAAA;;EAEA,wBAAA;;EACA,qBAAA;;EACA,eAAA;;;AAPF,aASE;AATa,WASb;AAT0B,YAS1B;AATwC,WASxC;AATqD,aASrD;AAToE,iBASpE;AATuF,gBASvF;EACE,qBAAA;EACA,mBAAA;EACA,kBAAA;EACA,kBAAA;EACA,kBAAA;EACA,yBAAA;EACA,kBAAA;EACA,eAAA;;AAjBJ,aASE,GAUE;AAnBW,WASb,GAUE;AAnBwB,YAS1B,GAUE;AAnBsC,WASxC,GAUE;AAnBmD,aASrD,GAUE;AAnBkE,iBASpE,GAUE;AAnBqF,gBASvF,GAUE;EACE,cAAA;EACA,kBAAA;EACA,OAAA;EACA,MAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA","file":"angular-chart.css","sourcesContent":[".chart-legend, .bar-legend, .line-legend, .pie-legend, .radar-legend, .polararea-legend, .doughnut-legend {\n list-style-type: none;\n margin-top: 5px;\n text-align: center;\n /* NOTE: Browsers automatically add 40px of padding-left to all lists, so we should offset that, otherwise the legend is off-center */\n -webkit-padding-start:0; /* Webkit */\n -moz-padding-start:0; /* Mozilla */\n padding-left:0; /* IE (handles all cases, really, but we should also include the vendor-specific properties just to be safe) */\n\n li {\n display: inline-block;\n white-space: nowrap;\n position: relative;\n margin-bottom: 4px;\n border-radius: 5px;\n padding: 2px 8px 2px 28px;\n font-size: smaller;\n cursor: default;\n\n span {\n display: block;\n position: absolute;\n left: 0;\n top: 0;\n width: 20px;\n height: 20px;\n border-radius: 5px;\n }\n }\n}\n"],"sourceRoot":"/source/"}
+0
-356
faraday/server/www/script/angular-chart.min.js less more
0 (function (factory) {
1 'use strict';
2 if (typeof define === 'function' && define.amd) {
3 // AMD. Register as an anonymous module.
4 define(['angular', 'chart'], factory);
5 } else if (typeof exports === 'object') {
6 // Node/CommonJS
7 module.exports = factory(require('angular'), require('chart.js'));
8 } else {
9 // Browser globals
10 factory(angular, Chart);
11 }
12 }(function (angular, Chart) {
13 'use strict';
14
15 Chart.defaults.global.responsive = true;
16 Chart.defaults.global.multiTooltipTemplate = '<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>';
17
18 Chart.defaults.global.colours = [
19 '#97BBCD', // blue
20 '#DCDCDC', // light grey
21 '#F7464A', // red
22 '#46BFBD', // green
23 '#FDB45C', // yellow
24 '#949FB1', // grey
25 '#4D5360' // dark grey
26 ];
27
28 var usingExcanvas = typeof window.G_vmlCanvasManager === 'object' &&
29 window.G_vmlCanvasManager !== null &&
30 typeof window.G_vmlCanvasManager.initElement === 'function';
31
32 if (usingExcanvas) Chart.defaults.global.animation = false;
33
34 return angular.module('chart.js', [])
35 .provider('ChartJs', ChartJsProvider)
36 .factory('ChartJsFactory', ['ChartJs', '$timeout', ChartJsFactory])
37 .directive('chartBase', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory(); }])
38 .directive('chartLine', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('Line'); }])
39 .directive('chartBar', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('Bar'); }])
40 .directive('chartRadar', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('Radar'); }])
41 .directive('chartDoughnut', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('Doughnut'); }])
42 .directive('chartPie', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('Pie'); }])
43 .directive('chartPolarArea', ['ChartJsFactory', function (ChartJsFactory) { return new ChartJsFactory('PolarArea'); }]);
44
45 /**
46 * Wrapper for chart.js
47 * Allows configuring chart js using the provider
48 *
49 * angular.module('myModule', ['chart.js']).config(function(ChartJsProvider) {
50 * ChartJsProvider.setOptions({ responsive: true });
51 * ChartJsProvider.setOptions('Line', { responsive: false });
52 * })))
53 */
54 function ChartJsProvider () {
55 var options = {};
56 var ChartJs = {
57 Chart: Chart,
58 getOptions: function (type) {
59 var typeOptions = type && options[type] || {};
60 return angular.extend({}, options, typeOptions);
61 }
62 };
63
64 /**
65 * Allow to set global options during configuration
66 */
67 this.setOptions = function (type, customOptions) {
68 // If no type was specified set option for the global object
69 if (! customOptions) {
70 customOptions = type;
71 options = angular.extend(options, customOptions);
72 return;
73 }
74 // Set options for the specific chart
75 options[type] = angular.extend(options[type] || {}, customOptions);
76 };
77
78 this.$get = function () {
79 return ChartJs;
80 };
81 }
82
83 function ChartJsFactory (ChartJs, $timeout) {
84 return function chart (type) {
85 return {
86 restrict: 'CA',
87 scope: {
88 data: '=?',
89 labels: '=?',
90 options: '=?',
91 series: '=?',
92 colours: '=?',
93 getColour: '=?',
94 chartType: '=',
95 legend: '@',
96 click: '=?',
97 hover: '=?',
98
99 chartData: '=?',
100 chartLabels: '=?',
101 chartOptions: '=?',
102 chartSeries: '=?',
103 chartColours: '=?',
104 chartLegend: '@',
105 chartClick: '=?',
106 chartHover: '=?'
107 },
108 link: function (scope, elem/*, attrs */) {
109 var chart, container = document.createElement('div');
110 container.className = 'chart-container';
111 elem.replaceWith(container);
112 container.appendChild(elem[0]);
113
114 if (usingExcanvas) window.G_vmlCanvasManager.initElement(elem[0]);
115
116 ['data', 'labels', 'options', 'series', 'colours', 'legend', 'click', 'hover'].forEach(deprecated);
117 function aliasVar (fromName, toName) {
118 scope.$watch(fromName, function (newVal) {
119 if (typeof newVal === 'undefined') return;
120 scope[toName] = newVal;
121 });
122 }
123 /* provide backward compatibility to "old" directive names, by
124 * having an alias point from the new names to the old names. */
125 aliasVar('chartData', 'data');
126 aliasVar('chartLabels', 'labels');
127 aliasVar('chartOptions', 'options');
128 aliasVar('chartSeries', 'series');
129 aliasVar('chartColours', 'colours');
130 aliasVar('chartLegend', 'legend');
131 aliasVar('chartClick', 'click');
132 aliasVar('chartHover', 'hover');
133
134 // Order of setting "watch" matter
135
136 scope.$watch('data', function (newVal, oldVal) {
137 if (! newVal || ! newVal.length || (Array.isArray(newVal[0]) && ! newVal[0].length)) return;
138 var chartType = type || scope.chartType;
139 if (! chartType) return;
140
141 if (chart) {
142 if (canUpdateChart(newVal, oldVal)) return updateChart(chart, newVal, scope, elem);
143 chart.destroy();
144 }
145
146 createChart(chartType);
147 }, true);
148
149 scope.$watch('series', resetChart, true);
150 scope.$watch('labels', resetChart, true);
151 scope.$watch('options', resetChart, true);
152 scope.$watch('colours', resetChart, true);
153
154 scope.$watch('chartType', function (newVal, oldVal) {
155 if (isEmpty(newVal)) return;
156 if (angular.equals(newVal, oldVal)) return;
157 if (chart) chart.destroy();
158 createChart(newVal);
159 });
160
161 scope.$on('$destroy', function () {
162 if (chart) chart.destroy();
163 });
164
165 function resetChart (newVal, oldVal) {
166 if (isEmpty(newVal)) return;
167 if (angular.equals(newVal, oldVal)) return;
168 var chartType = type || scope.chartType;
169 if (! chartType) return;
170
171 // chart.update() doesn't work for series and labels
172 // so we have to re-create the chart entirely
173 if (chart) chart.destroy();
174
175 createChart(chartType);
176 }
177
178 function createChart (type) {
179 if (isResponsive(type, scope) && elem[0].clientHeight === 0 && container.clientHeight === 0) {
180 return $timeout(function () {
181 createChart(type);
182 }, 50);
183 }
184 if (! scope.data || ! scope.data.length) return;
185 scope.getColour = typeof scope.getColour === 'function' ? scope.getColour : getRandomColour;
186 scope.colours = getColours(type, scope);
187 var cvs = elem[0], ctx = cvs.getContext('2d');
188 var data = Array.isArray(scope.data[0]) ?
189 getDataSets(scope.labels, scope.data, scope.series || [], scope.colours) :
190 getData(scope.labels, scope.data, scope.colours);
191 var options = angular.extend({}, ChartJs.getOptions(type), scope.options);
192 chart = new ChartJs.Chart(ctx)[type](data, options);
193 scope.$emit('create', chart);
194
195 ['hover', 'click'].forEach(function (action) {
196 if (scope[action])
197 cvs[action === 'click' ? 'onclick' : 'onmousemove'] = getEventHandler(scope, chart, action);
198 });
199 if (scope.legend && scope.legend !== 'false') setLegend(elem, chart);
200 }
201
202 function deprecated (attr) {
203 if (typeof console !== 'undefined' && ChartJs.getOptions().env !== 'test') {
204 var warn = typeof console.warn === 'function' ? console.warn : console.log;
205 if (!! scope[attr]) {
206 warn.call(console, '"%s" is deprecated and will be removed in a future version. ' +
207 'Please use "chart-%s" instead.', attr, attr);
208 }
209 }
210 }
211 }
212 };
213 };
214
215 function canUpdateChart (newVal, oldVal) {
216 if (newVal && oldVal && newVal.length && oldVal.length) {
217 return Array.isArray(newVal[0]) ?
218 newVal.length === oldVal.length && newVal.every(function (element, index) {
219 return element.length === oldVal[index].length; }) :
220 oldVal.reduce(sum, 0) > 0 ? newVal.length === oldVal.length : false;
221 }
222 return false;
223 }
224
225 function sum (carry, val) {
226 return carry + val;
227 }
228
229 function getEventHandler (scope, chart, action) {
230 return function (evt) {
231 var atEvent = chart.getPointsAtEvent || chart.getBarsAtEvent || chart.getSegmentsAtEvent;
232 if (atEvent) {
233 var activePoints = atEvent.call(chart, evt);
234 scope[action](activePoints, evt);
235 scope.$apply();
236 }
237 };
238 }
239
240 function getColours (type, scope) {
241 var colours = angular.copy(scope.colours ||
242 ChartJs.getOptions(type).colours ||
243 Chart.defaults.global.colours
244 );
245 while (colours.length < scope.data.length) {
246 colours.push(scope.getColour());
247 }
248 return colours.map(convertColour);
249 }
250
251 function convertColour (colour) {
252 if (typeof colour === 'object' && colour !== null) return colour;
253 if (typeof colour === 'string' && colour[0] === '#') return getColour(hexToRgb(colour.substr(1)));
254 return getRandomColour();
255 }
256
257 function getRandomColour () {
258 var colour = [getRandomInt(0, 255), getRandomInt(0, 255), getRandomInt(0, 255)];
259 return getColour(colour);
260 }
261
262 function getColour (colour) {
263 return {
264 fillColor: rgba(colour, 0.2),
265 strokeColor: rgba(colour, 1),
266 pointColor: rgba(colour, 1),
267 pointStrokeColor: '#fff',
268 pointHighlightFill: '#fff',
269 pointHighlightStroke: rgba(colour, 0.8)
270 };
271 }
272
273 function getRandomInt (min, max) {
274 return Math.floor(Math.random() * (max - min + 1)) + min;
275 }
276
277 function rgba (colour, alpha) {
278 if (usingExcanvas) {
279 // rgba not supported by IE8
280 return 'rgb(' + colour.join(',') + ')';
281 } else {
282 return 'rgba(' + colour.concat(alpha).join(',') + ')';
283 }
284 }
285
286 // Credit: http://stackoverflow.com/a/11508164/1190235
287 function hexToRgb (hex) {
288 var bigint = parseInt(hex, 16),
289 r = (bigint >> 16) & 255,
290 g = (bigint >> 8) & 255,
291 b = bigint & 255;
292
293 return [r, g, b];
294 }
295
296 function getDataSets (labels, data, series, colours) {
297 return {
298 labels: labels,
299 datasets: data.map(function (item, i) {
300 return angular.extend({}, colours[i], {
301 label: series[i],
302 data: item
303 });
304 })
305 };
306 }
307
308 function getData (labels, data, colours) {
309 return labels.map(function (label, i) {
310 return angular.extend({}, colours[i], {
311 label: label,
312 value: data[i],
313 color: colours[i].strokeColor,
314 highlight: colours[i].pointHighlightStroke
315 });
316 });
317 }
318
319 function setLegend (elem, chart) {
320 var $parent = elem.parent(),
321 $oldLegend = $parent.find('chart-legend'),
322 legend = '<chart-legend>' + chart.generateLegend() + '</chart-legend>';
323 if ($oldLegend.length) $oldLegend.replaceWith(legend);
324 else $parent.append(legend);
325 }
326
327 function updateChart (chart, values, scope, elem) {
328 if (Array.isArray(scope.data[0])) {
329 chart.datasets.forEach(function (dataset, i) {
330 (dataset.points || dataset.bars).forEach(function (dataItem, j) {
331 dataItem.value = values[i][j];
332 });
333 });
334 } else {
335 chart.segments.forEach(function (segment, i) {
336 segment.value = values[i];
337 });
338 }
339 chart.update();
340 scope.$emit('update', chart);
341 if (scope.legend && scope.legend !== 'false') setLegend(elem, chart);
342 }
343
344 function isEmpty (value) {
345 return ! value ||
346 (Array.isArray(value) && ! value.length) ||
347 (typeof value === 'object' && ! Object.keys(value).length);
348 }
349
350 function isResponsive (type, scope) {
351 var options = angular.extend({}, Chart.defaults.global, ChartJs.getOptions(type), scope.options);
352 return options.responsive;
353 }
354 }
355 }));
+0
-101
faraday/server/www/script/angular-clipboard.js less more
0 (function (root, factory) {
1 /* istanbul ignore next */
2 if (typeof define === 'function' && define.amd) {
3 define(['angular'], factory);
4 } else if (typeof module === 'object' && module.exports) {
5 module.exports = factory(require('angular'));
6 } else {
7 root.angularClipboard = factory(root.angular);
8 }
9 }(this, function (angular) {
10
11 return angular.module('angular-clipboard', [])
12 .factory('clipboard', ['$document', '$window', function ($document, $window) {
13 function createNode(text, context) {
14 var node = $document[0].createElement('textarea');
15 node.style.position = 'absolute';
16 node.style.fontSize = '12pt';
17 node.style.border = '0';
18 node.style.padding = '0';
19 node.style.margin = '0';
20 node.style.left = '-10000px';
21 node.style.top = ($window.pageYOffset || $document[0].documentElement.scrollTop) + 'px';
22 node.textContent = text;
23 return node;
24 }
25
26 function copyNode(node) {
27 try {
28 // Set inline style to override css styles
29 $document[0].body.style.webkitUserSelect = 'initial';
30
31 var selection = $document[0].getSelection();
32 selection.removeAllRanges();
33
34 var range = document.createRange();
35 range.selectNodeContents(node);
36 selection.addRange(range);
37 // This makes it work in all desktop browsers (Chrome)
38 node.select();
39 // This makes it work on Mobile Safari
40 node.setSelectionRange(0, 999999);
41
42 try {
43 if(!$document[0].execCommand('copy')) {
44 throw('failure copy');
45 }
46 } finally {
47 selection.removeAllRanges();
48 }
49 } finally {
50 // Reset inline style
51 $document[0].body.style.webkitUserSelect = '';
52 }
53 }
54
55 function copyText(text, context) {
56 var left = $window.pageXOffset || $document[0].documentElement.scrollLeft;
57 var top = $window.pageYOffset || $document[0].documentElement.scrollTop;
58
59 var node = createNode(text, context);
60 $document[0].body.appendChild(node);
61 copyNode(node);
62
63 $window.scrollTo(left, top);
64 $document[0].body.removeChild(node);
65 }
66
67 return {
68 copyText: copyText,
69 supported: 'queryCommandSupported' in $document[0] && $document[0].queryCommandSupported('copy')
70 };
71 }])
72 .directive('clipboard', ['clipboard', function (clipboard) {
73 return {
74 restrict: 'A',
75 scope: {
76 onCopied: '&',
77 onError: '&',
78 text: '=',
79 supported: '=?'
80 },
81 link: function (scope, element) {
82 scope.supported = clipboard.supported;
83
84 element.on('click', function (event) {
85 try {
86 clipboard.copyText(scope.text, element[0]);
87 if (angular.isFunction(scope.onCopied)) {
88 scope.$evalAsync(scope.onCopied());
89 }
90 } catch (err) {
91 if (angular.isFunction(scope.onError)) {
92 scope.$evalAsync(scope.onError({err: err}));
93 }
94 }
95 });
96 }
97 };
98 }]);
99
100 }));
+0
-1
faraday/server/www/script/angular-clipboard.min.js less more
0 !function(e,t){"function"==typeof define&&define.amd?define(["angular"],t):"object"==typeof module&&module.exports?module.exports=t(require("angular")):e.angularClipboard=t(e.angular)}(this,function(e){return e.module("angular-clipboard",[]).factory("clipboard",["$document","$window",function(e,t){return{copyText:function(o,n){var r=t.pageXOffset||e[0].documentElement.scrollLeft,l=t.pageYOffset||e[0].documentElement.scrollTop,i=function(o,n){var r=e[0].createElement("textarea");return r.style.position="absolute",r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.left="-10000px",r.style.top=(t.pageYOffset||e[0].documentElement.scrollTop)+"px",r.textContent=o,r}(o);e[0].body.appendChild(i),function(t){try{e[0].body.style.webkitUserSelect="initial";var o=e[0].getSelection();o.removeAllRanges();var n=document.createRange();n.selectNodeContents(t),o.addRange(n),t.select(),t.setSelectionRange(0,999999);try{if(!e[0].execCommand("copy"))throw"failure copy"}finally{o.removeAllRanges()}}finally{e[0].body.style.webkitUserSelect=""}}(i),t.scrollTo(r,l),e[0].body.removeChild(i)},supported:"queryCommandSupported"in e[0]&&e[0].queryCommandSupported("copy")}}]).directive("clipboard",["clipboard",function(t){return{restrict:"A",scope:{onCopied:"&",onError:"&",text:"=",supported:"=?"},link:function(o,n){o.supported=t.supported,n.on("click",function(r){try{t.copyText(o.text,n[0]),e.isFunction(o.onCopied)&&o.$evalAsync(o.onCopied())}catch(t){e.isFunction(o.onError)&&o.$evalAsync(o.onError({err:t}))}})}}}])});
+0
-321
faraday/server/www/script/angular-cookies.js less more
0 /**
1 * @license AngularJS v1.4.3
2 * (c) 2010-2015 Google, Inc. http://angularjs.org
3 * License: MIT
4 */
5 (function(window, angular, undefined) {'use strict';
6
7 /**
8 * @ngdoc module
9 * @name ngCookies
10 * @description
11 *
12 * # ngCookies
13 *
14 * The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
15 *
16 *
17 * <div doc-module-components="ngCookies"></div>
18 *
19 * See {@link ngCookies.$cookies `$cookies`} for usage.
20 */
21
22
23 angular.module('ngCookies', ['ng']).
24 /**
25 * @ngdoc provider
26 * @name $cookiesProvider
27 * @description
28 * Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
29 * */
30 provider('$cookies', [function $CookiesProvider() {
31 /**
32 * @ngdoc property
33 * @name $cookiesProvider#defaults
34 * @description
35 *
36 * Object containing default options to pass when setting cookies.
37 *
38 * The object may have following properties:
39 *
40 * - **path** - `{string}` - The cookie will be available only for this path and its
41 * sub-paths. By default, this would be the URL that appears in your base tag.
42 * - **domain** - `{string}` - The cookie will be available only for this domain and
43 * its sub-domains. For obvious security reasons the user agent will not accept the
44 * cookie if the current domain is not a sub domain or equals to the requested domain.
45 * - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
46 * or a Date object indicating the exact date/time this cookie will expire.
47 * - **secure** - `{boolean}` - The cookie will be available only in secured connection.
48 *
49 * Note: by default the address that appears in your `<base>` tag will be used as path.
50 * This is import so that cookies will be visible for all routes in case html5mode is enabled
51 *
52 **/
53 var defaults = this.defaults = {};
54
55 function calcOptions(options) {
56 return options ? angular.extend({}, defaults, options) : defaults;
57 }
58
59 /**
60 * @ngdoc service
61 * @name $cookies
62 *
63 * @description
64 * Provides read/write access to browser's cookies.
65 *
66 * <div class="alert alert-info">
67 * Up until Angular 1.3, `$cookies` exposed properties that represented the
68 * current browser cookie values. In version 1.4, this behavior has changed, and
69 * `$cookies` now provides a standard api of getters, setters etc.
70 * </div>
71 *
72 * Requires the {@link ngCookies `ngCookies`} module to be installed.
73 *
74 * @example
75 *
76 * ```js
77 * angular.module('cookiesExample', ['ngCookies'])
78 * .controller('ExampleController', ['$cookies', function($cookies) {
79 * // Retrieving a cookie
80 * var favoriteCookie = $cookies.get('myFavorite');
81 * // Setting a cookie
82 * $cookies.put('myFavorite', 'oatmeal');
83 * }]);
84 * ```
85 */
86 this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
87 return {
88 /**
89 * @ngdoc method
90 * @name $cookies#get
91 *
92 * @description
93 * Returns the value of given cookie key
94 *
95 * @param {string} key Id to use for lookup.
96 * @returns {string} Raw cookie value.
97 */
98 get: function(key) {
99 return $$cookieReader()[key];
100 },
101
102 /**
103 * @ngdoc method
104 * @name $cookies#getObject
105 *
106 * @description
107 * Returns the deserialized value of given cookie key
108 *
109 * @param {string} key Id to use for lookup.
110 * @returns {Object} Deserialized cookie value.
111 */
112 getObject: function(key) {
113 var value = this.get(key);
114 return value ? angular.fromJson(value) : value;
115 },
116
117 /**
118 * @ngdoc method
119 * @name $cookies#getAll
120 *
121 * @description
122 * Returns a key value object with all the cookies
123 *
124 * @returns {Object} All cookies
125 */
126 getAll: function() {
127 return $$cookieReader();
128 },
129
130 /**
131 * @ngdoc method
132 * @name $cookies#put
133 *
134 * @description
135 * Sets a value for given cookie key
136 *
137 * @param {string} key Id for the `value`.
138 * @param {string} value Raw value to be stored.
139 * @param {Object=} options Options object.
140 * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
141 */
142 put: function(key, value, options) {
143 $$cookieWriter(key, value, calcOptions(options));
144 },
145
146 /**
147 * @ngdoc method
148 * @name $cookies#putObject
149 *
150 * @description
151 * Serializes and sets a value for given cookie key
152 *
153 * @param {string} key Id for the `value`.
154 * @param {Object} value Value to be stored.
155 * @param {Object=} options Options object.
156 * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
157 */
158 putObject: function(key, value, options) {
159 this.put(key, angular.toJson(value), options);
160 },
161
162 /**
163 * @ngdoc method
164 * @name $cookies#remove
165 *
166 * @description
167 * Remove given cookie
168 *
169 * @param {string} key Id of the key-value pair to delete.
170 * @param {Object=} options Options object.
171 * See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
172 */
173 remove: function(key, options) {
174 $$cookieWriter(key, undefined, calcOptions(options));
175 }
176 };
177 }];
178 }]);
179
180 angular.module('ngCookies').
181 /**
182 * @ngdoc service
183 * @name $cookieStore
184 * @deprecated
185 * @requires $cookies
186 *
187 * @description
188 * Provides a key-value (string-object) storage, that is backed by session cookies.
189 * Objects put or retrieved from this storage are automatically serialized or
190 * deserialized by angular's toJson/fromJson.
191 *
192 * Requires the {@link ngCookies `ngCookies`} module to be installed.
193 *
194 * <div class="alert alert-danger">
195 * **Note:** The $cookieStore service is **deprecated**.
196 * Please use the {@link ngCookies.$cookies `$cookies`} service instead.
197 * </div>
198 *
199 * @example
200 *
201 * ```js
202 * angular.module('cookieStoreExample', ['ngCookies'])
203 * .controller('ExampleController', ['$cookieStore', function($cookieStore) {
204 * // Put cookie
205 * $cookieStore.put('myFavorite','oatmeal');
206 * // Get cookie
207 * var favoriteCookie = $cookieStore.get('myFavorite');
208 * // Removing a cookie
209 * $cookieStore.remove('myFavorite');
210 * }]);
211 * ```
212 */
213 factory('$cookieStore', ['$cookies', function($cookies) {
214
215 return {
216 /**
217 * @ngdoc method
218 * @name $cookieStore#get
219 *
220 * @description
221 * Returns the value of given cookie key
222 *
223 * @param {string} key Id to use for lookup.
224 * @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
225 */
226 get: function(key) {
227 return $cookies.getObject(key);
228 },
229
230 /**
231 * @ngdoc method
232 * @name $cookieStore#put
233 *
234 * @description
235 * Sets a value for given cookie key
236 *
237 * @param {string} key Id for the `value`.
238 * @param {Object} value Value to be stored.
239 */
240 put: function(key, value) {
241 $cookies.putObject(key, value);
242 },
243
244 /**
245 * @ngdoc method
246 * @name $cookieStore#remove
247 *
248 * @description
249 * Remove given cookie
250 *
251 * @param {string} key Id of the key-value pair to delete.
252 */
253 remove: function(key) {
254 $cookies.remove(key);
255 }
256 };
257
258 }]);
259
260 /**
261 * @name $$cookieWriter
262 * @requires $document
263 *
264 * @description
265 * This is a private service for writing cookies
266 *
267 * @param {string} name Cookie name
268 * @param {string=} value Cookie value (if undefined, cookie will be deleted)
269 * @param {Object=} options Object with options that need to be stored for the cookie.
270 */
271 function $$CookieWriter($document, $log, $browser) {
272 var cookiePath = $browser.baseHref();
273 var rawDocument = $document[0];
274
275 function buildCookieString(name, value, options) {
276 var path, expires;
277 options = options || {};
278 expires = options.expires;
279 path = angular.isDefined(options.path) ? options.path : cookiePath;
280 if (value === undefined) {
281 expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
282 value = '';
283 }
284 if (angular.isString(expires)) {
285 expires = new Date(expires);
286 }
287
288 var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
289 str += path ? ';path=' + path : '';
290 str += options.domain ? ';domain=' + options.domain : '';
291 str += expires ? ';expires=' + expires.toUTCString() : '';
292 str += options.secure ? ';secure' : '';
293
294 // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
295 // - 300 cookies
296 // - 20 cookies per unique domain
297 // - 4096 bytes per cookie
298 var cookieLength = str.length + 1;
299 if (cookieLength > 4096) {
300 $log.warn("Cookie '" + name +
301 "' possibly not set or overflowed because it was too large (" +
302 cookieLength + " > 4096 bytes)!");
303 }
304
305 return str;
306 }
307
308 return function(name, value, options) {
309 rawDocument.cookie = buildCookieString(name, value, options);
310 };
311 }
312
313 $$CookieWriter.$inject = ['$document', '$log', '$browser'];
314
315 angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() {
316 this.$get = $$CookieWriter;
317 });
318
319
320 })(window, window.angular);
+0
-9
faraday/server/www/script/angular-cookies.min.js less more
0 /*
1 AngularJS v1.4.3
2 (c) 2010-2015 Google, Inc. http://angularjs.org
3 License: MIT
4 */
5 (function(p,g,l){'use strict';function m(b,a,f){var c=f.baseHref(),k=b[0];return function(b,d,e){var f,h;e=e||{};h=e.expires;f=g.isDefined(e.path)?e.path:c;d===l&&(h="Thu, 01 Jan 1970 00:00:00 GMT",d="");g.isString(h)&&(h=new Date(h));d=encodeURIComponent(b)+"="+encodeURIComponent(d);d=d+(f?";path="+f:"")+(e.domain?";domain="+e.domain:"");d+=h?";expires="+h.toUTCString():"";d+=e.secure?";secure":"";e=d.length+1;4096<e&&a.warn("Cookie '"+b+"' possibly not set or overflowed because it was too large ("+
6 e+" > 4096 bytes)!");k.cookie=d}}g.module("ngCookies",["ng"]).provider("$cookies",[function(){var b=this.defaults={};this.$get=["$$cookieReader","$$cookieWriter",function(a,f){return{get:function(c){return a()[c]},getObject:function(c){return(c=this.get(c))?g.fromJson(c):c},getAll:function(){return a()},put:function(c,a,n){f(c,a,n?g.extend({},b,n):b)},putObject:function(c,b,a){this.put(c,g.toJson(b),a)},remove:function(a,k){f(a,l,k?g.extend({},b,k):b)}}}]}]);g.module("ngCookies").factory("$cookieStore",
7 ["$cookies",function(b){return{get:function(a){return b.getObject(a)},put:function(a,f){b.putObject(a,f)},remove:function(a){b.remove(a)}}}]);m.$inject=["$document","$log","$browser"];g.module("ngCookies").provider("$$cookieWriter",function(){this.$get=m})})(window,window.angular);
8 //# sourceMappingURL=angular-cookies.min.js.map
+0
-49
faraday/server/www/script/angular-drag-and-drop-lists.min.js less more
0 /**
1 * angular-drag-and-drop-lists v2.1.0
2 *
3 * Copyright (c) 2014 Marcel Juenemann [email protected]
4 * Copyright (c) 2014-2017 Google Inc.
5 * https://github.com/marceljuenemann/angular-drag-and-drop-lists
6 *
7 * License: MIT
8 */
9 !function(e){function n(e,n){return"all"==n?e:e.filter(function(e){return-1!=n.toLowerCase().indexOf(e)})}var a="application/x-dnd",r="application/json",t="Text",d=["move","copy","link"]
10 e.directive("dndDraggable",["$parse","$timeout",function(e,i){return function(l,f,c){f.attr("draggable","true"),c.dndDisableIf&&l.$watch(c.dndDisableIf,function(e){f.attr("draggable",!e)}),f.on("dragstart",function(s){if(s=s.originalEvent||s,"false"==f.attr("draggable"))return!0
11 o.isDragging=!0,o.itemType=c.dndType&&l.$eval(c.dndType).toLowerCase(),o.dropEffect="none",o.effectAllowed=c.dndEffectAllowed||d[0],s.dataTransfer.effectAllowed=o.effectAllowed
12 var g=l.$eval(c.dndDraggable),u=a+(o.itemType?"-"+o.itemType:"")
13 try{s.dataTransfer.setData(u,angular.toJson(g))}catch(p){var v=angular.toJson({item:g,type:o.itemType})
14 try{s.dataTransfer.setData(r,v)}catch(p){var D=n(d,o.effectAllowed)
15 s.dataTransfer.effectAllowed=D[0],s.dataTransfer.setData(t,v)}}if(f.addClass("dndDragging"),i(function(){f.addClass("dndDraggingSource")},0),s._dndHandle&&s.dataTransfer.setDragImage&&s.dataTransfer.setDragImage(f[0],0,0),e(c.dndDragstart)(l,{event:s}),c.dndCallback){var y=e(c.dndCallback)
16 o.callback=function(e){return y(l,e||{})}}s.stopPropagation()}),f.on("dragend",function(n){n=n.originalEvent||n,l.$apply(function(){var a=o.dropEffect,r={copy:"dndCopied",link:"dndLinked",move:"dndMoved",none:"dndCanceled"}
17 e(c[r[a]])(l,{event:n}),e(c.dndDragend)(l,{event:n,dropEffect:a})}),o.isDragging=!1,o.callback=void 0,f.removeClass("dndDragging"),f.removeClass("dndDraggingSource"),n.stopPropagation(),i(function(){f.removeClass("dndDraggingSource")},0)}),f.on("click",function(n){c.dndSelected&&(n=n.originalEvent||n,l.$apply(function(){e(c.dndSelected)(l,{event:n})}),n.stopPropagation())}),f.on("selectstart",function(){this.dragDrop&&this.dragDrop()})}}]),e.directive("dndList",["$parse",function(e){return function(i,l,f){function c(e){if(!e)return t
18 for(var n=0;n<e.length;n++)if(e[n]==t||e[n]==r||e[n].substr(0,a.length)==a)return e[n]
19 return null}function s(e){return o.isDragging?o.itemType||void 0:e==t||e==r?null:e&&e.substr(a.length+1)||void 0}function g(e){return E.disabled?!1:E.externalSources||o.isDragging?E.allowedTypes&&null!==e?e&&-1!=E.allowedTypes.indexOf(e):!0:!1}function u(e,a){var r=d
20 return a||(r=n(r,e.dataTransfer.effectAllowed)),o.isDragging&&(r=n(r,o.effectAllowed)),f.dndEffectAllowed&&(r=n(r,f.dndEffectAllowed)),r.length?e.ctrlKey&&-1!=r.indexOf("copy")?"copy":e.altKey&&-1!=r.indexOf("link")?"link":r[0]:"none"}function p(){return T.remove(),l.removeClass("dndDragover"),!0}function v(n,a,r,t,d,l){return e(n)(i,{callback:o.callback,dropEffect:r,event:a,external:!o.isDragging,index:void 0!==d?d:D(),item:l||void 0,type:t})}function D(){return Array.prototype.indexOf.call(m.children,h)}function y(){var e
21 return angular.forEach(l.children(),function(n){var a=angular.element(n)
22 a.hasClass("dndPlaceholder")&&(e=a)}),e||angular.element("<li class='dndPlaceholder'></li>")}var T=y()
23 T.remove()
24 var h=T[0],m=l[0],E={}
25 l.on("dragenter",function(e){e=e.originalEvent||e
26 var n=f.dndAllowedTypes&&i.$eval(f.dndAllowedTypes)
27 E={allowedTypes:angular.isArray(n)&&n.join("|").toLowerCase().split("|"),disabled:f.dndDisableIf&&i.$eval(f.dndDisableIf),externalSources:f.dndExternalSources&&i.$eval(f.dndExternalSources),horizontal:f.dndHorizontalList&&i.$eval(f.dndHorizontalList)}
28 var a=c(e.dataTransfer.types)
29 return a&&g(s(a))?void e.preventDefault():!0}),l.on("dragover",function(e){e=e.originalEvent||e
30 var n=c(e.dataTransfer.types),a=s(n)
31 if(!n||!g(a))return!0
32 if(h.parentNode!=m&&l.append(T),e.target!=m){for(var r=e.target;r.parentNode!=m&&r.parentNode;)r=r.parentNode
33 if(r.parentNode==m&&r!=h){var d=r.getBoundingClientRect()
34 if(E.horizontal)var o=e.clientX<d.left+d.width/2
35 else var o=e.clientY<d.top+d.height/2
36 m.insertBefore(h,o?r:r.nextSibling)}}var i=n==t,D=u(e,i)
37 return"none"==D?p():f.dndDragover&&!v(f.dndDragover,e,D,a)?p():(e.preventDefault(),i||(e.dataTransfer.dropEffect=D),l.addClass("dndDragover"),e.stopPropagation(),!1)}),l.on("drop",function(e){e=e.originalEvent||e
38 var n=c(e.dataTransfer.types),a=s(n)
39 if(!n||!g(a))return!0
40 e.preventDefault()
41 try{var d=JSON.parse(e.dataTransfer.getData(n))}catch(l){return p()}if((n==t||n==r)&&(a=d.type||void 0,d=d.item,!g(a)))return p()
42 var y=n==t,T=u(e,y)
43 if("none"==T)return p()
44 var h=D()
45 return f.dndDrop&&(d=v(f.dndDrop,e,T,a,h,d),!d)?p():(o.dropEffect=T,y||(e.dataTransfer.dropEffect=T),d!==!0&&i.$apply(function(){i.$eval(f.dndList).splice(h,0,d)}),v(f.dndInserted,e,T,a,h,d),p(),e.stopPropagation(),!1)}),l.on("dragleave",function(e){e=e.originalEvent||e
46 var n=document.elementFromPoint(e.clientX,e.clientY)
47 m.contains(n)&&!e._dndPhShown?e._dndPhShown=!0:p()})}}]),e.directive("dndNodrag",function(){return function(e,n,a){n.attr("draggable","true"),n.on("dragstart",function(e){e=e.originalEvent||e,e._dndHandle||(e.dataTransfer.types&&e.dataTransfer.types.length||e.preventDefault(),e.stopPropagation())}),n.on("dragend",function(e){e=e.originalEvent||e,e._dndHandle||e.stopPropagation()})}}),e.directive("dndHandle",function(){return function(e,n,a){n.attr("draggable","true"),n.on("dragstart dragend",function(e){e=e.originalEvent||e,e._dndHandle=!0})}})
48 var o={}}(angular.module("dndLists",[]));
+0
-7
faraday/server/www/script/angular-file-upload-lib.min.js less more
0 /*
1 angular-file-upload-lib v2.5.0
2 https://github.com/nervgh/angular-file-upload-lib
3 */
4
5 !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports["angular-file-upload-lib"]=t():e["angular-file-upload-lib"]=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={exports:{},id:o,loaded:!1};return e[o].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}var r=n(1),i=o(r),s=n(2),a=o(s),u=n(3),l=o(u),p=n(4),c=o(p),f=n(5),d=o(f),h=n(6),y=o(h),v=n(7),m=o(v),_=n(8),g=o(_),b=n(9),F=o(b),O=n(10),C=o(O),w=n(11),A=o(w),I=n(12),T=o(I),U=n(13),x=o(U);angular.module(i["default"].name,[]).value("fileUploaderOptions",a["default"]).factory("FileUploader",l["default"]).factory("FileLikeObject",c["default"]).factory("FileItem",d["default"]).factory("FileDirective",y["default"]).factory("FileSelect",m["default"]).factory("FileDrop",F["default"]).factory("FileOver",C["default"]).factory("Pipeline",g["default"]).directive("nvFileSelect",A["default"]).directive("nvFileDrop",T["default"]).directive("nvFileOver",x["default"]).run(["FileUploader","FileLikeObject","FileItem","FileDirective","FileSelect","FileDrop","FileOver","Pipeline",function(e,t,n,o,r,i,s,a){e.FileLikeObject=t,e.FileItem=n,e.FileDirective=o,e.FileSelect=r,e.FileDrop=i,e.FileOver=s,e.Pipeline=a}])},function(e,t){e.exports={name:"angularFileUploadLib"}},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t["default"]={url:"/",alias:"file",headers:{},queue:[],progress:0,autoUpload:!1,removeAfterUpload:!1,method:"POST",filters:[],formData:[],queueLimit:Number.MAX_VALUE,withCredentials:!1,disableMultipart:!1}},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t,n,o,i,a,u,g){var b=o.File,F=o.FormData,O=function(){function o(t){r(this,o);var n=p(e);c(this,n,t,{isUploading:!1,_nextIndex:0,_directives:{select:[],drop:[],over:[]}}),this.filters.unshift({name:"queueLimit",fn:this._queueLimitFilter}),this.filters.unshift({name:"folder",fn:this._folderFilter})}return o.prototype.addToQueue=function(e,t,n){var o=this,r=this.isArrayLikeObject(e)?Array.prototype.slice.call(e):[e],i=this._getFilters(n),l=this.queue.length,p=[],c=function d(){var e=r.shift();if(m(e))return f();var n=o.isFile(e)?e:new a(e),l=o._convertFiltersToPipes(i),c=new g(l),h=function(e){var t=e.pipe.originalFilter,n=s(e.args,2),r=n[0],i=n[1];o._onWhenAddingFileFailed(r,t,i),d()},y=function(e,t){var n=new u(o,e,t);p.push(n),o.queue.push(n),o._onAfterAddingFile(n),d()};c.onThrown=h,c.onSuccessful=y,c.exec(n,t)},f=function(){o.queue.length!==l&&(o._onAfterAddingAll(p),o.progress=o._getTotalProgress()),o._render(),o.autoUpload&&o.uploadAll()};c()},o.prototype.removeFromQueue=function(e){var t=this.getIndexOfItem(e),n=this.queue[t];n.isUploading&&n.cancel(),this.queue.splice(t,1),n._destroy(),this.progress=this._getTotalProgress()},o.prototype.clearQueue=function(){for(;this.queue.length;)this.queue[0].remove();this.progress=0},o.prototype.uploadItem=function(e){var t=this.getIndexOfItem(e),n=this.queue[t],o=this.isHTML5?"_xhrTransport":"_iframeTransport";n._prepareToUploading(),this.isUploading||(this._onBeforeUploadItem(n),n.isCancel||(n.isUploading=!0,this.isUploading=!0,this[o](n),this._render()))},o.prototype.cancelItem=function(e){var t=this,n=this.getIndexOfItem(e),o=this.queue[n],r=this.isHTML5?"_xhr":"_form";o&&(o.isCancel=!0,o.isUploading?o[r].abort():!function(){var e=[void 0,0,{}],n=function(){t._onCancelItem.apply(t,[o].concat(e)),t._onCompleteItem.apply(t,[o].concat(e))};i(n)}())},o.prototype.uploadAll=function(){var e=this.getNotUploadedItems().filter(function(e){return!e.isUploading});e.length&&(f(e,function(e){return e._prepareToUploading()}),e[0].upload())},o.prototype.cancelAll=function(){var e=this.getNotUploadedItems();f(e,function(e){return e.cancel()})},o.prototype.isFile=function(e){return this.constructor.isFile(e)},o.prototype.isFileLikeObject=function(e){return this.constructor.isFileLikeObject(e)},o.prototype.isArrayLikeObject=function(e){return this.constructor.isArrayLikeObject(e)},o.prototype.getIndexOfItem=function(e){return h(e)?e:this.queue.indexOf(e)},o.prototype.getNotUploadedItems=function(){return this.queue.filter(function(e){return!e.isUploaded})},o.prototype.getReadyItems=function(){return this.queue.filter(function(e){return e.isReady&&!e.isUploading}).sort(function(e,t){return e.index-t.index})},o.prototype.destroy=function(){var e=this;f(this._directives,function(t){f(e._directives[t],function(e){e.destroy()})})},o.prototype.onAfterAddingAll=function(e){},o.prototype.onAfterAddingFile=function(e){},o.prototype.onWhenAddingFileFailed=function(e,t,n){},o.prototype.onBeforeUploadItem=function(e){},o.prototype.onProgressItem=function(e,t){},o.prototype.onProgressAll=function(e){},o.prototype.onSuccessItem=function(e,t,n,o){},o.prototype.onErrorItem=function(e,t,n,o){},o.prototype.onCancelItem=function(e,t,n,o){},o.prototype.onCompleteItem=function(e,t,n,o){},o.prototype.onCompleteAll=function(){},o.prototype._getTotalProgress=function(e){if(this.removeAfterUpload)return e||0;var t=this.getNotUploadedItems().length,n=t?this.queue.length-t:this.queue.length,o=100/this.queue.length,r=(e||0)*o/100;return Math.round(n*o+r)},o.prototype._getFilters=function(e){if(!e)return this.filters;if(v(e))return e;var t=e.match(/[^\s,]+/g);return this.filters.filter(function(e){return-1!==t.indexOf(e.name)})},o.prototype._convertFiltersToPipes=function(e){var t=this;return e.map(function(e){var n=l(t,e.fn);return n.isAsync=3===e.fn.length,n.originalFilter=e,n})},o.prototype._render=function(){t.$$phase||t.$apply()},o.prototype._folderFilter=function(e){return!(!e.size&&!e.type)},o.prototype._queueLimitFilter=function(){return this.queue.length<this.queueLimit},o.prototype._isSuccessCode=function(e){return e>=200&&300>e||304===e},o.prototype._transformResponse=function(e,t){var o=this._headersGetter(t);return f(n.defaults.transformResponse,function(t){e=t(e,o)}),e},o.prototype._parseHeaders=function(e){var t,n,o,r={};return e?(f(e.split("\n"),function(e){o=e.indexOf(":"),t=e.slice(0,o).trim().toLowerCase(),n=e.slice(o+1).trim(),t&&(r[t]=r[t]?r[t]+", "+n:n)}),r):r},o.prototype._headersGetter=function(e){return function(t){return t?e[t.toLowerCase()]||null:e}},o.prototype._xhrTransport=function(e){var t,n=this,o=e._xhr=new XMLHttpRequest;if(e.disableMultipart?t=e._file:(t=new F,f(e.formData,function(e){f(e,function(e,n){t.append(n,e)})}),t.append(e.alias,e._file,e.file.name)),"number"!=typeof e._file.size)throw new TypeError("The file specified is no longer valid");o.upload.onprogress=function(t){var o=Math.round(t.lengthComputable?100*t.loaded/t.total:0);n._onProgressItem(e,o)},o.onload=function(){var t=n._parseHeaders(o.getAllResponseHeaders()),r=n._transformResponse(o.response,t),i=n._isSuccessCode(o.status)?"Success":"Error",s="_on"+i+"Item";n[s](e,r,o.status,t),n._onCompleteItem(e,r,o.status,t)},o.onerror=function(){var t=n._parseHeaders(o.getAllResponseHeaders()),r=n._transformResponse(o.response,t);n._onErrorItem(e,r,o.status,t),n._onCompleteItem(e,r,o.status,t)},o.onabort=function(){var t=n._parseHeaders(o.getAllResponseHeaders()),r=n._transformResponse(o.response,t);n._onCancelItem(e,r,o.status,t),n._onCompleteItem(e,r,o.status,t)},o.open(e.method,e.url,!0),o.withCredentials=e.withCredentials,f(e.headers,function(e,t){o.setRequestHeader(t,e)}),o.send(t)},o.prototype._iframeTransport=function(e){var t=this,n=_('<form style="display: none;" />'),o=_('<iframe name="iframeTransport'+Date.now()+'">'),r=e._input;e._form&&e._form.replaceWith(r),e._form=n,r.prop("name",e.alias),f(e.formData,function(e){f(e,function(e,t){var o=_('<input type="hidden" name="'+t+'" />');o.val(e),n.append(o)})}),n.prop({action:e.url,method:"POST",target:o.prop("name"),enctype:"multipart/form-data",encoding:"multipart/form-data"}),o.bind("load",function(){var n="",r=200;try{n=o[0].contentDocument.body.innerHTML}catch(i){r=500}var s={response:n,status:r,dummy:!0},a={},u=t._transformResponse(s.response,a);t._onSuccessItem(e,u,s.status,a),t._onCompleteItem(e,u,s.status,a)}),n.abort=function(){var i,s={status:0,dummy:!0},a={};o.unbind("load").prop("src","javascript:false;"),n.replaceWith(r),t._onCancelItem(e,i,s.status,a),t._onCompleteItem(e,i,s.status,a)},r.after(n),n.append(r).append(o),n[0].submit()},o.prototype._onWhenAddingFileFailed=function(e,t,n){this.onWhenAddingFileFailed(e,t,n)},o.prototype._onAfterAddingFile=function(e){this.onAfterAddingFile(e)},o.prototype._onAfterAddingAll=function(e){this.onAfterAddingAll(e)},o.prototype._onBeforeUploadItem=function(e){e._onBeforeUpload(),this.onBeforeUploadItem(e)},o.prototype._onProgressItem=function(e,t){var n=this._getTotalProgress(t);this.progress=n,e._onProgress(t),this.onProgressItem(e,t),this.onProgressAll(n),this._render()},o.prototype._onSuccessItem=function(e,t,n,o){e._onSuccess(t,n,o),this.onSuccessItem(e,t,n,o)},o.prototype._onErrorItem=function(e,t,n,o){e._onError(t,n,o),this.onErrorItem(e,t,n,o)},o.prototype._onCancelItem=function(e,t,n,o){e._onCancel(t,n,o),this.onCancelItem(e,t,n,o)},o.prototype._onCompleteItem=function(e,t,n,o){e._onComplete(t,n,o),this.onCompleteItem(e,t,n,o);var r=this.getReadyItems()[0];return this.isUploading=!1,y(r)?void r.upload():(this.onCompleteAll(),this.progress=this._getTotalProgress(),void this._render())},o.isFile=function(e){return b&&e instanceof b},o.isFileLikeObject=function(e){return e instanceof a},o.isArrayLikeObject=function(e){return d(e)&&"length"in e},o.inherit=function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.super_=t},o}();return O.prototype.isHTML5=!(!b||!F),O.isHTML5=O.prototype.isHTML5,O}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){var n=[],o=!0,r=!1,i=void 0;try{for(var s,a=e[Symbol.iterator]();!(o=(s=a.next()).done)&&(n.push(s.value),!t||n.length!==t);o=!0);}catch(u){r=!0,i=u}finally{try{!o&&a["return"]&&a["return"]()}finally{if(r)throw i}}return n}return function(t,n){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return e(t,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();t["default"]=i;var a=n(1),u=(o(a),angular),l=u.bind,p=u.copy,c=u.extend,f=u.forEach,d=u.isObject,h=u.isNumber,y=u.isDefined,v=u.isArray,m=u.isUndefined,_=u.element;i.$inject=["fileUploaderOptions","$rootScope","$http","$window","$timeout","FileLikeObject","FileItem","Pipeline"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(){return function(){function e(t){r(this,e);var n=l(t),o=n?t.value:t,i=p(o)?"FakePath":"Object",s="_createFrom"+i;this[s](o)}return e.prototype._createFromFakePath=function(e){this.lastModifiedDate=null,this.size=null,this.type="like/"+e.slice(e.lastIndexOf(".")+1).toLowerCase(),this.name=e.slice(e.lastIndexOf("/")+e.lastIndexOf("\\")+2)},e.prototype._createFromObject=function(e){this.lastModifiedDate=u(e.lastModifiedDate),this.size=e.size,this.type=e.type,this.name=e.name},e}()}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=i;var s=n(1),a=(o(s),angular),u=a.copy,l=a.isElement,p=a.isString},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){return function(){function n(e,o,i){r(this,n);var s=c(o),a=s?p(o):null,f=s?null:o;l(this,{url:e.url,alias:e.alias,headers:u(e.headers),formData:u(e.formData),removeAfterUpload:e.removeAfterUpload,withCredentials:e.withCredentials,disableMultipart:e.disableMultipart,method:e.method},i,{uploader:e,file:new t(o),isReady:!1,isUploading:!1,isUploaded:!1,isSuccess:!1,isCancel:!1,isError:!1,progress:0,index:null,_file:f,_input:a}),a&&this._replaceNode(a)}return n.prototype.upload=function(){try{this.uploader.uploadItem(this)}catch(e){var t=e.name+":"+e.message;this.uploader._onCompleteItem(this,t,e.code,[]),this.uploader._onErrorItem(this,t,e.code,[])}},n.prototype.cancel=function(){this.uploader.cancelItem(this)},n.prototype.remove=function(){this.uploader.removeFromQueue(this)},n.prototype.onBeforeUpload=function(){},n.prototype.onProgress=function(e){},n.prototype.onSuccess=function(e,t,n){},n.prototype.onError=function(e,t,n){},n.prototype.onCancel=function(e,t,n){},n.prototype.onComplete=function(e,t,n){},n.prototype._onBeforeUpload=function(){this.isReady=!0,this.isUploading=!1,this.isUploaded=!1,this.isSuccess=!1,this.isCancel=!1,this.isError=!1,this.progress=0,this.onBeforeUpload()},n.prototype._onProgress=function(e){this.progress=e,this.onProgress(e)},n.prototype._onSuccess=function(e,t,n){this.isReady=!1,this.isUploading=!1,this.isUploaded=!0,this.isSuccess=!0,this.isCancel=!1,this.isError=!1,this.progress=100,this.index=null,this.onSuccess(e,t,n)},n.prototype._onError=function(e,t,n){this.isReady=!1,this.isUploading=!1,this.isUploaded=!0,this.isSuccess=!1,this.isCancel=!1,this.isError=!0,this.progress=0,this.index=null,this.onError(e,t,n)},n.prototype._onCancel=function(e,t,n){this.isReady=!1,this.isUploading=!1,this.isUploaded=!1,this.isSuccess=!1,this.isCancel=!0,this.isError=!1,this.progress=0,this.index=null,this.onCancel(e,t,n)},n.prototype._onComplete=function(e,t,n){this.onComplete(e,t,n),this.removeAfterUpload&&this.remove()},n.prototype._destroy=function(){this._input&&this._input.remove(),this._form&&this._form.remove(),delete this._form,delete this._input},n.prototype._prepareToUploading=function(){this.index=this.index||++this.uploader._nextIndex,this.isReady=!0},n.prototype._replaceNode=function(t){var n=e(t.clone())(t.scope());n.prop("value",null),t.css("display","none"),t.after(n)},n}()}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=i;var s=n(1),a=(o(s),angular),u=a.copy,l=a.extend,p=a.element,c=a.isElement;i.$inject=["$compile","FileLikeObject"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(){var e=function(){function e(t){r(this,e),u(this,t),this.uploader._directives[this.prop].push(this),this._saveLinks(),this.bind()}return e.prototype.bind=function(){for(var e in this.events){var t=this.events[e];this.element.bind(e,this[t])}},e.prototype.unbind=function(){for(var e in this.events)this.element.unbind(e,this.events[e])},e.prototype.destroy=function(){var e=this.uploader._directives[this.prop].indexOf(this);this.uploader._directives[this.prop].splice(e,1),this.unbind()},e.prototype._saveLinks=function(){for(var e in this.events){var t=this.events[e];this[t]=this[t].bind(this)}},e}();return e.prototype.events={},e}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=i;var s=n(1),a=(o(s),angular),u=a.extend},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function a(e,t){return function(t){function n(e){r(this,n);var o=p(e,{events:{$destroy:"destroy",change:"onChange"},prop:"select"}),s=i(this,t.call(this,o));return s.uploader.isHTML5||s.element.removeAttr("multiple"),s.element.prop("value",null),s}return s(n,t),n.prototype.getOptions=function(){},n.prototype.getFilters=function(){},n.prototype.isEmptyAfterSelection=function(){return!!this.element.attr("multiple")},n.prototype.onChange=function(){var t=this.uploader.isHTML5?this.element[0].files:this.element[0],n=this.getOptions(),o=this.getFilters();this.uploader.isHTML5||this.destroy(),this.uploader.addToQueue(t,n,o),this.isEmptyAfterSelection()&&(this.element.prop("value",null),this.element.replaceWith(e(this.element.clone())(this.scope)))},n}(t)}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=a;var u=n(1),l=(o(u),angular),p=l.extend;a.$inject=["$compile","FileDirective"]},function(e,t){"use strict";function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e){return function(){function t(){var e=arguments.length<=0||void 0===arguments[0]?[]:arguments[0];o(this,t),this.pipes=e}return t.prototype.next=function(t){var o=this.pipes.shift();if(a(o))return void this.onSuccessful.apply(this,n(t));var r=new Error("The filter has not passed");if(r.pipe=o,r.args=t,o.isAsync){var i=e.defer(),u=s(this,this.next,t),l=s(this,this.onThrown,r);i.promise.then(u,l),o.apply(void 0,n(t).concat([i]))}else{var p=Boolean(o.apply(void 0,n(t)));p?this.next(t):this.onThrown(r)}},t.prototype.exec=function(){for(var e=arguments.length,t=Array(e),n=0;e>n;n++)t[n]=arguments[n];this.next(t)},t.prototype.onThrown=function(e){},t.prototype.onSuccessful=function(){},t}()}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=r;var i=angular,s=i.bind,a=i.isUndefined;r.$inject=["$q"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function a(e){return function(e){function t(n){r(this,t);var o=p(n,{events:{$destroy:"destroy",drop:"onDrop",dragover:"onDragOver",dragleave:"onDragLeave"},prop:"drop"});return i(this,e.call(this,o))}return s(t,e),t.prototype.getOptions=function(){},t.prototype.getFilters=function(){},t.prototype.onDrop=function(e){var t=this._getTransfer(e);if(t){var n=this.getOptions(),o=this.getFilters();this._preventAndStop(e),c(this.uploader._directives.over,this._removeOverClass,this),this.uploader.addToQueue(t.files,n,o)}},t.prototype.onDragOver=function(e){var t=this._getTransfer(e);this._haveFiles(t.types)&&(t.dropEffect="copy",this._preventAndStop(e),c(this.uploader._directives.over,this._addOverClass,this))},t.prototype.onDragLeave=function(e){e.currentTarget!==this.element[0]&&(this._preventAndStop(e),c(this.uploader._directives.over,this._removeOverClass,this))},t.prototype._getTransfer=function(e){return e.dataTransfer?e.dataTransfer:e.originalEvent.dataTransfer},t.prototype._preventAndStop=function(e){e.preventDefault(),e.stopPropagation()},t.prototype._haveFiles=function(e){return e?e.indexOf?-1!==e.indexOf("Files"):e.contains?e.contains("Files"):!1:!1},t.prototype._addOverClass=function(e){e.addOverClass()},t.prototype._removeOverClass=function(e){e.removeOverClass()},t}(e)}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=a;var u=n(1),l=(o(u),angular),p=l.extend,c=l.forEach;a.$inject=["FileDirective"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function a(e){return function(e){function t(n){r(this,t);var o=p(n,{events:{$destroy:"destroy"},prop:"over",overClass:"nv-file-over"});return i(this,e.call(this,o))}return s(t,e),t.prototype.addOverClass=function(){this.element.addClass(this.getOverClass())},t.prototype.removeOverClass=function(){this.element.removeClass(this.getOverClass())},t.prototype.getOverClass=function(){return this.overClass},t}(e)}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=a;var u=n(1),l=(o(u),angular),p=l.extend;a.$inject=["FileDirective"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t,n){return{link:function(o,r,i){var s=o.$eval(i.uploader);if(!(s instanceof t))throw new TypeError('"Uploader" must be an instance of FileUploader');var a=new n({uploader:s,element:r,scope:o});a.getOptions=e(i.options).bind(a,o),a.getFilters=function(){return i.filters}}}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=r;var i=n(1);o(i);r.$inject=["$parse","FileUploader","FileSelect"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t,n){return{link:function(o,r,i){var s=o.$eval(i.uploader);if(!(s instanceof t))throw new TypeError('"Uploader" must be an instance of FileUploader');if(s.isHTML5){var a=new n({uploader:s,element:r});a.getOptions=e(i.options).bind(a,o),a.getFilters=function(){return i.filters}}}}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=r;var i=n(1);o(i);r.$inject=["$parse","FileUploader","FileDrop"]},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){return{link:function(n,o,r){var i=n.$eval(r.uploader);if(!(i instanceof e))throw new TypeError('"Uploader" must be an instance of FileUploader');var s=new t({uploader:i,element:o});s.getOverClass=function(){return r.overClass||s.overClass}}}}Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=r;var i=n(1);o(i);r.$inject=["FileUploader","FileOver"]}])});
6 //# sourceMappingURL=angular-file-upload-lib.min.js.map
+0
-366
faraday/server/www/script/angular-file-upload-shim.js less more
0 /**!
1 * AngularJS file upload/drop directive with progress and abort
2 * FileAPI Flash shim for old browsers not supporting FormData
3 * @author Danial <[email protected]>
4 * @version 2.1.1
5 */
6
7 (function() {
8
9 var hasFlash = function() {
10 try {
11 var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
12 if (fo) return true;
13 } catch(e) {
14 if (navigator.mimeTypes['application/x-shockwave-flash'] != undefined) return true;
15 }
16 return false;
17 }
18
19 function patchXHR(fnName, newFn) {
20 window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);
21 };
22
23 if ((window.XMLHttpRequest && !window.FormData) || (window.FileAPI && FileAPI.forceLoad)) {
24 var initializeUploadListener = function(xhr) {
25 if (!xhr.__listeners) {
26 if (!xhr.upload) xhr.upload = {};
27 xhr.__listeners = [];
28 var origAddEventListener = xhr.upload.addEventListener;
29 xhr.upload.addEventListener = function(t, fn, b) {
30 xhr.__listeners[t] = fn;
31 origAddEventListener && origAddEventListener.apply(this, arguments);
32 };
33 }
34 }
35
36 patchXHR('open', function(orig) {
37 return function(m, url, b) {
38 initializeUploadListener(this);
39 this.__url = url;
40 try {
41 orig.apply(this, [m, url, b]);
42 } catch (e) {
43 if (e.message.indexOf('Access is denied') > -1) {
44 orig.apply(this, [m, '_fix_for_ie_crossdomain__', b]);
45 }
46 }
47 }
48 });
49
50 patchXHR('getResponseHeader', function(orig) {
51 return function(h) {
52 return this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h]));
53 };
54 });
55
56 patchXHR('getAllResponseHeaders', function(orig) {
57 return function() {
58 return this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this));
59 }
60 });
61
62 patchXHR('abort', function(orig) {
63 return function() {
64 return this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this));
65 }
66 });
67
68 patchXHR('setRequestHeader', function(orig) {
69 return function(header, value) {
70 if (header === '__setXHR_') {
71 initializeUploadListener(this);
72 var val = value(this);
73 // fix for angular < 1.2.0
74 if (val instanceof Function) {
75 val(this);
76 }
77 } else {
78 this.__requestHeaders = this.__requestHeaders || {};
79 this.__requestHeaders[header] = value;
80 orig.apply(this, arguments);
81 }
82 }
83 });
84
85 function redefineProp(xhr, prop, fn) {
86 try {
87 Object.defineProperty(xhr, prop, {get: fn});
88 } catch (e) {/*ignore*/}
89 }
90
91 patchXHR('send', function(orig) {
92 return function() {
93 var xhr = this;
94 if (arguments[0] && arguments[0].__isFileAPIShim) {
95 var formData = arguments[0];
96 var config = {
97 url: xhr.__url,
98 jsonp: false, //removes the callback form param
99 cache: true, //removes the ?fileapiXXX in the url
100 complete: function(err, fileApiXHR) {
101 xhr.__completed = true;
102 if (!err && xhr.__listeners['load'])
103 xhr.__listeners['load']({type: 'load', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});
104 if (!err && xhr.__listeners['loadend'])
105 xhr.__listeners['loadend']({type: 'loadend', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});
106 if (err === 'abort' && xhr.__listeners['abort'])
107 xhr.__listeners['abort']({type: 'abort', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true});
108 if (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function() {return (fileApiXHR.status == 0 && err && err !== 'abort') ? 500 : fileApiXHR.status});
109 if (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function() {return fileApiXHR.statusText});
110 redefineProp(xhr, 'readyState', function() {return 4});
111 if (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function() {return fileApiXHR.response});
112 var resp = fileApiXHR.responseText || (err && fileApiXHR.status == 0 && err !== 'abort' ? err : undefined);
113 redefineProp(xhr, 'responseText', function() {return resp});
114 redefineProp(xhr, 'response', function() {return resp});
115 if (err) redefineProp(xhr, 'err', function() {return err});
116 xhr.__fileApiXHR = fileApiXHR;
117 if (xhr.onreadystatechange) xhr.onreadystatechange();
118 if (xhr.onload) xhr.onload();
119 },
120 fileprogress: function(e) {
121 e.target = xhr;
122 xhr.__listeners['progress'] && xhr.__listeners['progress'](e);
123 xhr.__total = e.total;
124 xhr.__loaded = e.loaded;
125 if (e.total === e.loaded) {
126 // fix flash issue that doesn't call complete if there is no response text from the server
127 var _this = this
128 setTimeout(function() {
129 if (!xhr.__completed) {
130 xhr.getAllResponseHeaders = function(){};
131 _this.complete(null, {status: 204, statusText: 'No Content'});
132 }
133 }, 10000);
134 }
135 },
136 headers: xhr.__requestHeaders
137 }
138 config.data = {};
139 config.files = {}
140 for (var i = 0; i < formData.data.length; i++) {
141 var item = formData.data[i];
142 if (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {
143 config.files[item.key] = item.val;
144 } else {
145 config.data[item.key] = item.val;
146 }
147 }
148
149 setTimeout(function() {
150 if (!hasFlash()) {
151 throw 'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';
152 }
153 xhr.__fileApiXHR = FileAPI.upload(config);
154 }, 1);
155 } else {
156 orig.apply(xhr, arguments);
157 }
158 }
159 });
160 window.XMLHttpRequest.__isFileAPIShim = true;
161
162 var addFlash = function(elem) {
163 if (!hasFlash()) {
164 throw 'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';
165 }
166 var el = angular.element(elem);
167 if (!el.attr('disabled')) {
168 if (!el.hasClass('js-fileapi-wrapper') && (el.attr('ng-file-select') != null || el.attr('data-ng-file-select') != null ||
169 (el.attr('ng-file-generated-elem') &&
170 (el.parent().attr('ng-file-select') != null || el.parent().attr('data-ng-file-select') != null)))) {
171 if (FileAPI.wrapInsideDiv) {
172 var wrap = document.createElement('div');
173 wrap.innerHTML = '<div class="js-fileapi-wrapper" style="position:relative; overflow:hidden"></div>';
174 wrap = wrap.firstChild;
175 var parent = elem.parentNode;
176 parent.insertBefore(wrap, elem);
177 parent.removeChild(elem);
178 wrap.appendChild(elem);
179 } else {
180 el.addClass('js-fileapi-wrapper');
181 if (el.attr('ng-file-generated-elem')) {
182 if (el.parent().css('position') === '' || el.parent().css('position') === 'static') {
183 el.parent().css('position', 'relative');
184 }
185 el.css('top', 0).css('bottom', 0).css('left', 0).css('right', 0).css('width', '100%').css('height', '100%').
186 css('padding', 0).css('margin', 0);
187 el.parent().unbind('click', el.parent().__afu_fileClickDelegate__);
188 }
189 }
190 }
191 }
192 };
193 var changeFnWrapper = function(fn) {
194 return function(evt) {
195 var files = FileAPI.getFiles(evt);
196 //just a double check for #233
197 for (var i = 0; i < files.length; i++) {
198 if (files[i].size === undefined) files[i].size = 0;
199 if (files[i].name === undefined) files[i].name = 'file';
200 if (files[i].type === undefined) files[i].type = 'undefined';
201 }
202 if (!evt.target) {
203 evt.target = {};
204 }
205 evt.target.files = files;
206 // if evt.target.files is not writable use helper field
207 if (evt.target.files != files) {
208 evt.__files_ = files;
209 }
210 (evt.__files_ || evt.target.files).item = function(i) {
211 return (evt.__files_ || evt.target.files)[i] || null;
212 }
213 if (fn) fn.apply(this, [evt]);
214 };
215 };
216 var isFileChange = function(elem, e) {
217 return (e.toLowerCase() === 'change' || e.toLowerCase() === 'onchange') && elem.getAttribute('type') == 'file';
218 }
219 if (HTMLInputElement.prototype.addEventListener) {
220 HTMLInputElement.prototype.addEventListener = (function(origAddEventListener) {
221 return function(e, fn, b, d) {
222 if (isFileChange(this, e)) {
223 addFlash(this);
224 origAddEventListener.apply(this, [e, changeFnWrapper(fn), b, d]);
225 } else {
226 origAddEventListener.apply(this, [e, fn, b, d]);
227 }
228 }
229 })(HTMLInputElement.prototype.addEventListener);
230 }
231 if (HTMLInputElement.prototype.attachEvent) {
232 HTMLInputElement.prototype.attachEvent = (function(origAttachEvent) {
233 return function(e, fn) {
234 if (isFileChange(this, e)) {
235 addFlash(this);
236 if (window.jQuery) {
237 // fix for #281 jQuery on IE8
238 angular.element(this).bind('change', changeFnWrapper(null));
239 } else {
240 origAttachEvent.apply(this, [e, changeFnWrapper(fn)]);
241 }
242 } else {
243 origAttachEvent.apply(this, [e, fn]);
244 }
245 }
246 })(HTMLInputElement.prototype.attachEvent);
247 }
248
249 window.FormData = FormData = function() {
250 return {
251 append: function(key, val, name) {
252 this.data.push({
253 key: key,
254 val: val,
255 name: name
256 });
257 },
258 data: [],
259 __isFileAPIShim: true
260 };
261 };
262
263 (function () {
264 //load FileAPI
265 if (!window.FileAPI) {
266 window.FileAPI = {};
267 }
268 if (FileAPI.forceLoad) {
269 FileAPI.html5 = false;
270 }
271
272 if (!FileAPI.upload) {
273 var jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;
274 if (window.FileAPI.jsUrl) {
275 jsUrl = window.FileAPI.jsUrl;
276 } else if (window.FileAPI.jsPath) {
277 basePath = window.FileAPI.jsPath;
278 } else {
279 for (i = 0; i < allScripts.length; i++) {
280 src = allScripts[i].src;
281 index = src.search(/\/angular\-file\-upload[\-a-zA-z0-9\.]*\.js/)
282 if (index > -1) {
283 basePath = src.substring(0, index + 1);
284 break;
285 }
286 }
287 }
288
289 if (FileAPI.staticPath == null) FileAPI.staticPath = basePath;
290 script.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js');
291 document.getElementsByTagName('head')[0].appendChild(script);
292 FileAPI.hasFlash = hasFlash();
293 }
294 })();
295 FileAPI.disableFileInput = function(elem, disable) {
296 if (disable) {
297 elem.removeClass('js-fileapi-wrapper')
298 } else {
299 elem.addClass('js-fileapi-wrapper');
300 }
301 }
302 }
303
304
305 if (!window.FileReader) {
306 window.FileReader = function() {
307 var _this = this, loadStarted = false;
308 this.listeners = {};
309 this.addEventListener = function(type, fn) {
310 _this.listeners[type] = _this.listeners[type] || [];
311 _this.listeners[type].push(fn);
312 };
313 this.removeEventListener = function(type, fn) {
314 _this.listeners[type] && _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1);
315 };
316 this.dispatchEvent = function(evt) {
317 var list = _this.listeners[evt.type];
318 if (list) {
319 for (var i = 0; i < list.length; i++) {
320 list[i].call(_this, evt);
321 }
322 }
323 };
324 this.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null;
325
326 var constructEvent = function(type, evt) {
327 var e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error};
328 if (evt.result != null) e.target.result = evt.result;
329 return e;
330 };
331 var listener = function(evt) {
332 if (!loadStarted) {
333 loadStarted = true;
334 _this.onloadstart && this.onloadstart(constructEvent('loadstart', evt));
335 }
336 if (evt.type === 'load') {
337 _this.onloadend && _this.onloadend(constructEvent('loadend', evt));
338 var e = constructEvent('load', evt);
339 _this.onload && _this.onload(e);
340 _this.dispatchEvent(e);
341 } else if (evt.type === 'progress') {
342 var e = constructEvent('progress', evt);
343 _this.onprogress && _this.onprogress(e);
344 _this.dispatchEvent(e);
345 } else {
346 var e = constructEvent('error', evt);
347 _this.onerror && _this.onerror(e);
348 _this.dispatchEvent(e);
349 }
350 };
351 this.readAsArrayBuffer = function(file) {
352 FileAPI.readAsBinaryString(file, listener);
353 }
354 this.readAsBinaryString = function(file) {
355 FileAPI.readAsBinaryString(file, listener);
356 }
357 this.readAsDataURL = function(file) {
358 FileAPI.readAsDataURL(file, listener);
359 }
360 this.readAsText = function(file) {
361 FileAPI.readAsText(file, listener);
362 }
363 }
364 }
365 })();
+0
-2
faraday/server/www/script/angular-file-upload-shim.min.js less more
0 /*! 2.1.1 */
1 !function(){function a(a,b){window.XMLHttpRequest.prototype[a]=b(window.XMLHttpRequest.prototype[a])}function b(a,b,c){try{Object.defineProperty(a,b,{get:c})}catch(d){}}var c=function(){try{var a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");if(a)return!0}catch(b){if(void 0!=navigator.mimeTypes["application/x-shockwave-flash"])return!0}return!1};if(window.XMLHttpRequest&&!window.FormData||window.FileAPI&&FileAPI.forceLoad){var d=function(a){if(!a.__listeners){a.upload||(a.upload={}),a.__listeners=[];var b=a.upload.addEventListener;a.upload.addEventListener=function(c,d){a.__listeners[c]=d,b&&b.apply(this,arguments)}}};a("open",function(a){return function(b,c,e){d(this),this.__url=c;try{a.apply(this,[b,c,e])}catch(f){f.message.indexOf("Access is denied")>-1&&a.apply(this,[b,"_fix_for_ie_crossdomain__",e])}}}),a("getResponseHeader",function(a){return function(b){return this.__fileApiXHR&&this.__fileApiXHR.getResponseHeader?this.__fileApiXHR.getResponseHeader(b):null==a?null:a.apply(this,[b])}}),a("getAllResponseHeaders",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.getAllResponseHeaders?this.__fileApiXHR.getAllResponseHeaders():null==a?null:a.apply(this)}}),a("abort",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.abort?this.__fileApiXHR.abort():null==a?null:a.apply(this)}}),a("setRequestHeader",function(a){return function(b,c){if("__setXHR_"===b){d(this);var e=c(this);e instanceof Function&&e(this)}else this.__requestHeaders=this.__requestHeaders||{},this.__requestHeaders[b]=c,a.apply(this,arguments)}}),a("send",function(a){return function(){var d=this;if(arguments[0]&&arguments[0].__isFileAPIShim){var e=arguments[0],f={url:d.__url,jsonp:!1,cache:!0,complete:function(a,c){d.__completed=!0,!a&&d.__listeners.load&&d.__listeners.load({type:"load",loaded:d.__loaded,total:d.__total,target:d,lengthComputable:!0}),!a&&d.__listeners.loadend&&d.__listeners.loadend({type:"loadend",loaded:d.__loaded,total:d.__total,target:d,lengthComputable:!0}),"abort"===a&&d.__listeners.abort&&d.__listeners.abort({type:"abort",loaded:d.__loaded,total:d.__total,target:d,lengthComputable:!0}),void 0!==c.status&&b(d,"status",function(){return 0==c.status&&a&&"abort"!==a?500:c.status}),void 0!==c.statusText&&b(d,"statusText",function(){return c.statusText}),b(d,"readyState",function(){return 4}),void 0!==c.response&&b(d,"response",function(){return c.response});var e=c.responseText||(a&&0==c.status&&"abort"!==a?a:void 0);b(d,"responseText",function(){return e}),b(d,"response",function(){return e}),a&&b(d,"err",function(){return a}),d.__fileApiXHR=c,d.onreadystatechange&&d.onreadystatechange(),d.onload&&d.onload()},fileprogress:function(a){if(a.target=d,d.__listeners.progress&&d.__listeners.progress(a),d.__total=a.total,d.__loaded=a.loaded,a.total===a.loaded){var b=this;setTimeout(function(){d.__completed||(d.getAllResponseHeaders=function(){},b.complete(null,{status:204,statusText:"No Content"}))},1e4)}},headers:d.__requestHeaders};f.data={},f.files={};for(var g=0;g<e.data.length;g++){var h=e.data[g];null!=h.val&&null!=h.val.name&&null!=h.val.size&&null!=h.val.type?f.files[h.key]=h.val:f.data[h.key]=h.val}setTimeout(function(){if(!c())throw'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';d.__fileApiXHR=FileAPI.upload(f)},1)}else a.apply(d,arguments)}}),window.XMLHttpRequest.__isFileAPIShim=!0;var e=function(a){if(!c())throw'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';var b=angular.element(a);if(!b.attr("disabled")&&!b.hasClass("js-fileapi-wrapper")&&(null!=b.attr("ng-file-select")||null!=b.attr("data-ng-file-select")||b.attr("ng-file-generated-elem")&&(null!=b.parent().attr("ng-file-select")||null!=b.parent().attr("data-ng-file-select"))))if(FileAPI.wrapInsideDiv){var d=document.createElement("div");d.innerHTML='<div class="js-fileapi-wrapper" style="position:relative; overflow:hidden"></div>',d=d.firstChild;var e=a.parentNode;e.insertBefore(d,a),e.removeChild(a),d.appendChild(a)}else b.addClass("js-fileapi-wrapper"),b.attr("ng-file-generated-elem")&&((""===b.parent().css("position")||"static"===b.parent().css("position"))&&b.parent().css("position","relative"),b.css("top",0).css("bottom",0).css("left",0).css("right",0).css("width","100%").css("height","100%").css("padding",0).css("margin",0),b.parent().unbind("click",b.parent().__afu_fileClickDelegate__))},f=function(a){return function(b){for(var c=FileAPI.getFiles(b),d=0;d<c.length;d++)void 0===c[d].size&&(c[d].size=0),void 0===c[d].name&&(c[d].name="file"),void 0===c[d].type&&(c[d].type="undefined");b.target||(b.target={}),b.target.files=c,b.target.files!=c&&(b.__files_=c),(b.__files_||b.target.files).item=function(a){return(b.__files_||b.target.files)[a]||null},a&&a.apply(this,[b])}},g=function(a,b){return("change"===b.toLowerCase()||"onchange"===b.toLowerCase())&&"file"==a.getAttribute("type")};HTMLInputElement.prototype.addEventListener&&(HTMLInputElement.prototype.addEventListener=function(a){return function(b,c,d,h){g(this,b)?(e(this),a.apply(this,[b,f(c),d,h])):a.apply(this,[b,c,d,h])}}(HTMLInputElement.prototype.addEventListener)),HTMLInputElement.prototype.attachEvent&&(HTMLInputElement.prototype.attachEvent=function(a){return function(b,c){g(this,b)?(e(this),window.jQuery?angular.element(this).bind("change",f(null)):a.apply(this,[b,f(c)])):a.apply(this,[b,c])}}(HTMLInputElement.prototype.attachEvent)),window.FormData=FormData=function(){return{append:function(a,b,c){this.data.push({key:a,val:b,name:c})},data:[],__isFileAPIShim:!0}},function(){if(window.FileAPI||(window.FileAPI={}),FileAPI.forceLoad&&(FileAPI.html5=!1),!FileAPI.upload){var a,b,d,e,f,g=document.createElement("script"),h=document.getElementsByTagName("script");if(window.FileAPI.jsUrl)a=window.FileAPI.jsUrl;else if(window.FileAPI.jsPath)b=window.FileAPI.jsPath;else for(d=0;d<h.length;d++)if(f=h[d].src,e=f.search(/\/angular\-file\-upload[\-a-zA-z0-9\.]*\.js/),e>-1){b=f.substring(0,e+1);break}null==FileAPI.staticPath&&(FileAPI.staticPath=b),g.setAttribute("src",a||b+"FileAPI.min.js"),document.getElementsByTagName("head")[0].appendChild(g),FileAPI.hasFlash=c()}}(),FileAPI.disableFileInput=function(a,b){b?a.removeClass("js-fileapi-wrapper"):a.addClass("js-fileapi-wrapper")}}window.FileReader||(window.FileReader=function(){var a=this,b=!1;this.listeners={},this.addEventListener=function(b,c){a.listeners[b]=a.listeners[b]||[],a.listeners[b].push(c)},this.removeEventListener=function(b,c){a.listeners[b]&&a.listeners[b].splice(a.listeners[b].indexOf(c),1)},this.dispatchEvent=function(b){var c=a.listeners[b.type];if(c)for(var d=0;d<c.length;d++)c[d].call(a,b)},this.onabort=this.onerror=this.onload=this.onloadstart=this.onloadend=this.onprogress=null;var c=function(b,c){var d={type:b,target:a,loaded:c.loaded,total:c.total,error:c.error};return null!=c.result&&(d.target.result=c.result),d},d=function(d){if(b||(b=!0,a.onloadstart&&this.onloadstart(c("loadstart",d))),"load"===d.type){a.onloadend&&a.onloadend(c("loadend",d));var e=c("load",d);a.onload&&a.onload(e),a.dispatchEvent(e)}else if("progress"===d.type){var e=c("progress",d);a.onprogress&&a.onprogress(e),a.dispatchEvent(e)}else{var e=c("error",d);a.onerror&&a.onerror(e),a.dispatchEvent(e)}};this.readAsArrayBuffer=function(a){FileAPI.readAsBinaryString(a,d)},this.readAsBinaryString=function(a){FileAPI.readAsBinaryString(a,d)},this.readAsDataURL=function(a){FileAPI.readAsDataURL(a,d)},this.readAsText=function(a){FileAPI.readAsText(a,d)}})}();
+0
-499
faraday/server/www/script/angular-file-upload.js less more
0 /**!
1 * AngularJS file upload/drop directive with progress and abort
2 * @author Danial <[email protected]>
3 * @version 2.1.1
4 */
5 (function() {
6
7 function patchXHR(fnName, newFn) {
8 window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);
9 }
10
11 if (window.XMLHttpRequest && !window.XMLHttpRequest.__isFileAPIShim) {
12 patchXHR('setRequestHeader', function(orig) {
13 return function(header, value) {
14 if (header === '__setXHR_') {
15 var val = value(this);
16 // fix for angular < 1.2.0
17 if (val instanceof Function) {
18 val(this);
19 }
20 } else {
21 orig.apply(this, arguments);
22 }
23 }
24 });
25 }
26
27 var angularFileUpload = angular.module('angularFileUpload', []);
28 angularFileUpload.version = '2.1.1';
29 angularFileUpload.service('$upload', ['$http', '$q', '$timeout', function($http, $q, $timeout) {
30 function sendHttp(config) {
31 config.method = config.method || 'POST';
32 config.headers = config.headers || {};
33 config.transformRequest = config.transformRequest || function(data, headersGetter) {
34 if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {
35 return data;
36 }
37 return $http.defaults.transformRequest[0](data, headersGetter);
38 };
39 var deferred = $q.defer();
40 var promise = deferred.promise;
41
42 config.headers['__setXHR_'] = function() {
43 return function(xhr) {
44 if (!xhr) return;
45 config.__XHR = xhr;
46 config.xhrFn && config.xhrFn(xhr);
47 xhr.upload.addEventListener('progress', function(e) {
48 e.config = config;
49 deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function(){promise.progress_fn(e)});
50 }, false);
51 //fix for firefox not firing upload progress end, also IE8-9
52 xhr.upload.addEventListener('load', function(e) {
53 if (e.lengthComputable) {
54 e.config = config;
55 deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function(){promise.progress_fn(e)});
56 }
57 }, false);
58 };
59 };
60
61 $http(config).then(function(r){deferred.resolve(r)}, function(e){deferred.reject(e)}, function(n){deferred.notify(n)});
62
63 promise.success = function(fn) {
64 promise.then(function(response) {
65 fn(response.data, response.status, response.headers, config);
66 });
67 return promise;
68 };
69
70 promise.error = function(fn) {
71 promise.then(null, function(response) {
72 fn(response.data, response.status, response.headers, config);
73 });
74 return promise;
75 };
76
77 promise.progress = function(fn) {
78 promise.progress_fn = fn;
79 promise.then(null, null, function(update) {
80 fn(update);
81 });
82 return promise;
83 };
84 promise.abort = function() {
85 if (config.__XHR) {
86 $timeout(function() {
87 config.__XHR.abort();
88 });
89 }
90 return promise;
91 };
92 promise.xhr = function(fn) {
93 config.xhrFn = (function(origXhrFn) {
94 return function() {
95 origXhrFn && origXhrFn.apply(promise, arguments);
96 fn.apply(promise, arguments);
97 }
98 })(config.xhrFn);
99 return promise;
100 };
101
102 return promise;
103 }
104
105 this.upload = function(config) {
106 config.headers = config.headers || {};
107 config.headers['Content-Type'] = undefined;
108 config.transformRequest = config.transformRequest || $http.defaults.transformRequest;
109 var formData = new FormData();
110 var origTransformRequest = config.transformRequest;
111 var origData = config.data;
112 config.transformRequest = function(formData, headerGetter) {
113 if (origData) {
114 if (config.formDataAppender) {
115 for (var key in origData) {
116 var val = origData[key];
117 config.formDataAppender(formData, key, val);
118 }
119 } else {
120 for (var key in origData) {
121 var val = origData[key];
122 if (typeof origTransformRequest == 'function') {
123 val = origTransformRequest(val, headerGetter);
124 } else {
125 for (var i = 0; i < origTransformRequest.length; i++) {
126 var transformFn = origTransformRequest[i];
127 if (typeof transformFn == 'function') {
128 val = transformFn(val, headerGetter);
129 }
130 }
131 }
132 if (val != undefined) formData.append(key, val);
133 }
134 }
135 }
136
137 if (config.file != null) {
138 var fileFormName = config.fileFormDataName || 'file';
139
140 if (Object.prototype.toString.call(config.file) === '[object Array]') {
141 var isFileFormNameString = Object.prototype.toString.call(fileFormName) === '[object String]';
142 for (var i = 0; i < config.file.length; i++) {
143 formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],
144 (config.fileName && config.fileName[i]) || config.file[i].name);
145 }
146 } else {
147 formData.append(fileFormName, config.file, config.fileName || config.file.name);
148 }
149 }
150 return formData;
151 };
152
153 config.data = formData;
154
155 return sendHttp(config);
156 };
157
158 this.http = function(config) {
159 return sendHttp(config);
160 };
161 }]);
162
163 angularFileUpload.directive('ngFileSelect', [ '$parse', '$timeout', '$compile', function($parse, $timeout, $compile) { return {
164 restrict: 'AEC',
165 require:'?ngModel',
166 link: function(scope, elem, attr, ngModel) {
167 handleFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile);
168 }
169 }}]);
170
171 function handleFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile) {
172 if (attr.ngMultiple && $parse(attr.ngMultiple)(scope)) {
173 elem.attr('multiple', 'true');
174 attr['multiple'] = 'true';
175 }
176 var accept = attr.ngAccept && $parse(attr.ngAccept)(scope);
177 if (accept) {
178 elem.attr('accept', accept);
179 attr['accept'] = accept;
180 }
181 if (elem[0].tagName.toLowerCase() !== 'input' || (elem.attr('type') && elem.attr('type').toLowerCase()) !== 'file') {
182 var fileElem = angular.element('<input type="file">')
183 if (attr['multiple']) fileElem.attr('multiple', attr['multiple']);
184 if (attr['accept']) fileElem.attr('accept', attr['accept']);
185 fileElem.css('width', '1px').css('height', '1px').css('opacity', 0).css('position', 'absolute').css('filter', 'alpha(opacity=0)')
186 .css('padding', 0).css('margin', 0).css('overflow', 'hidden').attr('tabindex', '-1').attr('ng-file-generated-elem', true);
187 elem.append(fileElem);
188 elem.__afu_fileClickDelegate__ = function() {
189 fileElem[0].click();
190 };
191 elem.bind('click', elem.__afu_fileClickDelegate__);
192 elem.css('overflow', 'hidden');
193 var origElem = elem;
194 elem = fileElem;
195 }
196 var changeFn = $parse(attr.ngFileChange);
197 if ($parse(attr.resetOnClick)(scope) != false) {
198 if (navigator.appVersion.indexOf("MSIE 10") !== -1) {
199 // fix for IE10 cannot set the value of the input to null programmatically by replacing input
200 var replaceElem = function(evt) {
201 var inputFile = elem.clone();
202 inputFile.val('');
203 elem.replaceWith(inputFile);
204 $compile(inputFile)(scope);
205 fileElem = inputFile;
206 elem = inputFile;
207 elem.bind('change', onChangeFn);
208 elem.unbind('click');
209 elem[0].click();
210 elem.bind('click', replaceElem);
211 evt.preventDefault();
212 evt.stopPropagation();
213 };
214 elem.bind('click', replaceElem);
215 } else {
216 elem.bind('click', function(evt) {
217 elem[0].value = null;
218 });
219 }
220 }
221 var onChangeFn = function(evt) {
222 var files = [], fileList, i;
223 fileList = evt.__files_ || evt.target.files;
224 updateModel(fileList, attr, ngModel, changeFn, scope, evt);
225 };
226 elem.bind('change', onChangeFn);
227 if (attr['ngFileSelect'] != '') {
228 attr.ngFileChange = attr.ngFileSelect;
229 }
230
231 function updateModel(fileList, attr, ngModel, change, scope, evt) {
232 var files = [];
233 for (var i = 0; i < fileList.length; i++) {
234 files.push(fileList.item(i));
235 }
236 if (ngModel) {
237 scope[attr.ngModel] ? scope[attr.ngModel].value = files : scope[attr.ngModel] = files;
238 ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? '' : files);
239 }
240 if (change) {
241 $timeout(function() {
242 change(scope, {
243 $files : files,
244 $event : evt
245 });
246 });
247 }
248 }
249 }
250
251 angularFileUpload.directive('ngFileDrop', [ '$parse', '$timeout', '$location', function($parse, $timeout, $location) { return {
252 restrict: 'AEC',
253 require:'?ngModel',
254 link: function(scope, elem, attr, ngModel) {
255 handleDrop(scope, elem, attr, ngModel, $parse, $timeout, $location);
256 }
257 }}]);
258
259 angularFileUpload.directive('ngNoFileDrop', function() {
260 return function(scope, elem, attr) {
261 if (dropAvailable()) elem.css('display', 'none')
262 }
263 });
264
265 //for backward compatibility
266 angularFileUpload.directive('ngFileDropAvailable', [ '$parse', '$timeout', function($parse, $timeout) {
267 return function(scope, elem, attr) {
268 if (dropAvailable()) {
269 var fn = $parse(attr['ngFileDropAvailable']);
270 $timeout(function() {
271 fn(scope);
272 });
273 }
274 }
275 }]);
276
277 function handleDrop(scope, elem, attr, ngModel, $parse, $timeout, $location) {
278 var available = dropAvailable();
279 if (attr['dropAvailable']) {
280 $timeout(function() {
281 scope.dropAvailable ? scope.dropAvailable.value = available : scope.dropAvailable = available;
282 });
283 }
284 if (!available) {
285 if ($parse(attr.hideOnDropNotAvailable)(scope) != false) {
286 elem.css('display', 'none');
287 }
288 return;
289 }
290 var leaveTimeout = null;
291 var stopPropagation = $parse(attr.stopPropagation)(scope);
292 var dragOverDelay = 1;
293 var accept = $parse(attr.ngAccept)(scope) || attr.accept;
294 var regexp = accept ? new RegExp(globStringToRegex(accept)) : null;
295 var actualDragOverClass;
296 elem[0].addEventListener('dragover', function(evt) {
297 evt.preventDefault();
298 if (stopPropagation) evt.stopPropagation();
299 $timeout.cancel(leaveTimeout);
300 if (!scope.actualDragOverClass) {
301 actualDragOverClass = calculateDragOverClass(scope, attr, evt);
302 }
303 elem.addClass(actualDragOverClass);
304 }, false);
305 elem[0].addEventListener('dragenter', function(evt) {
306 evt.preventDefault();
307 if (stopPropagation) evt.stopPropagation();
308 }, false);
309 elem[0].addEventListener('dragleave', function(evt) {
310 leaveTimeout = $timeout(function() {
311 elem.removeClass(actualDragOverClass);
312 actualDragOverClass = null;
313 }, dragOverDelay || 1);
314 }, false);
315 if (attr['ngFileDrop'] != '') {
316 attr.ngFileChange = scope.ngFileDrop;
317 }
318 elem[0].addEventListener('drop', function(evt) {
319 evt.preventDefault();
320 if (stopPropagation) evt.stopPropagation();
321 elem.removeClass(actualDragOverClass);
322 actualDragOverClass = null;
323 extractFiles(evt, function(files, rejFiles) {
324 if (ngModel) {
325 scope[attr.ngModel] ? scope[attr.ngModel].value = files : scope[attr.ngModel] = files;
326 ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? '' : files);
327 }
328 if (attr['ngFileRejectedModel']) {
329 scope[attr.ngFileRejectedModel] ? scope[attr.ngFileRejectedModel].value = rejFiles :
330 scope[attr.ngFileRejectedModel] = rejFiles;
331 }
332
333 $timeout(function() {
334 $parse(attr.ngFileChange)(scope, {
335 $files : files,
336 $rejectedFiles: rejFiles,
337 $event : evt
338 });
339 });
340 }, $parse(attr.allowDir)(scope) != false, attr.multiple || $parse(attr.ngMultiple)(scope));
341 }, false);
342
343 function calculateDragOverClass(scope, attr, evt) {
344 var valid = true;
345 if (regexp) {
346 var items = evt.dataTransfer.items;
347 if (items != null) {
348 for (var i = 0 ; i < items.length && valid; i++) {
349 valid = valid && (items[i].kind == 'file' || items[i].kind == '') &&
350 (items[i].type.match(regexp) != null || (items[i].name != null && items[i].name.match(regexp) != null));
351 }
352 }
353 }
354 var clazz = $parse(attr.dragOverClass)(scope, {$event : evt});
355 if (clazz) {
356 if (clazz.delay) dragOverDelay = clazz.delay;
357 if (clazz.accept) clazz = valid ? clazz.accept : clazz.reject;
358 }
359 return clazz || attr['dragOverClass'] || 'dragover';
360 }
361
362 function extractFiles(evt, callback, allowDir, multiple) {
363 var files = [], rejFiles = [], items = evt.dataTransfer.items, processing = 0;
364
365 function addFile(file) {
366 if (!regexp || file.type.match(regexp) || (file.name != null && file.name.match(regexp))) {
367 files.push(file);
368 } else {
369 rejFiles.push(file);
370 }
371 }
372
373 if (items && items.length > 0 && $location.protocol() != 'file') {
374 for (var i = 0; i < items.length; i++) {
375 if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {
376 var entry = items[i].webkitGetAsEntry();
377 if (entry.isDirectory && !allowDir) {
378 continue;
379 }
380 if (entry != null) {
381 //fix for chrome bug https://code.google.com/p/chromium/issues/detail?id=149735
382 if (isASCII(entry.name)) {
383 traverseFileTree(files, entry);
384 } else if (!items[i].webkitGetAsEntry().isDirectory) {
385 addFile(items[i].getAsFile());
386 }
387 }
388 } else {
389 var f = items[i].getAsFile();
390 if (f != null) addFile(f);
391 }
392 if (!multiple && files.length > 0) break;
393 }
394 } else {
395 var fileList = evt.dataTransfer.files;
396 if (fileList != null) {
397 for (var i = 0; i < fileList.length; i++) {
398 addFile(fileList.item(i));
399 if (!multiple && files.length > 0) break;
400 }
401 }
402 }
403 var delays = 0;
404 (function waitForProcess(delay) {
405 $timeout(function() {
406 if (!processing) {
407 if (!multiple && files.length > 1) {
408 var i = 0;
409 while (files[i].type == 'directory') i++;
410 files = [files[i]];
411 }
412 callback(files, rejFiles);
413 } else {
414 if (delays++ * 10 < 20 * 1000) {
415 waitForProcess(10);
416 }
417 }
418 }, delay || 0)
419 })();
420
421 function traverseFileTree(files, entry, path) {
422 if (entry != null) {
423 if (entry.isDirectory) {
424 var filePath = (path || '') + entry.name;
425 addFile({name: entry.name, type: 'directory', path: filePath});
426 var dirReader = entry.createReader();
427 var entries = [];
428 processing++;
429 var readEntries = function() {
430 dirReader.readEntries(function(results) {
431 try {
432 if (!results.length) {
433 for (var i = 0; i < entries.length; i++) {
434 traverseFileTree(files, entries[i], (path ? path : '') + entry.name + '/');
435 }
436 processing--;
437 } else {
438 entries = entries.concat(Array.prototype.slice.call(results || [], 0));
439 readEntries();
440 }
441 } catch (e) {
442 processing--;
443 console.error(e);
444 }
445 }, function() {
446 processing--;
447 });
448 };
449 readEntries();
450 } else {
451 processing++;
452 entry.file(function(file) {
453 try {
454 processing--;
455 file.path = (path ? path : '') + file.name;
456 addFile(file);
457 } catch (e) {
458 processing--;
459 console.error(e);
460 }
461 }, function(e) {
462 processing--;
463 });
464 }
465 }
466 }
467 }
468 }
469
470 function dropAvailable() {
471 var div = document.createElement('div');
472 return ('draggable' in div) && ('ondrop' in div);
473 }
474
475 function isASCII(str) {
476 return /^[\000-\177]*$/.test(str);
477 }
478
479 function globStringToRegex(str) {
480 if (str.length > 2 && str[0] === '/' && str[str.length -1] === '/') {
481 return str.substring(1, str.length - 1);
482 }
483 var split = str.split(','), result = '';
484 if (split.length > 1) {
485 for (var i = 0; i < split.length; i++) {
486 result += '(' + globStringToRegex(split[i]) + ')';
487 if (i < split.length - 1) {
488 result += '|'
489 }
490 }
491 } else {
492 result = '^' + str.replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + '-]', 'g'), '\\$&') + '$';
493 result = result.replace(/\\\*/g, '.*').replace(/\\\?/g, '.');
494 }
495 return result;
496 }
497
498 })();
+0
-2
faraday/server/www/script/angular-file-upload.min.js less more
0 /*! 2.1.1 */
1 !function(){function a(a,b){window.XMLHttpRequest.prototype[a]=b(window.XMLHttpRequest.prototype[a])}function b(a,b,c,d,e,f,g){function h(a,b,c,d,e,g){for(var h=[],i=0;i<a.length;i++)h.push(a.item(i));c&&(e[b.ngModel]?e[b.ngModel].value=h:e[b.ngModel]=h,c&&c.$setViewValue(null!=h&&0==h.length?"":h)),d&&f(function(){d(e,{$files:h,$event:g})})}c.ngMultiple&&e(c.ngMultiple)(a)&&(b.attr("multiple","true"),c.multiple="true");var i=c.ngAccept&&e(c.ngAccept)(a);if(i&&(b.attr("accept",i),c.accept=i),"input"!==b[0].tagName.toLowerCase()||"file"!==(b.attr("type")&&b.attr("type").toLowerCase())){var j=angular.element('<input type="file">');c.multiple&&j.attr("multiple",c.multiple),c.accept&&j.attr("accept",c.accept),j.css("width","1px").css("height","1px").css("opacity",0).css("position","absolute").css("filter","alpha(opacity=0)").css("padding",0).css("margin",0).css("overflow","hidden").attr("tabindex","-1").attr("ng-file-generated-elem",!0),b.append(j),b.__afu_fileClickDelegate__=function(){j[0].click()},b.bind("click",b.__afu_fileClickDelegate__),b.css("overflow","hidden");b=j}var k=e(c.ngFileChange);if(0!=e(c.resetOnClick)(a))if(-1!==navigator.appVersion.indexOf("MSIE 10")){var l=function(c){var d=b.clone();d.val(""),b.replaceWith(d),g(d)(a),j=d,b=d,b.bind("change",m),b.unbind("click"),b[0].click(),b.bind("click",l),c.preventDefault(),c.stopPropagation()};b.bind("click",l)}else b.bind("click",function(){b[0].value=null});var m=function(b){var e;e=b.__files_||b.target.files,h(e,c,d,k,a,b)};b.bind("change",m),""!=c.ngFileSelect&&(c.ngFileChange=c.ngFileSelect)}function c(a,b,c,g,h,i,j){function k(a,b,c){var d=!0;if(s){var e=c.dataTransfer.items;if(null!=e)for(var f=0;f<e.length&&d;f++)d=d&&("file"==e[f].kind||""==e[f].kind)&&(null!=e[f].type.match(s)||null!=e[f].name&&null!=e[f].name.match(s))}var g=h(b.dragOverClass)(a,{$event:c});return g&&(g.delay&&(q=g.delay),g.accept&&(g=d?g.accept:g.reject)),g||b.dragOverClass||"dragover"}function l(a,b,c,d){function f(a){!s||a.type.match(s)||null!=a.name&&a.name.match(s)?h.push(a):k.push(a)}function g(a,b,c){if(null!=b)if(b.isDirectory){var d=(c||"")+b.name;f({name:b.name,type:"directory",path:d});var e=b.createReader(),h=[];m++;var i=function(){e.readEntries(function(d){try{if(d.length)h=h.concat(Array.prototype.slice.call(d||[],0)),i();else{for(var e=0;e<h.length;e++)g(a,h[e],(c?c:"")+b.name+"/");m--}}catch(f){m--,console.error(f)}},function(){m--})};i()}else m++,b.file(function(a){try{m--,a.path=(c?c:"")+a.name,f(a)}catch(b){m--,console.error(b)}},function(){m--})}var h=[],k=[],l=a.dataTransfer.items,m=0;if(l&&l.length>0&&"file"!=j.protocol())for(var n=0;n<l.length;n++){if(l[n].webkitGetAsEntry&&l[n].webkitGetAsEntry()&&l[n].webkitGetAsEntry().isDirectory){var o=l[n].webkitGetAsEntry();if(o.isDirectory&&!c)continue;null!=o&&(e(o.name)?g(h,o):l[n].webkitGetAsEntry().isDirectory||f(l[n].getAsFile()))}else{var p=l[n].getAsFile();null!=p&&f(p)}if(!d&&h.length>0)break}else{var q=a.dataTransfer.files;if(null!=q)for(var n=0;n<q.length&&(f(q.item(n)),d||!(h.length>0));n++);}var r=0;!function t(a){i(function(){if(m)10*r++<2e4&&t(10);else{if(!d&&h.length>1){for(var a=0;"directory"==h[a].type;)a++;h=[h[a]]}b(h,k)}},a||0)}()}var m=d();if(c.dropAvailable&&i(function(){a.dropAvailable?a.dropAvailable.value=m:a.dropAvailable=m}),!m)return 0!=h(c.hideOnDropNotAvailable)(a)&&b.css("display","none"),void 0;var n,o=null,p=h(c.stopPropagation)(a),q=1,r=h(c.ngAccept)(a)||c.accept,s=r?new RegExp(f(r)):null;b[0].addEventListener("dragover",function(d){d.preventDefault(),p&&d.stopPropagation(),i.cancel(o),a.actualDragOverClass||(n=k(a,c,d)),b.addClass(n)},!1),b[0].addEventListener("dragenter",function(a){a.preventDefault(),p&&a.stopPropagation()},!1),b[0].addEventListener("dragleave",function(){o=i(function(){b.removeClass(n),n=null},q||1)},!1),""!=c.ngFileDrop&&(c.ngFileChange=a.ngFileDrop),b[0].addEventListener("drop",function(d){d.preventDefault(),p&&d.stopPropagation(),b.removeClass(n),n=null,l(d,function(b,e){g&&(a[c.ngModel]?a[c.ngModel].value=b:a[c.ngModel]=b,g&&g.$setViewValue(null!=b&&0==b.length?"":b)),c.ngFileRejectedModel&&(a[c.ngFileRejectedModel]?a[c.ngFileRejectedModel].value=e:a[c.ngFileRejectedModel]=e),i(function(){h(c.ngFileChange)(a,{$files:b,$rejectedFiles:e,$event:d})})},0!=h(c.allowDir)(a),c.multiple||h(c.ngMultiple)(a))},!1)}function d(){var a=document.createElement("div");return"draggable"in a&&"ondrop"in a}function e(a){return/^[\000-\177]*$/.test(a)}function f(a){if(a.length>2&&"/"===a[0]&&"/"===a[a.length-1])return a.substring(1,a.length-1);var b=a.split(","),c="";if(b.length>1)for(var d=0;d<b.length;d++)c+="("+f(b[d])+")",d<b.length-1&&(c+="|");else c="^"+a.replace(new RegExp("[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]","g"),"\\$&")+"$",c=c.replace(/\\\*/g,".*").replace(/\\\?/g,".");return c}window.XMLHttpRequest&&!window.XMLHttpRequest.__isFileAPIShim&&a("setRequestHeader",function(a){return function(b,c){if("__setXHR_"===b){var d=c(this);d instanceof Function&&d(this)}else a.apply(this,arguments)}});var g=angular.module("angularFileUpload",[]);g.version="2.1.1",g.service("$upload",["$http","$q","$timeout",function(a,b,c){function d(d){d.method=d.method||"POST",d.headers=d.headers||{},d.transformRequest=d.transformRequest||function(b,c){return window.ArrayBuffer&&b instanceof window.ArrayBuffer?b:a.defaults.transformRequest[0](b,c)};var e=b.defer(),f=e.promise;return d.headers.__setXHR_=function(){return function(a){a&&(d.__XHR=a,d.xhrFn&&d.xhrFn(a),a.upload.addEventListener("progress",function(a){a.config=d,e.notify?e.notify(a):f.progress_fn&&c(function(){f.progress_fn(a)})},!1),a.upload.addEventListener("load",function(a){a.lengthComputable&&(a.config=d,e.notify?e.notify(a):f.progress_fn&&c(function(){f.progress_fn(a)}))},!1))}},a(d).then(function(a){e.resolve(a)},function(a){e.reject(a)},function(a){e.notify(a)}),f.success=function(a){return f.then(function(b){a(b.data,b.status,b.headers,d)}),f},f.error=function(a){return f.then(null,function(b){a(b.data,b.status,b.headers,d)}),f},f.progress=function(a){return f.progress_fn=a,f.then(null,null,function(b){a(b)}),f},f.abort=function(){return d.__XHR&&c(function(){d.__XHR.abort()}),f},f.xhr=function(a){return d.xhrFn=function(b){return function(){b&&b.apply(f,arguments),a.apply(f,arguments)}}(d.xhrFn),f},f}this.upload=function(b){b.headers=b.headers||{},b.headers["Content-Type"]=void 0,b.transformRequest=b.transformRequest||a.defaults.transformRequest;var c=new FormData,e=b.transformRequest,f=b.data;return b.transformRequest=function(a,c){if(f)if(b.formDataAppender)for(var d in f){var g=f[d];b.formDataAppender(a,d,g)}else for(var d in f){var g=f[d];if("function"==typeof e)g=e(g,c);else for(var h=0;h<e.length;h++){var i=e[h];"function"==typeof i&&(g=i(g,c))}void 0!=g&&a.append(d,g)}if(null!=b.file){var j=b.fileFormDataName||"file";if("[object Array]"===Object.prototype.toString.call(b.file))for(var k="[object String]"===Object.prototype.toString.call(j),h=0;h<b.file.length;h++)a.append(k?j:j[h],b.file[h],b.fileName&&b.fileName[h]||b.file[h].name);else a.append(j,b.file,b.fileName||b.file.name)}return a},b.data=c,d(b)},this.http=function(a){return d(a)}}]),g.directive("ngFileSelect",["$parse","$timeout","$compile",function(a,c,d){return{restrict:"AEC",require:"?ngModel",link:function(e,f,g,h){b(e,f,g,h,a,c,d)}}}]),g.directive("ngFileDrop",["$parse","$timeout","$location",function(a,b,d){return{restrict:"AEC",require:"?ngModel",link:function(e,f,g,h){c(e,f,g,h,a,b,d)}}}]),g.directive("ngNoFileDrop",function(){return function(a,b){d()&&b.css("display","none")}}),g.directive("ngFileDropAvailable",["$parse","$timeout",function(a,b){return function(c,e,f){if(d()){var g=a(f.ngFileDropAvailable);b(function(){g(c)})}}}])}();
+0
-596
faraday/server/www/script/angular-hotkeys.js less more
0 /*
1 * angular-hotkeys
2 *
3 * Automatic keyboard shortcuts for your angular apps
4 *
5 * (c) 2014 Wes Cruver
6 * License: MIT
7 */
8
9 (function() {
10
11 'use strict';
12
13 angular.module('cfp.hotkeys', []).provider('hotkeys', function($injector) {
14
15 /**
16 * Configurable setting to disable the cheatsheet entirely
17 * @type {Boolean}
18 */
19 this.includeCheatSheet = true;
20
21 /**
22 * Configurable setting to disable ngRoute hooks
23 * @type {Boolean}
24 */
25 this.useNgRoute = $injector.has('ngViewDirective');
26
27 /**
28 * Configurable setting for the cheat sheet title
29 * @type {String}
30 */
31
32 this.templateTitle = 'Keyboard Shortcuts:';
33
34 /**
35 * Configurable settings for the cheat sheet header and footer. Both are HTML, and the header
36 * overrides the normal title if specified.
37 * @type {String}
38 */
39 this.templateHeader = null;
40 this.templateFooter = null;
41
42 /**
43 * Cheat sheet template in the event you want to totally customize it.
44 * @type {String}
45 */
46 this.template = '<div class="cfp-hotkeys-container fade" ng-class="{in: helpVisible}" style="display: none;"><div class="cfp-hotkeys">' +
47 '<h4 class="cfp-hotkeys-title" ng-if="!header">{{ title }}</h4>' +
48 '<div ng-bind-html="header" ng-if="header"></div>' +
49 '<table><tbody>' +
50 '<tr ng-repeat="hotkey in hotkeys | filter:{ description: \'!$$undefined$$\' }">' +
51 '<td class="cfp-hotkeys-keys">' +
52 '<span ng-repeat="key in hotkey.format() track by $index" class="cfp-hotkeys-key">{{ key }}</span>' +
53 '</td>' +
54 '<td class="cfp-hotkeys-text">{{ hotkey.description }}</td>' +
55 '</tr>' +
56 '</tbody></table>' +
57 '<div ng-bind-html="footer" ng-if="footer"></div>' +
58 '<div class="cfp-hotkeys-close" ng-click="toggleCheatSheet()">×</div>' +
59 '</div></div>';
60
61 /**
62 * Configurable setting for the cheat sheet hotkey
63 * @type {String}
64 */
65 this.cheatSheetHotkey = '?';
66
67 /**
68 * Configurable setting for the cheat sheet description
69 * @type {String}
70 */
71 this.cheatSheetDescription = 'Show / hide this help menu';
72
73 this.$get = function ($rootElement, $rootScope, $compile, $window, $document) {
74
75 // monkeypatch Mousetrap's stopCallback() function
76 // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA
77 // (instead we will perform this check per-key in the _add() method)
78 Mousetrap.prototype.stopCallback = function(event, element) {
79 // if the element has the class "mousetrap" then no need to stop
80 if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
81 return false;
82 }
83
84 return (element.contentEditable && element.contentEditable == 'true');
85 };
86
87 /**
88 * Convert strings like cmd into symbols like ⌘
89 * @param {String} combo Key combination, e.g. 'mod+f'
90 * @return {String} The key combination with symbols
91 */
92 function symbolize (combo) {
93 var map = {
94 command : '⌘',
95 shift : '⇧',
96 left : '←',
97 right : '→',
98 up : '↑',
99 down : '↓',
100 'return' : '↩',
101 backspace : '⌫'
102 };
103 combo = combo.split('+');
104
105 for (var i = 0; i < combo.length; i++) {
106 // try to resolve command / ctrl based on OS:
107 if (combo[i] === 'mod') {
108 if ($window.navigator && $window.navigator.platform.indexOf('Mac') >=0 ) {
109 combo[i] = 'command';
110 } else {
111 combo[i] = 'ctrl';
112 }
113 }
114
115 combo[i] = map[combo[i]] || combo[i];
116 }
117
118 return combo.join(' + ');
119 }
120
121 /**
122 * Hotkey object used internally for consistency
123 *
124 * @param {array} combo The keycombo. it's an array to support multiple combos
125 * @param {String} description Description for the keycombo
126 * @param {Function} callback function to execute when keycombo pressed
127 * @param {string} action the type of event to listen for (for mousetrap)
128 * @param {array} allowIn an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')
129 * @param {Boolean} persistent Whether the hotkey persists navigation events
130 */
131 function Hotkey (combo, description, callback, action, allowIn, persistent) {
132 // TODO: Check that the values are sane because we could
133 // be trying to instantiate a new Hotkey with outside dev's
134 // supplied values
135
136 this.combo = combo instanceof Array ? combo : [combo];
137 this.description = description;
138 this.callback = callback;
139 this.action = action;
140 this.allowIn = allowIn;
141 this.persistent = persistent;
142 this._formated = null;
143 }
144
145 /**
146 * Helper method to format (symbolize) the key combo for display
147 *
148 * @return {[Array]} An array of the key combination sequence
149 * for example: "command+g c i" becomes ["⌘ + g", "c", "i"]
150 *
151 */
152 Hotkey.prototype.format = function() {
153 if(this._formated === null) {
154 // Don't show all the possible key combos, just the first one. Not sure
155 // of usecase here, so open a ticket if my assumptions are wrong
156 var combo = this.combo[0];
157
158 var sequence = combo.split(/[\s]/);
159 for (var i = 0; i < sequence.length; i++) {
160 sequence[i] = symbolize(sequence[i]);
161 }
162 this._formated = sequence;
163 }
164
165 return this._formated;
166 };
167
168 /**
169 * A new scope used internally for the cheatsheet
170 * @type {$rootScope.Scope}
171 */
172 var scope = $rootScope.$new();
173
174 /**
175 * Holds an array of Hotkey objects currently bound
176 * @type {Array}
177 */
178 scope.hotkeys = [];
179
180 /**
181 * Contains the state of the help's visibility
182 * @type {Boolean}
183 */
184 scope.helpVisible = false;
185
186 /**
187 * Holds the title string for the help menu
188 * @type {String}
189 */
190 scope.title = this.templateTitle;
191
192 /**
193 * Holds the header HTML for the help menu
194 * @type {String}
195 */
196 scope.header = this.templateHeader;
197
198 /**
199 * Holds the footer HTML for the help menu
200 * @type {String}
201 */
202 scope.footer = this.templateFooter;
203
204 /**
205 * Expose toggleCheatSheet to hotkeys scope so we can call it using
206 * ng-click from the template
207 * @type {function}
208 */
209 scope.toggleCheatSheet = toggleCheatSheet;
210
211
212 /**
213 * Holds references to the different scopes that have bound hotkeys
214 * attached. This is useful to catch when the scopes are `$destroy`d and
215 * then automatically unbind the hotkey.
216 *
217 * @type {Array}
218 */
219 var boundScopes = [];
220
221 if (this.useNgRoute) {
222 $rootScope.$on('$routeChangeSuccess', function (event, route) {
223 purgeHotkeys();
224
225 if (route && route.hotkeys) {
226 angular.forEach(route.hotkeys, function (hotkey) {
227 // a string was given, which implies this is a function that is to be
228 // $eval()'d within that controller's scope
229 // TODO: hotkey here is super confusing. sometimes a function (that gets turned into an array), sometimes a string
230 var callback = hotkey[2];
231 if (typeof(callback) === 'string' || callback instanceof String) {
232 hotkey[2] = [callback, route];
233 }
234
235 // todo: perform check to make sure not already defined:
236 // this came from a route, so it's likely not meant to be persistent
237 hotkey[5] = false;
238 _add.apply(this, hotkey);
239 });
240 }
241 });
242 }
243
244
245
246 // Auto-create a help menu:
247 if (this.includeCheatSheet) {
248 var document = $document[0];
249 var element = $rootElement[0];
250 var helpMenu = angular.element(this.template);
251 _add(this.cheatSheetHotkey, this.cheatSheetDescription, toggleCheatSheet);
252
253 // If $rootElement is document or documentElement, then body must be used
254 if (element === document || element === document.documentElement) {
255 element = document.body;
256 }
257
258 angular.element(element).append($compile(helpMenu)(scope));
259 }
260
261
262 /**
263 * Purges all non-persistent hotkeys (such as those defined in routes)
264 *
265 * Without this, the same hotkey would get recreated everytime
266 * the route is accessed.
267 */
268 function purgeHotkeys() {
269 var i = scope.hotkeys.length;
270 while (i--) {
271 var hotkey = scope.hotkeys[i];
272 if (hotkey && !hotkey.persistent) {
273 _del(hotkey);
274 }
275 }
276 }
277
278 /**
279 * Toggles the help menu element's visiblity
280 */
281 var previousEsc = false;
282
283 function toggleCheatSheet() {
284 scope.helpVisible = !scope.helpVisible;
285
286 // Bind to esc to remove the cheat sheet. Ideally, this would be done
287 // as a directive in the template, but that would create a nasty
288 // circular dependency issue that I don't feel like sorting out.
289 if (scope.helpVisible) {
290 previousEsc = _get('esc');
291 _del('esc');
292
293 // Here's an odd way to do this: we're going to use the original
294 // description of the hotkey on the cheat sheet so that it shows up.
295 // without it, no entry for esc will ever show up (#22)
296 _add('esc', previousEsc.description, toggleCheatSheet, null, ['INPUT', 'SELECT', 'TEXTAREA']);
297 } else {
298 _del('esc');
299
300 // restore the previously bound ESC key
301 if (previousEsc !== false) {
302 _add(previousEsc);
303 }
304 }
305 }
306
307 /**
308 * Creates a new Hotkey and creates the Mousetrap binding
309 *
310 * @param {string} combo mousetrap key binding
311 * @param {string} description description for the help menu
312 * @param {Function} callback method to call when key is pressed
313 * @param {string} action the type of event to listen for (for mousetrap)
314 * @param {array} allowIn an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')
315 * @param {boolean} persistent if true, the binding is preserved upon route changes
316 */
317 function _add (combo, description, callback, action, allowIn, persistent) {
318
319 // used to save original callback for "allowIn" wrapping:
320 var _callback;
321
322 // these elements are prevented by the default Mousetrap.stopCallback():
323 var preventIn = ['INPUT', 'SELECT', 'TEXTAREA'];
324
325 // Determine if object format was given:
326 var objType = Object.prototype.toString.call(combo);
327
328 if (objType === '[object Object]') {
329 description = combo.description;
330 callback = combo.callback;
331 action = combo.action;
332 persistent = combo.persistent;
333 allowIn = combo.allowIn;
334 combo = combo.combo;
335 }
336
337 // description is optional:
338 if (description instanceof Function) {
339 action = callback;
340 callback = description;
341 description = '$$undefined$$';
342 } else if (angular.isUndefined(description)) {
343 description = '$$undefined$$';
344 }
345
346 // any items added through the public API are for controllers
347 // that persist through navigation, and thus undefined should mean
348 // true in this case.
349 if (persistent === undefined) {
350 persistent = true;
351 }
352 // if callback is defined, then wrap it in a function
353 // that checks if the event originated from a form element.
354 // the function blocks the callback from executing unless the element is specified
355 // in allowIn (emulates Mousetrap.stopCallback() on a per-key level)
356 if (typeof callback === 'function') {
357
358 // save the original callback
359 _callback = callback;
360
361 // make sure allowIn is an array
362 if (!(allowIn instanceof Array)) {
363 allowIn = [];
364 }
365
366 // remove anything from preventIn that's present in allowIn
367 var index;
368 for (var i=0; i < allowIn.length; i++) {
369 allowIn[i] = allowIn[i].toUpperCase();
370 index = preventIn.indexOf(allowIn[i]);
371 if (index !== -1) {
372 preventIn.splice(index, 1);
373 }
374 }
375
376 // create the new wrapper callback
377 callback = function(event) {
378 var shouldExecute = true;
379 var target = event.target || event.srcElement; // srcElement is IE only
380 var nodeName = target.nodeName.toUpperCase();
381
382 // check if the input has a mousetrap class, and skip checking preventIn if so
383 if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {
384 shouldExecute = true;
385 } else {
386 // don't execute callback if the event was fired from inside an element listed in preventIn
387 for (var i=0; i<preventIn.length; i++) {
388 if (preventIn[i] === nodeName) {
389 shouldExecute = false;
390 break;
391 }
392 }
393 }
394
395 if (shouldExecute) {
396 wrapApply(_callback.apply(this, arguments));
397 }
398 };
399 }
400
401 if (typeof(action) === 'string') {
402 Mousetrap.bind(combo, wrapApply(callback), action);
403 } else {
404 Mousetrap.bind(combo, wrapApply(callback));
405 }
406
407 var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);
408 scope.hotkeys.push(hotkey);
409 return hotkey;
410 }
411
412 /**
413 * delete and unbind a Hotkey
414 *
415 * @param {mixed} hotkey Either the bound key or an instance of Hotkey
416 * @return {boolean} true if successful
417 */
418 function _del (hotkey) {
419 var combo = (hotkey instanceof Hotkey) ? hotkey.combo : hotkey;
420
421 Mousetrap.unbind(combo);
422
423 if (angular.isArray(combo)) {
424 var retStatus = true;
425 var i = combo.length;
426 while (i--) {
427 retStatus = _del(combo[i]) && retStatus;
428 }
429 return retStatus;
430 } else {
431 var index = scope.hotkeys.indexOf(_get(combo));
432
433 if (index > -1) {
434 // if the combo has other combos bound, don't unbind the whole thing, just the one combo:
435 if (scope.hotkeys[index].combo.length > 1) {
436 scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);
437 } else {
438 scope.hotkeys.splice(index, 1);
439 }
440 return true;
441 }
442 }
443
444 return false;
445
446 }
447
448 /**
449 * Get a Hotkey object by key binding
450 *
451 * @param {[string]} combo the key the Hotkey is bound to
452 * @return {Hotkey} The Hotkey object
453 */
454 function _get (combo) {
455
456 var hotkey;
457
458 for (var i = 0; i < scope.hotkeys.length; i++) {
459 hotkey = scope.hotkeys[i];
460
461 if (hotkey.combo.indexOf(combo) > -1) {
462 return hotkey;
463 }
464 }
465
466 return false;
467 }
468
469 /**
470 * Binds the hotkey to a particular scope. Useful if the scope is
471 * destroyed, we can automatically destroy the hotkey binding.
472 *
473 * @param {Object} scope The scope to bind to
474 */
475 function bindTo (scope) {
476 // Only initialize once to allow multiple calls for same scope.
477 if (!(scope.$id in boundScopes)) {
478
479 // Add the scope to the list of bound scopes
480 boundScopes[scope.$id] = [];
481
482 scope.$on('$destroy', function () {
483 var i = boundScopes[scope.$id].length;
484 while (i--) {
485 _del(boundScopes[scope.$id].pop());
486 }
487 });
488 }
489 // return an object with an add function so we can keep track of the
490 // hotkeys and their scope that we added via this chaining method
491 return {
492 add: function (args) {
493 var hotkey;
494
495 if (arguments.length > 1) {
496 hotkey = _add.apply(this, arguments);
497 } else {
498 hotkey = _add(args);
499 }
500
501 boundScopes[scope.$id].push(hotkey);
502 return this;
503 }
504 };
505 }
506
507 /**
508 * All callbacks sent to Mousetrap are wrapped using this function
509 * so that we can force a $scope.$apply()
510 *
511 * @param {Function} callback [description]
512 * @return {[type]} [description]
513 */
514 function wrapApply (callback) {
515 // return mousetrap a function to call
516 return function (event, combo) {
517
518 // if this is an array, it means we provided a route object
519 // because the scope wasn't available yet, so rewrap the callback
520 // now that the scope is available:
521 if (callback instanceof Array) {
522 var funcString = callback[0];
523 var route = callback[1];
524 callback = function (event) {
525 route.scope.$eval(funcString);
526 };
527 }
528
529 // this takes place outside angular, so we'll have to call
530 // $apply() to make sure angular's digest happens
531 $rootScope.$apply(function() {
532 // call the original hotkey callback with the keyboard event
533 callback(event, _get(combo));
534 });
535 };
536 }
537
538
539 var publicApi = {
540 add : _add,
541 del : _del,
542 get : _get,
543 bindTo : bindTo,
544 template : this.template,
545 toggleCheatSheet : toggleCheatSheet,
546 includeCheatSheet : this.includeCheatSheet,
547 cheatSheetHotkey : this.cheatSheetHotkey,
548 cheatSheetDescription : this.cheatSheetDescription,
549 useNgRoute : this.useNgRoute,
550 purgeHotkeys : purgeHotkeys,
551 templateTitle : this.templateTitle
552 };
553
554 return publicApi;
555
556 };
557
558
559 })
560
561 .directive('hotkey', function (hotkeys) {
562 return {
563 restrict: 'A',
564 link: function (scope, el, attrs) {
565 var key, allowIn;
566
567 angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {
568 // split and trim the hotkeys string into array
569 allowIn = typeof attrs.hotkeyAllowIn === "string" ? attrs.hotkeyAllowIn.split(/[\s,]+/) : [];
570
571 key = hotkey;
572
573 hotkeys.add({
574 combo: hotkey,
575 description: attrs.hotkeyDescription,
576 callback: func,
577 action: attrs.hotkeyAction,
578 allowIn: allowIn
579 });
580 });
581
582 // remove the hotkey if the directive is destroyed:
583 el.bind('$destroy', function() {
584 hotkeys.del(key);
585 });
586 }
587 };
588 })
589
590 .run(function(hotkeys) {
591 // force hotkeys to run by injecting it. Without this, hotkeys only runs
592 // when a controller or something else asks for it via DI.
593 });
594
595 })();
+0
-2436
faraday/server/www/script/angular-mocks.js less more
0 /**
1 * @license AngularJS v1.4.3
2 * (c) 2010-2015 Google, Inc. http://angularjs.org
3 * License: MIT
4 */
5 (function(window, angular, undefined) {
6
7 'use strict';
8
9 /**
10 * @ngdoc object
11 * @name angular.mock
12 * @description
13 *
14 * Namespace from 'angular-mocks.js' which contains testing related code.
15 */
16 angular.mock = {};
17
18 /**
19 * ! This is a private undocumented service !
20 *
21 * @name $browser
22 *
23 * @description
24 * This service is a mock implementation of {@link ng.$browser}. It provides fake
25 * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr,
26 * cookies, etc...
27 *
28 * The api of this service is the same as that of the real {@link ng.$browser $browser}, except
29 * that there are several helper methods available which can be used in tests.
30 */
31 angular.mock.$BrowserProvider = function() {
32 this.$get = function() {
33 return new angular.mock.$Browser();
34 };
35 };
36
37 angular.mock.$Browser = function() {
38 var self = this;
39
40 this.isMock = true;
41 self.$$url = "http://server/";
42 self.$$lastUrl = self.$$url; // used by url polling fn
43 self.pollFns = [];
44
45 // TODO(vojta): remove this temporary api
46 self.$$completeOutstandingRequest = angular.noop;
47 self.$$incOutstandingRequestCount = angular.noop;
48
49
50 // register url polling fn
51
52 self.onUrlChange = function(listener) {
53 self.pollFns.push(
54 function() {
55 if (self.$$lastUrl !== self.$$url || self.$$state !== self.$$lastState) {
56 self.$$lastUrl = self.$$url;
57 self.$$lastState = self.$$state;
58 listener(self.$$url, self.$$state);
59 }
60 }
61 );
62
63 return listener;
64 };
65
66 self.$$applicationDestroyed = angular.noop;
67 self.$$checkUrlChange = angular.noop;
68
69 self.deferredFns = [];
70 self.deferredNextId = 0;
71
72 self.defer = function(fn, delay) {
73 delay = delay || 0;
74 self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId});
75 self.deferredFns.sort(function(a, b) { return a.time - b.time;});
76 return self.deferredNextId++;
77 };
78
79
80 /**
81 * @name $browser#defer.now
82 *
83 * @description
84 * Current milliseconds mock time.
85 */
86 self.defer.now = 0;
87
88
89 self.defer.cancel = function(deferId) {
90 var fnIndex;
91
92 angular.forEach(self.deferredFns, function(fn, index) {
93 if (fn.id === deferId) fnIndex = index;
94 });
95
96 if (fnIndex !== undefined) {
97 self.deferredFns.splice(fnIndex, 1);
98 return true;
99 }
100
101 return false;
102 };
103
104
105 /**
106 * @name $browser#defer.flush
107 *
108 * @description
109 * Flushes all pending requests and executes the defer callbacks.
110 *
111 * @param {number=} number of milliseconds to flush. See {@link #defer.now}
112 */
113 self.defer.flush = function(delay) {
114 if (angular.isDefined(delay)) {
115 self.defer.now += delay;
116 } else {
117 if (self.deferredFns.length) {
118 self.defer.now = self.deferredFns[self.deferredFns.length - 1].time;
119 } else {
120 throw new Error('No deferred tasks to be flushed');
121 }
122 }
123
124 while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
125 self.deferredFns.shift().fn();
126 }
127 };
128
129 self.$$baseHref = '/';
130 self.baseHref = function() {
131 return this.$$baseHref;
132 };
133 };
134 angular.mock.$Browser.prototype = {
135
136 /**
137 * @name $browser#poll
138 *
139 * @description
140 * run all fns in pollFns
141 */
142 poll: function poll() {
143 angular.forEach(this.pollFns, function(pollFn) {
144 pollFn();
145 });
146 },
147
148 url: function(url, replace, state) {
149 if (angular.isUndefined(state)) {
150 state = null;
151 }
152 if (url) {
153 this.$$url = url;
154 // Native pushState serializes & copies the object; simulate it.
155 this.$$state = angular.copy(state);
156 return this;
157 }
158
159 return this.$$url;
160 },
161
162 state: function() {
163 return this.$$state;
164 },
165
166 notifyWhenNoOutstandingRequests: function(fn) {
167 fn();
168 }
169 };
170
171
172 /**
173 * @ngdoc provider
174 * @name $exceptionHandlerProvider
175 *
176 * @description
177 * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors
178 * passed to the `$exceptionHandler`.
179 */
180
181 /**
182 * @ngdoc service
183 * @name $exceptionHandler
184 *
185 * @description
186 * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed
187 * to it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration
188 * information.
189 *
190 *
191 * ```js
192 * describe('$exceptionHandlerProvider', function() {
193 *
194 * it('should capture log messages and exceptions', function() {
195 *
196 * module(function($exceptionHandlerProvider) {
197 * $exceptionHandlerProvider.mode('log');
198 * });
199 *
200 * inject(function($log, $exceptionHandler, $timeout) {
201 * $timeout(function() { $log.log(1); });
202 * $timeout(function() { $log.log(2); throw 'banana peel'; });
203 * $timeout(function() { $log.log(3); });
204 * expect($exceptionHandler.errors).toEqual([]);
205 * expect($log.assertEmpty());
206 * $timeout.flush();
207 * expect($exceptionHandler.errors).toEqual(['banana peel']);
208 * expect($log.log.logs).toEqual([[1], [2], [3]]);
209 * });
210 * });
211 * });
212 * ```
213 */
214
215 angular.mock.$ExceptionHandlerProvider = function() {
216 var handler;
217
218 /**
219 * @ngdoc method
220 * @name $exceptionHandlerProvider#mode
221 *
222 * @description
223 * Sets the logging mode.
224 *
225 * @param {string} mode Mode of operation, defaults to `rethrow`.
226 *
227 * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log`
228 * mode stores an array of errors in `$exceptionHandler.errors`, to allow later
229 * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and
230 * {@link ngMock.$log#reset reset()}
231 * - `rethrow`: If any errors are passed to the handler in tests, it typically means that there
232 * is a bug in the application or test, so this mock will make these tests fail.
233 * For any implementations that expect exceptions to be thrown, the `rethrow` mode
234 * will also maintain a log of thrown errors.
235 */
236 this.mode = function(mode) {
237
238 switch (mode) {
239 case 'log':
240 case 'rethrow':
241 var errors = [];
242 handler = function(e) {
243 if (arguments.length == 1) {
244 errors.push(e);
245 } else {
246 errors.push([].slice.call(arguments, 0));
247 }
248 if (mode === "rethrow") {
249 throw e;
250 }
251 };
252 handler.errors = errors;
253 break;
254 default:
255 throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!");
256 }
257 };
258
259 this.$get = function() {
260 return handler;
261 };
262
263 this.mode('rethrow');
264 };
265
266
267 /**
268 * @ngdoc service
269 * @name $log
270 *
271 * @description
272 * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays
273 * (one array per logging level). These arrays are exposed as `logs` property of each of the
274 * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`.
275 *
276 */
277 angular.mock.$LogProvider = function() {
278 var debug = true;
279
280 function concat(array1, array2, index) {
281 return array1.concat(Array.prototype.slice.call(array2, index));
282 }
283
284 this.debugEnabled = function(flag) {
285 if (angular.isDefined(flag)) {
286 debug = flag;
287 return this;
288 } else {
289 return debug;
290 }
291 };
292
293 this.$get = function() {
294 var $log = {
295 log: function() { $log.log.logs.push(concat([], arguments, 0)); },
296 warn: function() { $log.warn.logs.push(concat([], arguments, 0)); },
297 info: function() { $log.info.logs.push(concat([], arguments, 0)); },
298 error: function() { $log.error.logs.push(concat([], arguments, 0)); },
299 debug: function() {
300 if (debug) {
301 $log.debug.logs.push(concat([], arguments, 0));
302 }
303 }
304 };
305
306 /**
307 * @ngdoc method
308 * @name $log#reset
309 *
310 * @description
311 * Reset all of the logging arrays to empty.
312 */
313 $log.reset = function() {
314 /**
315 * @ngdoc property
316 * @name $log#log.logs
317 *
318 * @description
319 * Array of messages logged using {@link ng.$log#log `log()`}.
320 *
321 * @example
322 * ```js
323 * $log.log('Some Log');
324 * var first = $log.log.logs.unshift();
325 * ```
326 */
327 $log.log.logs = [];
328 /**
329 * @ngdoc property
330 * @name $log#info.logs
331 *
332 * @description
333 * Array of messages logged using {@link ng.$log#info `info()`}.
334 *
335 * @example
336 * ```js
337 * $log.info('Some Info');
338 * var first = $log.info.logs.unshift();
339 * ```
340 */
341 $log.info.logs = [];
342 /**
343 * @ngdoc property
344 * @name $log#warn.logs
345 *
346 * @description
347 * Array of messages logged using {@link ng.$log#warn `warn()`}.
348 *
349 * @example
350 * ```js
351 * $log.warn('Some Warning');
352 * var first = $log.warn.logs.unshift();
353 * ```
354 */
355 $log.warn.logs = [];
356 /**
357 * @ngdoc property
358 * @name $log#error.logs
359 *
360 * @description
361 * Array of messages logged using {@link ng.$log#error `error()`}.
362 *
363 * @example
364 * ```js
365 * $log.error('Some Error');
366 * var first = $log.error.logs.unshift();
367 * ```
368 */
369 $log.error.logs = [];
370 /**
371 * @ngdoc property
372 * @name $log#debug.logs
373 *
374 * @description
375 * Array of messages logged using {@link ng.$log#debug `debug()`}.
376 *
377 * @example
378 * ```js
379 * $log.debug('Some Error');
380 * var first = $log.debug.logs.unshift();
381 * ```
382 */
383 $log.debug.logs = [];
384 };
385
386 /**
387 * @ngdoc method
388 * @name $log#assertEmpty
389 *
390 * @description
391 * Assert that all of the logging methods have no logged messages. If any messages are present,
392 * an exception is thrown.
393 */
394 $log.assertEmpty = function() {
395 var errors = [];
396 angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) {
397 angular.forEach($log[logLevel].logs, function(log) {
398 angular.forEach(log, function(logItem) {
399 errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' +
400 (logItem.stack || ''));
401 });
402 });
403 });
404 if (errors.length) {
405 errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or " +
406 "an expected log message was not checked and removed:");
407 errors.push('');
408 throw new Error(errors.join('\n---------\n'));
409 }
410 };
411
412 $log.reset();
413 return $log;
414 };
415 };
416
417
418 /**
419 * @ngdoc service
420 * @name $interval
421 *
422 * @description
423 * Mock implementation of the $interval service.
424 *
425 * Use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
426 * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
427 * time.
428 *
429 * @param {function()} fn A function that should be called repeatedly.
430 * @param {number} delay Number of milliseconds between each function call.
431 * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
432 * indefinitely.
433 * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
434 * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
435 * @param {...*=} Pass additional parameters to the executed function.
436 * @returns {promise} A promise which will be notified on each iteration.
437 */
438 angular.mock.$IntervalProvider = function() {
439 this.$get = ['$browser', '$rootScope', '$q', '$$q',
440 function($browser, $rootScope, $q, $$q) {
441 var repeatFns = [],
442 nextRepeatId = 0,
443 now = 0;
444
445 var $interval = function(fn, delay, count, invokeApply) {
446 var hasParams = arguments.length > 4,
447 args = hasParams ? Array.prototype.slice.call(arguments, 4) : [],
448 iteration = 0,
449 skipApply = (angular.isDefined(invokeApply) && !invokeApply),
450 deferred = (skipApply ? $$q : $q).defer(),
451 promise = deferred.promise;
452
453 count = (angular.isDefined(count)) ? count : 0;
454 promise.then(null, null, (!hasParams) ? fn : function() {
455 fn.apply(null, args);
456 });
457
458 promise.$$intervalId = nextRepeatId;
459
460 function tick() {
461 deferred.notify(iteration++);
462
463 if (count > 0 && iteration >= count) {
464 var fnIndex;
465 deferred.resolve(iteration);
466
467 angular.forEach(repeatFns, function(fn, index) {
468 if (fn.id === promise.$$intervalId) fnIndex = index;
469 });
470
471 if (fnIndex !== undefined) {
472 repeatFns.splice(fnIndex, 1);
473 }
474 }
475
476 if (skipApply) {
477 $browser.defer.flush();
478 } else {
479 $rootScope.$apply();
480 }
481 }
482
483 repeatFns.push({
484 nextTime:(now + delay),
485 delay: delay,
486 fn: tick,
487 id: nextRepeatId,
488 deferred: deferred
489 });
490 repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
491
492 nextRepeatId++;
493 return promise;
494 };
495 /**
496 * @ngdoc method
497 * @name $interval#cancel
498 *
499 * @description
500 * Cancels a task associated with the `promise`.
501 *
502 * @param {promise} promise A promise from calling the `$interval` function.
503 * @returns {boolean} Returns `true` if the task was successfully cancelled.
504 */
505 $interval.cancel = function(promise) {
506 if (!promise) return false;
507 var fnIndex;
508
509 angular.forEach(repeatFns, function(fn, index) {
510 if (fn.id === promise.$$intervalId) fnIndex = index;
511 });
512
513 if (fnIndex !== undefined) {
514 repeatFns[fnIndex].deferred.reject('canceled');
515 repeatFns.splice(fnIndex, 1);
516 return true;
517 }
518
519 return false;
520 };
521
522 /**
523 * @ngdoc method
524 * @name $interval#flush
525 * @description
526 *
527 * Runs interval tasks scheduled to be run in the next `millis` milliseconds.
528 *
529 * @param {number=} millis maximum timeout amount to flush up until.
530 *
531 * @return {number} The amount of time moved forward.
532 */
533 $interval.flush = function(millis) {
534 now += millis;
535 while (repeatFns.length && repeatFns[0].nextTime <= now) {
536 var task = repeatFns[0];
537 task.fn();
538 task.nextTime += task.delay;
539 repeatFns.sort(function(a, b) { return a.nextTime - b.nextTime;});
540 }
541 return millis;
542 };
543
544 return $interval;
545 }];
546 };
547
548
549 /* jshint -W101 */
550 /* The R_ISO8061_STR regex is never going to fit into the 100 char limit!
551 * This directive should go inside the anonymous function but a bug in JSHint means that it would
552 * not be enacted early enough to prevent the warning.
553 */
554 var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/;
555
556 function jsonStringToDate(string) {
557 var match;
558 if (match = string.match(R_ISO8061_STR)) {
559 var date = new Date(0),
560 tzHour = 0,
561 tzMin = 0;
562 if (match[9]) {
563 tzHour = toInt(match[9] + match[10]);
564 tzMin = toInt(match[9] + match[11]);
565 }
566 date.setUTCFullYear(toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
567 date.setUTCHours(toInt(match[4] || 0) - tzHour,
568 toInt(match[5] || 0) - tzMin,
569 toInt(match[6] || 0),
570 toInt(match[7] || 0));
571 return date;
572 }
573 return string;
574 }
575
576 function toInt(str) {
577 return parseInt(str, 10);
578 }
579
580 function padNumber(num, digits, trim) {
581 var neg = '';
582 if (num < 0) {
583 neg = '-';
584 num = -num;
585 }
586 num = '' + num;
587 while (num.length < digits) num = '0' + num;
588 if (trim) {
589 num = num.substr(num.length - digits);
590 }
591 return neg + num;
592 }
593
594
595 /**
596 * @ngdoc type
597 * @name angular.mock.TzDate
598 * @description
599 *
600 * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`.
601 *
602 * Mock of the Date type which has its timezone specified via constructor arg.
603 *
604 * The main purpose is to create Date-like instances with timezone fixed to the specified timezone
605 * offset, so that we can test code that depends on local timezone settings without dependency on
606 * the time zone settings of the machine where the code is running.
607 *
608 * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored)
609 * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC*
610 *
611 * @example
612 * !!!! WARNING !!!!!
613 * This is not a complete Date object so only methods that were implemented can be called safely.
614 * To make matters worse, TzDate instances inherit stuff from Date via a prototype.
615 *
616 * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is
617 * incomplete we might be missing some non-standard methods. This can result in errors like:
618 * "Date.prototype.foo called on incompatible Object".
619 *
620 * ```js
621 * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
622 * newYearInBratislava.getTimezoneOffset() => -60;
623 * newYearInBratislava.getFullYear() => 2010;
624 * newYearInBratislava.getMonth() => 0;
625 * newYearInBratislava.getDate() => 1;
626 * newYearInBratislava.getHours() => 0;
627 * newYearInBratislava.getMinutes() => 0;
628 * newYearInBratislava.getSeconds() => 0;
629 * ```
630 *
631 */
632 angular.mock.TzDate = function(offset, timestamp) {
633 var self = new Date(0);
634 if (angular.isString(timestamp)) {
635 var tsStr = timestamp;
636
637 self.origDate = jsonStringToDate(timestamp);
638
639 timestamp = self.origDate.getTime();
640 if (isNaN(timestamp)) {
641 throw {
642 name: "Illegal Argument",
643 message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
644 };
645 }
646 } else {
647 self.origDate = new Date(timestamp);
648 }
649
650 var localOffset = new Date(timestamp).getTimezoneOffset();
651 self.offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60;
652 self.date = new Date(timestamp + self.offsetDiff);
653
654 self.getTime = function() {
655 return self.date.getTime() - self.offsetDiff;
656 };
657
658 self.toLocaleDateString = function() {
659 return self.date.toLocaleDateString();
660 };
661
662 self.getFullYear = function() {
663 return self.date.getFullYear();
664 };
665
666 self.getMonth = function() {
667 return self.date.getMonth();
668 };
669
670 self.getDate = function() {
671 return self.date.getDate();
672 };
673
674 self.getHours = function() {
675 return self.date.getHours();
676 };
677
678 self.getMinutes = function() {
679 return self.date.getMinutes();
680 };
681
682 self.getSeconds = function() {
683 return self.date.getSeconds();
684 };
685
686 self.getMilliseconds = function() {
687 return self.date.getMilliseconds();
688 };
689
690 self.getTimezoneOffset = function() {
691 return offset * 60;
692 };
693
694 self.getUTCFullYear = function() {
695 return self.origDate.getUTCFullYear();
696 };
697
698 self.getUTCMonth = function() {
699 return self.origDate.getUTCMonth();
700 };
701
702 self.getUTCDate = function() {
703 return self.origDate.getUTCDate();
704 };
705
706 self.getUTCHours = function() {
707 return self.origDate.getUTCHours();
708 };
709
710 self.getUTCMinutes = function() {
711 return self.origDate.getUTCMinutes();
712 };
713
714 self.getUTCSeconds = function() {
715 return self.origDate.getUTCSeconds();
716 };
717
718 self.getUTCMilliseconds = function() {
719 return self.origDate.getUTCMilliseconds();
720 };
721
722 self.getDay = function() {
723 return self.date.getDay();
724 };
725
726 // provide this method only on browsers that already have it
727 if (self.toISOString) {
728 self.toISOString = function() {
729 return padNumber(self.origDate.getUTCFullYear(), 4) + '-' +
730 padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' +
731 padNumber(self.origDate.getUTCDate(), 2) + 'T' +
732 padNumber(self.origDate.getUTCHours(), 2) + ':' +
733 padNumber(self.origDate.getUTCMinutes(), 2) + ':' +
734 padNumber(self.origDate.getUTCSeconds(), 2) + '.' +
735 padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z';
736 };
737 }
738
739 //hide all methods not implemented in this mock that the Date prototype exposes
740 var unimplementedMethods = ['getUTCDay',
741 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
742 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
743 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
744 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString',
745 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
746
747 angular.forEach(unimplementedMethods, function(methodName) {
748 self[methodName] = function() {
749 throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock");
750 };
751 });
752
753 return self;
754 };
755
756 //make "tzDateInstance instanceof Date" return true
757 angular.mock.TzDate.prototype = Date.prototype;
758 /* jshint +W101 */
759
760 angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
761
762 .config(['$provide', function($provide) {
763
764 var reflowQueue = [];
765 $provide.value('$$animateReflow', function(fn) {
766 var index = reflowQueue.length;
767 reflowQueue.push(fn);
768 return function cancel() {
769 reflowQueue.splice(index, 1);
770 };
771 });
772
773 $provide.decorator('$animate', ['$delegate', '$timeout', '$browser', '$$rAF',
774 function($delegate, $timeout, $browser, $$rAF) {
775 var animate = {
776 queue: [],
777 cancel: $delegate.cancel,
778 enabled: $delegate.enabled,
779 triggerCallbackEvents: function() {
780 $$rAF.flush();
781 },
782 triggerCallbackPromise: function() {
783 $timeout.flush(0);
784 },
785 triggerCallbacks: function() {
786 this.triggerCallbackEvents();
787 this.triggerCallbackPromise();
788 },
789 triggerReflow: function() {
790 angular.forEach(reflowQueue, function(fn) {
791 fn();
792 });
793 reflowQueue = [];
794 }
795 };
796
797 angular.forEach(
798 ['animate','enter','leave','move','addClass','removeClass','setClass'], function(method) {
799 animate[method] = function() {
800 animate.queue.push({
801 event: method,
802 element: arguments[0],
803 options: arguments[arguments.length - 1],
804 args: arguments
805 });
806 return $delegate[method].apply($delegate, arguments);
807 };
808 });
809
810 return animate;
811 }]);
812
813 }]);
814
815
816 /**
817 * @ngdoc function
818 * @name angular.mock.dump
819 * @description
820 *
821 * *NOTE*: this is not an injectable instance, just a globally available function.
822 *
823 * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
824 * debugging.
825 *
826 * This method is also available on window, where it can be used to display objects on debug
827 * console.
828 *
829 * @param {*} object - any object to turn into string.
830 * @return {string} a serialized string of the argument
831 */
832 angular.mock.dump = function(object) {
833 return serialize(object);
834
835 function serialize(object) {
836 var out;
837
838 if (angular.isElement(object)) {
839 object = angular.element(object);
840 out = angular.element('<div></div>');
841 angular.forEach(object, function(element) {
842 out.append(angular.element(element).clone());
843 });
844 out = out.html();
845 } else if (angular.isArray(object)) {
846 out = [];
847 angular.forEach(object, function(o) {
848 out.push(serialize(o));
849 });
850 out = '[ ' + out.join(', ') + ' ]';
851 } else if (angular.isObject(object)) {
852 if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) {
853 out = serializeScope(object);
854 } else if (object instanceof Error) {
855 out = object.stack || ('' + object.name + ': ' + object.message);
856 } else {
857 // TODO(i): this prevents methods being logged,
858 // we should have a better way to serialize objects
859 out = angular.toJson(object, true);
860 }
861 } else {
862 out = String(object);
863 }
864
865 return out;
866 }
867
868 function serializeScope(scope, offset) {
869 offset = offset || ' ';
870 var log = [offset + 'Scope(' + scope.$id + '): {'];
871 for (var key in scope) {
872 if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) {
873 log.push(' ' + key + ': ' + angular.toJson(scope[key]));
874 }
875 }
876 var child = scope.$$childHead;
877 while (child) {
878 log.push(serializeScope(child, offset + ' '));
879 child = child.$$nextSibling;
880 }
881 log.push('}');
882 return log.join('\n' + offset);
883 }
884 };
885
886 /**
887 * @ngdoc service
888 * @name $httpBackend
889 * @description
890 * Fake HTTP backend implementation suitable for unit testing applications that use the
891 * {@link ng.$http $http service}.
892 *
893 * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less
894 * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}.
895 *
896 * During unit testing, we want our unit tests to run quickly and have no external dependencies so
897 * we don’t want to send [XHR](https://developer.mozilla.org/en/xmlhttprequest) or
898 * [JSONP](http://en.wikipedia.org/wiki/JSONP) requests to a real server. All we really need is
899 * to verify whether a certain request has been sent or not, or alternatively just let the
900 * application make requests, respond with pre-trained responses and assert that the end result is
901 * what we expect it to be.
902 *
903 * This mock implementation can be used to respond with static or dynamic responses via the
904 * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc).
905 *
906 * When an Angular application needs some data from a server, it calls the $http service, which
907 * sends the request to a real server using $httpBackend service. With dependency injection, it is
908 * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify
909 * the requests and respond with some testing data without sending a request to a real server.
910 *
911 * There are two ways to specify what test data should be returned as http responses by the mock
912 * backend when the code under test makes http requests:
913 *
914 * - `$httpBackend.expect` - specifies a request expectation
915 * - `$httpBackend.when` - specifies a backend definition
916 *
917 *
918 * # Request Expectations vs Backend Definitions
919 *
920 * Request expectations provide a way to make assertions about requests made by the application and
921 * to define responses for those requests. The test will fail if the expected requests are not made
922 * or they are made in the wrong order.
923 *
924 * Backend definitions allow you to define a fake backend for your application which doesn't assert
925 * if a particular request was made or not, it just returns a trained response if a request is made.
926 * The test will pass whether or not the request gets made during testing.
927 *
928 *
929 * <table class="table">
930 * <tr><th width="220px"></th><th>Request expectations</th><th>Backend definitions</th></tr>
931 * <tr>
932 * <th>Syntax</th>
933 * <td>.expect(...).respond(...)</td>
934 * <td>.when(...).respond(...)</td>
935 * </tr>
936 * <tr>
937 * <th>Typical usage</th>
938 * <td>strict unit tests</td>
939 * <td>loose (black-box) unit testing</td>
940 * </tr>
941 * <tr>
942 * <th>Fulfills multiple requests</th>
943 * <td>NO</td>
944 * <td>YES</td>
945 * </tr>
946 * <tr>
947 * <th>Order of requests matters</th>
948 * <td>YES</td>
949 * <td>NO</td>
950 * </tr>
951 * <tr>
952 * <th>Request required</th>
953 * <td>YES</td>
954 * <td>NO</td>
955 * </tr>
956 * <tr>
957 * <th>Response required</th>
958 * <td>optional (see below)</td>
959 * <td>YES</td>
960 * </tr>
961 * </table>
962 *
963 * In cases where both backend definitions and request expectations are specified during unit
964 * testing, the request expectations are evaluated first.
965 *
966 * If a request expectation has no response specified, the algorithm will search your backend
967 * definitions for an appropriate response.
968 *
969 * If a request didn't match any expectation or if the expectation doesn't have the response
970 * defined, the backend definitions are evaluated in sequential order to see if any of them match
971 * the request. The response from the first matched definition is returned.
972 *
973 *
974 * # Flushing HTTP requests
975 *
976 * The $httpBackend used in production always responds to requests asynchronously. If we preserved
977 * this behavior in unit testing, we'd have to create async unit tests, which are hard to write,
978 * to follow and to maintain. But neither can the testing mock respond synchronously; that would
979 * change the execution of the code under test. For this reason, the mock $httpBackend has a
980 * `flush()` method, which allows the test to explicitly flush pending requests. This preserves
981 * the async api of the backend, while allowing the test to execute synchronously.
982 *
983 *
984 * # Unit testing with mock $httpBackend
985 * The following code shows how to setup and use the mock backend when unit testing a controller.
986 * First we create the controller under test:
987 *
988 ```js
989 // The module code
990 angular
991 .module('MyApp', [])
992 .controller('MyController', MyController);
993
994 // The controller code
995 function MyController($scope, $http) {
996 var authToken;
997
998 $http.get('/auth.py').success(function(data, status, headers) {
999 authToken = headers('A-Token');
1000 $scope.user = data;
1001 });
1002
1003 $scope.saveMessage = function(message) {
1004 var headers = { 'Authorization': authToken };
1005 $scope.status = 'Saving...';
1006
1007 $http.post('/add-msg.py', message, { headers: headers } ).success(function(response) {
1008 $scope.status = '';
1009 }).error(function() {
1010 $scope.status = 'ERROR!';
1011 });
1012 };
1013 }
1014 ```
1015 *
1016 * Now we setup the mock backend and create the test specs:
1017 *
1018 ```js
1019 // testing controller
1020 describe('MyController', function() {
1021 var $httpBackend, $rootScope, createController, authRequestHandler;
1022
1023 // Set up the module
1024 beforeEach(module('MyApp'));
1025
1026 beforeEach(inject(function($injector) {
1027 // Set up the mock http service responses
1028 $httpBackend = $injector.get('$httpBackend');
1029 // backend definition common for all tests
1030 authRequestHandler = $httpBackend.when('GET', '/auth.py')
1031 .respond({userId: 'userX'}, {'A-Token': 'xxx'});
1032
1033 // Get hold of a scope (i.e. the root scope)
1034 $rootScope = $injector.get('$rootScope');
1035 // The $controller service is used to create instances of controllers
1036 var $controller = $injector.get('$controller');
1037
1038 createController = function() {
1039 return $controller('MyController', {'$scope' : $rootScope });
1040 };
1041 }));
1042
1043
1044 afterEach(function() {
1045 $httpBackend.verifyNoOutstandingExpectation();
1046 $httpBackend.verifyNoOutstandingRequest();
1047 });
1048
1049
1050 it('should fetch authentication token', function() {
1051 $httpBackend.expectGET('/auth.py');
1052 var controller = createController();
1053 $httpBackend.flush();
1054 });
1055
1056
1057 it('should fail authentication', function() {
1058
1059 // Notice how you can change the response even after it was set
1060 authRequestHandler.respond(401, '');
1061
1062 $httpBackend.expectGET('/auth.py');
1063 var controller = createController();
1064 $httpBackend.flush();
1065 expect($rootScope.status).toBe('Failed...');
1066 });
1067
1068
1069 it('should send msg to server', function() {
1070 var controller = createController();
1071 $httpBackend.flush();
1072
1073 // now you don’t care about the authentication, but
1074 // the controller will still send the request and
1075 // $httpBackend will respond without you having to
1076 // specify the expectation and response for this request
1077
1078 $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
1079 $rootScope.saveMessage('message content');
1080 expect($rootScope.status).toBe('Saving...');
1081 $httpBackend.flush();
1082 expect($rootScope.status).toBe('');
1083 });
1084
1085
1086 it('should send auth header', function() {
1087 var controller = createController();
1088 $httpBackend.flush();
1089
1090 $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
1091 // check if the header was sent, if it wasn't the expectation won't
1092 // match the request and the test will fail
1093 return headers['Authorization'] == 'xxx';
1094 }).respond(201, '');
1095
1096 $rootScope.saveMessage('whatever');
1097 $httpBackend.flush();
1098 });
1099 });
1100 ```
1101 */
1102 angular.mock.$HttpBackendProvider = function() {
1103 this.$get = ['$rootScope', '$timeout', createHttpBackendMock];
1104 };
1105
1106 /**
1107 * General factory function for $httpBackend mock.
1108 * Returns instance for unit testing (when no arguments specified):
1109 * - passing through is disabled
1110 * - auto flushing is disabled
1111 *
1112 * Returns instance for e2e testing (when `$delegate` and `$browser` specified):
1113 * - passing through (delegating request to real backend) is enabled
1114 * - auto flushing is enabled
1115 *
1116 * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified)
1117 * @param {Object=} $browser Auto-flushing enabled if specified
1118 * @return {Object} Instance of $httpBackend mock
1119 */
1120 function createHttpBackendMock($rootScope, $timeout, $delegate, $browser) {
1121 var definitions = [],
1122 expectations = [],
1123 responses = [],
1124 responsesPush = angular.bind(responses, responses.push),
1125 copy = angular.copy;
1126
1127 function createResponse(status, data, headers, statusText) {
1128 if (angular.isFunction(status)) return status;
1129
1130 return function() {
1131 return angular.isNumber(status)
1132 ? [status, data, headers, statusText]
1133 : [200, status, data, headers];
1134 };
1135 }
1136
1137 // TODO(vojta): change params to: method, url, data, headers, callback
1138 function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) {
1139 var xhr = new MockXhr(),
1140 expectation = expectations[0],
1141 wasExpected = false;
1142
1143 function prettyPrint(data) {
1144 return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp)
1145 ? data
1146 : angular.toJson(data);
1147 }
1148
1149 function wrapResponse(wrapped) {
1150 if (!$browser && timeout) {
1151 timeout.then ? timeout.then(handleTimeout) : $timeout(handleTimeout, timeout);
1152 }
1153
1154 return handleResponse;
1155
1156 function handleResponse() {
1157 var response = wrapped.response(method, url, data, headers);
1158 xhr.$$respHeaders = response[2];
1159 callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders(),
1160 copy(response[3] || ''));
1161 }
1162
1163 function handleTimeout() {
1164 for (var i = 0, ii = responses.length; i < ii; i++) {
1165 if (responses[i] === handleResponse) {
1166 responses.splice(i, 1);
1167 callback(-1, undefined, '');
1168 break;
1169 }
1170 }
1171 }
1172 }
1173
1174 if (expectation && expectation.match(method, url)) {
1175 if (!expectation.matchData(data)) {
1176 throw new Error('Expected ' + expectation + ' with different data\n' +
1177 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data);
1178 }
1179
1180 if (!expectation.matchHeaders(headers)) {
1181 throw new Error('Expected ' + expectation + ' with different headers\n' +
1182 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' +
1183 prettyPrint(headers));
1184 }
1185
1186 expectations.shift();
1187
1188 if (expectation.response) {
1189 responses.push(wrapResponse(expectation));
1190 return;
1191 }
1192 wasExpected = true;
1193 }
1194
1195 var i = -1, definition;
1196 while ((definition = definitions[++i])) {
1197 if (definition.match(method, url, data, headers || {})) {
1198 if (definition.response) {
1199 // if $browser specified, we do auto flush all requests
1200 ($browser ? $browser.defer : responsesPush)(wrapResponse(definition));
1201 } else if (definition.passThrough) {
1202 $delegate(method, url, data, callback, headers, timeout, withCredentials);
1203 } else throw new Error('No response defined !');
1204 return;
1205 }
1206 }
1207 throw wasExpected ?
1208 new Error('No response defined !') :
1209 new Error('Unexpected request: ' + method + ' ' + url + '\n' +
1210 (expectation ? 'Expected ' + expectation : 'No more request expected'));
1211 }
1212
1213 /**
1214 * @ngdoc method
1215 * @name $httpBackend#when
1216 * @description
1217 * Creates a new backend definition.
1218 *
1219 * @param {string} method HTTP method.
1220 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1221 * and returns true if the url matches the current definition.
1222 * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1223 * data string and returns true if the data is as expected.
1224 * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1225 * object and returns true if the headers match the current definition.
1226 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1227 * request is handled. You can save this object for later use and invoke `respond` again in
1228 * order to change how a matched request is handled.
1229 *
1230 * - respond –
1231 * `{function([status,] data[, headers, statusText])
1232 * | function(function(method, url, data, headers)}`
1233 * – The respond method takes a set of static data to be returned or a function that can
1234 * return an array containing response status (number), response data (string), response
1235 * headers (Object), and the text for the status (string). The respond method returns the
1236 * `requestHandler` object for possible overrides.
1237 */
1238 $httpBackend.when = function(method, url, data, headers) {
1239 var definition = new MockHttpExpectation(method, url, data, headers),
1240 chain = {
1241 respond: function(status, data, headers, statusText) {
1242 definition.passThrough = undefined;
1243 definition.response = createResponse(status, data, headers, statusText);
1244 return chain;
1245 }
1246 };
1247
1248 if ($browser) {
1249 chain.passThrough = function() {
1250 definition.response = undefined;
1251 definition.passThrough = true;
1252 return chain;
1253 };
1254 }
1255
1256 definitions.push(definition);
1257 return chain;
1258 };
1259
1260 /**
1261 * @ngdoc method
1262 * @name $httpBackend#whenGET
1263 * @description
1264 * Creates a new backend definition for GET requests. For more info see `when()`.
1265 *
1266 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1267 * and returns true if the url matches the current definition.
1268 * @param {(Object|function(Object))=} headers HTTP headers.
1269 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1270 * request is handled. You can save this object for later use and invoke `respond` again in
1271 * order to change how a matched request is handled.
1272 */
1273
1274 /**
1275 * @ngdoc method
1276 * @name $httpBackend#whenHEAD
1277 * @description
1278 * Creates a new backend definition for HEAD requests. For more info see `when()`.
1279 *
1280 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1281 * and returns true if the url matches the current definition.
1282 * @param {(Object|function(Object))=} headers HTTP headers.
1283 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1284 * request is handled. You can save this object for later use and invoke `respond` again in
1285 * order to change how a matched request is handled.
1286 */
1287
1288 /**
1289 * @ngdoc method
1290 * @name $httpBackend#whenDELETE
1291 * @description
1292 * Creates a new backend definition for DELETE requests. For more info see `when()`.
1293 *
1294 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1295 * and returns true if the url matches the current definition.
1296 * @param {(Object|function(Object))=} headers HTTP headers.
1297 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1298 * request is handled. You can save this object for later use and invoke `respond` again in
1299 * order to change how a matched request is handled.
1300 */
1301
1302 /**
1303 * @ngdoc method
1304 * @name $httpBackend#whenPOST
1305 * @description
1306 * Creates a new backend definition for POST requests. For more info see `when()`.
1307 *
1308 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1309 * and returns true if the url matches the current definition.
1310 * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1311 * data string and returns true if the data is as expected.
1312 * @param {(Object|function(Object))=} headers HTTP headers.
1313 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1314 * request is handled. You can save this object for later use and invoke `respond` again in
1315 * order to change how a matched request is handled.
1316 */
1317
1318 /**
1319 * @ngdoc method
1320 * @name $httpBackend#whenPUT
1321 * @description
1322 * Creates a new backend definition for PUT requests. For more info see `when()`.
1323 *
1324 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1325 * and returns true if the url matches the current definition.
1326 * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives
1327 * data string and returns true if the data is as expected.
1328 * @param {(Object|function(Object))=} headers HTTP headers.
1329 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1330 * request is handled. You can save this object for later use and invoke `respond` again in
1331 * order to change how a matched request is handled.
1332 */
1333
1334 /**
1335 * @ngdoc method
1336 * @name $httpBackend#whenJSONP
1337 * @description
1338 * Creates a new backend definition for JSONP requests. For more info see `when()`.
1339 *
1340 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1341 * and returns true if the url matches the current definition.
1342 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1343 * request is handled. You can save this object for later use and invoke `respond` again in
1344 * order to change how a matched request is handled.
1345 */
1346 createShortMethods('when');
1347
1348
1349 /**
1350 * @ngdoc method
1351 * @name $httpBackend#expect
1352 * @description
1353 * Creates a new request expectation.
1354 *
1355 * @param {string} method HTTP method.
1356 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1357 * and returns true if the url matches the current definition.
1358 * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1359 * receives data string and returns true if the data is as expected, or Object if request body
1360 * is in JSON format.
1361 * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1362 * object and returns true if the headers match the current expectation.
1363 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1364 * request is handled. You can save this object for later use and invoke `respond` again in
1365 * order to change how a matched request is handled.
1366 *
1367 * - respond –
1368 * `{function([status,] data[, headers, statusText])
1369 * | function(function(method, url, data, headers)}`
1370 * – The respond method takes a set of static data to be returned or a function that can
1371 * return an array containing response status (number), response data (string), response
1372 * headers (Object), and the text for the status (string). The respond method returns the
1373 * `requestHandler` object for possible overrides.
1374 */
1375 $httpBackend.expect = function(method, url, data, headers) {
1376 var expectation = new MockHttpExpectation(method, url, data, headers),
1377 chain = {
1378 respond: function(status, data, headers, statusText) {
1379 expectation.response = createResponse(status, data, headers, statusText);
1380 return chain;
1381 }
1382 };
1383
1384 expectations.push(expectation);
1385 return chain;
1386 };
1387
1388
1389 /**
1390 * @ngdoc method
1391 * @name $httpBackend#expectGET
1392 * @description
1393 * Creates a new request expectation for GET requests. For more info see `expect()`.
1394 *
1395 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1396 * and returns true if the url matches the current definition.
1397 * @param {Object=} headers HTTP headers.
1398 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1399 * request is handled. You can save this object for later use and invoke `respond` again in
1400 * order to change how a matched request is handled. See #expect for more info.
1401 */
1402
1403 /**
1404 * @ngdoc method
1405 * @name $httpBackend#expectHEAD
1406 * @description
1407 * Creates a new request expectation for HEAD requests. For more info see `expect()`.
1408 *
1409 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1410 * and returns true if the url matches the current definition.
1411 * @param {Object=} headers HTTP headers.
1412 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1413 * request is handled. You can save this object for later use and invoke `respond` again in
1414 * order to change how a matched request is handled.
1415 */
1416
1417 /**
1418 * @ngdoc method
1419 * @name $httpBackend#expectDELETE
1420 * @description
1421 * Creates a new request expectation for DELETE requests. For more info see `expect()`.
1422 *
1423 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1424 * and returns true if the url matches the current definition.
1425 * @param {Object=} headers HTTP headers.
1426 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1427 * request is handled. You can save this object for later use and invoke `respond` again in
1428 * order to change how a matched request is handled.
1429 */
1430
1431 /**
1432 * @ngdoc method
1433 * @name $httpBackend#expectPOST
1434 * @description
1435 * Creates a new request expectation for POST requests. For more info see `expect()`.
1436 *
1437 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1438 * and returns true if the url matches the current definition.
1439 * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1440 * receives data string and returns true if the data is as expected, or Object if request body
1441 * is in JSON format.
1442 * @param {Object=} headers HTTP headers.
1443 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1444 * request is handled. You can save this object for later use and invoke `respond` again in
1445 * order to change how a matched request is handled.
1446 */
1447
1448 /**
1449 * @ngdoc method
1450 * @name $httpBackend#expectPUT
1451 * @description
1452 * Creates a new request expectation for PUT requests. For more info see `expect()`.
1453 *
1454 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1455 * and returns true if the url matches the current definition.
1456 * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1457 * receives data string and returns true if the data is as expected, or Object if request body
1458 * is in JSON format.
1459 * @param {Object=} headers HTTP headers.
1460 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1461 * request is handled. You can save this object for later use and invoke `respond` again in
1462 * order to change how a matched request is handled.
1463 */
1464
1465 /**
1466 * @ngdoc method
1467 * @name $httpBackend#expectPATCH
1468 * @description
1469 * Creates a new request expectation for PATCH requests. For more info see `expect()`.
1470 *
1471 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1472 * and returns true if the url matches the current definition.
1473 * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that
1474 * receives data string and returns true if the data is as expected, or Object if request body
1475 * is in JSON format.
1476 * @param {Object=} headers HTTP headers.
1477 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1478 * request is handled. You can save this object for later use and invoke `respond` again in
1479 * order to change how a matched request is handled.
1480 */
1481
1482 /**
1483 * @ngdoc method
1484 * @name $httpBackend#expectJSONP
1485 * @description
1486 * Creates a new request expectation for JSONP requests. For more info see `expect()`.
1487 *
1488 * @param {string|RegExp|function(string)} url HTTP url or function that receives an url
1489 * and returns true if the url matches the current definition.
1490 * @returns {requestHandler} Returns an object with `respond` method that controls how a matched
1491 * request is handled. You can save this object for later use and invoke `respond` again in
1492 * order to change how a matched request is handled.
1493 */
1494 createShortMethods('expect');
1495
1496
1497 /**
1498 * @ngdoc method
1499 * @name $httpBackend#flush
1500 * @description
1501 * Flushes all pending requests using the trained responses.
1502 *
1503 * @param {number=} count Number of responses to flush (in the order they arrived). If undefined,
1504 * all pending requests will be flushed. If there are no pending requests when the flush method
1505 * is called an exception is thrown (as this typically a sign of programming error).
1506 */
1507 $httpBackend.flush = function(count, digest) {
1508 if (digest !== false) $rootScope.$digest();
1509 if (!responses.length) throw new Error('No pending request to flush !');
1510
1511 if (angular.isDefined(count) && count !== null) {
1512 while (count--) {
1513 if (!responses.length) throw new Error('No more pending request to flush !');
1514 responses.shift()();
1515 }
1516 } else {
1517 while (responses.length) {
1518 responses.shift()();
1519 }
1520 }
1521 $httpBackend.verifyNoOutstandingExpectation(digest);
1522 };
1523
1524
1525 /**
1526 * @ngdoc method
1527 * @name $httpBackend#verifyNoOutstandingExpectation
1528 * @description
1529 * Verifies that all of the requests defined via the `expect` api were made. If any of the
1530 * requests were not made, verifyNoOutstandingExpectation throws an exception.
1531 *
1532 * Typically, you would call this method following each test case that asserts requests using an
1533 * "afterEach" clause.
1534 *
1535 * ```js
1536 * afterEach($httpBackend.verifyNoOutstandingExpectation);
1537 * ```
1538 */
1539 $httpBackend.verifyNoOutstandingExpectation = function(digest) {
1540 if (digest !== false) $rootScope.$digest();
1541 if (expectations.length) {
1542 throw new Error('Unsatisfied requests: ' + expectations.join(', '));
1543 }
1544 };
1545
1546
1547 /**
1548 * @ngdoc method
1549 * @name $httpBackend#verifyNoOutstandingRequest
1550 * @description
1551 * Verifies that there are no outstanding requests that need to be flushed.
1552 *
1553 * Typically, you would call this method following each test case that asserts requests using an
1554 * "afterEach" clause.
1555 *
1556 * ```js
1557 * afterEach($httpBackend.verifyNoOutstandingRequest);
1558 * ```
1559 */
1560 $httpBackend.verifyNoOutstandingRequest = function() {
1561 if (responses.length) {
1562 throw new Error('Unflushed requests: ' + responses.length);
1563 }
1564 };
1565
1566
1567 /**
1568 * @ngdoc method
1569 * @name $httpBackend#resetExpectations
1570 * @description
1571 * Resets all request expectations, but preserves all backend definitions. Typically, you would
1572 * call resetExpectations during a multiple-phase test when you want to reuse the same instance of
1573 * $httpBackend mock.
1574 */
1575 $httpBackend.resetExpectations = function() {
1576 expectations.length = 0;
1577 responses.length = 0;
1578 };
1579
1580 return $httpBackend;
1581
1582
1583 function createShortMethods(prefix) {
1584 angular.forEach(['GET', 'DELETE', 'JSONP', 'HEAD'], function(method) {
1585 $httpBackend[prefix + method] = function(url, headers) {
1586 return $httpBackend[prefix](method, url, undefined, headers);
1587 };
1588 });
1589
1590 angular.forEach(['PUT', 'POST', 'PATCH'], function(method) {
1591 $httpBackend[prefix + method] = function(url, data, headers) {
1592 return $httpBackend[prefix](method, url, data, headers);
1593 };
1594 });
1595 }
1596 }
1597
1598 function MockHttpExpectation(method, url, data, headers) {
1599
1600 this.data = data;
1601 this.headers = headers;
1602
1603 this.match = function(m, u, d, h) {
1604 if (method != m) return false;
1605 if (!this.matchUrl(u)) return false;
1606 if (angular.isDefined(d) && !this.matchData(d)) return false;
1607 if (angular.isDefined(h) && !this.matchHeaders(h)) return false;
1608 return true;
1609 };
1610
1611 this.matchUrl = function(u) {
1612 if (!url) return true;
1613 if (angular.isFunction(url.test)) return url.test(u);
1614 if (angular.isFunction(url)) return url(u);
1615 return url == u;
1616 };
1617
1618 this.matchHeaders = function(h) {
1619 if (angular.isUndefined(headers)) return true;
1620 if (angular.isFunction(headers)) return headers(h);
1621 return angular.equals(headers, h);
1622 };
1623
1624 this.matchData = function(d) {
1625 if (angular.isUndefined(data)) return true;
1626 if (data && angular.isFunction(data.test)) return data.test(d);
1627 if (data && angular.isFunction(data)) return data(d);
1628 if (data && !angular.isString(data)) {
1629 return angular.equals(angular.fromJson(angular.toJson(data)), angular.fromJson(d));
1630 }
1631 return data == d;
1632 };
1633
1634 this.toString = function() {
1635 return method + ' ' + url;
1636 };
1637 }
1638
1639 function createMockXhr() {
1640 return new MockXhr();
1641 }
1642
1643 function MockXhr() {
1644
1645 // hack for testing $http, $httpBackend
1646 MockXhr.$$lastInstance = this;
1647
1648 this.open = function(method, url, async) {
1649 this.$$method = method;
1650 this.$$url = url;
1651 this.$$async = async;
1652 this.$$reqHeaders = {};
1653 this.$$respHeaders = {};
1654 };
1655
1656 this.send = function(data) {
1657 this.$$data = data;
1658 };
1659
1660 this.setRequestHeader = function(key, value) {
1661 this.$$reqHeaders[key] = value;
1662 };
1663
1664 this.getResponseHeader = function(name) {
1665 // the lookup must be case insensitive,
1666 // that's why we try two quick lookups first and full scan last
1667 var header = this.$$respHeaders[name];
1668 if (header) return header;
1669
1670 name = angular.lowercase(name);
1671 header = this.$$respHeaders[name];
1672 if (header) return header;
1673
1674 header = undefined;
1675 angular.forEach(this.$$respHeaders, function(headerVal, headerName) {
1676 if (!header && angular.lowercase(headerName) == name) header = headerVal;
1677 });
1678 return header;
1679 };
1680
1681 this.getAllResponseHeaders = function() {
1682 var lines = [];
1683
1684 angular.forEach(this.$$respHeaders, function(value, key) {
1685 lines.push(key + ': ' + value);
1686 });
1687 return lines.join('\n');
1688 };
1689
1690 this.abort = angular.noop;
1691 }
1692
1693
1694 /**
1695 * @ngdoc service
1696 * @name $timeout
1697 * @description
1698 *
1699 * This service is just a simple decorator for {@link ng.$timeout $timeout} service
1700 * that adds a "flush" and "verifyNoPendingTasks" methods.
1701 */
1702
1703 angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $browser) {
1704
1705 /**
1706 * @ngdoc method
1707 * @name $timeout#flush
1708 * @description
1709 *
1710 * Flushes the queue of pending tasks.
1711 *
1712 * @param {number=} delay maximum timeout amount to flush up until
1713 */
1714 $delegate.flush = function(delay) {
1715 $browser.defer.flush(delay);
1716 };
1717
1718 /**
1719 * @ngdoc method
1720 * @name $timeout#verifyNoPendingTasks
1721 * @description
1722 *
1723 * Verifies that there are no pending tasks that need to be flushed.
1724 */
1725 $delegate.verifyNoPendingTasks = function() {
1726 if ($browser.deferredFns.length) {
1727 throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' +
1728 formatPendingTasksAsString($browser.deferredFns));
1729 }
1730 };
1731
1732 function formatPendingTasksAsString(tasks) {
1733 var result = [];
1734 angular.forEach(tasks, function(task) {
1735 result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}');
1736 });
1737
1738 return result.join(', ');
1739 }
1740
1741 return $delegate;
1742 }];
1743
1744 angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
1745 var queue = [];
1746 var rafFn = function(fn) {
1747 var index = queue.length;
1748 queue.push(fn);
1749 return function() {
1750 queue.splice(index, 1);
1751 };
1752 };
1753
1754 rafFn.supported = $delegate.supported;
1755
1756 rafFn.flush = function() {
1757 if (queue.length === 0) {
1758 throw new Error('No rAF callbacks present');
1759 }
1760
1761 var length = queue.length;
1762 for (var i = 0; i < length; i++) {
1763 queue[i]();
1764 }
1765
1766 queue = queue.slice(i);
1767 };
1768
1769 return rafFn;
1770 }];
1771
1772 /**
1773 *
1774 */
1775 angular.mock.$RootElementProvider = function() {
1776 this.$get = function() {
1777 return angular.element('<div ng-app></div>');
1778 };
1779 };
1780
1781 /**
1782 * @ngdoc service
1783 * @name $controller
1784 * @description
1785 * A decorator for {@link ng.$controller} with additional `bindings` parameter, useful when testing
1786 * controllers of directives that use {@link $compile#-bindtocontroller- `bindToController`}.
1787 *
1788 *
1789 * ## Example
1790 *
1791 * ```js
1792 *
1793 * // Directive definition ...
1794 *
1795 * myMod.directive('myDirective', {
1796 * controller: 'MyDirectiveController',
1797 * bindToController: {
1798 * name: '@'
1799 * }
1800 * });
1801 *
1802 *
1803 * // Controller definition ...
1804 *
1805 * myMod.controller('MyDirectiveController', ['log', function($log) {
1806 * $log.info(this.name);
1807 * })];
1808 *
1809 *
1810 * // In a test ...
1811 *
1812 * describe('myDirectiveController', function() {
1813 * it('should write the bound name to the log', inject(function($controller, $log) {
1814 * var ctrl = $controller('MyDirective', { /* no locals &#42;/ }, { name: 'Clark Kent' });
1815 * expect(ctrl.name).toEqual('Clark Kent');
1816 * expect($log.info.logs).toEqual(['Clark Kent']);
1817 * });
1818 * });
1819 *
1820 * ```
1821 *
1822 * @param {Function|string} constructor If called with a function then it's considered to be the
1823 * controller constructor function. Otherwise it's considered to be a string which is used
1824 * to retrieve the controller constructor using the following steps:
1825 *
1826 * * check if a controller with given name is registered via `$controllerProvider`
1827 * * check if evaluating the string on the current scope returns a constructor
1828 * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
1829 * `window` object (not recommended)
1830 *
1831 * The string can use the `controller as property` syntax, where the controller instance is published
1832 * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
1833 * to work correctly.
1834 *
1835 * @param {Object} locals Injection locals for Controller.
1836 * @param {Object=} bindings Properties to add to the controller before invoking the constructor. This is used
1837 * to simulate the `bindToController` feature and simplify certain kinds of tests.
1838 * @return {Object} Instance of given controller.
1839 */
1840 angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
1841 return function(expression, locals, later, ident) {
1842 if (later && typeof later === 'object') {
1843 var create = $delegate(expression, locals, true, ident);
1844 angular.extend(create.instance, later);
1845 return create();
1846 }
1847 return $delegate(expression, locals, later, ident);
1848 };
1849 }];
1850
1851
1852 /**
1853 * @ngdoc module
1854 * @name ngMock
1855 * @packageName angular-mocks
1856 * @description
1857 *
1858 * # ngMock
1859 *
1860 * The `ngMock` module provides support to inject and mock Angular services into unit tests.
1861 * In addition, ngMock also extends various core ng services such that they can be
1862 * inspected and controlled in a synchronous manner within test code.
1863 *
1864 *
1865 * <div doc-module-components="ngMock"></div>
1866 *
1867 */
1868 angular.module('ngMock', ['ng']).provider({
1869 $browser: angular.mock.$BrowserProvider,
1870 $exceptionHandler: angular.mock.$ExceptionHandlerProvider,
1871 $log: angular.mock.$LogProvider,
1872 $interval: angular.mock.$IntervalProvider,
1873 $httpBackend: angular.mock.$HttpBackendProvider,
1874 $rootElement: angular.mock.$RootElementProvider
1875 }).config(['$provide', function($provide) {
1876 $provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
1877 $provide.decorator('$$rAF', angular.mock.$RAFDecorator);
1878 $provide.decorator('$rootScope', angular.mock.$RootScopeDecorator);
1879 $provide.decorator('$controller', angular.mock.$ControllerDecorator);
1880 }]);
1881
1882 /**
1883 * @ngdoc module
1884 * @name ngMockE2E
1885 * @module ngMockE2E
1886 * @packageName angular-mocks
1887 * @description
1888 *
1889 * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing.
1890 * Currently there is only one mock present in this module -
1891 * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
1892 */
1893 angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
1894 $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
1895 }]);
1896
1897 /**
1898 * @ngdoc service
1899 * @name $httpBackend
1900 * @module ngMockE2E
1901 * @description
1902 * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of
1903 * applications that use the {@link ng.$http $http service}.
1904 *
1905 * *Note*: For fake http backend implementation suitable for unit testing please see
1906 * {@link ngMock.$httpBackend unit-testing $httpBackend mock}.
1907 *
1908 * This implementation can be used to respond with static or dynamic responses via the `when` api
1909 * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the
1910 * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch
1911 * templates from a webserver).
1912 *
1913 * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application
1914 * is being developed with the real backend api replaced with a mock, it is often desirable for
1915 * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch
1916 * templates or static files from the webserver). To configure the backend with this behavior
1917 * use the `passThrough` request handler of `when` instead of `respond`.
1918 *
1919 * Additionally, we don't want to manually have to flush mocked out requests like we do during unit
1920 * testing. For this reason the e2e $httpBackend flushes mocked out requests
1921 * automatically, closely simulating the behavior of the XMLHttpRequest object.
1922 *
1923 * To setup the application to run with this http backend, you have to create a module that depends
1924 * on the `ngMockE2E` and your application modules and defines the fake backend:
1925 *
1926 * ```js
1927 * myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
1928 * myAppDev.run(function($httpBackend) {
1929 * phones = [{name: 'phone1'}, {name: 'phone2'}];
1930 *
1931 * // returns the current list of phones
1932 * $httpBackend.whenGET('/phones').respond(phones);
1933 *
1934 * // adds a new phone to the phones array
1935 * $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
1936 * var phone = angular.fromJson(data);
1937 * phones.push(phone);
1938 * return [200, phone, {}];
1939 * });
1940 * $httpBackend.whenGET(/^\/templates\//).passThrough();
1941 * //...
1942 * });
1943 * ```
1944 *
1945 * Afterwards, bootstrap your app with this new module.
1946 */
1947
1948 /**
1949 * @ngdoc method
1950 * @name $httpBackend#when
1951 * @module ngMockE2E
1952 * @description
1953 * Creates a new backend definition.
1954 *
1955 * @param {string} method HTTP method.
1956 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1957 * and returns true if the url matches the current definition.
1958 * @param {(string|RegExp)=} data HTTP request body.
1959 * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header
1960 * object and returns true if the headers match the current definition.
1961 * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1962 * control how a matched request is handled. You can save this object for later use and invoke
1963 * `respond` or `passThrough` again in order to change how a matched request is handled.
1964 *
1965 * - respond –
1966 * `{function([status,] data[, headers, statusText])
1967 * | function(function(method, url, data, headers)}`
1968 * – The respond method takes a set of static data to be returned or a function that can return
1969 * an array containing response status (number), response data (string), response headers
1970 * (Object), and the text for the status (string).
1971 * - passThrough – `{function()}` – Any request matching a backend definition with
1972 * `passThrough` handler will be passed through to the real backend (an XHR request will be made
1973 * to the server.)
1974 * - Both methods return the `requestHandler` object for possible overrides.
1975 */
1976
1977 /**
1978 * @ngdoc method
1979 * @name $httpBackend#whenGET
1980 * @module ngMockE2E
1981 * @description
1982 * Creates a new backend definition for GET requests. For more info see `when()`.
1983 *
1984 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
1985 * and returns true if the url matches the current definition.
1986 * @param {(Object|function(Object))=} headers HTTP headers.
1987 * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
1988 * control how a matched request is handled. You can save this object for later use and invoke
1989 * `respond` or `passThrough` again in order to change how a matched request is handled.
1990 */
1991
1992 /**
1993 * @ngdoc method
1994 * @name $httpBackend#whenHEAD
1995 * @module ngMockE2E
1996 * @description
1997 * Creates a new backend definition for HEAD requests. For more info see `when()`.
1998 *
1999 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2000 * and returns true if the url matches the current definition.
2001 * @param {(Object|function(Object))=} headers HTTP headers.
2002 * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2003 * control how a matched request is handled. You can save this object for later use and invoke
2004 * `respond` or `passThrough` again in order to change how a matched request is handled.
2005 */
2006
2007 /**
2008 * @ngdoc method
2009 * @name $httpBackend#whenDELETE
2010 * @module ngMockE2E
2011 * @description
2012 * Creates a new backend definition for DELETE requests. For more info see `when()`.
2013 *
2014 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2015 * and returns true if the url matches the current definition.
2016 * @param {(Object|function(Object))=} headers HTTP headers.
2017 * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2018 * control how a matched request is handled. You can save this object for later use and invoke
2019 * `respond` or `passThrough` again in order to change how a matched request is handled.
2020 */
2021
2022 /**
2023 * @ngdoc method
2024 * @name $httpBackend#whenPOST
2025 * @module ngMockE2E
2026 * @description
2027 * Creates a new backend definition for POST requests. For more info see `when()`.
2028 *
2029 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2030 * and returns true if the url matches the current definition.
2031 * @param {(string|RegExp)=} data HTTP request body.
2032 * @param {(Object|function(Object))=} headers HTTP headers.
2033 * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2034 * control how a matched request is handled. You can save this object for later use and invoke
2035 * `respond` or `passThrough` again in order to change how a matched request is handled.
2036 */
2037
2038 /**
2039 * @ngdoc method
2040 * @name $httpBackend#whenPUT
2041 * @module ngMockE2E
2042 * @description
2043 * Creates a new backend definition for PUT requests. For more info see `when()`.
2044 *
2045 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2046 * and returns true if the url matches the current definition.
2047 * @param {(string|RegExp)=} data HTTP request body.
2048 * @param {(Object|function(Object))=} headers HTTP headers.
2049 * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2050 * control how a matched request is handled. You can save this object for later use and invoke
2051 * `respond` or `passThrough` again in order to change how a matched request is handled.
2052 */
2053
2054 /**
2055 * @ngdoc method
2056 * @name $httpBackend#whenPATCH
2057 * @module ngMockE2E
2058 * @description
2059 * Creates a new backend definition for PATCH requests. For more info see `when()`.
2060 *
2061 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2062 * and returns true if the url matches the current definition.
2063 * @param {(string|RegExp)=} data HTTP request body.
2064 * @param {(Object|function(Object))=} headers HTTP headers.
2065 * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2066 * control how a matched request is handled. You can save this object for later use and invoke
2067 * `respond` or `passThrough` again in order to change how a matched request is handled.
2068 */
2069
2070 /**
2071 * @ngdoc method
2072 * @name $httpBackend#whenJSONP
2073 * @module ngMockE2E
2074 * @description
2075 * Creates a new backend definition for JSONP requests. For more info see `when()`.
2076 *
2077 * @param {string|RegExp|function(string)} url HTTP url or function that receives a url
2078 * and returns true if the url matches the current definition.
2079 * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that
2080 * control how a matched request is handled. You can save this object for later use and invoke
2081 * `respond` or `passThrough` again in order to change how a matched request is handled.
2082 */
2083 angular.mock.e2e = {};
2084 angular.mock.e2e.$httpBackendDecorator =
2085 ['$rootScope', '$timeout', '$delegate', '$browser', createHttpBackendMock];
2086
2087
2088 /**
2089 * @ngdoc type
2090 * @name $rootScope.Scope
2091 * @module ngMock
2092 * @description
2093 * {@link ng.$rootScope.Scope Scope} type decorated with helper methods useful for testing. These
2094 * methods are automatically available on any {@link ng.$rootScope.Scope Scope} instance when
2095 * `ngMock` module is loaded.
2096 *
2097 * In addition to all the regular `Scope` methods, the following helper methods are available:
2098 */
2099 angular.mock.$RootScopeDecorator = ['$delegate', function($delegate) {
2100
2101 var $rootScopePrototype = Object.getPrototypeOf($delegate);
2102
2103 $rootScopePrototype.$countChildScopes = countChildScopes;
2104 $rootScopePrototype.$countWatchers = countWatchers;
2105
2106 return $delegate;
2107
2108 // ------------------------------------------------------------------------------------------ //
2109
2110 /**
2111 * @ngdoc method
2112 * @name $rootScope.Scope#$countChildScopes
2113 * @module ngMock
2114 * @description
2115 * Counts all the direct and indirect child scopes of the current scope.
2116 *
2117 * The current scope is excluded from the count. The count includes all isolate child scopes.
2118 *
2119 * @returns {number} Total number of child scopes.
2120 */
2121 function countChildScopes() {
2122 // jshint validthis: true
2123 var count = 0; // exclude the current scope
2124 var pendingChildHeads = [this.$$childHead];
2125 var currentScope;
2126
2127 while (pendingChildHeads.length) {
2128 currentScope = pendingChildHeads.shift();
2129
2130 while (currentScope) {
2131 count += 1;
2132 pendingChildHeads.push(currentScope.$$childHead);
2133 currentScope = currentScope.$$nextSibling;
2134 }
2135 }
2136
2137 return count;
2138 }
2139
2140
2141 /**
2142 * @ngdoc method
2143 * @name $rootScope.Scope#$countWatchers
2144 * @module ngMock
2145 * @description
2146 * Counts all the watchers of direct and indirect child scopes of the current scope.
2147 *
2148 * The watchers of the current scope are included in the count and so are all the watchers of
2149 * isolate child scopes.
2150 *
2151 * @returns {number} Total number of watchers.
2152 */
2153 function countWatchers() {
2154 // jshint validthis: true
2155 var count = this.$$watchers ? this.$$watchers.length : 0; // include the current scope
2156 var pendingChildHeads = [this.$$childHead];
2157 var currentScope;
2158
2159 while (pendingChildHeads.length) {
2160 currentScope = pendingChildHeads.shift();
2161
2162 while (currentScope) {
2163 count += currentScope.$$watchers ? currentScope.$$watchers.length : 0;
2164 pendingChildHeads.push(currentScope.$$childHead);
2165 currentScope = currentScope.$$nextSibling;
2166 }
2167 }
2168
2169 return count;
2170 }
2171 }];
2172
2173
2174 if (window.jasmine || window.mocha) {
2175
2176 var currentSpec = null,
2177 annotatedFunctions = [],
2178 isSpecRunning = function() {
2179 return !!currentSpec;
2180 };
2181
2182 angular.mock.$$annotate = angular.injector.$$annotate;
2183 angular.injector.$$annotate = function(fn) {
2184 if (typeof fn === 'function' && !fn.$inject) {
2185 annotatedFunctions.push(fn);
2186 }
2187 return angular.mock.$$annotate.apply(this, arguments);
2188 };
2189
2190
2191 (window.beforeEach || window.setup)(function() {
2192 annotatedFunctions = [];
2193 currentSpec = this;
2194 });
2195
2196 (window.afterEach || window.teardown)(function() {
2197 var injector = currentSpec.$injector;
2198
2199 annotatedFunctions.forEach(function(fn) {
2200 delete fn.$inject;
2201 });
2202
2203 angular.forEach(currentSpec.$modules, function(module) {
2204 if (module && module.$$hashKey) {
2205 module.$$hashKey = undefined;
2206 }
2207 });
2208
2209 currentSpec.$injector = null;
2210 currentSpec.$modules = null;
2211 currentSpec = null;
2212
2213 if (injector) {
2214 injector.get('$rootElement').off();
2215 }
2216
2217 // clean up jquery's fragment cache
2218 angular.forEach(angular.element.fragments, function(val, key) {
2219 delete angular.element.fragments[key];
2220 });
2221
2222 MockXhr.$$lastInstance = null;
2223
2224 angular.forEach(angular.callbacks, function(val, key) {
2225 delete angular.callbacks[key];
2226 });
2227 angular.callbacks.counter = 0;
2228 });
2229
2230 /**
2231 * @ngdoc function
2232 * @name angular.mock.module
2233 * @description
2234 *
2235 * *NOTE*: This function is also published on window for easy access.<br>
2236 * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
2237 *
2238 * This function registers a module configuration code. It collects the configuration information
2239 * which will be used when the injector is created by {@link angular.mock.inject inject}.
2240 *
2241 * See {@link angular.mock.inject inject} for usage example
2242 *
2243 * @param {...(string|Function|Object)} fns any number of modules which are represented as string
2244 * aliases or as anonymous module initialization functions. The modules are used to
2245 * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an
2246 * object literal is passed they will be registered as values in the module, the key being
2247 * the module name and the value being what is returned.
2248 */
2249 window.module = angular.mock.module = function() {
2250 var moduleFns = Array.prototype.slice.call(arguments, 0);
2251 return isSpecRunning() ? workFn() : workFn;
2252 /////////////////////
2253 function workFn() {
2254 if (currentSpec.$injector) {
2255 throw new Error('Injector already created, can not register a module!');
2256 } else {
2257 var modules = currentSpec.$modules || (currentSpec.$modules = []);
2258 angular.forEach(moduleFns, function(module) {
2259 if (angular.isObject(module) && !angular.isArray(module)) {
2260 modules.push(function($provide) {
2261 angular.forEach(module, function(value, key) {
2262 $provide.value(key, value);
2263 });
2264 });
2265 } else {
2266 modules.push(module);
2267 }
2268 });
2269 }
2270 }
2271 };
2272
2273 /**
2274 * @ngdoc function
2275 * @name angular.mock.inject
2276 * @description
2277 *
2278 * *NOTE*: This function is also published on window for easy access.<br>
2279 * *NOTE*: This function is declared ONLY WHEN running tests with jasmine or mocha
2280 *
2281 * The inject function wraps a function into an injectable function. The inject() creates new
2282 * instance of {@link auto.$injector $injector} per test, which is then used for
2283 * resolving references.
2284 *
2285 *
2286 * ## Resolving References (Underscore Wrapping)
2287 * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this
2288 * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable
2289 * that is declared in the scope of the `describe()` block. Since we would, most likely, want
2290 * the variable to have the same name of the reference we have a problem, since the parameter
2291 * to the `inject()` function would hide the outer variable.
2292 *
2293 * To help with this, the injected parameters can, optionally, be enclosed with underscores.
2294 * These are ignored by the injector when the reference name is resolved.
2295 *
2296 * For example, the parameter `_myService_` would be resolved as the reference `myService`.
2297 * Since it is available in the function body as _myService_, we can then assign it to a variable
2298 * defined in an outer scope.
2299 *
2300 * ```
2301 * // Defined out reference variable outside
2302 * var myService;
2303 *
2304 * // Wrap the parameter in underscores
2305 * beforeEach( inject( function(_myService_){
2306 * myService = _myService_;
2307 * }));
2308 *
2309 * // Use myService in a series of tests.
2310 * it('makes use of myService', function() {
2311 * myService.doStuff();
2312 * });
2313 *
2314 * ```
2315 *
2316 * See also {@link angular.mock.module angular.mock.module}
2317 *
2318 * ## Example
2319 * Example of what a typical jasmine tests looks like with the inject method.
2320 * ```js
2321 *
2322 * angular.module('myApplicationModule', [])
2323 * .value('mode', 'app')
2324 * .value('version', 'v1.0.1');
2325 *
2326 *
2327 * describe('MyApp', function() {
2328 *
2329 * // You need to load modules that you want to test,
2330 * // it loads only the "ng" module by default.
2331 * beforeEach(module('myApplicationModule'));
2332 *
2333 *
2334 * // inject() is used to inject arguments of all given functions
2335 * it('should provide a version', inject(function(mode, version) {
2336 * expect(version).toEqual('v1.0.1');
2337 * expect(mode).toEqual('app');
2338 * }));
2339 *
2340 *
2341 * // The inject and module method can also be used inside of the it or beforeEach
2342 * it('should override a version and test the new version is injected', function() {
2343 * // module() takes functions or strings (module aliases)
2344 * module(function($provide) {
2345 * $provide.value('version', 'overridden'); // override version here
2346 * });
2347 *
2348 * inject(function(version) {
2349 * expect(version).toEqual('overridden');
2350 * });
2351 * });
2352 * });
2353 *
2354 * ```
2355 *
2356 * @param {...Function} fns any number of functions which will be injected using the injector.
2357 */
2358
2359
2360
2361 var ErrorAddingDeclarationLocationStack = function(e, errorForStack) {
2362 this.message = e.message;
2363 this.name = e.name;
2364 if (e.line) this.line = e.line;
2365 if (e.sourceId) this.sourceId = e.sourceId;
2366 if (e.stack && errorForStack)
2367 this.stack = e.stack + '\n' + errorForStack.stack;
2368 if (e.stackArray) this.stackArray = e.stackArray;
2369 };
2370 ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString;
2371
2372 window.inject = angular.mock.inject = function() {
2373 var blockFns = Array.prototype.slice.call(arguments, 0);
2374 var errorForStack = new Error('Declaration Location');
2375 return isSpecRunning() ? workFn.call(currentSpec) : workFn;
2376 /////////////////////
2377 function workFn() {
2378 var modules = currentSpec.$modules || [];
2379 var strictDi = !!currentSpec.$injectorStrict;
2380 modules.unshift('ngMock');
2381 modules.unshift('ng');
2382 var injector = currentSpec.$injector;
2383 if (!injector) {
2384 if (strictDi) {
2385 // If strictDi is enabled, annotate the providerInjector blocks
2386 angular.forEach(modules, function(moduleFn) {
2387 if (typeof moduleFn === "function") {
2388 angular.injector.$$annotate(moduleFn);
2389 }
2390 });
2391 }
2392 injector = currentSpec.$injector = angular.injector(modules, strictDi);
2393 currentSpec.$injectorStrict = strictDi;
2394 }
2395 for (var i = 0, ii = blockFns.length; i < ii; i++) {
2396 if (currentSpec.$injectorStrict) {
2397 // If the injector is strict / strictDi, and the spec wants to inject using automatic
2398 // annotation, then annotate the function here.
2399 injector.annotate(blockFns[i]);
2400 }
2401 try {
2402 /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */
2403 injector.invoke(blockFns[i] || angular.noop, this);
2404 /* jshint +W040 */
2405 } catch (e) {
2406 if (e.stack && errorForStack) {
2407 throw new ErrorAddingDeclarationLocationStack(e, errorForStack);
2408 }
2409 throw e;
2410 } finally {
2411 errorForStack = null;
2412 }
2413 }
2414 }
2415 };
2416
2417
2418 angular.mock.inject.strictDi = function(value) {
2419 value = arguments.length ? !!value : true;
2420 return isSpecRunning() ? workFn() : workFn;
2421
2422 function workFn() {
2423 if (value !== currentSpec.$injectorStrict) {
2424 if (currentSpec.$injector) {
2425 throw new Error('Injector already created, can not modify strict annotations');
2426 } else {
2427 currentSpec.$injectorStrict = value;
2428 }
2429 }
2430 }
2431 };
2432 }
2433
2434
2435 })(window, window.angular);
+0
-737
faraday/server/www/script/angular-moment.js less more
0 /* angular-moment.js / v1.2.0 / (c) 2013, 2014, 2015, 2016, 2017 Uri Shaked / MIT Licence */
1
2 'format amd';
3 /* global define */
4
5 (function () {
6 'use strict';
7
8 function isUndefinedOrNull(val) {
9 return angular.isUndefined(val) || val === null;
10 }
11
12 function requireMoment() {
13 try {
14 return require('moment'); // Using nw.js or browserify?
15 } catch (e) {
16 throw new Error('Please install moment via npm. Please reference to: https://github.com/urish/angular-moment'); // Add wiki/troubleshooting section?
17 }
18 }
19
20 function angularMoment(angular, moment) {
21
22 if(typeof moment === 'undefined') {
23 if(typeof require === 'function') {
24 moment = requireMoment();
25 }else{
26 throw new Error('Moment cannot be found by angular-moment! Please reference to: https://github.com/urish/angular-moment'); // Add wiki/troubleshooting section?
27 }
28 }
29
30 /**
31 * @ngdoc overview
32 * @name angularMoment
33 *
34 * @description
35 * angularMoment module provides moment.js functionality for angular.js apps.
36 */
37 angular.module('angularMoment', [])
38
39 /**
40 * @ngdoc object
41 * @name angularMoment.config:angularMomentConfig
42 *
43 * @description
44 * Common configuration of the angularMoment module
45 */
46 .constant('angularMomentConfig', {
47 /**
48 * @ngdoc property
49 * @name angularMoment.config.angularMomentConfig#preprocess
50 * @propertyOf angularMoment.config:angularMomentConfig
51 * @returns {function} A preprocessor function that will be applied on all incoming dates
52 *
53 * @description
54 * Defines a preprocessor function to apply on all input dates (e.g. the input of `am-time-ago`,
55 * `amCalendar`, etc.). The function must return a `moment` object.
56 *
57 * @example
58 * // Causes angular-moment to always treat the input values as unix timestamps
59 * angularMomentConfig.preprocess = function(value) {
60 * return moment.unix(value);
61 * }
62 */
63 preprocess: null,
64
65 /**
66 * @ngdoc property
67 * @name angularMoment.config.angularMomentConfig#timezone
68 * @propertyOf angularMoment.config:angularMomentConfig
69 * @returns {string} The default timezone
70 *
71 * @description
72 * The default timezone (e.g. 'Europe/London'). Empty string by default (does not apply
73 * any timezone shift).
74 *
75 * NOTE: This option requires moment-timezone >= 0.3.0.
76 */
77 timezone: null,
78
79 /**
80 * @ngdoc property
81 * @name angularMoment.config.angularMomentConfig#format
82 * @propertyOf angularMoment.config:angularMomentConfig
83 * @returns {string} The pre-conversion format of the date
84 *
85 * @description
86 * Specify the format of the input date. Essentially it's a
87 * default and saves you from specifying a format in every
88 * element. Overridden by element attr. Null by default.
89 */
90 format: null,
91
92 /**
93 * @ngdoc property
94 * @name angularMoment.config.angularMomentConfig#statefulFilters
95 * @propertyOf angularMoment.config:angularMomentConfig
96 * @returns {boolean} Whether angular-moment filters should be stateless (or not)
97 *
98 * @description
99 * Specifies whether the filters included with angular-moment are stateful.
100 * Stateful filters will automatically re-evaluate whenever you change the timezone
101 * or locale settings, but may negatively impact performance. true by default.
102 */
103 statefulFilters: true
104 })
105
106 /**
107 * @ngdoc object
108 * @name angularMoment.object:moment
109 *
110 * @description
111 * moment global (as provided by the moment.js library)
112 */
113 .constant('moment', moment)
114
115 /**
116 * @ngdoc object
117 * @name angularMoment.config:amTimeAgoConfig
118 * @module angularMoment
119 *
120 * @description
121 * configuration specific to the amTimeAgo directive
122 */
123 .constant('amTimeAgoConfig', {
124 /**
125 * @ngdoc property
126 * @name angularMoment.config.amTimeAgoConfig#withoutSuffix
127 * @propertyOf angularMoment.config:amTimeAgoConfig
128 * @returns {boolean} Whether to include a suffix in am-time-ago directive
129 *
130 * @description
131 * Defaults to false.
132 */
133 withoutSuffix: false,
134
135 /**
136 * @ngdoc property
137 * @name angularMoment.config.amTimeAgoConfig#serverTime
138 * @propertyOf angularMoment.config:amTimeAgoConfig
139 * @returns {number} Server time in milliseconds since the epoch
140 *
141 * @description
142 * If set, time ago will be calculated relative to the given value.
143 * If null, local time will be used. Defaults to null.
144 */
145 serverTime: null,
146
147 /**
148 * @ngdoc property
149 * @name angularMoment.config.amTimeAgoConfig#titleFormat
150 * @propertyOf angularMoment.config:amTimeAgoConfig
151 * @returns {string} The format of the date to be displayed in the title of the element. If null,
152 * the directive set the title of the element.
153 *
154 * @description
155 * The format of the date used for the title of the element. null by default.
156 */
157 titleFormat: null,
158
159 /**
160 * @ngdoc property
161 * @name angularMoment.config.amTimeAgoConfig#fullDateThreshold
162 * @propertyOf angularMoment.config:amTimeAgoConfig
163 * @returns {number} The minimum number of days for showing a full date instead of relative time
164 *
165 * @description
166 * The threshold for displaying a full date. The default is null, which means the date will always
167 * be relative, and full date will never be displayed.
168 */
169 fullDateThreshold: null,
170
171 /**
172 * @ngdoc property
173 * @name angularMoment.config.amTimeAgoConfig#fullDateFormat
174 * @propertyOf angularMoment.config:amTimeAgoConfig
175 * @returns {string} The format to use when displaying a full date.
176 *
177 * @description
178 * Specify the format of the date when displayed as full date. null by default.
179 */
180 fullDateFormat: null,
181
182 fullDateThresholdUnit: 'day'
183 })
184
185 /**
186 * @ngdoc directive
187 * @name angularMoment.directive:amTimeAgo
188 * @module angularMoment
189 *
190 * @restrict A
191 */
192 .directive('amTimeAgo', ['$window', 'moment', 'amMoment', 'amTimeAgoConfig', function ($window, moment, amMoment, amTimeAgoConfig) {
193
194 return function (scope, element, attr) {
195 var activeTimeout = null;
196 var currentValue;
197 var withoutSuffix = amTimeAgoConfig.withoutSuffix;
198 var titleFormat = amTimeAgoConfig.titleFormat;
199 var fullDateThreshold = amTimeAgoConfig.fullDateThreshold;
200 var fullDateFormat = amTimeAgoConfig.fullDateFormat;
201 var fullDateThresholdUnit = amTimeAgoConfig.fullDateThresholdUnit;
202
203 var localDate = new Date().getTime();
204 var modelName = attr.amTimeAgo;
205 var currentFrom;
206 var isTimeElement = ('TIME' === element[0].nodeName.toUpperCase());
207 var setTitleTime = !element.attr('title');
208
209 function getNow() {
210 var now;
211 if (currentFrom) {
212 now = currentFrom;
213 } else if (amTimeAgoConfig.serverTime) {
214 var localNow = new Date().getTime();
215 var nowMillis = localNow - localDate + amTimeAgoConfig.serverTime;
216 now = moment(nowMillis);
217 }
218 else {
219 now = moment();
220 }
221 return now;
222 }
223
224 function cancelTimer() {
225 if (activeTimeout) {
226 $window.clearTimeout(activeTimeout);
227 activeTimeout = null;
228 }
229 }
230
231 function updateTime(momentInstance) {
232 var timeAgo = getNow().diff(momentInstance, fullDateThresholdUnit);
233 var showFullDate = fullDateThreshold && timeAgo >= fullDateThreshold;
234
235 if (showFullDate) {
236 element.text(momentInstance.format(fullDateFormat));
237 } else {
238 element.text(momentInstance.from(getNow(), withoutSuffix));
239 }
240
241 if (titleFormat && setTitleTime) {
242 element.attr('title', momentInstance.format(titleFormat));
243 }
244
245 if (!showFullDate) {
246 var howOld = Math.abs(getNow().diff(momentInstance, 'minute'));
247 var secondsUntilUpdate = 3600;
248 if (howOld < 1) {
249 secondsUntilUpdate = 1;
250 } else if (howOld < 60) {
251 secondsUntilUpdate = 30;
252 } else if (howOld < 180) {
253 secondsUntilUpdate = 300;
254 }
255
256 activeTimeout = $window.setTimeout(function () {
257 updateTime(momentInstance);
258 }, secondsUntilUpdate * 1000);
259 }
260 }
261
262 function updateDateTimeAttr(value) {
263 if (isTimeElement) {
264 element.attr('datetime', value);
265 }
266 }
267
268 function updateMoment() {
269 cancelTimer();
270 if (currentValue) {
271 var momentValue = amMoment.preprocessDate(currentValue);
272 updateTime(momentValue);
273 updateDateTimeAttr(momentValue.toISOString());
274 }
275 }
276
277 scope.$watch(modelName, function (value) {
278 if (isUndefinedOrNull(value) || (value === '')) {
279 cancelTimer();
280 if (currentValue) {
281 element.text('');
282 updateDateTimeAttr('');
283 currentValue = null;
284 }
285 return;
286 }
287
288 currentValue = value;
289 updateMoment();
290 });
291
292 if (angular.isDefined(attr.amFrom)) {
293 scope.$watch(attr.amFrom, function (value) {
294 if (isUndefinedOrNull(value) || (value === '')) {
295 currentFrom = null;
296 } else {
297 currentFrom = moment(value);
298 }
299 updateMoment();
300 });
301 }
302
303 if (angular.isDefined(attr.amWithoutSuffix)) {
304 scope.$watch(attr.amWithoutSuffix, function (value) {
305 if (typeof value === 'boolean') {
306 withoutSuffix = value;
307 updateMoment();
308 } else {
309 withoutSuffix = amTimeAgoConfig.withoutSuffix;
310 }
311 });
312 }
313
314 attr.$observe('amFullDateThreshold', function (newValue) {
315 fullDateThreshold = newValue;
316 updateMoment();
317 });
318
319 attr.$observe('amFullDateFormat', function (newValue) {
320 fullDateFormat = newValue;
321 updateMoment();
322 });
323
324 attr.$observe('amFullDateThresholdUnit', function (newValue) {
325 fullDateThresholdUnit = newValue;
326 updateMoment();
327 });
328
329 scope.$on('$destroy', function () {
330 cancelTimer();
331 });
332
333 scope.$on('amMoment:localeChanged', function () {
334 updateMoment();
335 });
336 };
337 }])
338
339 /**
340 * @ngdoc service
341 * @name angularMoment.service.amMoment
342 * @module angularMoment
343 */
344 .service('amMoment', ['moment', '$rootScope', '$log', 'angularMomentConfig', function (moment, $rootScope, $log, angularMomentConfig) {
345 var defaultTimezone = null;
346
347 /**
348 * @ngdoc function
349 * @name angularMoment.service.amMoment#changeLocale
350 * @methodOf angularMoment.service.amMoment
351 *
352 * @description
353 * Changes the locale for moment.js and updates all the am-time-ago directive instances
354 * with the new locale. Also broadcasts an `amMoment:localeChanged` event on $rootScope.
355 *
356 * @param {string} locale Locale code (e.g. en, es, ru, pt-br, etc.)
357 * @param {object} customization object of locale strings to override
358 */
359 this.changeLocale = function (locale, customization) {
360 var result = moment.locale(locale, customization);
361 if (angular.isDefined(locale)) {
362 $rootScope.$broadcast('amMoment:localeChanged');
363
364 }
365 return result;
366 };
367
368 /**
369 * @ngdoc function
370 * @name angularMoment.service.amMoment#changeTimezone
371 * @methodOf angularMoment.service.amMoment
372 *
373 * @description
374 * Changes the default timezone for amCalendar, amDateFormat and amTimeAgo. Also broadcasts an
375 * `amMoment:timezoneChanged` event on $rootScope.
376 *
377 * Note: this method works only if moment-timezone > 0.3.0 is loaded
378 *
379 * @param {string} timezone Timezone name (e.g. UTC)
380 */
381 this.changeTimezone = function (timezone) {
382 if (moment.tz && moment.tz.setDefault) {
383 moment.tz.setDefault(timezone);
384 $rootScope.$broadcast('amMoment:timezoneChanged');
385 } else {
386 $log.warn('angular-moment: changeTimezone() works only with moment-timezone.js v0.3.0 or greater.');
387 }
388 angularMomentConfig.timezone = timezone;
389 defaultTimezone = timezone;
390 };
391
392 /**
393 * @ngdoc function
394 * @name angularMoment.service.amMoment#preprocessDate
395 * @methodOf angularMoment.service.amMoment
396 *
397 * @description
398 * Preprocess a given value and convert it into a Moment instance appropriate for use in the
399 * am-time-ago directive and the filters. The behavior of this function can be overriden by
400 * setting `angularMomentConfig.preprocess`.
401 *
402 * @param {*} value The value to be preprocessed
403 * @return {Moment} A `moment` object
404 */
405 this.preprocessDate = function (value) {
406 // Configure the default timezone if needed
407 if (defaultTimezone !== angularMomentConfig.timezone) {
408 this.changeTimezone(angularMomentConfig.timezone);
409 }
410
411 if (angularMomentConfig.preprocess) {
412 return angularMomentConfig.preprocess(value);
413 }
414
415 if (!isNaN(parseFloat(value)) && isFinite(value)) {
416 // Milliseconds since the epoch
417 return moment(parseInt(value, 10));
418 }
419
420 // else just returns the value as-is.
421 return moment(value);
422 };
423 }])
424
425 /**
426 * @ngdoc filter
427 * @name angularMoment.filter:amParse
428 * @module angularMoment
429 */
430 .filter('amParse', ['moment', function (moment) {
431 return function (value, format) {
432 return moment(value, format);
433 };
434 }])
435
436 /**
437 * @ngdoc filter
438 * @name angularMoment.filter:amFromUnix
439 * @module angularMoment
440 */
441 .filter('amFromUnix', ['moment', function (moment) {
442 return function (value) {
443 return moment.unix(value);
444 };
445 }])
446
447 /**
448 * @ngdoc filter
449 * @name angularMoment.filter:amUtc
450 * @module angularMoment
451 */
452 .filter('amUtc', ['moment', function (moment) {
453 return function (value) {
454 return moment.utc(value);
455 };
456 }])
457
458 /**
459 * @ngdoc filter
460 * @name angularMoment.filter:amUtcOffset
461 * @module angularMoment
462 *
463 * @description
464 * Adds a UTC offset to the given timezone object. The offset can be a number of minutes, or a string such as
465 * '+0300', '-0300' or 'Z'.
466 */
467 .filter('amUtcOffset', ['amMoment', function (amMoment) {
468 function amUtcOffset(value, offset) {
469 return amMoment.preprocessDate(value).utcOffset(offset);
470 }
471
472 return amUtcOffset;
473 }])
474
475 /**
476 * @ngdoc filter
477 * @name angularMoment.filter:amLocal
478 * @module angularMoment
479 */
480 .filter('amLocal', ['moment', function (moment) {
481 return function (value) {
482 return moment.isMoment(value) ? value.local() : null;
483 };
484 }])
485
486 /**
487 * @ngdoc filter
488 * @name angularMoment.filter:amTimezone
489 * @module angularMoment
490 *
491 * @description
492 * Apply a timezone onto a given moment object, e.g. 'America/Phoenix').
493 *
494 * You need to include moment-timezone.js for timezone support.
495 */
496 .filter('amTimezone', ['amMoment', 'angularMomentConfig', '$log', function (amMoment, angularMomentConfig, $log) {
497 function amTimezone(value, timezone) {
498 var aMoment = amMoment.preprocessDate(value);
499
500 if (!timezone) {
501 return aMoment;
502 }
503
504 if (aMoment.tz) {
505 return aMoment.tz(timezone);
506 } else {
507 $log.warn('angular-moment: named timezone specified but moment.tz() is undefined. Did you forget to include moment-timezone.js ?');
508 return aMoment;
509 }
510 }
511
512 return amTimezone;
513 }])
514
515 /**
516 * @ngdoc filter
517 * @name angularMoment.filter:amCalendar
518 * @module angularMoment
519 */
520 .filter('amCalendar', ['moment', 'amMoment', 'angularMomentConfig', function (moment, amMoment, angularMomentConfig) {
521 function amCalendarFilter(value, referenceTime, formats) {
522 if (isUndefinedOrNull(value)) {
523 return '';
524 }
525
526 var date = amMoment.preprocessDate(value);
527 return date.isValid() ? date.calendar(referenceTime, formats) : '';
528 }
529
530 // Since AngularJS 1.3, filters have to explicitly define being stateful
531 // (this is no longer the default).
532 amCalendarFilter.$stateful = angularMomentConfig.statefulFilters;
533
534 return amCalendarFilter;
535 }])
536
537 /**
538 * @ngdoc filter
539 * @name angularMoment.filter:amDifference
540 * @module angularMoment
541 */
542 .filter('amDifference', ['moment', 'amMoment', 'angularMomentConfig', function (moment, amMoment, angularMomentConfig) {
543 function amDifferenceFilter(value, otherValue, unit, usePrecision) {
544 if (isUndefinedOrNull(value)) {
545 return '';
546 }
547
548 var date = amMoment.preprocessDate(value);
549 var date2 = !isUndefinedOrNull(otherValue) ? amMoment.preprocessDate(otherValue) : moment();
550
551 if (!date.isValid() || !date2.isValid()) {
552 return '';
553 }
554
555 return date.diff(date2, unit, usePrecision);
556 }
557
558 amDifferenceFilter.$stateful = angularMomentConfig.statefulFilters;
559
560 return amDifferenceFilter;
561 }])
562
563 /**
564 * @ngdoc filter
565 * @name angularMoment.filter:amDateFormat
566 * @module angularMoment
567 * @function
568 */
569 .filter('amDateFormat', ['moment', 'amMoment', 'angularMomentConfig', function (moment, amMoment, angularMomentConfig) {
570 function amDateFormatFilter(value, format) {
571 if (isUndefinedOrNull(value)) {
572 return '';
573 }
574
575 var date = amMoment.preprocessDate(value);
576 if (!date.isValid()) {
577 return '';
578 }
579
580 return date.format(format);
581 }
582
583 amDateFormatFilter.$stateful = angularMomentConfig.statefulFilters;
584
585 return amDateFormatFilter;
586 }])
587
588 /**
589 * @ngdoc filter
590 * @name angularMoment.filter:amDurationFormat
591 * @module angularMoment
592 * @function
593 */
594 .filter('amDurationFormat', ['moment', 'angularMomentConfig', function (moment, angularMomentConfig) {
595 function amDurationFormatFilter(value, format, suffix) {
596 if (isUndefinedOrNull(value)) {
597 return '';
598 }
599
600 return moment.duration(value, format).humanize(suffix);
601 }
602
603 amDurationFormatFilter.$stateful = angularMomentConfig.statefulFilters;
604
605 return amDurationFormatFilter;
606 }])
607
608 /**
609 * @ngdoc filter
610 * @name angularMoment.filter:amTimeAgo
611 * @module angularMoment
612 * @function
613 */
614 .filter('amTimeAgo', ['moment', 'amMoment', 'angularMomentConfig', function (moment, amMoment, angularMomentConfig) {
615 function amTimeAgoFilter(value, suffix, from) {
616 var date, dateFrom;
617
618 if (isUndefinedOrNull(value)) {
619 return '';
620 }
621
622 value = amMoment.preprocessDate(value);
623 date = moment(value);
624 if (!date.isValid()) {
625 return '';
626 }
627
628 dateFrom = moment(from);
629 if (!isUndefinedOrNull(from) && dateFrom.isValid()) {
630 return date.from(dateFrom, suffix);
631 }
632
633 return date.fromNow(suffix);
634 }
635
636 amTimeAgoFilter.$stateful = angularMomentConfig.statefulFilters;
637
638 return amTimeAgoFilter;
639 }])
640
641 /**
642 * @ngdoc filter
643 * @name angularMoment.filter:amSubtract
644 * @module angularMoment
645 * @function
646 */
647 .filter('amSubtract', ['moment', 'angularMomentConfig', function (moment, angularMomentConfig) {
648 function amSubtractFilter(value, amount, type) {
649
650 if (isUndefinedOrNull(value)) {
651 return '';
652 }
653
654 return moment(value).subtract(parseInt(amount, 10), type);
655 }
656
657 amSubtractFilter.$stateful = angularMomentConfig.statefulFilters;
658
659 return amSubtractFilter;
660 }])
661
662 /**
663 * @ngdoc filter
664 * @name angularMoment.filter:amAdd
665 * @module angularMoment
666 * @function
667 */
668 .filter('amAdd', ['moment', 'angularMomentConfig', function (moment, angularMomentConfig) {
669 function amAddFilter(value, amount, type) {
670
671 if (isUndefinedOrNull(value)) {
672 return '';
673 }
674
675 return moment(value).add(parseInt(amount, 10), type);
676 }
677
678 amAddFilter.$stateful = angularMomentConfig.statefulFilters;
679
680 return amAddFilter;
681 }])
682
683 /**
684 * @ngdoc filter
685 * @name angularMoment.filter:amStartOf
686 * @module angularMoment
687 * @function
688 */
689 .filter('amStartOf', ['moment', 'angularMomentConfig', function (moment, angularMomentConfig) {
690 function amStartOfFilter(value, type) {
691
692 if (isUndefinedOrNull(value)) {
693 return '';
694 }
695
696 return moment(value).startOf(type);
697 }
698
699 amStartOfFilter.$stateful = angularMomentConfig.statefulFilters;
700
701 return amStartOfFilter;
702 }])
703
704 /**
705 * @ngdoc filter
706 * @name angularMoment.filter:amEndOf
707 * @module angularMoment
708 * @function
709 */
710 .filter('amEndOf', ['moment', 'angularMomentConfig', function (moment, angularMomentConfig) {
711 function amEndOfFilter(value, type) {
712
713 if (isUndefinedOrNull(value)) {
714 return '';
715 }
716
717 return moment(value).endOf(type);
718 }
719
720 amEndOfFilter.$stateful = angularMomentConfig.statefulFilters;
721
722 return amEndOfFilter;
723 }]);
724
725 return 'angularMoment';
726 }
727
728 var isElectron = window && window.process && window.process.type;
729 if (typeof define === 'function' && define.amd) {
730 define(['angular', 'moment'], angularMoment);
731 } else if (typeof module !== 'undefined' && module && module.exports && (typeof require === 'function') && !isElectron) {
732 module.exports = angularMoment(require('angular'), require('moment'));
733 } else {
734 angularMoment(angular, (typeof global !== 'undefined' && typeof global.moment !== 'undefined' ? global : window).moment);
735 }
736 })();
+0
-2
faraday/server/www/script/angular-moment.min.js less more
0 "format amd";!function(){"use strict";function a(a){return angular.isUndefined(a)||null===a}function b(){try{return require("moment")}catch(a){throw new Error("Please install moment via npm. Please reference to: https://github.com/urish/angular-moment")}}function c(c,d){if("undefined"==typeof d){if("function"!=typeof require)throw new Error("Moment cannot be found by angular-moment! Please reference to: https://github.com/urish/angular-moment");d=b()}return c.module("angularMoment",[]).constant("angularMomentConfig",{preprocess:null,timezone:null,format:null,statefulFilters:!0}).constant("moment",d).constant("amTimeAgoConfig",{withoutSuffix:!1,serverTime:null,titleFormat:null,fullDateThreshold:null,fullDateFormat:null,fullDateThresholdUnit:"day"}).directive("amTimeAgo",["$window","moment","amMoment","amTimeAgoConfig",function(b,d,e,f){return function(g,h,i){function j(){var a;if(p)a=p;else if(f.serverTime){var b=(new Date).getTime(),c=b-w+f.serverTime;a=d(c)}else a=d();return a}function k(){q&&(b.clearTimeout(q),q=null)}function l(a){var c=j().diff(a,v),d=t&&c>=t;if(d?h.text(a.format(u)):h.text(a.from(j(),r)),s&&z&&h.attr("title",a.format(s)),!d){var e=Math.abs(j().diff(a,"minute")),f=3600;e<1?f=1:e<60?f=30:e<180&&(f=300),q=b.setTimeout(function(){l(a)},1e3*f)}}function m(a){y&&h.attr("datetime",a)}function n(){if(k(),o){var a=e.preprocessDate(o);l(a),m(a.toISOString())}}var o,p,q=null,r=f.withoutSuffix,s=f.titleFormat,t=f.fullDateThreshold,u=f.fullDateFormat,v=f.fullDateThresholdUnit,w=(new Date).getTime(),x=i.amTimeAgo,y="TIME"===h[0].nodeName.toUpperCase(),z=!h.attr("title");g.$watch(x,function(b){return a(b)||""===b?(k(),void(o&&(h.text(""),m(""),o=null))):(o=b,void n())}),c.isDefined(i.amFrom)&&g.$watch(i.amFrom,function(b){p=a(b)||""===b?null:d(b),n()}),c.isDefined(i.amWithoutSuffix)&&g.$watch(i.amWithoutSuffix,function(a){"boolean"==typeof a?(r=a,n()):r=f.withoutSuffix}),i.$observe("amFullDateThreshold",function(a){t=a,n()}),i.$observe("amFullDateFormat",function(a){u=a,n()}),i.$observe("amFullDateThresholdUnit",function(a){v=a,n()}),g.$on("$destroy",function(){k()}),g.$on("amMoment:localeChanged",function(){n()})}}]).service("amMoment",["moment","$rootScope","$log","angularMomentConfig",function(a,b,d,e){var f=null;this.changeLocale=function(d,e){var f=a.locale(d,e);return c.isDefined(d)&&b.$broadcast("amMoment:localeChanged"),f},this.changeTimezone=function(c){a.tz&&a.tz.setDefault?(a.tz.setDefault(c),b.$broadcast("amMoment:timezoneChanged")):d.warn("angular-moment: changeTimezone() works only with moment-timezone.js v0.3.0 or greater."),e.timezone=c,f=c},this.preprocessDate=function(b){return f!==e.timezone&&this.changeTimezone(e.timezone),e.preprocess?e.preprocess(b):a(!isNaN(parseFloat(b))&&isFinite(b)?parseInt(b,10):b)}}]).filter("amParse",["moment",function(a){return function(b,c){return a(b,c)}}]).filter("amFromUnix",["moment",function(a){return function(b){return a.unix(b)}}]).filter("amUtc",["moment",function(a){return function(b){return a.utc(b)}}]).filter("amUtcOffset",["amMoment",function(a){function b(b,c){return a.preprocessDate(b).utcOffset(c)}return b}]).filter("amLocal",["moment",function(a){return function(b){return a.isMoment(b)?b.local():null}}]).filter("amTimezone",["amMoment","angularMomentConfig","$log",function(a,b,c){function d(b,d){var e=a.preprocessDate(b);return d?e.tz?e.tz(d):(c.warn("angular-moment: named timezone specified but moment.tz() is undefined. Did you forget to include moment-timezone.js ?"),e):e}return d}]).filter("amCalendar",["moment","amMoment","angularMomentConfig",function(b,c,d){function e(b,d,e){if(a(b))return"";var f=c.preprocessDate(b);return f.isValid()?f.calendar(d,e):""}return e.$stateful=d.statefulFilters,e}]).filter("amDifference",["moment","amMoment","angularMomentConfig",function(b,c,d){function e(d,e,f,g){if(a(d))return"";var h=c.preprocessDate(d),i=a(e)?b():c.preprocessDate(e);return h.isValid()&&i.isValid()?h.diff(i,f,g):""}return e.$stateful=d.statefulFilters,e}]).filter("amDateFormat",["moment","amMoment","angularMomentConfig",function(b,c,d){function e(b,d){if(a(b))return"";var e=c.preprocessDate(b);return e.isValid()?e.format(d):""}return e.$stateful=d.statefulFilters,e}]).filter("amDurationFormat",["moment","angularMomentConfig",function(b,c){function d(c,d,e){return a(c)?"":b.duration(c,d).humanize(e)}return d.$stateful=c.statefulFilters,d}]).filter("amTimeAgo",["moment","amMoment","angularMomentConfig",function(b,c,d){function e(d,e,f){var g,h;return a(d)?"":(d=c.preprocessDate(d),g=b(d),g.isValid()?(h=b(f),!a(f)&&h.isValid()?g.from(h,e):g.fromNow(e)):"")}return e.$stateful=d.statefulFilters,e}]).filter("amSubtract",["moment","angularMomentConfig",function(b,c){function d(c,d,e){return a(c)?"":b(c).subtract(parseInt(d,10),e)}return d.$stateful=c.statefulFilters,d}]).filter("amAdd",["moment","angularMomentConfig",function(b,c){function d(c,d,e){return a(c)?"":b(c).add(parseInt(d,10),e)}return d.$stateful=c.statefulFilters,d}]).filter("amStartOf",["moment","angularMomentConfig",function(b,c){function d(c,d){return a(c)?"":b(c).startOf(d)}return d.$stateful=c.statefulFilters,d}]).filter("amEndOf",["moment","angularMomentConfig",function(b,c){function d(c,d){return a(c)?"":b(c).endOf(d)}return d.$stateful=c.statefulFilters,d}]),"angularMoment"}var d=window&&window.process&&window.process.type;"function"==typeof define&&define.amd?define(["angular","moment"],c):"undefined"!=typeof module&&module&&module.exports&&"function"==typeof require&&!d?module.exports=c(require("angular"),require("moment")):c(angular,("undefined"!=typeof global?global:window).moment)}();
1 //# sourceMappingURL=angular-moment.min.js.map
+0
-992
faraday/server/www/script/angular-route.js less more
0 /**
1 * @license AngularJS v1.4.3
2 * (c) 2010-2015 Google, Inc. http://angularjs.org
3 * License: MIT
4 */
5 (function(window, angular, undefined) {'use strict';
6
7 /**
8 * @ngdoc module
9 * @name ngRoute
10 * @description
11 *
12 * # ngRoute
13 *
14 * The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
15 *
16 * ## Example
17 * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
18 *
19 *
20 * <div doc-module-components="ngRoute"></div>
21 */
22 /* global -ngRouteModule */
23 var ngRouteModule = angular.module('ngRoute', ['ng']).
24 provider('$route', $RouteProvider),
25 $routeMinErr = angular.$$minErr('ngRoute');
26
27 /**
28 * @ngdoc provider
29 * @name $routeProvider
30 *
31 * @description
32 *
33 * Used for configuring routes.
34 *
35 * ## Example
36 * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
37 *
38 * ## Dependencies
39 * Requires the {@link ngRoute `ngRoute`} module to be installed.
40 */
41 function $RouteProvider() {
42 function inherit(parent, extra) {
43 return angular.extend(Object.create(parent), extra);
44 }
45
46 var routes = {};
47
48 /**
49 * @ngdoc method
50 * @name $routeProvider#when
51 *
52 * @param {string} path Route path (matched against `$location.path`). If `$location.path`
53 * contains redundant trailing slash or is missing one, the route will still match and the
54 * `$location.path` will be updated to add or drop the trailing slash to exactly match the
55 * route definition.
56 *
57 * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
58 * to the next slash are matched and stored in `$routeParams` under the given `name`
59 * when the route matches.
60 * * `path` can contain named groups starting with a colon and ending with a star:
61 * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
62 * when the route matches.
63 * * `path` can contain optional named groups with a question mark: e.g.`:name?`.
64 *
65 * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
66 * `/color/brown/largecode/code/with/slashes/edit` and extract:
67 *
68 * * `color: brown`
69 * * `largecode: code/with/slashes`.
70 *
71 *
72 * @param {Object} route Mapping information to be assigned to `$route.current` on route
73 * match.
74 *
75 * Object properties:
76 *
77 * - `controller` – `{(string|function()=}` – Controller fn that should be associated with
78 * newly created scope or the name of a {@link angular.Module#controller registered
79 * controller} if passed as a string.
80 * - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
81 * If present, the controller will be published to scope under the `controllerAs` name.
82 * - `template` – `{string=|function()=}` – html template as a string or a function that
83 * returns an html template as a string which should be used by {@link
84 * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
85 * This property takes precedence over `templateUrl`.
86 *
87 * If `template` is a function, it will be called with the following parameters:
88 *
89 * - `{Array.<Object>}` - route parameters extracted from the current
90 * `$location.path()` by applying the current route
91 *
92 * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
93 * template that should be used by {@link ngRoute.directive:ngView ngView}.
94 *
95 * If `templateUrl` is a function, it will be called with the following parameters:
96 *
97 * - `{Array.<Object>}` - route parameters extracted from the current
98 * `$location.path()` by applying the current route
99 *
100 * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
101 * be injected into the controller. If any of these dependencies are promises, the router
102 * will wait for them all to be resolved or one to be rejected before the controller is
103 * instantiated.
104 * If all the promises are resolved successfully, the values of the resolved promises are
105 * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
106 * fired. If any of the promises are rejected the
107 * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
108 * is:
109 *
110 * - `key` – `{string}`: a name of a dependency to be injected into the controller.
111 * - `factory` - `{string|function}`: If `string` then it is an alias for a service.
112 * Otherwise if function, then it is {@link auto.$injector#invoke injected}
113 * and the return value is treated as the dependency. If the result is a promise, it is
114 * resolved before its value is injected into the controller. Be aware that
115 * `ngRoute.$routeParams` will still refer to the previous route within these resolve
116 * functions. Use `$route.current.params` to access the new route parameters, instead.
117 *
118 * - `redirectTo` – {(string|function())=} – value to update
119 * {@link ng.$location $location} path with and trigger route redirection.
120 *
121 * If `redirectTo` is a function, it will be called with the following parameters:
122 *
123 * - `{Object.<string>}` - route parameters extracted from the current
124 * `$location.path()` by applying the current route templateUrl.
125 * - `{string}` - current `$location.path()`
126 * - `{Object}` - current `$location.search()`
127 *
128 * The custom `redirectTo` function is expected to return a string which will be used
129 * to update `$location.path()` and `$location.search()`.
130 *
131 * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
132 * or `$location.hash()` changes.
133 *
134 * If the option is set to `false` and url in the browser changes, then
135 * `$routeUpdate` event is broadcasted on the root scope.
136 *
137 * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
138 *
139 * If the option is set to `true`, then the particular route can be matched without being
140 * case sensitive
141 *
142 * @returns {Object} self
143 *
144 * @description
145 * Adds a new route definition to the `$route` service.
146 */
147 this.when = function(path, route) {
148 //copy original route object to preserve params inherited from proto chain
149 var routeCopy = angular.copy(route);
150 if (angular.isUndefined(routeCopy.reloadOnSearch)) {
151 routeCopy.reloadOnSearch = true;
152 }
153 if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {
154 routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;
155 }
156 routes[path] = angular.extend(
157 routeCopy,
158 path && pathRegExp(path, routeCopy)
159 );
160
161 // create redirection for trailing slashes
162 if (path) {
163 var redirectPath = (path[path.length - 1] == '/')
164 ? path.substr(0, path.length - 1)
165 : path + '/';
166
167 routes[redirectPath] = angular.extend(
168 {redirectTo: path},
169 pathRegExp(redirectPath, routeCopy)
170 );
171 }
172
173 return this;
174 };
175
176 /**
177 * @ngdoc property
178 * @name $routeProvider#caseInsensitiveMatch
179 * @description
180 *
181 * A boolean property indicating if routes defined
182 * using this provider should be matched using a case insensitive
183 * algorithm. Defaults to `false`.
184 */
185 this.caseInsensitiveMatch = false;
186
187 /**
188 * @param path {string} path
189 * @param opts {Object} options
190 * @return {?Object}
191 *
192 * @description
193 * Normalizes the given path, returning a regular expression
194 * and the original path.
195 *
196 * Inspired by pathRexp in visionmedia/express/lib/utils.js.
197 */
198 function pathRegExp(path, opts) {
199 var insensitive = opts.caseInsensitiveMatch,
200 ret = {
201 originalPath: path,
202 regexp: path
203 },
204 keys = ret.keys = [];
205
206 path = path
207 .replace(/([().])/g, '\\$1')
208 .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
209 var optional = option === '?' ? option : null;
210 var star = option === '*' ? option : null;
211 keys.push({ name: key, optional: !!optional });
212 slash = slash || '';
213 return ''
214 + (optional ? '' : slash)
215 + '(?:'
216 + (optional ? slash : '')
217 + (star && '(.+?)' || '([^/]+)')
218 + (optional || '')
219 + ')'
220 + (optional || '');
221 })
222 .replace(/([\/$\*])/g, '\\$1');
223
224 ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
225 return ret;
226 }
227
228 /**
229 * @ngdoc method
230 * @name $routeProvider#otherwise
231 *
232 * @description
233 * Sets route definition that will be used on route change when no other route definition
234 * is matched.
235 *
236 * @param {Object|string} params Mapping information to be assigned to `$route.current`.
237 * If called with a string, the value maps to `redirectTo`.
238 * @returns {Object} self
239 */
240 this.otherwise = function(params) {
241 if (typeof params === 'string') {
242 params = {redirectTo: params};
243 }
244 this.when(null, params);
245 return this;
246 };
247
248
249 this.$get = ['$rootScope',
250 '$location',
251 '$routeParams',
252 '$q',
253 '$injector',
254 '$templateRequest',
255 '$sce',
256 function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {
257
258 /**
259 * @ngdoc service
260 * @name $route
261 * @requires $location
262 * @requires $routeParams
263 *
264 * @property {Object} current Reference to the current route definition.
265 * The route definition contains:
266 *
267 * - `controller`: The controller constructor as define in route definition.
268 * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
269 * controller instantiation. The `locals` contain
270 * the resolved values of the `resolve` map. Additionally the `locals` also contain:
271 *
272 * - `$scope` - The current route scope.
273 * - `$template` - The current route template HTML.
274 *
275 * @property {Object} routes Object with all route configuration Objects as its properties.
276 *
277 * @description
278 * `$route` is used for deep-linking URLs to controllers and views (HTML partials).
279 * It watches `$location.url()` and tries to map the path to an existing route definition.
280 *
281 * Requires the {@link ngRoute `ngRoute`} module to be installed.
282 *
283 * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
284 *
285 * The `$route` service is typically used in conjunction with the
286 * {@link ngRoute.directive:ngView `ngView`} directive and the
287 * {@link ngRoute.$routeParams `$routeParams`} service.
288 *
289 * @example
290 * This example shows how changing the URL hash causes the `$route` to match a route against the
291 * URL, and the `ngView` pulls in the partial.
292 *
293 * <example name="$route-service" module="ngRouteExample"
294 * deps="angular-route.js" fixBase="true">
295 * <file name="index.html">
296 * <div ng-controller="MainController">
297 * Choose:
298 * <a href="Book/Moby">Moby</a> |
299 * <a href="Book/Moby/ch/1">Moby: Ch1</a> |
300 * <a href="Book/Gatsby">Gatsby</a> |
301 * <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
302 * <a href="Book/Scarlet">Scarlet Letter</a><br/>
303 *
304 * <div ng-view></div>
305 *
306 * <hr />
307 *
308 * <pre>$location.path() = {{$location.path()}}</pre>
309 * <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
310 * <pre>$route.current.params = {{$route.current.params}}</pre>
311 * <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
312 * <pre>$routeParams = {{$routeParams}}</pre>
313 * </div>
314 * </file>
315 *
316 * <file name="book.html">
317 * controller: {{name}}<br />
318 * Book Id: {{params.bookId}}<br />
319 * </file>
320 *
321 * <file name="chapter.html">
322 * controller: {{name}}<br />
323 * Book Id: {{params.bookId}}<br />
324 * Chapter Id: {{params.chapterId}}
325 * </file>
326 *
327 * <file name="script.js">
328 * angular.module('ngRouteExample', ['ngRoute'])
329 *
330 * .controller('MainController', function($scope, $route, $routeParams, $location) {
331 * $scope.$route = $route;
332 * $scope.$location = $location;
333 * $scope.$routeParams = $routeParams;
334 * })
335 *
336 * .controller('BookController', function($scope, $routeParams) {
337 * $scope.name = "BookController";
338 * $scope.params = $routeParams;
339 * })
340 *
341 * .controller('ChapterController', function($scope, $routeParams) {
342 * $scope.name = "ChapterController";
343 * $scope.params = $routeParams;
344 * })
345 *
346 * .config(function($routeProvider, $locationProvider) {
347 * $routeProvider
348 * .when('/Book/:bookId', {
349 * templateUrl: 'book.html',
350 * controller: 'BookController',
351 * resolve: {
352 * // I will cause a 1 second delay
353 * delay: function($q, $timeout) {
354 * var delay = $q.defer();
355 * $timeout(delay.resolve, 1000);
356 * return delay.promise;
357 * }
358 * }
359 * })
360 * .when('/Book/:bookId/ch/:chapterId', {
361 * templateUrl: 'chapter.html',
362 * controller: 'ChapterController'
363 * });
364 *
365 * // configure html5 to get links working on jsfiddle
366 * $locationProvider.html5Mode(true);
367 * });
368 *
369 * </file>
370 *
371 * <file name="protractor.js" type="protractor">
372 * it('should load and compile correct template', function() {
373 * element(by.linkText('Moby: Ch1')).click();
374 * var content = element(by.css('[ng-view]')).getText();
375 * expect(content).toMatch(/controller\: ChapterController/);
376 * expect(content).toMatch(/Book Id\: Moby/);
377 * expect(content).toMatch(/Chapter Id\: 1/);
378 *
379 * element(by.partialLinkText('Scarlet')).click();
380 *
381 * content = element(by.css('[ng-view]')).getText();
382 * expect(content).toMatch(/controller\: BookController/);
383 * expect(content).toMatch(/Book Id\: Scarlet/);
384 * });
385 * </file>
386 * </example>
387 */
388
389 /**
390 * @ngdoc event
391 * @name $route#$routeChangeStart
392 * @eventType broadcast on root scope
393 * @description
394 * Broadcasted before a route change. At this point the route services starts
395 * resolving all of the dependencies needed for the route change to occur.
396 * Typically this involves fetching the view template as well as any dependencies
397 * defined in `resolve` route property. Once all of the dependencies are resolved
398 * `$routeChangeSuccess` is fired.
399 *
400 * The route change (and the `$location` change that triggered it) can be prevented
401 * by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}
402 * for more details about event object.
403 *
404 * @param {Object} angularEvent Synthetic event object.
405 * @param {Route} next Future route information.
406 * @param {Route} current Current route information.
407 */
408
409 /**
410 * @ngdoc event
411 * @name $route#$routeChangeSuccess
412 * @eventType broadcast on root scope
413 * @description
414 * Broadcasted after a route change has happened successfully.
415 * The `resolve` dependencies are now available in the `current.locals` property.
416 *
417 * {@link ngRoute.directive:ngView ngView} listens for the directive
418 * to instantiate the controller and render the view.
419 *
420 * @param {Object} angularEvent Synthetic event object.
421 * @param {Route} current Current route information.
422 * @param {Route|Undefined} previous Previous route information, or undefined if current is
423 * first route entered.
424 */
425
426 /**
427 * @ngdoc event
428 * @name $route#$routeChangeError
429 * @eventType broadcast on root scope
430 * @description
431 * Broadcasted if any of the resolve promises are rejected.
432 *
433 * @param {Object} angularEvent Synthetic event object
434 * @param {Route} current Current route information.
435 * @param {Route} previous Previous route information.
436 * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
437 */
438
439 /**
440 * @ngdoc event
441 * @name $route#$routeUpdate
442 * @eventType broadcast on root scope
443 * @description
444 * The `reloadOnSearch` property has been set to false, and we are reusing the same
445 * instance of the Controller.
446 *
447 * @param {Object} angularEvent Synthetic event object
448 * @param {Route} current Current/previous route information.
449 */
450
451 var forceReload = false,
452 preparedRoute,
453 preparedRouteIsUpdateOnly,
454 $route = {
455 routes: routes,
456
457 /**
458 * @ngdoc method
459 * @name $route#reload
460 *
461 * @description
462 * Causes `$route` service to reload the current route even if
463 * {@link ng.$location $location} hasn't changed.
464 *
465 * As a result of that, {@link ngRoute.directive:ngView ngView}
466 * creates new scope and reinstantiates the controller.
467 */
468 reload: function() {
469 forceReload = true;
470 $rootScope.$evalAsync(function() {
471 // Don't support cancellation of a reload for now...
472 prepareRoute();
473 commitRoute();
474 });
475 },
476
477 /**
478 * @ngdoc method
479 * @name $route#updateParams
480 *
481 * @description
482 * Causes `$route` service to update the current URL, replacing
483 * current route parameters with those specified in `newParams`.
484 * Provided property names that match the route's path segment
485 * definitions will be interpolated into the location's path, while
486 * remaining properties will be treated as query params.
487 *
488 * @param {!Object<string, string>} newParams mapping of URL parameter names to values
489 */
490 updateParams: function(newParams) {
491 if (this.current && this.current.$$route) {
492 newParams = angular.extend({}, this.current.params, newParams);
493 $location.path(interpolate(this.current.$$route.originalPath, newParams));
494 // interpolate modifies newParams, only query params are left
495 $location.search(newParams);
496 } else {
497 throw $routeMinErr('norout', 'Tried updating route when with no current route');
498 }
499 }
500 };
501
502 $rootScope.$on('$locationChangeStart', prepareRoute);
503 $rootScope.$on('$locationChangeSuccess', commitRoute);
504
505 return $route;
506
507 /////////////////////////////////////////////////////
508
509 /**
510 * @param on {string} current url
511 * @param route {Object} route regexp to match the url against
512 * @return {?Object}
513 *
514 * @description
515 * Check if the route matches the current url.
516 *
517 * Inspired by match in
518 * visionmedia/express/lib/router/router.js.
519 */
520 function switchRouteMatcher(on, route) {
521 var keys = route.keys,
522 params = {};
523
524 if (!route.regexp) return null;
525
526 var m = route.regexp.exec(on);
527 if (!m) return null;
528
529 for (var i = 1, len = m.length; i < len; ++i) {
530 var key = keys[i - 1];
531
532 var val = m[i];
533
534 if (key && val) {
535 params[key.name] = val;
536 }
537 }
538 return params;
539 }
540
541 function prepareRoute($locationEvent) {
542 var lastRoute = $route.current;
543
544 preparedRoute = parseRoute();
545 preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route
546 && angular.equals(preparedRoute.pathParams, lastRoute.pathParams)
547 && !preparedRoute.reloadOnSearch && !forceReload;
548
549 if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {
550 if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {
551 if ($locationEvent) {
552 $locationEvent.preventDefault();
553 }
554 }
555 }
556 }
557
558 function commitRoute() {
559 var lastRoute = $route.current;
560 var nextRoute = preparedRoute;
561
562 if (preparedRouteIsUpdateOnly) {
563 lastRoute.params = nextRoute.params;
564 angular.copy(lastRoute.params, $routeParams);
565 $rootScope.$broadcast('$routeUpdate', lastRoute);
566 } else if (nextRoute || lastRoute) {
567 forceReload = false;
568 $route.current = nextRoute;
569 if (nextRoute) {
570 if (nextRoute.redirectTo) {
571 if (angular.isString(nextRoute.redirectTo)) {
572 $location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)
573 .replace();
574 } else {
575 $location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))
576 .replace();
577 }
578 }
579 }
580
581 $q.when(nextRoute).
582 then(function() {
583 if (nextRoute) {
584 var locals = angular.extend({}, nextRoute.resolve),
585 template, templateUrl;
586
587 angular.forEach(locals, function(value, key) {
588 locals[key] = angular.isString(value) ?
589 $injector.get(value) : $injector.invoke(value, null, null, key);
590 });
591
592 if (angular.isDefined(template = nextRoute.template)) {
593 if (angular.isFunction(template)) {
594 template = template(nextRoute.params);
595 }
596 } else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {
597 if (angular.isFunction(templateUrl)) {
598 templateUrl = templateUrl(nextRoute.params);
599 }
600 if (angular.isDefined(templateUrl)) {
601 nextRoute.loadedTemplateUrl = $sce.valueOf(templateUrl);
602 template = $templateRequest(templateUrl);
603 }
604 }
605 if (angular.isDefined(template)) {
606 locals['$template'] = template;
607 }
608 return $q.all(locals);
609 }
610 }).
611 then(function(locals) {
612 // after route change
613 if (nextRoute == $route.current) {
614 if (nextRoute) {
615 nextRoute.locals = locals;
616 angular.copy(nextRoute.params, $routeParams);
617 }
618 $rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);
619 }
620 }, function(error) {
621 if (nextRoute == $route.current) {
622 $rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);
623 }
624 });
625 }
626 }
627
628
629 /**
630 * @returns {Object} the current active route, by matching it against the URL
631 */
632 function parseRoute() {
633 // Match a route
634 var params, match;
635 angular.forEach(routes, function(route, path) {
636 if (!match && (params = switchRouteMatcher($location.path(), route))) {
637 match = inherit(route, {
638 params: angular.extend({}, $location.search(), params),
639 pathParams: params});
640 match.$$route = route;
641 }
642 });
643 // No route matched; fallback to "otherwise" route
644 return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
645 }
646
647 /**
648 * @returns {string} interpolation of the redirect path with the parameters
649 */
650 function interpolate(string, params) {
651 var result = [];
652 angular.forEach((string || '').split(':'), function(segment, i) {
653 if (i === 0) {
654 result.push(segment);
655 } else {
656 var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/);
657 var key = segmentMatch[1];
658 result.push(params[key]);
659 result.push(segmentMatch[2] || '');
660 delete params[key];
661 }
662 });
663 return result.join('');
664 }
665 }];
666 }
667
668 ngRouteModule.provider('$routeParams', $RouteParamsProvider);
669
670
671 /**
672 * @ngdoc service
673 * @name $routeParams
674 * @requires $route
675 *
676 * @description
677 * The `$routeParams` service allows you to retrieve the current set of route parameters.
678 *
679 * Requires the {@link ngRoute `ngRoute`} module to be installed.
680 *
681 * The route parameters are a combination of {@link ng.$location `$location`}'s
682 * {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
683 * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
684 *
685 * In case of parameter name collision, `path` params take precedence over `search` params.
686 *
687 * The service guarantees that the identity of the `$routeParams` object will remain unchanged
688 * (but its properties will likely change) even when a route change occurs.
689 *
690 * Note that the `$routeParams` are only updated *after* a route change completes successfully.
691 * This means that you cannot rely on `$routeParams` being correct in route resolve functions.
692 * Instead you can use `$route.current.params` to access the new route's parameters.
693 *
694 * @example
695 * ```js
696 * // Given:
697 * // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
698 * // Route: /Chapter/:chapterId/Section/:sectionId
699 * //
700 * // Then
701 * $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
702 * ```
703 */
704 function $RouteParamsProvider() {
705 this.$get = function() { return {}; };
706 }
707
708 ngRouteModule.directive('ngView', ngViewFactory);
709 ngRouteModule.directive('ngView', ngViewFillContentFactory);
710
711
712 /**
713 * @ngdoc directive
714 * @name ngView
715 * @restrict ECA
716 *
717 * @description
718 * # Overview
719 * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
720 * including the rendered template of the current route into the main layout (`index.html`) file.
721 * Every time the current route changes, the included view changes with it according to the
722 * configuration of the `$route` service.
723 *
724 * Requires the {@link ngRoute `ngRoute`} module to be installed.
725 *
726 * @animations
727 * enter - animation is used to bring new content into the browser.
728 * leave - animation is used to animate existing content away.
729 *
730 * The enter and leave animation occur concurrently.
731 *
732 * @scope
733 * @priority 400
734 * @param {string=} onload Expression to evaluate whenever the view updates.
735 *
736 * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
737 * $anchorScroll} to scroll the viewport after the view is updated.
738 *
739 * - If the attribute is not set, disable scrolling.
740 * - If the attribute is set without value, enable scrolling.
741 * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
742 * as an expression yields a truthy value.
743 * @example
744 <example name="ngView-directive" module="ngViewExample"
745 deps="angular-route.js;angular-animate.js"
746 animations="true" fixBase="true">
747 <file name="index.html">
748 <div ng-controller="MainCtrl as main">
749 Choose:
750 <a href="Book/Moby">Moby</a> |
751 <a href="Book/Moby/ch/1">Moby: Ch1</a> |
752 <a href="Book/Gatsby">Gatsby</a> |
753 <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
754 <a href="Book/Scarlet">Scarlet Letter</a><br/>
755
756 <div class="view-animate-container">
757 <div ng-view class="view-animate"></div>
758 </div>
759 <hr />
760
761 <pre>$location.path() = {{main.$location.path()}}</pre>
762 <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
763 <pre>$route.current.params = {{main.$route.current.params}}</pre>
764 <pre>$routeParams = {{main.$routeParams}}</pre>
765 </div>
766 </file>
767
768 <file name="book.html">
769 <div>
770 controller: {{book.name}}<br />
771 Book Id: {{book.params.bookId}}<br />
772 </div>
773 </file>
774
775 <file name="chapter.html">
776 <div>
777 controller: {{chapter.name}}<br />
778 Book Id: {{chapter.params.bookId}}<br />
779 Chapter Id: {{chapter.params.chapterId}}
780 </div>
781 </file>
782
783 <file name="animations.css">
784 .view-animate-container {
785 position:relative;
786 height:100px!important;
787 background:white;
788 border:1px solid black;
789 height:40px;
790 overflow:hidden;
791 }
792
793 .view-animate {
794 padding:10px;
795 }
796
797 .view-animate.ng-enter, .view-animate.ng-leave {
798 -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
799 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
800
801 display:block;
802 width:100%;
803 border-left:1px solid black;
804
805 position:absolute;
806 top:0;
807 left:0;
808 right:0;
809 bottom:0;
810 padding:10px;
811 }
812
813 .view-animate.ng-enter {
814 left:100%;
815 }
816 .view-animate.ng-enter.ng-enter-active {
817 left:0;
818 }
819 .view-animate.ng-leave.ng-leave-active {
820 left:-100%;
821 }
822 </file>
823
824 <file name="script.js">
825 angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
826 .config(['$routeProvider', '$locationProvider',
827 function($routeProvider, $locationProvider) {
828 $routeProvider
829 .when('/Book/:bookId', {
830 templateUrl: 'book.html',
831 controller: 'BookCtrl',
832 controllerAs: 'book'
833 })
834 .when('/Book/:bookId/ch/:chapterId', {
835 templateUrl: 'chapter.html',
836 controller: 'ChapterCtrl',
837 controllerAs: 'chapter'
838 });
839
840 $locationProvider.html5Mode(true);
841 }])
842 .controller('MainCtrl', ['$route', '$routeParams', '$location',
843 function($route, $routeParams, $location) {
844 this.$route = $route;
845 this.$location = $location;
846 this.$routeParams = $routeParams;
847 }])
848 .controller('BookCtrl', ['$routeParams', function($routeParams) {
849 this.name = "BookCtrl";
850 this.params = $routeParams;
851 }])
852 .controller('ChapterCtrl', ['$routeParams', function($routeParams) {
853 this.name = "ChapterCtrl";
854 this.params = $routeParams;
855 }]);
856
857 </file>
858
859 <file name="protractor.js" type="protractor">
860 it('should load and compile correct template', function() {
861 element(by.linkText('Moby: Ch1')).click();
862 var content = element(by.css('[ng-view]')).getText();
863 expect(content).toMatch(/controller\: ChapterCtrl/);
864 expect(content).toMatch(/Book Id\: Moby/);
865 expect(content).toMatch(/Chapter Id\: 1/);
866
867 element(by.partialLinkText('Scarlet')).click();
868
869 content = element(by.css('[ng-view]')).getText();
870 expect(content).toMatch(/controller\: BookCtrl/);
871 expect(content).toMatch(/Book Id\: Scarlet/);
872 });
873 </file>
874 </example>
875 */
876
877
878 /**
879 * @ngdoc event
880 * @name ngView#$viewContentLoaded
881 * @eventType emit on the current ngView scope
882 * @description
883 * Emitted every time the ngView content is reloaded.
884 */
885 ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
886 function ngViewFactory($route, $anchorScroll, $animate) {
887 return {
888 restrict: 'ECA',
889 terminal: true,
890 priority: 400,
891 transclude: 'element',
892 link: function(scope, $element, attr, ctrl, $transclude) {
893 var currentScope,
894 currentElement,
895 previousLeaveAnimation,
896 autoScrollExp = attr.autoscroll,
897 onloadExp = attr.onload || '';
898
899 scope.$on('$routeChangeSuccess', update);
900 update();
901
902 function cleanupLastView() {
903 if (previousLeaveAnimation) {
904 $animate.cancel(previousLeaveAnimation);
905 previousLeaveAnimation = null;
906 }
907
908 if (currentScope) {
909 currentScope.$destroy();
910 currentScope = null;
911 }
912 if (currentElement) {
913 previousLeaveAnimation = $animate.leave(currentElement);
914 previousLeaveAnimation.then(function() {
915 previousLeaveAnimation = null;
916 });
917 currentElement = null;
918 }
919 }
920
921 function update() {
922 var locals = $route.current && $route.current.locals,
923 template = locals && locals.$template;
924
925 if (angular.isDefined(template)) {
926 var newScope = scope.$new();
927 var current = $route.current;
928
929 // Note: This will also link all children of ng-view that were contained in the original
930 // html. If that content contains controllers, ... they could pollute/change the scope.
931 // However, using ng-view on an element with additional content does not make sense...
932 // Note: We can't remove them in the cloneAttchFn of $transclude as that
933 // function is called before linking the content, which would apply child
934 // directives to non existing elements.
935 var clone = $transclude(newScope, function(clone) {
936 $animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {
937 if (angular.isDefined(autoScrollExp)
938 && (!autoScrollExp || scope.$eval(autoScrollExp))) {
939 $anchorScroll();
940 }
941 });
942 cleanupLastView();
943 });
944
945 currentElement = clone;
946 currentScope = current.scope = newScope;
947 currentScope.$emit('$viewContentLoaded');
948 currentScope.$eval(onloadExp);
949 } else {
950 cleanupLastView();
951 }
952 }
953 }
954 };
955 }
956
957 // This directive is called during the $transclude call of the first `ngView` directive.
958 // It will replace and compile the content of the element with the loaded template.
959 // We need this directive so that the element content is already filled when
960 // the link function of another directive on the same element as ngView
961 // is called.
962 ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
963 function ngViewFillContentFactory($compile, $controller, $route) {
964 return {
965 restrict: 'ECA',
966 priority: -400,
967 link: function(scope, $element) {
968 var current = $route.current,
969 locals = current.locals;
970
971 $element.html(locals.$template);
972
973 var link = $compile($element.contents());
974
975 if (current.controller) {
976 locals.$scope = scope;
977 var controller = $controller(current.controller, locals);
978 if (current.controllerAs) {
979 scope[current.controllerAs] = controller;
980 }
981 $element.data('$ngControllerController', controller);
982 $element.children().data('$ngControllerController', controller);
983 }
984
985 link(scope);
986 }
987 };
988 }
989
990
991 })(window, window.angular);
+0
-15
faraday/server/www/script/angular-route.min.js less more
0 /*
1 AngularJS v1.4.3
2 (c) 2010-2015 Google, Inc. http://angularjs.org
3 License: MIT
4 */
5 (function(p,c,C){'use strict';function v(r,h,g){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",link:function(a,f,b,d,y){function z(){k&&(g.cancel(k),k=null);l&&(l.$destroy(),l=null);m&&(k=g.leave(m),k.then(function(){k=null}),m=null)}function x(){var b=r.current&&r.current.locals;if(c.isDefined(b&&b.$template)){var b=a.$new(),d=r.current;m=y(b,function(b){g.enter(b,null,m||f).then(function(){!c.isDefined(t)||t&&!a.$eval(t)||h()});z()});l=d.scope=b;l.$emit("$viewContentLoaded");
6 l.$eval(w)}else z()}var l,m,k,t=b.autoscroll,w=b.onload||"";a.$on("$routeChangeSuccess",x);x()}}}function A(c,h,g){return{restrict:"ECA",priority:-400,link:function(a,f){var b=g.current,d=b.locals;f.html(d.$template);var y=c(f.contents());b.controller&&(d.$scope=a,d=h(b.controller,d),b.controllerAs&&(a[b.controllerAs]=d),f.data("$ngControllerController",d),f.children().data("$ngControllerController",d));y(a)}}}p=c.module("ngRoute",["ng"]).provider("$route",function(){function r(a,f){return c.extend(Object.create(a),
7 f)}function h(a,c){var b=c.caseInsensitiveMatch,d={originalPath:a,regexp:a},g=d.keys=[];a=a.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?\*])?/g,function(a,c,b,d){a="?"===d?d:null;d="*"===d?d:null;g.push({name:b,optional:!!a});c=c||"";return""+(a?"":c)+"(?:"+(a?c:"")+(d&&"(.+?)"||"([^/]+)")+(a||"")+")"+(a||"")}).replace(/([\/$\*])/g,"\\$1");d.regexp=new RegExp("^"+a+"$",b?"i":"");return d}var g={};this.when=function(a,f){var b=c.copy(f);c.isUndefined(b.reloadOnSearch)&&(b.reloadOnSearch=!0);
8 c.isUndefined(b.caseInsensitiveMatch)&&(b.caseInsensitiveMatch=this.caseInsensitiveMatch);g[a]=c.extend(b,a&&h(a,b));if(a){var d="/"==a[a.length-1]?a.substr(0,a.length-1):a+"/";g[d]=c.extend({redirectTo:a},h(d,b))}return this};this.caseInsensitiveMatch=!1;this.otherwise=function(a){"string"===typeof a&&(a={redirectTo:a});this.when(null,a);return this};this.$get=["$rootScope","$location","$routeParams","$q","$injector","$templateRequest","$sce",function(a,f,b,d,h,p,x){function l(b){var e=s.current;
9 (v=(n=k())&&e&&n.$$route===e.$$route&&c.equals(n.pathParams,e.pathParams)&&!n.reloadOnSearch&&!w)||!e&&!n||a.$broadcast("$routeChangeStart",n,e).defaultPrevented&&b&&b.preventDefault()}function m(){var u=s.current,e=n;if(v)u.params=e.params,c.copy(u.params,b),a.$broadcast("$routeUpdate",u);else if(e||u)w=!1,(s.current=e)&&e.redirectTo&&(c.isString(e.redirectTo)?f.path(t(e.redirectTo,e.params)).search(e.params).replace():f.url(e.redirectTo(e.pathParams,f.path(),f.search())).replace()),d.when(e).then(function(){if(e){var a=
10 c.extend({},e.resolve),b,f;c.forEach(a,function(b,e){a[e]=c.isString(b)?h.get(b):h.invoke(b,null,null,e)});c.isDefined(b=e.template)?c.isFunction(b)&&(b=b(e.params)):c.isDefined(f=e.templateUrl)&&(c.isFunction(f)&&(f=f(e.params)),c.isDefined(f)&&(e.loadedTemplateUrl=x.valueOf(f),b=p(f)));c.isDefined(b)&&(a.$template=b);return d.all(a)}}).then(function(f){e==s.current&&(e&&(e.locals=f,c.copy(e.params,b)),a.$broadcast("$routeChangeSuccess",e,u))},function(b){e==s.current&&a.$broadcast("$routeChangeError",
11 e,u,b)})}function k(){var a,b;c.forEach(g,function(d,g){var q;if(q=!b){var h=f.path();q=d.keys;var l={};if(d.regexp)if(h=d.regexp.exec(h)){for(var k=1,m=h.length;k<m;++k){var n=q[k-1],p=h[k];n&&p&&(l[n.name]=p)}q=l}else q=null;else q=null;q=a=q}q&&(b=r(d,{params:c.extend({},f.search(),a),pathParams:a}),b.$$route=d)});return b||g[null]&&r(g[null],{params:{},pathParams:{}})}function t(a,b){var d=[];c.forEach((a||"").split(":"),function(a,c){if(0===c)d.push(a);else{var f=a.match(/(\w+)(?:[?*])?(.*)/),
12 g=f[1];d.push(b[g]);d.push(f[2]||"");delete b[g]}});return d.join("")}var w=!1,n,v,s={routes:g,reload:function(){w=!0;a.$evalAsync(function(){l();m()})},updateParams:function(a){if(this.current&&this.current.$$route)a=c.extend({},this.current.params,a),f.path(t(this.current.$$route.originalPath,a)),f.search(a);else throw B("norout");}};a.$on("$locationChangeStart",l);a.$on("$locationChangeSuccess",m);return s}]});var B=c.$$minErr("ngRoute");p.provider("$routeParams",function(){this.$get=function(){return{}}});
13 p.directive("ngView",v);p.directive("ngView",A);v.$inject=["$route","$anchorScroll","$animate"];A.$inject=["$compile","$controller","$route"]})(window,window.angular);
14 //# sourceMappingURL=angular-route.min.js.map
+0
-563
faraday/server/www/script/angular-selection-model.js less more
0
1 /**
2 * The Selection Model module
3 *
4 * The ngRepeat companion. This module exists to give developers a lightweight
5 * option for easily managing selections in lists and tables. It also aims to
6 * play nicely with native angular features so you can leverage existing tools
7 * for filtering, sorting, animations, etc.
8 *
9 * @package selectionModel
10 */
11
12 angular.module('selectionModel', []);
13
14
15 /**
16 * Selection Model Ignore
17 *
18 * For clickable elements that don't directly interact with `selectionModel`.
19 *
20 * Useful for when you want to manually change the selection, or for things like
21 * "delete" buttons that belong under `ngRepeat` but shouldn't select an item
22 * when clicked.
23 *
24 * @package selectionModel
25 * @copyright 2014 Justin Russell, released under the MIT license
26 */
27
28 angular.module('selectionModel').directive('selectionModelIgnore', [
29 function() {
30 'use strict';
31 return {
32 restrict: 'A',
33 link: function(scope, element, attrs) {
34 element.on('click', function(event) {
35 event.selectionModelIgnore = true;
36
37 /**
38 * If jQuery is on the page `event` will actually be a jQuery Event
39 * and other handlers will only get to see a subset of the event
40 * properties that supported by all browsers. Our custom attribute
41 * will be dropped. We need to instead decorate the original event
42 * object.
43 *
44 * @see https://github.com/jtrussell/angular-selection-model/issues/27
45 */
46 if(event.originalEvent) {
47 event.originalEvent.selectionModelIgnore = true;
48 }
49 });
50 }
51 };
52 }
53 ]);
54
55
56 /**
57 * Selection Model - a selection aware companion for ngRepeat
58 *
59 * @package selectionModel
60 * @copyright 2014 Justin Russell, released under the MIT license
61 */
62
63 angular.module('selectionModel').directive('selectionModel', [
64 'selectionStack', 'uuidGen', 'selectionModelOptions',
65 function(selectionStack, uuidGen, selectionModelOptions) {
66 'use strict';
67 return {
68 restrict: 'A',
69 link: function(scope, element, attrs) {
70
71 /**
72 * Defaults from the options provider
73 *
74 * Use `selectionModelOptionsProvider` when configuring your module to
75 * set application wide defaults
76 */
77 var defaultOptions = selectionModelOptions.get()
78 , defaultSelectedAttribute = defaultOptions.selectedAttribute
79 , defaultSelectedClass = defaultOptions.selectedClass
80 , defaultType = defaultOptions.type
81 , defaultMode = defaultOptions.mode
82 , defaultCleanupStrategy = defaultOptions.cleanupStrategy;
83
84 /**
85 * The selection model type
86 *
87 * Controls how selections are presented on the underlying element. Use
88 * 'basic' (the default) to simplye assign a "selected" class to
89 * selected items. If set to 'checkbox' it'll also sync the checked
90 * state of the first checkbox child in each underlying `tr` or `li`
91 * element.
92 *
93 * Note that the 'checkbox' type assumes the first input child element
94 * will be the checkbox.
95 */
96 var smType = attrs.selectionModelType || defaultType;
97
98 /**
99 * The selection mode
100 *
101 * Supports 'single', 'multi[ple]', and 'multi[ple]-additive'. Single
102 * mode will only allow one item to be marked as selected at a time.
103 * Vanilla multi mode allows for multiple selectioned items but requires
104 * modifier keys to select more than one item at a time. Additive-multi
105 * mode allows for multiple items to be selected and will not deselect
106 * other items when a vanilla click is made. Additive multi also allows
107 * for de-selection without a modifier key (think of `'multi-additive'`
108 * as turning every click into a ctrl-click.
109 */
110 var smMode = attrs.selectionModelMode || defaultMode
111 , isMultiMode = /^multi(ple)?(-additive)?$/.test(smMode)
112 , isModeAdditive = /^multi(ple)?-additive/.test(smMode);
113
114 /**
115 * The item attribute to track selected status
116 *
117 * Use `selection-model-selected-attribute` to override the default
118 * attribute.
119 */
120 var selectedAttribute = attrs.selectionModelSelectedAttribute || defaultSelectedAttribute;
121
122 /**
123 * The selected class name
124 *
125 * Will be applied to dom items (e.g. `tr` or `li`) representing
126 * selected items. Use `selection-model-selected-class` to override the
127 * default class name.
128 */
129 var selectedClass = attrs.selectionModelSelectedClass || defaultSelectedClass;
130
131 /**
132 * The cleanup strategy
133 *
134 * How to handle items that are removed from the current view. By
135 * default no action is taken, you may set this to `deselect` to force
136 * items to be deselected when they are filtered away, paged away, or
137 * otherwise no longer visible on the client.
138 */
139 var cleanupStrategy = attrs.selectionModelCleanupStrategy || defaultCleanupStrategy;
140
141 /**
142 * The change callback
143 *
144 * To be executed whenever the item's selected state changes.
145 */
146 var smOnChange = attrs.selectionModelOnChange;
147
148 /**
149 * The list of items
150 *
151 * selectionModel must be attached to the same element as an ngRepeat
152 */
153 var repeatLine = attrs.ngRepeat;
154 if(!repeatLine) {
155 throw 'selectionModel must be used along side ngRepeat';
156 }
157
158 /**
159 * The list of selected items
160 *
161 * If used should resolve to an (initially empty) array. Use this in
162 * your view as **read only** if you'd like to do something with just
163 * the selected items. Note that order is not guarenteed and any items
164 * added to this array programmatically are ignored.
165 */
166 var selectedItemsList = scope.$eval(attrs.selectionModelSelectedItems);
167
168 /**
169 * The last-click stack id
170 *
171 * There may be multiple selection models on the page and each will need
172 * independent click stacks.
173 */
174 var clickStackId = (function() {
175 if(!isMultiMode) {
176 return null;
177 }
178 var idAttr = 'data-selection-model-stack-id';
179 // Id may be cached on this element
180 var stackId = element.attr(idAttr);
181 if(stackId) {
182 return stackId;
183 }
184
185 // Otherwise it may be on the partent
186 stackId = element.parent().attr(idAttr);
187 if(stackId) {
188 element.attr(idAttr, stackId);
189 return stackId;
190 }
191
192 // welp guess we're the first, create a new one and cache it on this
193 // element (for us) and the parent element (for others)
194 stackId = uuidGen.create();
195 element.attr(idAttr, stackId);
196 element.parent().attr(idAttr, stackId);
197 return stackId;
198 }());
199
200 var repeatParts = repeatLine.split(' in ')
201 , smItem = scope.$eval(repeatParts[0]);
202
203 var updateDom = function() {
204 if(smItem[selectedAttribute]) {
205 element.addClass(selectedClass);
206 } else {
207 element.removeClass(selectedClass);
208 }
209
210 if('checkbox' === smType) {
211 var cb = element.find('input');
212 cb.prop('checked', smItem[selectedAttribute]);
213 }
214 };
215
216 var getAllVisibleItems = function() {
217 return scope.$eval(repeatParts[1]);
218 };
219
220 // Strips away filters - this lets us e.g. deselect items that are
221 // filtered out
222 var getAllItems = function() {
223 return scope.$eval(repeatParts[1].split('|')[0]);
224 };
225
226 // Get us back to a "clean" state. Usually we'll want to skip
227 // deselection for items that are about to be selected again to avoid
228 // firing the `selection-mode-on-change` handler extra times.
229 //
230 // `except` param may be `undefined` (deselect all the things), a single
231 // item (don't deselect *that* item), or an array of two items (don't
232 // deselect anything between those items inclusively).
233 var deselectAllItemsExcept = function(except) {
234 var useSelectedArray = angular.isArray(selectedItemsList)
235 , isRange = angular.isArray(except) && 2 === except.length
236 , allItems = getAllItems()
237 , numItemsFound = 0
238 , doDeselect = false
239 , ixItem;
240 if(useSelectedArray) {
241 selectedItemsList.length = 0;
242 }
243 angular.forEach(allItems, function(item) {
244 if(isRange) {
245 ixItem = except.indexOf(item);
246 if(ixItem > -1) {
247 numItemsFound++;
248 doDeselect = false;
249 except.splice(ixItem, 1);
250 } else {
251 doDeselect = 1 !== numItemsFound;
252 }
253 } else {
254 doDeselect = item !== except;
255 }
256 if(doDeselect) {
257 item[selectedAttribute] = false;
258 } else {
259 if(useSelectedArray && item[selectedAttribute]) {
260 selectedItemsList.push(item);
261 }
262 }
263 });
264 };
265
266 var selectItemsBetween = function(lastItem) {
267 var allItems = getAllVisibleItems()
268 , foundLastItem = false
269 , foundThisItem = false;
270
271 lastItem = lastItem || smItem;
272
273 angular.forEach(getAllVisibleItems(), function(item) {
274 foundThisItem = foundThisItem || item === smItem;
275 foundLastItem = foundLastItem || item === lastItem;
276 var inRange = (foundLastItem + foundThisItem) === 1;
277 if(inRange || item === smItem || item === lastItem) {
278 item[selectedAttribute] = true;
279 }
280 });
281 };
282
283 /**
284 * Item click handler
285 *
286 * Use the `ctrl` key to select/deselect while preserving the rest of
287 * your selection. Note your your selection mode must be set to
288 * `'multiple'` to allow for more than one selected item at a time. In
289 * single select mode you still must use the `ctrl` or `shitft` keys to
290 * deselect an item.
291 *
292 * The `shift` key allows you to select ranges of items at a time. Use
293 * `ctrl` + `shift` to select a range while preserving your existing
294 * selection. In single select mode `shift` behaves like `ctrl`.
295 *
296 * When an item is clicked with no modifier keys pressed it will be the
297 * only selected item.
298 *
299 * On Mac the `meta` key is treated as `ctrl`.
300 *
301 * Note that when using the `'checkbox'` selection model type clicking
302 * on a checkbox will have no effect on any row other than the one the
303 * checkbox is in.
304 */
305 var handleClick = function(event) {
306
307 /**
308 * Set by the `selectionModelIgnore` directive
309 *
310 * Use `selectionModelIgnore` to cause `selectionModel` to selectively
311 * ignore clicks on elements. This is useful if you want to manually
312 * change a selection when certain things are clicked.
313 */
314 if(event.selectionModelIgnore || (event.originalEvent && event.originalEvent.selectionModelIgnore)) {
315 return;
316 }
317
318 // Never handle a single click twice.
319 if(event.selectionModelClickHandled || (event.originalEvent && event.originalEvent.selectionModelClickHandled)) {
320 return;
321 }
322 event.selectionModelClickHandled = true;
323 if(event.originalEvent) {
324 event.originalEvent.selectionModelClickHandled = true;
325 }
326
327 var isCtrlKeyDown = event.ctrlKey || event.metaKey || isModeAdditive
328 , isShiftKeyDown = event.shiftKey
329 , target = event.target || event.srcElement
330 , isCheckboxClick = 'checkbox' === smType &&
331 'INPUT' === target.tagName &&
332 'checkbox' === target.type;
333
334 /**
335 * Guard against label + checkbox clicks
336 *
337 * Clicking a label will cause a click event to also be fired on the
338 * associated input element. If that input is nearby (i.e. under the
339 * selection model element) we'll suppress the click on the label to
340 * avoid duplicate click events.
341 */
342 if('LABEL' === target.tagName) {
343 var labelFor = angular.element(target).attr('for');
344 if(labelFor) {
345 var childInputs = element[0].getElementsByTagName('INPUT'), ix;
346 for(ix = childInputs.length; ix--;) {
347 if(childInputs[ix].id === labelFor) {
348 return;
349 }
350 }
351 } else if(target.getElementsByTagName('INPUT').length) {
352 // Label has a nested input element, we'll handle the click on
353 // that element
354 return;
355 }
356 }
357
358 // Select multiple allows for ranges - use shift key
359 if(isShiftKeyDown && isMultiMode && !isCheckboxClick) {
360 // Use ctrl+shift for additive ranges
361 if(!isCtrlKeyDown) {
362 scope.$apply(function() {
363 deselectAllItemsExcept([smItem, selectionStack.peek(clickStackId)]);
364 });
365 }
366 selectItemsBetween(selectionStack.peek(clickStackId));
367 scope.$apply();
368 return;
369 }
370
371 // Use ctrl/shift without multi select to true toggle a row
372 if(isCtrlKeyDown || isShiftKeyDown || isCheckboxClick) {
373 var isSelected = !smItem[selectedAttribute];
374 if(!isMultiMode) {
375 deselectAllItemsExcept(smItem);
376 }
377 smItem[selectedAttribute] = isSelected;
378 if(smItem[selectedAttribute]) {
379 selectionStack.push(clickStackId, smItem);
380 }
381 scope.$apply();
382 return;
383 }
384
385 // Otherwise the clicked on row becomes the only selected item
386 deselectAllItemsExcept(smItem);
387 scope.$apply();
388
389 smItem[selectedAttribute] = true;
390 selectionStack.push(clickStackId, smItem);
391 scope.$apply();
392 };
393
394 /**
395 * Routine to keep the list of selected items up to date
396 *
397 * Adds/removes this item from `selectionModelSelectedItems`.
398 */
399 var updateSelectedItemsList = function() {
400 if(angular.isArray(selectedItemsList)) {
401 var ixSmItem = selectedItemsList.indexOf(smItem);
402 if(smItem[selectedAttribute]) {
403 if(-1 === ixSmItem) {
404 selectedItemsList.push(smItem);
405 }
406 } else {
407 if(-1 < ixSmItem) {
408 selectedItemsList.splice(ixSmItem, 1);
409 }
410 }
411 }
412 };
413
414 element.on('click', handleClick);
415 if('checkbox' === smType) {
416 var elCb = element.find('input');
417 if(elCb[0] && 'checkbox' === elCb[0].type) {
418 element.find('input').on('click', handleClick);
419 }
420 }
421
422 // We might be coming in with a selection
423 updateDom();
424 updateSelectedItemsList();
425
426 // If we were given a cleanup strategy then setup a `'$destroy'`
427 // listener on the scope.
428 if('deselect' === cleanupStrategy) {
429 scope.$on('$destroy', function() {
430 var oldSelectedStatus = smItem[selectedAttribute];
431 smItem[selectedAttribute] = false;
432 updateSelectedItemsList();
433 if(smOnChange && oldSelectedStatus) {
434 scope.$eval(smOnChange);
435 }
436 });
437 }
438
439 scope.$watch(repeatParts[0] + '.' + selectedAttribute, function(newVal, oldVal) {
440 // Be mindful of programmatic changes to selected state
441 if(newVal !== oldVal) {
442 if(!isMultiMode && newVal && !oldVal) {
443 deselectAllItemsExcept(smItem);
444 smItem[selectedAttribute] = true;
445 }
446 updateDom();
447 updateSelectedItemsList();
448
449 if(smOnChange) {
450 scope.$eval(smOnChange);
451 }
452 }
453 });
454 }
455 };
456 }
457 ]);
458
459
460 /**
461 * Default options for the selection model directive
462 *
463 *
464 *
465 * @package selectionModel
466 */
467
468 angular.module('selectionModel').provider('selectionModelOptions', [function() {
469 'use strict';
470
471 var options = {
472 selectedAttribute: 'selected',
473 selectedClass: 'selected',
474 type: 'basic',
475 mode: 'single',
476 cleanupStrategy: 'none'
477 };
478
479 this.set = function(userOpts) {
480 angular.extend(options, userOpts);
481 };
482
483 this.$get = function() {
484 var exports = {
485 get: function() {
486 return angular.copy(options);
487 }
488 };
489 return exports;
490 };
491
492
493 }]);
494
495
496 angular.module('selectionModel').service('selectionStack', function() {
497 'use strict';
498 var exports = {}
499 , maxSize = 1000
500 , stacks = {};
501
502 exports.push = function(id, item) {
503 if(!stacks.hasOwnProperty(id)) {
504 stacks[id] = [];
505 }
506 var stack = stacks[id];
507 stack.push(item);
508 while(stack.length > maxSize) {
509 stack.shift();
510 }
511 return stack.length;
512 };
513
514 exports.pop = function(id) {
515 if(!stacks.hasOwnProperty(id)) {
516 stacks[id] = [];
517 }
518 var stack = stacks[id];
519 return stack.pop();
520 };
521
522 exports.peek = function(id) {
523 if(!stacks.hasOwnProperty(id)) {
524 stacks[id] = [];
525 }
526 var stack = stacks[id];
527 return stack.length ? stack[stack.length - 1] : undefined;
528 };
529
530 return exports;
531 });
532
533 /*jshint bitwise:false */
534
535 angular.module('selectionModel').service('uuidGen', function() {
536 'use strict';
537 var exports = {};
538 var uid = ['0', '0', '0'];
539
540 exports.create = function() {
541 var index = uid.length;
542 var digit;
543 while (index) {
544 index--;
545 digit = uid[index].charCodeAt(0);
546 if (digit === 57 /*'9'*/ ) {
547 uid[index] = 'A';
548 return uid.join('');
549 }
550 if (digit === 90 /*'Z'*/ ) {
551 uid[index] = '0';
552 } else {
553 uid[index] = String.fromCharCode(digit + 1);
554 return uid.join('');
555 }
556 }
557 uid.unshift('0');
558 return uid.join('');
559 };
560
561 return exports;
562 });
+0
-1
faraday/server/www/script/angular-selection-model.min.js less more
0 angular.module("selectionModel",[]),angular.module("selectionModel").directive("selectionModelIgnore",[function(){"use strict";return{restrict:"A",link:function(a,b){b.on("click",function(a){a.selectionModelIgnore=!0,a.originalEvent&&(a.originalEvent.selectionModelIgnore=!0)})}}}]),angular.module("selectionModel").directive("selectionModel",["selectionStack","uuidGen","selectionModelOptions",function(a,b,c){"use strict";return{restrict:"A",link:function(d,e,f){var g=c.get(),h=g.selectedAttribute,i=g.selectedClass,j=g.type,k=g.mode,l=g.cleanupStrategy,m=f.selectionModelType||j,n=f.selectionModelMode||k,o=/^multi(ple)?(-additive)?$/.test(n),p=/^multi(ple)?-additive/.test(n),q=f.selectionModelSelectedAttribute||h,r=f.selectionModelSelectedClass||i,s=f.selectionModelCleanupStrategy||l,t=f.selectionModelOnChange,u=f.ngRepeat;if(!u)throw"selectionModel must be used along side ngRepeat";var v=d.$eval(f.selectionModelSelectedItems),w=function(){if(!o)return null;var a="data-selection-model-stack-id",c=e.attr(a);return c?c:(c=e.parent().attr(a))?(e.attr(a,c),c):(c=b.create(),e.attr(a,c),e.parent().attr(a,c),c)}(),x=u.split(" in "),y=d.$eval(x[0]),z=function(){if(y[q]?e.addClass(r):e.removeClass(r),"checkbox"===m){var a=e.find("input");a.prop("checked",y[q])}},A=function(){return d.$eval(x[1])},B=function(){return d.$eval(x[1].split("|")[0])},C=function(a){var b,c=angular.isArray(v),d=angular.isArray(a)&&2===a.length,e=B(),f=0,g=!1;c&&(v.length=0),angular.forEach(e,function(e){d?(b=a.indexOf(e),b>-1?(f++,g=!1,a.splice(b,1)):g=1!==f):g=e!==a,g?e[q]=!1:c&&e[q]&&v.push(e)})},D=function(a){var b=(A(),!1),c=!1;a=a||y,angular.forEach(A(),function(d){c=c||d===y,b=b||d===a;var e=b+c===1;(e||d===y||d===a)&&(d[q]=!0)})},E=function(b){if(!(b.selectionModelIgnore||b.originalEvent&&b.originalEvent.selectionModelIgnore||b.selectionModelClickHandled)){b.selectionModelClickHandled=!0;var c=b.ctrlKey||b.metaKey||p,f=b.shiftKey,g=b.target||b.srcElement,h="checkbox"===m&&"INPUT"===g.tagName&&"checkbox"===g.type;if("LABEL"===g.tagName){var i=angular.element(g).attr("for");if(i){var j,k=e[0].getElementsByTagName("INPUT");for(j=k.length;j--;)if(k[j].id===i)return}else if(g.getElementsByTagName("INPUT").length)return}if(h&&b.stopPropagation(),f&&o&&!h)return c||d.$apply(function(){C([y,a.peek(w)])}),D(a.peek(w)),d.$apply(),void 0;if(c||f||h){var l=!y[q];return o||C(y),y[q]=l,y[q]&&a.push(w,y),d.$apply(),void 0}C(y),d.$apply(),y[q]=!0,a.push(w,y),d.$apply()}},F=function(){if(angular.isArray(v)){var a=v.indexOf(y);y[q]?-1===a&&v.push(y):a>-1&&v.splice(a,1)}};if(e.on("click",E),"checkbox"===m){var G=e.find("input");G[0]&&"checkbox"===G[0].type&&e.find("input").on("click",E)}z(),F(),"deselect"===s&&d.$on("$destroy",function(){var a=y[q];y[q]=!1,F(),t&&a&&d.$eval(t)}),d.$watch(x[0]+"."+q,function(a,b){a!==b&&(o||!a||b||(C(y),y[q]=!0),z(),F(),t&&d.$eval(t))})}}}]),angular.module("selectionModel").provider("selectionModelOptions",[function(){"use strict";var a={selectedAttribute:"selected",selectedClass:"selected",type:"basic",mode:"single",cleanupStrategy:"none"};this.set=function(b){angular.extend(a,b)},this.$get=function(){var b={get:function(){return angular.copy(a)}};return b}}]),angular.module("selectionModel").service("selectionStack",function(){"use strict";var a={},b=1e3,c={};return a.push=function(a,d){c.hasOwnProperty(a)||(c[a]=[]);var e=c[a];for(e.push(d);e.length>b;)e.shift();return e.length},a.pop=function(a){c.hasOwnProperty(a)||(c[a]=[]);var b=c[a];return b.pop()},a.peek=function(a){c.hasOwnProperty(a)||(c[a]=[]);var b=c[a];return b.length?b[b.length-1]:void 0},a}),angular.module("selectionModel").service("uuidGen",function(){"use strict";var a={},b=["0","0","0"];return a.create=function(){for(var a,c=b.length;c;){if(c--,a=b[c].charCodeAt(0),57===a)return b[c]="A",b.join("");if(90!==a)return b[c]=String.fromCharCode(a+1),b.join("");b[c]="0"}return b.unshift("0"),b.join("")},a});
+0
-28
faraday/server/www/script/angular-table-resize.css less more
0 /*
1 * angular-table-resize
2 * https://github.com/tympanix/angular-table-resize
3 * - minimal stylesheet
4 */
5
6 table.rz-table {
7 /*table-layout: fixed;*/
8 border-collapse: collapse;
9 }
10
11 table.rz-table th {
12 position: relative;
13 min-width: 25px;
14 }
15
16 table.rz-table th .rz-handle {
17 width: 10px;
18 height: 100%;
19 position: absolute;
20 top: 0;
21 right: 0;
22 cursor: ew-resize !important;
23 }
24
25 table.rz-table th .rz-handle.rz-handle-active {
26 border-right: 1px dotted #000;
27 }
+0
-640
faraday/server/www/script/angular-table-resize.js less more
0 angular.module("rzTable", []);
1
2 angular.module("rzTable").directive('rzTable', ['resizeStorage', '$injector', '$parse', function(resizeStorage, $injector, $parse) {
3
4 var mode;
5 var saveTableSizes;
6 var profile;
7
8 var columns = null;
9 var ctrlColumns = null;
10 var handleColumns = null;
11 var listener = null;
12 var handles = []
13 var table = null;
14 var container = null;
15 var resizer = null;
16 var isFirstDrag = true;
17
18 var cache = null;
19
20 RzController.$inject = ['$scope', '$attrs', '$element'];
21
22 function RzController($scope) {
23
24 }
25
26 function link(scope, element, attr) {
27 // Set global reference to table
28 table = element;
29
30 // Set global reference to container
31 container = scope.container ? $(scope.container) : $(table).parent();
32
33 // Set options to an empty object if undefined
34 scope.options = attr.rzOptions ? scope.options || {} : {}
35
36 // Add css styling/properties to table
37 $(table).addClass(scope.options.tableClass || 'rz-table');
38
39 // Initialise handlers, bindings and modes
40 initialiseAll(table, attr, scope);
41
42 // Bind utility functions to scope object
43 bindUtilityFunctions(table, attr, scope)
44
45 // Watch for changes in columns
46 watchTableChanges(table, attr, scope)
47
48 // Watch for scope bindings
49 setUpWatchers(table, attr, scope)
50 }
51
52 function renderWatch(table, attr, scope) {
53 return function(oldVal, newVal) {
54 if (scope.busy === true) return
55 if (newVal === undefined) return
56 if (newVal !== oldVal) {
57 cleanUpAll(table);
58 initialiseAll(table, attr, scope);
59 }
60 }
61 }
62
63 function setUpWatchers(table, attr, scope) {
64 scope.$watch('profile', renderWatch(table, attr, scope))
65 scope.$watch('mode', renderWatch(table, attr, scope))
66 scope.$watch('busy', renderWatch(table, attr, scope))
67 }
68
69 function watchTableChanges(table, attr, scope) {
70 scope.$watch(function () {
71 return $(table).find('th').length;
72 }, renderWatch(table, attr, scope));
73 }
74
75 function bindUtilityFunctions(table, attr, scope) {
76 if (!attr.rzModel) return;
77 var model = $parse(attr.rzModel)
78 model.assign(scope.$parent, {
79 update: function() {
80 cleanUpAll(table)
81 initialiseAll(table, attr, scope)
82 },
83 reset: function() {
84 resetTable(table)
85 this.clearStorageActive()
86 this.update()
87 },
88 clearStorage: function() {
89 resizeStorage.clearAll()
90 },
91 clearStorageActive: function() {
92 resizeStorage.clearCurrent(table, mode, profile)
93 }
94 })
95 }
96
97 function cleanUpAll(table) {
98 isFirstDrag = true;
99 deleteHandles(table);
100 }
101
102 function resetTable(table) {
103 $(table).outerWidth('100%');
104 $(table).find('th').width('auto');
105 }
106
107 function deleteHandles(table) {
108 handles.map(function(h) { h.remove() })
109 handles = []
110 }
111
112 function initialiseAll(table, attr, scope) {
113 // If busy, postpone initialization
114 if (scope.busy) return
115
116 // Get all column headers
117 columns = $(table).find('th');
118
119 mode = scope.mode;
120 saveTableSizes = angular.isDefined(scope.saveTableSizes) ? scope.saveTableSizes : true;
121 profile = scope.profile
122
123 // Get the resizer object for the current mode
124 var ResizeModel = getResizer(scope, attr);
125 if (!ResizeModel) return;
126 resizer = new ResizeModel(table, columns, container);
127
128 if (saveTableSizes) {
129 // Load column sizes from saved storage
130 cache = resizeStorage.loadTableSizes(table, scope.mode, scope.profile)
131 }
132
133 // Decide which columns should have a handler attached
134 handleColumns = resizer.handles(columns);
135
136 // Decide which columns are controlled and resized
137 ctrlColumns = resizer.ctrlColumns;
138
139 // Execute setup function for the given resizer mode
140 resizer.setup();
141
142 // Set column sizes from cache
143 setColumnSizes(cache);
144
145 // Initialise all handlers for every column
146 handleColumns.each(function(index, column) {
147 initHandle(scope, table, column);
148 })
149
150 }
151
152 function initHandle(scope, table, column) {
153 // Prepend a new handle div to the column
154 var handle = $('<div>', {
155 class: scope.options.handleClass || 'rz-handle'
156 });
157 $(column).prepend(handle);
158
159 // Add handles to handles for later removal
160 handles.push(handle)
161
162 // Use the middleware to decide which columns this handle controls
163 var controlledColumn = resizer.handleMiddleware(handle, column)
164
165 // Bind mousedown, mousemove & mouseup events
166 bindEventToHandle(scope, table, handle, controlledColumn);
167 }
168
169 function bindEventToHandle(scope, table, handle, column) {
170
171 // This event starts the dragging
172 $(handle).mousedown(function(event) {
173 if (isFirstDrag) {
174 resizer.onFirstDrag(column, handle);
175 resizer.onTableReady();
176 isFirstDrag = false;
177 }
178
179 scope.options.onResizeStarted && scope.options.onResizeStarted(column)
180
181 var optional = {}
182 if (resizer.intervene) {
183 optional = resizer.intervene.selector(column);
184 optional.column = optional;
185 optional.orgWidth = $(optional).width();
186 }
187
188 // Prevent text-selection, object dragging ect.
189 event.preventDefault();
190
191 // Change css styles for the handle
192 $(handle).addClass(scope.options.handleClassActive || 'rz-handle-active');
193
194 // Get mouse and column origin measurements
195 var orgX = event.clientX;
196 var orgWidth = $(column).width();
197
198 // On every mouse move, calculate the new width
199 listener = calculateWidthEvent(scope, column, orgX, orgWidth, optional)
200 $(window).mousemove(listener)
201
202 // Stop dragging as soon as the mouse is released
203 $(window).one('mouseup', unbindEvent(scope, column, handle))
204 })
205 }
206
207 function calculateWidthEvent(scope, column, orgX, orgWidth, optional) {
208 return function(event) {
209 // Get current mouse position
210 var newX = event.clientX;
211
212 // Use calculator function to calculate new width
213 var diffX = newX - orgX;
214 var newWidth = resizer.calculate(orgWidth, diffX);
215
216 if (newWidth < getMinWidth(column)) return;
217 if (resizer.restrict(newWidth, diffX)) return;
218
219 // Extra optional column
220 if (resizer.intervene){
221 var optWidth = resizer.intervene.calculator(optional.orgWidth, diffX);
222 if (optWidth < getMinWidth(optional.column)) return;
223 if (resizer.intervene.restrict(optWidth, diffX)) return;
224 $(optional.column).width(optWidth)
225 }
226
227 scope.options.onResizeInProgress && scope.options.onResizeInProgress(column, newWidth, diffX)
228
229 // Set size
230 $(column).width(newWidth);
231 }
232 }
233
234 function getMinWidth(column) {
235 // "25px" -> 25
236 return parseInt($(column).css('min-width')) || 0;
237 }
238
239 function getResizer(scope, attr) {
240 try {
241 var mode = attr.rzMode ? scope.mode : 'BasicResizer';
242 var Resizer = $injector.get(mode)
243 return Resizer;
244 } catch (e) {
245 console.error("The resizer "+ scope.mode +" was not found");
246 return null;
247 }
248 }
249
250
251 function unbindEvent(scope, column, handle) {
252 // Event called at end of drag
253 return function( /*event*/ ) {
254 $(handle).removeClass(scope.options.handleClassActive || 'rz-handle-active');
255
256 if (listener) {
257 $(window).unbind('mousemove', listener);
258 }
259
260 scope.options.onResizeEnded && scope.options.onResizeEnded(column)
261
262 resizer.onEndDrag();
263
264 saveColumnSizes();
265 }
266 }
267
268 function saveColumnSizes() {
269 if (!saveTableSizes) return;
270
271 if (!cache) cache = {};
272 $(columns).each(function(index, column) {
273 var colScope = angular.element(column).scope()
274 var id = colScope.rzCol || $(column).attr('id')
275 if (!id) return;
276 cache[id] = resizer.saveAttr(column);
277 })
278
279 resizeStorage.saveTableSizes(table, mode, profile, cache);
280 }
281
282 function setColumnSizes(cache) {
283 if (!cache) {
284 return;
285 }
286
287 $(table).width('auto');
288
289 ctrlColumns.each(function(index, column){
290 var colScope = angular.element(column).scope()
291 var id = colScope.rzCol || $(column).attr('id')
292 var cacheWidth = cache[id];
293 $(column).css({ width: cacheWidth });
294 })
295
296 resizer.onTableReady();
297 }
298
299 // Return this directive as a object literal
300 return {
301 restrict: 'A',
302 link: link,
303 controller: RzController,
304 scope: {
305 // rzMode will determine the rezising behavior
306 mode: '=rzMode',
307 // rzProfile loads a profile from local storage
308 profile: '=?rzProfile',
309 // rzBusy will postpone initialisation
310 busy: '=?rzBusy',
311 // rzSave saves columns to local storage
312 saveTableSizes: '=?rzSave',
313 // rzOptions supplies addition options
314 options: '=?rzOptions',
315 // rzModel binds utility function to controller
316 model: '=rzModel',
317 // rzContainer is a query selector for the container DOM
318 container: '@rzContainer'
319 }
320 };
321
322 }]);
323
324 angular.module("rzTable").directive('rzCol', [function() {
325 // Return this directive as a object literal
326 return {
327 restrict: 'A',
328 priority: 650, /* before ng-if */
329 link: link,
330 require: '^^rzTable',
331 scope: true
332 };
333
334 function link(scope, element, attr) {
335 scope.rzCol = scope.$eval(attr.rzCol)
336 }
337 }])
338 angular.module("rzTable").service('resizeStorage', ['$window', function($window) {
339
340 var prefix = "ngColumnResize";
341
342 this.loadTableSizes = function(table, mode, profile) {
343 var key = getStorageKey(table, mode, profile);
344 var object = $window.localStorage.getItem(key);
345 return JSON.parse(object);
346 }
347
348 this.saveTableSizes = function(table, mode, profile, sizes) {
349 var key = getStorageKey(table, mode, profile);
350 if (!key) return;
351 var string = JSON.stringify(sizes);
352 $window.localStorage.setItem(key, string)
353 }
354
355 this.clearAll = function() {
356 var keys = []
357 for (var i = 0; i < $window.localStorage.length; ++i) {
358 var key = localStorage.key(i)
359 if (key && key.startsWith(prefix)) {
360 keys.push(key)
361 }
362 }
363 keys.map(function(k) { $window.localStorage.removeItem(k) })
364 }
365
366 this.clearCurrent = function(table, mode, profile) {
367 var key = getStorageKey(table, mode, profile);
368 if (key) {
369 $window.localStorage.removeItem(key)
370 }
371 }
372
373 function getStorageKey(table, mode, profile) {
374 var id = table.attr('id');
375 if (!id) {
376 console.error("Table has no id", table);
377 return undefined;
378 }
379 return prefix + '.' + table.attr('id') + '.' + mode + (profile ? '.' + profile : '');
380 }
381
382 }]);
383
384 angular.module("rzTable").factory("ResizerModel", [function() {
385
386 function ResizerModel(table, columns, container){
387 this.table = table;
388 this.columns = columns;
389 this.container = container;
390
391 this.handleColumns = this.handles();
392 this.ctrlColumns = this.ctrlColumns();
393 }
394
395 ResizerModel.prototype.setup = function() {
396 // Hide overflow by default
397 $(this.container).css({
398 overflowX: 'hidden'
399 })
400 }
401
402 ResizerModel.prototype.onTableReady = function () {
403 // Table is by default 100% width
404 $(this.table).outerWidth('100%');
405 };
406
407 ResizerModel.prototype.getMinWidth = function(column) {
408 // "25px" -> 25
409 return parseInt($(column).css('min-width')) || 0;
410 }
411
412 ResizerModel.prototype.handles = function () {
413 // By default all columns should be assigned a handle
414 return this.columns;
415 };
416
417 ResizerModel.prototype.ctrlColumns = function () {
418 // By default all columns assigned a handle are resized
419 return this.handleColumns;
420 };
421
422 ResizerModel.prototype.onFirstDrag = function () {
423 // By default, set all columns to absolute widths
424 $(this.ctrlColumns).each(function(index, column) {
425 $(column).width($(column).width());
426 })
427 };
428
429 ResizerModel.prototype.handleMiddleware = function (handle, column) {
430 // By default, every handle controls the column it is placed in
431 return column;
432 };
433
434 ResizerModel.prototype.restrict = function (newWidth) {
435 return false;
436 };
437
438 ResizerModel.prototype.calculate = function (orgWidth, diffX) {
439 // By default, simply add the width difference to the original
440 return orgWidth + diffX;
441 };
442
443 ResizerModel.prototype.onEndDrag = function () {
444 // By default, do nothing when dragging a column ends
445 return;
446 };
447
448 ResizerModel.prototype.saveAttr = function (column) {
449 return $(column).outerWidth();
450 };
451
452 return ResizerModel;
453 }]);
454
455 angular.module("rzTable").factory("BasicResizer", ["ResizerModel", function(ResizerModel) {
456
457 function BasicResizer(table, columns, container) {
458 // Call super constructor
459 ResizerModel.call(this, table, columns, container)
460
461 // All columns are controlled in basic mode
462 this.ctrlColumns = this.columns;
463
464 this.intervene = {
465 selector: interveneSelector,
466 calculator: interveneCalculator,
467 restrict: interveneRestrict
468 }
469 }
470
471 // Inherit by prototypal inheritance
472 BasicResizer.prototype = Object.create(ResizerModel.prototype);
473
474 function interveneSelector(column) {
475 return $(column).next()
476 }
477
478 function interveneCalculator(orgWidth, diffX) {
479 return orgWidth - diffX;
480 }
481
482 function interveneRestrict(newWidth){
483 return newWidth < 25;
484 }
485
486 BasicResizer.prototype.setup = function() {
487 // Hide overflow in mode fixed
488 $(this.container).css({
489 overflowX: 'hidden'
490 })
491
492 $(this.table).css({
493 width: '100%'
494 })
495 };
496
497 BasicResizer.prototype.handles = function() {
498 // Mode fixed does not require handler on last column
499 return $(this.columns).not(':last')
500 };
501
502 BasicResizer.prototype.onFirstDrag = function() {
503 // Replace all column's width with absolute measurements
504 this.onEndDrag()
505 };
506
507 BasicResizer.prototype.onEndDrag = function () {
508 // Calculates the percent width of each column
509 var totWidth = $(this.table).outerWidth();
510
511 var callbacks = []
512
513 // Calculate the width of every column
514 $(this.columns).each(function(index, column) {
515 var colWidth = $(column).outerWidth();
516 var percentWidth = colWidth / totWidth * 100 + '%';
517 callbacks.push(function() {
518 $(column).css({ width: percentWidth });
519 })
520 })
521
522 // Apply the calculated width of every column
523 callbacks.map(function(cb) { cb() })
524 };
525
526 BasicResizer.prototype.saveAttr = function (column) {
527 return $(column)[0].style.width;
528 };
529
530 // Return constructor
531 return BasicResizer;
532
533 }]);
534
535 angular.module("rzTable").factory("FixedResizer", ["ResizerModel", function(ResizerModel) {
536
537 function FixedResizer(table, columns, container) {
538 // Call super constructor
539 ResizerModel.call(this, table, columns, container)
540
541 this.fixedColumn = $(table).find('th').first();
542 this.bound = false;
543 }
544
545 // Inherit by prototypal inheritance
546 FixedResizer.prototype = Object.create(ResizerModel.prototype);
547
548 FixedResizer.prototype.setup = function() {
549 // Hide overflow in mode fixed
550 $(this.container).css({
551 overflowX: 'hidden'
552 })
553
554 $(this.table).css({
555 width: '100%'
556 })
557
558 // First column is auto to compensate for 100% table width
559 $(this.columns).first().css({
560 width: 'auto'
561 });
562 };
563
564 FixedResizer.prototype.handles = function() {
565 // Mode fixed does not require handler on last column
566 return $(this.columns).not(':last')
567 };
568
569 FixedResizer.prototype.ctrlColumns = function() {
570 // In mode fixed, all but the first column should be resized
571 return $(this.columns).not(':first');
572 };
573
574 FixedResizer.prototype.onFirstDrag = function() {
575 // Replace each column's width with absolute measurements
576 $(this.ctrlColumns).each(function(index, column) {
577 $(column).width($(column).width());
578 })
579 };
580
581 FixedResizer.prototype.handleMiddleware = function (handle, column) {
582 // Fixed mode handles always controll next neightbour column
583 return $(column).next();
584 };
585
586 FixedResizer.prototype.restrict = function (newWidth, diffX) {
587 if (this.bound && this.bound < diffX) {
588 this.bound = false
589 return false
590 } if (this.bound && this.bound > diffX) {
591 return true
592 } else if (this.fixedColumn.width() <= this.getMinWidth(this.fixedColumn)) {
593 this.bound = diffX
594 $(this.fixedColumn).width(this.minWidth);
595 return true;
596 }
597 };
598
599 FixedResizer.prototype.onEndDrag = function () {
600 this.bound = false
601 };
602
603 FixedResizer.prototype.calculate = function (orgWidth, diffX) {
604 // Subtract difference - neightbour grows
605 return orgWidth - diffX;
606 };
607
608 // Return constructor
609 return FixedResizer;
610
611 }]);
612
613 angular.module("rzTable").factory("OverflowResizer", ["ResizerModel", function(ResizerModel) {
614
615 function OverflowResizer(table, columns, container) {
616 // Call super constructor
617 ResizerModel.call(this, table, columns, container)
618 }
619
620 // Inherit by prototypal inheritance
621 OverflowResizer.prototype = Object.create(ResizerModel.prototype);
622
623
624 OverflowResizer.prototype.setup = function() {
625 // Allow overflow in this mode
626 $(this.container).css({
627 overflow: 'auto'
628 });
629 };
630
631 OverflowResizer.prototype.onTableReady = function() {
632 // For mode overflow, make table as small as possible
633 $(this.table).width(1);
634 };
635
636 // Return constructor
637 return OverflowResizer;
638
639 }]);
+0
-1
faraday/server/www/script/angular-table-resize.min.js less more
0 angular.module("rzTable",[]),angular.module("rzTable").directive("rzTable",["resizeStorage","$injector","$parse",function(t,n,e){function o(t){}function r(t,n,e){W=n,I=t.container?$(t.container):$(W).parent(),t.options=e.rzOptions?t.options||{}:{},$(W).addClass(t.options.tableClass||"rz-table"),h(W,e,t),u(W,e,t),a(W,e,t),s(W,e,t)}function i(t,n,e){return function(o,r){e.busy!==!0&&void 0!==r&&r!==o&&(l(t),h(t,n,e))}}function s(t,n,e){e.$watch("profile",i(t,n,e)),e.$watch("mode",i(t,n,e)),e.$watch("busy",i(t,n,e))}function a(t,n,e){e.$watch(function(){return $(t).find("th").length},i(t,n,e))}function u(n,o,r){if(o.rzModel){var i=e(o.rzModel);i.assign(r.$parent,{update:function(){l(n),h(n,o,r)},reset:function(){c(n),this.clearStorageActive(),this.update()},clearStorage:function(){t.clearAll()},clearStorageActive:function(){t.clearCurrent(n,w,S)}})}}function l(t){x=!0,d(t)}function c(t){$(t).outerWidth("100%"),$(t).find("th").width("auto")}function d(t){D.map(function(t){t.remove()}),D=[]}function h(n,e,o){if(!o.busy){T=$(n).find("th"),w=o.mode,C=!angular.isDefined(o.saveTableSizes)||o.saveTableSizes,S=o.profile;var r=z(o,e);r&&(O=new r(n,T,I),C&&(E=t.loadTableSizes(n,o.mode,o.profile)),M=O.handles(T),R=O.ctrlColumns,O.setup(),g(E),M.each(function(t,e){f(o,n,e)}))}}function f(t,n,e){var o=$("<div>",{"class":t.options.handleClass||"rz-handle"});$(e).prepend(o),D.push(o);var r=O.handleMiddleware(o,e);p(t,n,o,r)}function p(t,n,e,o){$(e).mousedown(function(n){x&&(O.onFirstDrag(o,e),O.onTableReady(),x=!1),t.options.onResizeStarted&&t.options.onResizeStarted(o);var r={};O.intervene&&(r=O.intervene.selector(o),r.column=r,r.orgWidth=$(r).width()),n.preventDefault(),$(e).addClass(t.options.handleClassActive||"rz-handle-active");var i=n.clientX,s=$(o).width();A=m(t,o,i,s,r),$(window).mousemove(A),$(window).one("mouseup",y(t,o,e))})}function m(t,n,e,o,r){return function(i){var s=i.clientX,a=s-e,u=O.calculate(o,a);if(!(u<v(n)||O.restrict(u,a))){if(O.intervene){var l=O.intervene.calculator(r.orgWidth,a);if(l<v(r.column))return;if(O.intervene.restrict(l,a))return;$(r.column).width(l)}t.options.onResizeInProgress&&t.options.onResizeInProgress(n,u,a),$(n).width(u)}}}function v(t){return parseInt($(t).css("min-width"))||0}function z(t,e){try{var o=e.rzMode?t.mode:"BasicResizer",r=n.get(o);return r}catch(i){return console.error("The resizer "+t.mode+" was not found"),null}}function y(t,n,e){return function(){$(e).removeClass(t.options.handleClassActive||"rz-handle-active"),A&&$(window).unbind("mousemove",A),t.options.onResizeEnded&&t.options.onResizeEnded(n),O.onEndDrag(),b()}}function b(){C&&(E||(E={}),$(T).each(function(t,n){var e=angular.element(n).scope(),o=e.rzCol||$(n).attr("id");o&&(E[o]=O.saveAttr(n))}),t.saveTableSizes(W,w,S,E))}function g(t){t&&($(W).width("auto"),R.each(function(n,e){var o=angular.element(e).scope(),r=o.rzCol||$(e).attr("id"),i=t[r];$(e).css({width:i})}),O.onTableReady())}var w,C,S,T=null,R=null,M=null,A=null,D=[],W=null,I=null,O=null,x=!0,E=null;return o.$inject=["$scope","$attrs","$element"],{restrict:"A",link:r,controller:o,scope:{mode:"=rzMode",profile:"=?rzProfile",busy:"=?rzBusy",saveTableSizes:"=?rzSave",options:"=?rzOptions",model:"=rzModel",container:"@rzContainer"}}}]),angular.module("rzTable").directive("rzCol",[function(){function t(t,n,e){t.rzCol=t.$eval(e.rzCol)}return{restrict:"A",priority:650,link:t,require:"^^rzTable",scope:!0}}]),angular.module("rzTable").service("resizeStorage",["$window",function(t){function n(t,n,o){var r=t.attr("id");return r?e+"."+t.attr("id")+"."+n+(o?"."+o:""):void console.error("Table has no id",t)}var e="ngColumnResize";this.loadTableSizes=function(e,o,r){var i=n(e,o,r),s=t.localStorage.getItem(i);return JSON.parse(s)},this.saveTableSizes=function(e,o,r,i){var s=n(e,o,r);if(s){var a=JSON.stringify(i);t.localStorage.setItem(s,a)}},this.clearAll=function(){for(var n=[],o=0;o<t.localStorage.length;++o){var r=localStorage.key(o);r&&r.startsWith(e)&&n.push(r)}n.map(function(n){t.localStorage.removeItem(n)})},this.clearCurrent=function(e,o,r){var i=n(e,o,r);i&&t.localStorage.removeItem(i)}}]),angular.module("rzTable").factory("ResizerModel",[function(){function t(t,n,e){this.table=t,this.columns=n,this.container=e,this.handleColumns=this.handles(),this.ctrlColumns=this.ctrlColumns()}return t.prototype.setup=function(){$(this.container).css({overflowX:"hidden"})},t.prototype.onTableReady=function(){$(this.table).outerWidth("100%")},t.prototype.getMinWidth=function(t){return parseInt($(t).css("min-width"))||0},t.prototype.handles=function(){return this.columns},t.prototype.ctrlColumns=function(){return this.handleColumns},t.prototype.onFirstDrag=function(){$(this.ctrlColumns).each(function(t,n){$(n).width($(n).width())})},t.prototype.handleMiddleware=function(t,n){return n},t.prototype.restrict=function(t){return!1},t.prototype.calculate=function(t,n){return t+n},t.prototype.onEndDrag=function(){},t.prototype.saveAttr=function(t){return $(t).outerWidth()},t}]),angular.module("rzTable").factory("BasicResizer",["ResizerModel",function(t){function n(n,i,s){t.call(this,n,i,s),this.ctrlColumns=this.columns,this.intervene={selector:e,calculator:o,restrict:r}}function e(t){return $(t).next()}function o(t,n){return t-n}function r(t){return t<25}return n.prototype=Object.create(t.prototype),n.prototype.setup=function(){$(this.container).css({overflowX:"hidden"}),$(this.table).css({width:"100%"})},n.prototype.handles=function(){return $(this.columns).not(":last")},n.prototype.onFirstDrag=function(){this.onEndDrag()},n.prototype.onEndDrag=function(){var t=$(this.table).outerWidth(),n=[];$(this.columns).each(function(e,o){var r=$(o).outerWidth(),i=r/t*100+"%";n.push(function(){$(o).css({width:i})})}),n.map(function(t){t()})},n.prototype.saveAttr=function(t){return $(t)[0].style.width},n}]),angular.module("rzTable").factory("FixedResizer",["ResizerModel",function(t){function n(n,e,o){t.call(this,n,e,o),this.fixedColumn=$(n).find("th").first(),this.bound=!1}return n.prototype=Object.create(t.prototype),n.prototype.setup=function(){$(this.container).css({overflowX:"hidden"}),$(this.table).css({width:"100%"}),$(this.columns).first().css({width:"auto"})},n.prototype.handles=function(){return $(this.columns).not(":last")},n.prototype.ctrlColumns=function(){return $(this.columns).not(":first")},n.prototype.onFirstDrag=function(){$(this.ctrlColumns).each(function(t,n){$(n).width($(n).width())})},n.prototype.handleMiddleware=function(t,n){return $(n).next()},n.prototype.restrict=function(t,n){return this.bound&&this.bound<n?(this.bound=!1,!1):!!(this.bound&&this.bound>n)||(this.fixedColumn.width()<=this.getMinWidth(this.fixedColumn)?(this.bound=n,$(this.fixedColumn).width(this.minWidth),!0):void 0)},n.prototype.onEndDrag=function(){this.bound=!1},n.prototype.calculate=function(t,n){return t-n},n}]),angular.module("rzTable").factory("OverflowResizer",["ResizerModel",function(t){function n(n,e,o){t.call(this,n,e,o)}return n.prototype=Object.create(t.prototype),n.prototype.setup=function(){$(this.container).css({overflow:"auto"})},n.prototype.onTableReady=function(){$(this.table).width(1)},n}]);
+0
-8
faraday/server/www/script/angular-ui-notification.min.js less more
0 /**
1 * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
2 * @author Alex_Crack
3 * @version v0.2.0
4 * @link https://github.com/alexcrack/angular-ui-notification
5 * @license MIT
6 */
7 angular.module("ui-notification",[]),angular.module("ui-notification").provider("Notification",function(){this.options={delay:5e3,startTop:10,startRight:10,verticalSpacing:10,horizontalSpacing:10,positionX:"right",positionY:"top",replaceMessage:!1,templateUrl:"angular-ui-notification.html",onClose:void 0,closeOnClick:!0,maxCount:0,container:"body"},this.setOptions=function(e){if(!angular.isObject(e))throw new Error("Options should be an object!");this.options=angular.extend({},this.options,e)},this.$get=["$timeout","$http","$compile","$templateCache","$rootScope","$injector","$sce","$q","$window",function(e,t,n,i,o,s,a,l,r){var c=this.options,p=c.startTop,d=c.startRight,u=c.verticalSpacing,f=c.horizontalSpacing,m=c.delay,g=[],h=!1,C=function(s,C){var y=l.defer();return"object"!=typeof s&&(s={message:s}),s.scope=s.scope?s.scope:o,s.template=s.templateUrl?s.templateUrl:c.templateUrl,s.delay=angular.isUndefined(s.delay)?m:s.delay,s.type=C||c.type||"",s.positionY=s.positionY?s.positionY:c.positionY,s.positionX=s.positionX?s.positionX:c.positionX,s.replaceMessage=s.replaceMessage?s.replaceMessage:c.replaceMessage,s.onClose=s.onClose?s.onClose:c.onClose,s.closeOnClick=null!==s.closeOnClick&&void 0!==s.closeOnClick?s.closeOnClick:c.closeOnClick,s.container=s.container?s.container:c.container,t.get(s.template,{cache:i}).success(function(t){function i(e){["-webkit-transition","-o-transition","transition"].forEach(function(t){m.css(t,e)})}var o=s.scope.$new();o.message=a.trustAsHtml(s.message),o.title=a.trustAsHtml(s.title),o.t=s.type.substr(0,1),o.delay=s.delay,o.onClose=s.onClose;var l=function(){for(var e=0,t=0,n=p,i=d,o=[],a=g.length-1;a>=0;a--){var l=g[a];if(s.replaceMessage&&a<g.length-1)l.addClass("killed");else{var r=parseInt(l[0].offsetHeight),m=parseInt(l[0].offsetWidth),h=o[l._positionY+l._positionX];C+r>window.innerHeight&&(h=p,t++,e=0);var C=n=h?0===e?h:h+u:p,y=i+t*(f+m);l.css(l._positionY,C+"px"),"center"==l._positionX?l.css("left",parseInt(window.innerWidth/2-m/2)+"px"):l.css(l._positionX,y+"px"),o[l._positionY+l._positionX]=C+r,c.maxCount>0&&g.length>c.maxCount&&0===a&&l.scope().kill(!0),e++}}},m=n(t)(o);m._positionY=s.positionY,m._positionX=s.positionX,m.addClass(s.type);var C=function(e){e=e.originalEvent||e,("click"===e.type||"opacity"===e.propertyName&&e.elapsedTime>=1)&&(o.onClose&&o.$apply(o.onClose(m)),m.remove(),g.splice(g.indexOf(m),1),o.$destroy(),l())};s.closeOnClick&&(m.addClass("clickable"),m.bind("click",C)),m.bind("webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd",C),angular.isNumber(s.delay)&&e(function(){m.addClass("killed")},s.delay),i("none"),angular.element(document.querySelector(s.container)).append(m);var v=-(parseInt(m[0].offsetHeight)+50);if(m.css(m._positionY,v+"px"),g.push(m),"center"==s.positionX){var k=parseInt(m[0].offsetWidth);m.css("left",parseInt(window.innerWidth/2-k/2)+"px")}e(function(){i("")}),o._templateElement=m,o.kill=function(t){t?(o.onClose&&o.$apply(o.onClose(o._templateElement)),g.splice(g.indexOf(o._templateElement),1),o._templateElement.remove(),o.$destroy(),e(l)):o._templateElement.addClass("killed")},e(l),h||(angular.element(r).bind("resize",function(t){e(l)}),h=!0),y.resolve(o)}).error(function(e){throw new Error("Template ("+s.template+") could not be loaded. "+e)}),y.promise};return C.primary=function(e){return this(e,"primary")},C.error=function(e){return this(e,"error")},C.success=function(e){return this(e,"success")},C.info=function(e){return this(e,"info")},C.warning=function(e){return this(e,"warning")},C.clearAll=function(){angular.forEach(g,function(e){e.addClass("killed")})},C}]}),angular.module("ui-notification").run(["$templateCache",function(e){e.put("angular-ui-notification.html",'<div class="ui-notification"><h3 ng-show="title" ng-bind-html="title"></h3><div class="message" ng-bind-html="message"></div></div>')}]);
+0
-1461
faraday/server/www/script/angular-ui.js less more
0 /**
1 * AngularUI - The companion suite for AngularJS
2 * @version v0.4.0 - 2013-02-15
3 * @link http://angular-ui.github.com
4 * @license MIT License, http://www.opensource.org/licenses/MIT
5 */
6
7
8 angular.module('ui.config', []).value('ui.config', {});
9 angular.module('ui.filters', ['ui.config']);
10 angular.module('ui.directives', ['ui.config']);
11 angular.module('ui', ['ui.filters', 'ui.directives', 'ui.config']);
12
13 /**
14 * Animates the injection of new DOM elements by simply creating the DOM with a class and then immediately removing it
15 * Animations must be done using CSS3 transitions, but provide excellent flexibility
16 *
17 * @todo Add proper support for animating out
18 * @param [options] {mixed} Can be an object with multiple options, or a string with the animation class
19 * class {string} the CSS class(es) to use. For example, 'ui-hide' might be an excellent alternative class.
20 * @example <li ng-repeat="item in items" ui-animate=" 'ui-hide' ">{{item}}</li>
21 */
22 angular.module('ui.directives').directive('uiAnimate', ['ui.config', '$timeout', function (uiConfig, $timeout) {
23 var options = {};
24 if (angular.isString(uiConfig.animate)) {
25 options['class'] = uiConfig.animate;
26 } else if (uiConfig.animate) {
27 options = uiConfig.animate;
28 }
29 return {
30 restrict: 'A', // supports using directive as element, attribute and class
31 link: function ($scope, element, attrs) {
32 var opts = {};
33 if (attrs.uiAnimate) {
34 opts = $scope.$eval(attrs.uiAnimate);
35 if (angular.isString(opts)) {
36 opts = {'class': opts};
37 }
38 }
39 opts = angular.extend({'class': 'ui-animate'}, options, opts);
40
41 element.addClass(opts['class']);
42 $timeout(function () {
43 element.removeClass(opts['class']);
44 }, 20, false);
45 }
46 };
47 }]);
48
49
50 /*
51 * AngularJs Fullcalendar Wrapper for the JQuery FullCalendar
52 * API @ http://arshaw.com/fullcalendar/
53 *
54 * Angular Calendar Directive that takes in the [eventSources] nested array object as the ng-model and watches (eventSources.length + eventSources[i].length) for changes.
55 * Can also take in multiple event urls as a source object(s) and feed the events per view.
56 * The calendar will watch any eventSource array and update itself when a delta is created
57 * An equalsTracker attrs has been added for use cases that would render the overall length tracker the same even though the events have changed to force updates.
58 *
59 */
60
61 angular.module('ui.directives').directive('uiCalendar',['ui.config', '$parse', function (uiConfig,$parse) {
62 uiConfig.uiCalendar = uiConfig.uiCalendar || {};
63 //returns calendar
64 return {
65 require: 'ngModel',
66 restrict: 'A',
67 link: function(scope, elm, attrs, $timeout) {
68 var sources = scope.$eval(attrs.ngModel);
69 var tracker = 0;
70 /* returns the length of all source arrays plus the length of eventSource itself */
71 var getSources = function () {
72 var equalsTracker = scope.$eval(attrs.equalsTracker);
73 tracker = 0;
74 angular.forEach(sources,function(value,key){
75 if(angular.isArray(value)){
76 tracker += value.length;
77 }
78 });
79 if(angular.isNumber(equalsTracker)){
80 return tracker + sources.length + equalsTracker;
81 }else{
82 return tracker + sources.length;
83 }
84 };
85 /* update the calendar with the correct options */
86 function update() {
87 //calendar object exposed on scope
88 scope.calendar = elm.html('');
89 var view = scope.calendar.fullCalendar('getView');
90 if(view){
91 view = view.name; //setting the default view to be whatever the current view is. This can be overwritten.
92 }
93 /* If the calendar has options added then render them */
94 var expression,
95 options = {
96 defaultView : view,
97 eventSources: sources
98 };
99 if (attrs.uiCalendar) {
100 expression = scope.$eval(attrs.uiCalendar);
101 } else {
102 expression = {};
103 }
104 angular.extend(options, uiConfig.uiCalendar, expression);
105 scope.calendar.fullCalendar(options);
106 }
107 update();
108 /* watches all eventSources */
109 scope.$watch(getSources, function( newVal, oldVal )
110 {
111 update();
112 });
113 }
114 };
115 }]);
116 /*global angular, CodeMirror, Error*/
117 /**
118 * Binds a CodeMirror widget to a <textarea> element.
119 */
120 angular.module('ui.directives').directive('uiCodemirror', ['ui.config', '$timeout', function (uiConfig, $timeout) {
121 'use strict';
122
123 var events = ["cursorActivity", "viewportChange", "gutterClick", "focus", "blur", "scroll", "update"];
124 return {
125 restrict:'A',
126 require:'ngModel',
127 link:function (scope, elm, attrs, ngModel) {
128 var options, opts, onChange, deferCodeMirror, codeMirror;
129
130 if (elm[0].type !== 'textarea') {
131 throw new Error('uiCodemirror3 can only be applied to a textarea element');
132 }
133
134 options = uiConfig.codemirror || {};
135 opts = angular.extend({}, options, scope.$eval(attrs.uiCodemirror));
136
137 onChange = function (aEvent) {
138 return function (instance, changeObj) {
139 var newValue = instance.getValue();
140 if (newValue !== ngModel.$viewValue) {
141 ngModel.$setViewValue(newValue);
142 scope.$apply();
143 }
144 if (typeof aEvent === "function")
145 aEvent(instance, changeObj);
146 };
147 };
148
149 deferCodeMirror = function () {
150 codeMirror = CodeMirror.fromTextArea(elm[0], opts);
151 codeMirror.on("change", onChange(opts.onChange));
152
153 for (var i = 0, n = events.length, aEvent; i < n; ++i) {
154 aEvent = opts["on" + events[i].charAt(0).toUpperCase() + events[i].slice(1)];
155 if (aEvent === void 0) continue;
156 if (typeof aEvent !== "function") continue;
157 codeMirror.on(events[i], aEvent);
158 }
159
160 // CodeMirror expects a string, so make sure it gets one.
161 // This does not change the model.
162 ngModel.$formatters.push(function (value) {
163 if (angular.isUndefined(value) || value === null) {
164 return '';
165 }
166 else if (angular.isObject(value) || angular.isArray(value)) {
167 throw new Error('ui-codemirror cannot use an object or an array as a model');
168 }
169 return value;
170 });
171
172 // Override the ngModelController $render method, which is what gets called when the model is updated.
173 // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else.
174 ngModel.$render = function () {
175 codeMirror.setValue(ngModel.$viewValue);
176 };
177
178 // Watch ui-refresh and refresh the directive
179 if (attrs.uiRefresh) {
180 scope.$watch(attrs.uiRefresh, function(newVal, oldVal){
181 // Skip the initial watch firing
182 if (newVal !== oldVal)
183 $timeout(codeMirror.refresh);
184 });
185 }
186 };
187
188 $timeout(deferCodeMirror);
189
190 }
191 };
192 }]);
193
194 /*
195 Gives the ability to style currency based on its sign.
196 */
197 angular.module('ui.directives').directive('uiCurrency', ['ui.config', 'currencyFilter' , function (uiConfig, currencyFilter) {
198 var options = {
199 pos: 'ui-currency-pos',
200 neg: 'ui-currency-neg',
201 zero: 'ui-currency-zero'
202 };
203 if (uiConfig.currency) {
204 angular.extend(options, uiConfig.currency);
205 }
206 return {
207 restrict: 'EAC',
208 require: 'ngModel',
209 link: function (scope, element, attrs, controller) {
210 var opts, // instance-specific options
211 renderview,
212 value;
213
214 opts = angular.extend({}, options, scope.$eval(attrs.uiCurrency));
215
216 renderview = function (viewvalue) {
217 var num;
218 num = viewvalue * 1;
219 element.toggleClass(opts.pos, (num > 0) );
220 element.toggleClass(opts.neg, (num < 0) );
221 element.toggleClass(opts.zero, (num === 0) );
222 if (viewvalue === '') {
223 element.text('');
224 } else {
225 element.text(currencyFilter(num, opts.symbol));
226 }
227 return true;
228 };
229
230 controller.$render = function () {
231 value = controller.$viewValue;
232 element.val(value);
233 renderview(value);
234 };
235
236 }
237 };
238 }]);
239
240 /*global angular */
241 /*
242 jQuery UI Datepicker plugin wrapper
243
244 @note If ≤ IE8 make sure you have a polyfill for Date.toISOString()
245 @param [ui-date] {object} Options to pass to $.fn.datepicker() merged onto ui.config
246 */
247
248 angular.module('ui.directives')
249
250 .directive('uiDate', ['ui.config', function (uiConfig) {
251 'use strict';
252 var options;
253 options = {};
254 if (angular.isObject(uiConfig.date)) {
255 angular.extend(options, uiConfig.date);
256 }
257 return {
258 require:'?ngModel',
259 link:function (scope, element, attrs, controller) {
260 var getOptions = function () {
261 return angular.extend({}, uiConfig.date, scope.$eval(attrs.uiDate));
262 };
263 var initDateWidget = function () {
264 var opts = getOptions();
265
266 // If we have a controller (i.e. ngModelController) then wire it up
267 if (controller) {
268 var updateModel = function () {
269 scope.$apply(function () {
270 var date = element.datepicker("getDate");
271 element.datepicker("setDate", element.val());
272 controller.$setViewValue(date);
273 element.blur();
274 });
275 };
276 if (opts.onSelect) {
277 // Caller has specified onSelect, so call this as well as updating the model
278 var userHandler = opts.onSelect;
279 opts.onSelect = function (value, picker) {
280 updateModel();
281 scope.$apply(function() {
282 userHandler(value, picker);
283 });
284 };
285 } else {
286 // No onSelect already specified so just update the model
287 opts.onSelect = updateModel;
288 }
289 // In case the user changes the text directly in the input box
290 element.bind('change', updateModel);
291
292 // Update the date picker when the model changes
293 controller.$render = function () {
294 var date = controller.$viewValue;
295 if ( angular.isDefined(date) && date !== null && !angular.isDate(date) ) {
296 throw new Error('ng-Model value must be a Date object - currently it is a ' + typeof date + ' - use ui-date-format to convert it from a string');
297 }
298 element.datepicker("setDate", date);
299 };
300 }
301 // If we don't destroy the old one it doesn't update properly when the config changes
302 element.datepicker('destroy');
303 // Create the new datepicker widget
304 element.datepicker(opts);
305 if ( controller ) {
306 // Force a render to override whatever is in the input text box
307 controller.$render();
308 }
309 };
310 // Watch for changes to the directives options
311 scope.$watch(getOptions, initDateWidget, true);
312 }
313 };
314 }
315 ])
316
317 .directive('uiDateFormat', ['ui.config', function(uiConfig) {
318 var directive = {
319 require:'ngModel',
320 link: function(scope, element, attrs, modelCtrl) {
321 var dateFormat = attrs.uiDateFormat || uiConfig.dateFormat;
322 if ( dateFormat ) {
323 // Use the datepicker with the attribute value as the dateFormat string to convert to and from a string
324 modelCtrl.$formatters.push(function(value) {
325 if (angular.isString(value) ) {
326 return $.datepicker.parseDate(dateFormat, value);
327 }
328 });
329 modelCtrl.$parsers.push(function(value){
330 if (value) {
331 return $.datepicker.formatDate(dateFormat, value);
332 }
333 });
334 } else {
335 // Default to ISO formatting
336 modelCtrl.$formatters.push(function(value) {
337 if (angular.isString(value) ) {
338 return new Date(value);
339 }
340 });
341 modelCtrl.$parsers.push(function(value){
342 if (value) {
343 return value.toISOString();
344 }
345 });
346 }
347 }
348 };
349 return directive;
350 }]);
351
352 /**
353 * General-purpose Event binding. Bind any event not natively supported by Angular
354 * Pass an object with keynames for events to ui-event
355 * Allows $event object and $params object to be passed
356 *
357 * @example <input ui-event="{ focus : 'counter++', blur : 'someCallback()' }">
358 * @example <input ui-event="{ myCustomEvent : 'myEventHandler($event, $params)'}">
359 *
360 * @param ui-event {string|object literal} The event to bind to as a string or a hash of events with their callbacks
361 */
362 angular.module('ui.directives').directive('uiEvent', ['$parse',
363 function ($parse) {
364 return function (scope, elm, attrs) {
365 var events = scope.$eval(attrs.uiEvent);
366 angular.forEach(events, function (uiEvent, eventName) {
367 var fn = $parse(uiEvent);
368 elm.bind(eventName, function (evt) {
369 var params = Array.prototype.slice.call(arguments);
370 //Take out first paramater (event object);
371 params = params.splice(1);
372 scope.$apply(function () {
373 fn(scope, {$event: evt, $params: params});
374 });
375 });
376 });
377 };
378 }]);
379
380 /*
381 * Defines the ui-if tag. This removes/adds an element from the dom depending on a condition
382 * Originally created by @tigbro, for the @jquery-mobile-angular-adapter
383 * https://github.com/tigbro/jquery-mobile-angular-adapter
384 */
385 angular.module('ui.directives').directive('uiIf', [function () {
386 return {
387 transclude: 'element',
388 priority: 1000,
389 terminal: true,
390 restrict: 'A',
391 compile: function (element, attr, transclude) {
392 return function (scope, element, attr) {
393
394 var childElement;
395 var childScope;
396
397 scope.$watch(attr['uiIf'], function (newValue) {
398 if (childElement) {
399 childElement.remove();
400 childElement = undefined;
401 }
402 if (childScope) {
403 childScope.$destroy();
404 childScope = undefined;
405 }
406
407 if (newValue) {
408 childScope = scope.$new();
409 transclude(childScope, function (clone) {
410 childElement = clone;
411 element.after(clone);
412 });
413 }
414 });
415 };
416 }
417 };
418 }]);
419 /**
420 * General-purpose jQuery wrapper. Simply pass the plugin name as the expression.
421 *
422 * It is possible to specify a default set of parameters for each jQuery plugin.
423 * Under the jq key, namespace each plugin by that which will be passed to ui-jq.
424 * Unfortunately, at this time you can only pre-define the first parameter.
425 * @example { jq : { datepicker : { showOn:'click' } } }
426 *
427 * @param ui-jq {string} The $elm.[pluginName]() to call.
428 * @param [ui-options] {mixed} Expression to be evaluated and passed as options to the function
429 * Multiple parameters can be separated by commas
430 * @param [ui-refresh] {expression} Watch expression and refire plugin on changes
431 *
432 * @example <input ui-jq="datepicker" ui-options="{showOn:'click'},secondParameter,thirdParameter" ui-refresh="iChange">
433 */
434 angular.module('ui.directives').directive('uiJq', ['ui.config', '$timeout', function uiJqInjectingFunction(uiConfig, $timeout) {
435
436 return {
437 restrict: 'A',
438 compile: function uiJqCompilingFunction(tElm, tAttrs) {
439
440 if (!angular.isFunction(tElm[tAttrs.uiJq])) {
441 throw new Error('ui-jq: The "' + tAttrs.uiJq + '" function does not exist');
442 }
443 var options = uiConfig.jq && uiConfig.jq[tAttrs.uiJq];
444
445 return function uiJqLinkingFunction(scope, elm, attrs) {
446
447 var linkOptions = [];
448
449 // If ui-options are passed, merge (or override) them onto global defaults and pass to the jQuery method
450 if (attrs.uiOptions) {
451 linkOptions = scope.$eval('[' + attrs.uiOptions + ']');
452 if (angular.isObject(options) && angular.isObject(linkOptions[0])) {
453 linkOptions[0] = angular.extend({}, options, linkOptions[0]);
454 }
455 } else if (options) {
456 linkOptions = [options];
457 }
458 // If change compatibility is enabled, the form input's "change" event will trigger an "input" event
459 if (attrs.ngModel && elm.is('select,input,textarea')) {
460 elm.on('change', function() {
461 elm.trigger('input');
462 });
463 }
464
465 // Call jQuery method and pass relevant options
466 function callPlugin() {
467 $timeout(function() {
468 elm[attrs.uiJq].apply(elm, linkOptions);
469 }, 0, false);
470 }
471
472 // If ui-refresh is used, re-fire the the method upon every change
473 if (attrs.uiRefresh) {
474 scope.$watch(attrs.uiRefresh, function(newVal) {
475 callPlugin();
476 });
477 }
478 callPlugin();
479 };
480 }
481 };
482 }]);
483
484 angular.module('ui.directives').factory('keypressHelper', ['$parse', function keypress($parse){
485 var keysByCode = {
486 8: 'backspace',
487 9: 'tab',
488 13: 'enter',
489 27: 'esc',
490 32: 'space',
491 33: 'pageup',
492 34: 'pagedown',
493 35: 'end',
494 36: 'home',
495 37: 'left',
496 38: 'up',
497 39: 'right',
498 40: 'down',
499 45: 'insert',
500 46: 'delete'
501 };
502
503 var capitaliseFirstLetter = function (string) {
504 return string.charAt(0).toUpperCase() + string.slice(1);
505 };
506
507 return function(mode, scope, elm, attrs) {
508 var params, combinations = [];
509 params = scope.$eval(attrs['ui'+capitaliseFirstLetter(mode)]);
510
511 // Prepare combinations for simple checking
512 angular.forEach(params, function (v, k) {
513 var combination, expression;
514 expression = $parse(v);
515
516 angular.forEach(k.split(' '), function(variation) {
517 combination = {
518 expression: expression,
519 keys: {}
520 };
521 angular.forEach(variation.split('-'), function (value) {
522 combination.keys[value] = true;
523 });
524 combinations.push(combination);
525 });
526 });
527
528 // Check only matching of pressed keys one of the conditions
529 elm.bind(mode, function (event) {
530 // No need to do that inside the cycle
531 var altPressed = event.metaKey || event.altKey;
532 var ctrlPressed = event.ctrlKey;
533 var shiftPressed = event.shiftKey;
534 var keyCode = event.keyCode;
535
536 // normalize keycodes
537 if (mode === 'keypress' && !shiftPressed && keyCode >= 97 && keyCode <= 122) {
538 keyCode = keyCode - 32;
539 }
540
541 // Iterate over prepared combinations
542 angular.forEach(combinations, function (combination) {
543
544 var mainKeyPressed = (combination.keys[keysByCode[event.keyCode]] || combination.keys[event.keyCode.toString()]) || false;
545
546 var altRequired = combination.keys.alt || false;
547 var ctrlRequired = combination.keys.ctrl || false;
548 var shiftRequired = combination.keys.shift || false;
549
550 if (
551 mainKeyPressed &&
552 ( altRequired == altPressed ) &&
553 ( ctrlRequired == ctrlPressed ) &&
554 ( shiftRequired == shiftPressed )
555 ) {
556 // Run the function
557 scope.$apply(function () {
558 combination.expression(scope, { '$event': event });
559 });
560 }
561 });
562 });
563 };
564 }]);
565
566 /**
567 * Bind one or more handlers to particular keys or their combination
568 * @param hash {mixed} keyBindings Can be an object or string where keybinding expression of keys or keys combinations and AngularJS Exspressions are set. Object syntax: "{ keys1: expression1 [, keys2: expression2 [ , ... ]]}". String syntax: ""expression1 on keys1 [ and expression2 on keys2 [ and ... ]]"". Expression is an AngularJS Expression, and key(s) are dash-separated combinations of keys and modifiers (one or many, if any. Order does not matter). Supported modifiers are 'ctrl', 'shift', 'alt' and key can be used either via its keyCode (13 for Return) or name. Named keys are 'backspace', 'tab', 'enter', 'esc', 'space', 'pageup', 'pagedown', 'end', 'home', 'left', 'up', 'right', 'down', 'insert', 'delete'.
569 * @example <input ui-keypress="{enter:'x = 1', 'ctrl-shift-space':'foo()', 'shift-13':'bar()'}" /> <input ui-keypress="foo = 2 on ctrl-13 and bar('hello') on shift-esc" />
570 **/
571 angular.module('ui.directives').directive('uiKeydown', ['keypressHelper', function(keypressHelper){
572 return {
573 link: function (scope, elm, attrs) {
574 keypressHelper('keydown', scope, elm, attrs);
575 }
576 };
577 }]);
578
579 angular.module('ui.directives').directive('uiKeypress', ['keypressHelper', function(keypressHelper){
580 return {
581 link: function (scope, elm, attrs) {
582 keypressHelper('keypress', scope, elm, attrs);
583 }
584 };
585 }]);
586
587 angular.module('ui.directives').directive('uiKeyup', ['keypressHelper', function(keypressHelper){
588 return {
589 link: function (scope, elm, attrs) {
590 keypressHelper('keyup', scope, elm, attrs);
591 }
592 };
593 }]);
594 (function () {
595 var app = angular.module('ui.directives');
596
597 //Setup map events from a google map object to trigger on a given element too,
598 //then we just use ui-event to catch events from an element
599 function bindMapEvents(scope, eventsStr, googleObject, element) {
600 angular.forEach(eventsStr.split(' '), function (eventName) {
601 //Prefix all googlemap events with 'map-', so eg 'click'
602 //for the googlemap doesn't interfere with a normal 'click' event
603 var $event = { type: 'map-' + eventName };
604 google.maps.event.addListener(googleObject, eventName, function (evt) {
605 element.triggerHandler(angular.extend({}, $event, evt));
606 //We create an $apply if it isn't happening. we need better support for this
607 //We don't want to use timeout because tons of these events fire at once,
608 //and we only need one $apply
609 if (!scope.$$phase) scope.$apply();
610 });
611 });
612 }
613
614 app.directive('uiMap',
615 ['ui.config', '$parse', function (uiConfig, $parse) {
616
617 var mapEvents = 'bounds_changed center_changed click dblclick drag dragend ' +
618 'dragstart heading_changed idle maptypeid_changed mousemove mouseout ' +
619 'mouseover projection_changed resize rightclick tilesloaded tilt_changed ' +
620 'zoom_changed';
621 var options = uiConfig.map || {};
622
623 return {
624 restrict: 'A',
625 //doesn't work as E for unknown reason
626 link: function (scope, elm, attrs) {
627 var opts = angular.extend({}, options, scope.$eval(attrs.uiOptions));
628 var map = new google.maps.Map(elm[0], opts);
629 var model = $parse(attrs.uiMap);
630
631 //Set scope variable for the map
632 model.assign(scope, map);
633
634 bindMapEvents(scope, mapEvents, map, elm);
635 }
636 };
637 }]);
638
639 app.directive('uiMapInfoWindow',
640 ['ui.config', '$parse', '$compile', function (uiConfig, $parse, $compile) {
641
642 var infoWindowEvents = 'closeclick content_change domready ' +
643 'position_changed zindex_changed';
644 var options = uiConfig.mapInfoWindow || {};
645
646 return {
647 link: function (scope, elm, attrs) {
648 var opts = angular.extend({}, options, scope.$eval(attrs.uiOptions));
649 opts.content = elm[0];
650 var model = $parse(attrs.uiMapInfoWindow);
651 var infoWindow = model(scope);
652
653 if (!infoWindow) {
654 infoWindow = new google.maps.InfoWindow(opts);
655 model.assign(scope, infoWindow);
656 }
657
658 bindMapEvents(scope, infoWindowEvents, infoWindow, elm);
659
660 /* The info window's contents dont' need to be on the dom anymore,
661 google maps has them stored. So we just replace the infowindow element
662 with an empty div. (we don't just straight remove it from the dom because
663 straight removing things from the dom can mess up angular) */
664 elm.replaceWith('<div></div>');
665
666 //Decorate infoWindow.open to $compile contents before opening
667 var _open = infoWindow.open;
668 infoWindow.open = function open(a1, a2, a3, a4, a5, a6) {
669 $compile(elm.contents())(scope);
670 _open.call(infoWindow, a1, a2, a3, a4, a5, a6);
671 };
672 }
673 };
674 }]);
675
676 /*
677 * Map overlay directives all work the same. Take map marker for example
678 * <ui-map-marker="myMarker"> will $watch 'myMarker' and each time it changes,
679 * it will hook up myMarker's events to the directive dom element. Then
680 * ui-event will be able to catch all of myMarker's events. Super simple.
681 */
682 function mapOverlayDirective(directiveName, events) {
683 app.directive(directiveName, [function () {
684 return {
685 restrict: 'A',
686 link: function (scope, elm, attrs) {
687 scope.$watch(attrs[directiveName], function (newObject) {
688 bindMapEvents(scope, events, newObject, elm);
689 });
690 }
691 };
692 }]);
693 }
694
695 mapOverlayDirective('uiMapMarker',
696 'animation_changed click clickable_changed cursor_changed ' +
697 'dblclick drag dragend draggable_changed dragstart flat_changed icon_changed ' +
698 'mousedown mouseout mouseover mouseup position_changed rightclick ' +
699 'shadow_changed shape_changed title_changed visible_changed zindex_changed');
700
701 mapOverlayDirective('uiMapPolyline',
702 'click dblclick mousedown mousemove mouseout mouseover mouseup rightclick');
703
704 mapOverlayDirective('uiMapPolygon',
705 'click dblclick mousedown mousemove mouseout mouseover mouseup rightclick');
706
707 mapOverlayDirective('uiMapRectangle',
708 'bounds_changed click dblclick mousedown mousemove mouseout mouseover ' +
709 'mouseup rightclick');
710
711 mapOverlayDirective('uiMapCircle',
712 'center_changed click dblclick mousedown mousemove ' +
713 'mouseout mouseover mouseup radius_changed rightclick');
714
715 mapOverlayDirective('uiMapGroundOverlay',
716 'click dblclick');
717
718 })();
719 /*
720 Attaches jquery-ui input mask onto input element
721 */
722 angular.module('ui.directives').directive('uiMask', [
723 function () {
724 return {
725 require:'ngModel',
726 link:function ($scope, element, attrs, controller) {
727
728 /* We override the render method to run the jQuery mask plugin
729 */
730 controller.$render = function () {
731 var value = controller.$viewValue || '';
732 element.val(value);
733 element.mask($scope.$eval(attrs.uiMask));
734 };
735
736 /* Add a parser that extracts the masked value into the model but only if the mask is valid
737 */
738 controller.$parsers.push(function (value) {
739 //the second check (or) is only needed due to the fact that element.isMaskValid() will keep returning undefined
740 //until there was at least one key event
741 var isValid = element.isMaskValid() || angular.isUndefined(element.isMaskValid()) && element.val().length>0;
742 controller.$setValidity('mask', isValid);
743 return isValid ? value : undefined;
744 });
745
746 /* When keyup, update the view value
747 */
748 element.bind('keyup', function () {
749 $scope.$apply(function () {
750 controller.$setViewValue(element.mask());
751 });
752 });
753 }
754 };
755 }
756 ]);
757
758 /**
759 * Add a clear button to form inputs to reset their value
760 */
761 angular.module('ui.directives').directive('uiReset', ['ui.config', function (uiConfig) {
762 var resetValue = null;
763 if (uiConfig.reset !== undefined)
764 resetValue = uiConfig.reset;
765 return {
766 require: 'ngModel',
767 link: function (scope, elm, attrs, ctrl) {
768 var aElement;
769 aElement = angular.element('<a class="ui-reset" />');
770 elm.wrap('<span class="ui-resetwrap" />').after(aElement);
771 aElement.bind('click', function (e) {
772 e.preventDefault();
773 scope.$apply(function () {
774 if (attrs.uiReset)
775 ctrl.$setViewValue(scope.$eval(attrs.uiReset));
776 else
777 ctrl.$setViewValue(resetValue);
778 ctrl.$render();
779 });
780 });
781 }
782 };
783 }]);
784
785 /**
786 * Set a $uiRoute boolean to see if the current route matches
787 */
788 angular.module('ui.directives').directive('uiRoute', ['$location', '$parse', function ($location, $parse) {
789 return {
790 restrict: 'AC',
791 compile: function(tElement, tAttrs) {
792 var useProperty;
793 if (tAttrs.uiRoute) {
794 useProperty = 'uiRoute';
795 } else if (tAttrs.ngHref) {
796 useProperty = 'ngHref';
797 } else if (tAttrs.href) {
798 useProperty = 'href';
799 } else {
800 throw new Error('uiRoute missing a route or href property on ' + tElement[0]);
801 }
802 return function ($scope, elm, attrs) {
803 var modelSetter = $parse(attrs.ngModel || attrs.routeModel || '$uiRoute').assign;
804 var watcher = angular.noop;
805
806 // Used by href and ngHref
807 function staticWatcher(newVal) {
808 if ((hash = newVal.indexOf('#')) > -1)
809 newVal = newVal.substr(hash + 1);
810 watcher = function watchHref() {
811 modelSetter($scope, ($location.path().indexOf(newVal) > -1));
812 };
813 watcher();
814 }
815 // Used by uiRoute
816 function regexWatcher(newVal) {
817 if ((hash = newVal.indexOf('#')) > -1)
818 newVal = newVal.substr(hash + 1);
819 watcher = function watchRegex() {
820 var regexp = new RegExp('^' + newVal + '$', ['i']);
821 modelSetter($scope, regexp.test($location.path()));
822 };
823 watcher();
824 }
825
826 switch (useProperty) {
827 case 'uiRoute':
828 // if uiRoute={{}} this will be undefined, otherwise it will have a value and $observe() never gets triggered
829 if (attrs.uiRoute)
830 regexWatcher(attrs.uiRoute);
831 else
832 attrs.$observe('uiRoute', regexWatcher);
833 break;
834 case 'ngHref':
835 // Setup watcher() every time ngHref changes
836 if (attrs.ngHref)
837 staticWatcher(attrs.ngHref);
838 else
839 attrs.$observe('ngHref', staticWatcher);
840 break;
841 case 'href':
842 // Setup watcher()
843 staticWatcher(attrs.href);
844 }
845
846 $scope.$on('$routeChangeSuccess', function(){
847 watcher();
848 });
849 }
850 }
851 };
852 }]);
853
854 /*global angular, $, document*/
855 /**
856 * Adds a 'ui-scrollfix' class to the element when the page scrolls past it's position.
857 * @param [offset] {int} optional Y-offset to override the detected offset.
858 * Takes 300 (absolute) or -300 or +300 (relative to detected)
859 */
860 angular.module('ui.directives').directive('uiScrollfix', ['$window', function ($window) {
861 'use strict';
862 return {
863 link: function (scope, elm, attrs) {
864 var top = elm.offset().top;
865 if (!attrs.uiScrollfix) {
866 attrs.uiScrollfix = top;
867 } else {
868 // chartAt is generally faster than indexOf: http://jsperf.com/indexof-vs-chartat
869 if (attrs.uiScrollfix.charAt(0) === '-') {
870 attrs.uiScrollfix = top - attrs.uiScrollfix.substr(1);
871 } else if (attrs.uiScrollfix.charAt(0) === '+') {
872 attrs.uiScrollfix = top + parseFloat(attrs.uiScrollfix.substr(1));
873 }
874 }
875 angular.element($window).on('scroll.ui-scrollfix', function () {
876 // if pageYOffset is defined use it, otherwise use other crap for IE
877 var offset;
878 if (angular.isDefined($window.pageYOffset)) {
879 offset = $window.pageYOffset;
880 } else {
881 var iebody = (document.compatMode && document.compatMode !== "BackCompat") ? document.documentElement : document.body;
882 offset = iebody.scrollTop;
883 }
884 if (!elm.hasClass('ui-scrollfix') && offset > attrs.uiScrollfix) {
885 elm.addClass('ui-scrollfix');
886 } else if (elm.hasClass('ui-scrollfix') && offset < attrs.uiScrollfix) {
887 elm.removeClass('ui-scrollfix');
888 }
889 });
890 }
891 };
892 }]);
893
894 /**
895 * Enhanced Select2 Dropmenus
896 *
897 * @AJAX Mode - When in this mode, your value will be an object (or array of objects) of the data used by Select2
898 * This change is so that you do not have to do an additional query yourself on top of Select2's own query
899 * @params [options] {object} The configuration options passed to $.fn.select2(). Refer to the documentation
900 */
901 angular.module('ui.directives').directive('uiSelect2', ['ui.config', '$timeout', function (uiConfig, $timeout) {
902 var options = {};
903 if (uiConfig.select2) {
904 angular.extend(options, uiConfig.select2);
905 }
906 return {
907 require: '?ngModel',
908 compile: function (tElm, tAttrs) {
909 var watch,
910 repeatOption,
911 repeatAttr,
912 isSelect = tElm.is('select'),
913 isMultiple = (tAttrs.multiple !== undefined);
914
915 // Enable watching of the options dataset if in use
916 if (tElm.is('select')) {
917 repeatOption = tElm.find('option[ng-repeat], option[data-ng-repeat]');
918
919 if (repeatOption.length) {
920 repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');
921 watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();
922 }
923 }
924
925 return function (scope, elm, attrs, controller) {
926 // instance-specific options
927 var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
928
929 if (isSelect) {
930 // Use <select multiple> instead
931 delete opts.multiple;
932 delete opts.initSelection;
933 } else if (isMultiple) {
934 opts.multiple = true;
935 }
936
937 if (controller) {
938 // Watch the model for programmatic changes
939 controller.$render = function () {
940 if (isSelect) {
941 elm.select2('val', controller.$modelValue);
942 } else {
943 if (isMultiple) {
944 if (!controller.$modelValue) {
945 elm.select2('data', []);
946 } else if (angular.isArray(controller.$modelValue)) {
947 elm.select2('data', controller.$modelValue);
948 } else {
949 elm.select2('val', controller.$modelValue);
950 }
951 } else {
952 if (angular.isObject(controller.$modelValue)) {
953 elm.select2('data', controller.$modelValue);
954 } else {
955 elm.select2('val', controller.$modelValue);
956 }
957 }
958 }
959 };
960
961 // Watch the options dataset for changes
962 if (watch) {
963 scope.$watch(watch, function (newVal, oldVal, scope) {
964 if (!newVal) return;
965 // Delayed so that the options have time to be rendered
966 $timeout(function () {
967 elm.select2('val', controller.$viewValue);
968 // Refresh angular to remove the superfluous option
969 elm.trigger('change');
970 });
971 });
972 }
973
974 if (!isSelect) {
975 // Set the view and model value and update the angular template manually for the ajax/multiple select2.
976 elm.bind("change", function () {
977 scope.$apply(function () {
978 controller.$setViewValue(elm.select2('data'));
979 });
980 });
981
982 if (opts.initSelection) {
983 var initSelection = opts.initSelection;
984 opts.initSelection = function (element, callback) {
985 initSelection(element, function (value) {
986 controller.$setViewValue(value);
987 callback(value);
988 });
989 };
990 }
991 }
992 }
993
994 attrs.$observe('disabled', function (value) {
995 elm.select2(value && 'disable' || 'enable');
996 });
997
998 if (attrs.ngMultiple) {
999 scope.$watch(attrs.ngMultiple, function(newVal) {
1000 elm.select2(opts);
1001 });
1002 }
1003
1004 // Set initial value since Angular doesn't
1005 elm.val(scope.$eval(attrs.ngModel));
1006
1007 // Initialize the plugin late so that the injected DOM does not disrupt the template compiler
1008 $timeout(function () {
1009 elm.select2(opts);
1010 // Not sure if I should just check for !isSelect OR if I should check for 'tags' key
1011 if (!opts.initSelection && !isSelect)
1012 controller.$setViewValue(elm.select2('data'));
1013 });
1014 };
1015 }
1016 };
1017 }]);
1018
1019 /**
1020 * uiShow Directive
1021 *
1022 * Adds a 'ui-show' class to the element instead of display:block
1023 * Created to allow tighter control of CSS without bulkier directives
1024 *
1025 * @param expression {boolean} evaluated expression to determine if the class should be added
1026 */
1027 angular.module('ui.directives').directive('uiShow', [function () {
1028 return function (scope, elm, attrs) {
1029 scope.$watch(attrs.uiShow, function (newVal, oldVal) {
1030 if (newVal) {
1031 elm.addClass('ui-show');
1032 } else {
1033 elm.removeClass('ui-show');
1034 }
1035 });
1036 };
1037 }])
1038
1039 /**
1040 * uiHide Directive
1041 *
1042 * Adds a 'ui-hide' class to the element instead of display:block
1043 * Created to allow tighter control of CSS without bulkier directives
1044 *
1045 * @param expression {boolean} evaluated expression to determine if the class should be added
1046 */
1047 .directive('uiHide', [function () {
1048 return function (scope, elm, attrs) {
1049 scope.$watch(attrs.uiHide, function (newVal, oldVal) {
1050 if (newVal) {
1051 elm.addClass('ui-hide');
1052 } else {
1053 elm.removeClass('ui-hide');
1054 }
1055 });
1056 };
1057 }])
1058
1059 /**
1060 * uiToggle Directive
1061 *
1062 * Adds a class 'ui-show' if true, and a 'ui-hide' if false to the element instead of display:block/display:none
1063 * Created to allow tighter control of CSS without bulkier directives. This also allows you to override the
1064 * default visibility of the element using either class.
1065 *
1066 * @param expression {boolean} evaluated expression to determine if the class should be added
1067 */
1068 .directive('uiToggle', [function () {
1069 return function (scope, elm, attrs) {
1070 scope.$watch(attrs.uiToggle, function (newVal, oldVal) {
1071 if (newVal) {
1072 elm.removeClass('ui-hide').addClass('ui-show');
1073 } else {
1074 elm.removeClass('ui-show').addClass('ui-hide');
1075 }
1076 });
1077 };
1078 }]);
1079
1080 /*
1081 jQuery UI Sortable plugin wrapper
1082
1083 @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config
1084 */
1085 angular.module('ui.directives').directive('uiSortable', [
1086 'ui.config', function(uiConfig) {
1087 return {
1088 require: '?ngModel',
1089 link: function(scope, element, attrs, ngModel) {
1090 var onReceive, onRemove, onStart, onUpdate, opts, _receive, _remove, _start, _update;
1091
1092 opts = angular.extend({}, uiConfig.sortable, scope.$eval(attrs.uiSortable));
1093
1094 if (ngModel) {
1095
1096 ngModel.$render = function() {
1097 element.sortable( "refresh" );
1098 };
1099
1100 onStart = function(e, ui) {
1101 // Save position of dragged item
1102 ui.item.sortable = { index: ui.item.index() };
1103 };
1104
1105 onUpdate = function(e, ui) {
1106 // For some reason the reference to ngModel in stop() is wrong
1107 ui.item.sortable.resort = ngModel;
1108 };
1109
1110 onReceive = function(e, ui) {
1111 ui.item.sortable.relocate = true;
1112 // added item to array into correct position and set up flag
1113 ngModel.$modelValue.splice(ui.item.index(), 0, ui.item.sortable.moved);
1114 };
1115
1116 onRemove = function(e, ui) {
1117 // copy data into item
1118 if (ngModel.$modelValue.length === 1) {
1119 ui.item.sortable.moved = ngModel.$modelValue.splice(0, 1)[0];
1120 } else {
1121 ui.item.sortable.moved = ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0];
1122 }
1123 };
1124
1125 onStop = function(e, ui) {
1126 // digest all prepared changes
1127 if (ui.item.sortable.resort && !ui.item.sortable.relocate) {
1128
1129 // Fetch saved and current position of dropped element
1130 var end, start;
1131 start = ui.item.sortable.index;
1132 end = ui.item.index();
1133 if (start < end)
1134 end--;
1135
1136 // Reorder array and apply change to scope
1137 ui.item.sortable.resort.$modelValue.splice(end, 0, ui.item.sortable.resort.$modelValue.splice(start, 1)[0]);
1138
1139 }
1140 if (ui.item.sortable.resort || ui.item.sortable.relocate) {
1141 scope.$apply();
1142 }
1143 };
1144
1145 // If user provided 'start' callback compose it with onStart function
1146 _start = opts.start;
1147 opts.start = function(e, ui) {
1148 onStart(e, ui);
1149 if (typeof _start === "function")
1150 _start(e, ui);
1151 };
1152
1153 // If user provided 'start' callback compose it with onStart function
1154 _stop = opts.stop;
1155 opts.stop = function(e, ui) {
1156 onStop(e, ui);
1157 if (typeof _stop === "function")
1158 _stop(e, ui);
1159 };
1160
1161 // If user provided 'update' callback compose it with onUpdate function
1162 _update = opts.update;
1163 opts.update = function(e, ui) {
1164 onUpdate(e, ui);
1165 if (typeof _update === "function")
1166 _update(e, ui);
1167 };
1168
1169 // If user provided 'receive' callback compose it with onReceive function
1170 _receive = opts.receive;
1171 opts.receive = function(e, ui) {
1172 onReceive(e, ui);
1173 if (typeof _receive === "function")
1174 _receive(e, ui);
1175 };
1176
1177 // If user provided 'remove' callback compose it with onRemove function
1178 _remove = opts.remove;
1179 opts.remove = function(e, ui) {
1180 onRemove(e, ui);
1181 if (typeof _remove === "function")
1182 _remove(e, ui);
1183 };
1184 }
1185
1186 // Create sortable
1187 element.sortable(opts);
1188 }
1189 };
1190 }
1191 ]);
1192
1193 /**
1194 * Binds a TinyMCE widget to <textarea> elements.
1195 */
1196 angular.module('ui.directives').directive('uiTinymce', ['ui.config', function (uiConfig) {
1197 uiConfig.tinymce = uiConfig.tinymce || {};
1198 return {
1199 require: 'ngModel',
1200 link: function (scope, elm, attrs, ngModel) {
1201 var expression,
1202 options = {
1203 // Update model on button click
1204 onchange_callback: function (inst) {
1205 if (inst.isDirty()) {
1206 inst.save();
1207 ngModel.$setViewValue(elm.val());
1208 if (!scope.$$phase)
1209 scope.$apply();
1210 }
1211 },
1212 // Update model on keypress
1213 handle_event_callback: function (e) {
1214 if (this.isDirty()) {
1215 this.save();
1216 ngModel.$setViewValue(elm.val());
1217 if (!scope.$$phase)
1218 scope.$apply();
1219 }
1220 return true; // Continue handling
1221 },
1222 // Update model when calling setContent (such as from the source editor popup)
1223 setup: function (ed) {
1224 ed.onSetContent.add(function (ed, o) {
1225 if (ed.isDirty()) {
1226 ed.save();
1227 ngModel.$setViewValue(elm.val());
1228 if (!scope.$$phase)
1229 scope.$apply();
1230 }
1231 });
1232 }
1233 };
1234 if (attrs.uiTinymce) {
1235 expression = scope.$eval(attrs.uiTinymce);
1236 } else {
1237 expression = {};
1238 }
1239 angular.extend(options, uiConfig.tinymce, expression);
1240 setTimeout(function () {
1241 elm.tinymce(options);
1242 });
1243 }
1244 };
1245 }]);
1246
1247 /**
1248 * General-purpose validator for ngModel.
1249 * angular.js comes with several built-in validation mechanism for input fields (ngRequired, ngPattern etc.) but using
1250 * an arbitrary validation function requires creation of a custom formatters and / or parsers.
1251 * The ui-validate directive makes it easy to use any function(s) defined in scope as a validator function(s).
1252 * A validator function will trigger validation on both model and input changes.
1253 *
1254 * @example <input ui-validate=" 'myValidatorFunction($value)' ">
1255 * @example <input ui-validate="{ foo : '$value > anotherModel', bar : 'validateFoo($value)' }">
1256 * @example <input ui-validate="{ foo : '$value > anotherModel' }" ui-validate-watch=" 'anotherModel' ">
1257 * @example <input ui-validate="{ foo : '$value > anotherModel', bar : 'validateFoo($value)' }" ui-validate-watch=" { foo : 'anotherModel' } ">
1258 *
1259 * @param ui-validate {string|object literal} If strings is passed it should be a scope's function to be used as a validator.
1260 * If an object literal is passed a key denotes a validation error key while a value should be a validator function.
1261 * In both cases validator function should take a value to validate as its argument and should return true/false indicating a validation result.
1262 */
1263 angular.module('ui.directives').directive('uiValidate', function () {
1264
1265 return {
1266 restrict: 'A',
1267 require: 'ngModel',
1268 link: function (scope, elm, attrs, ctrl) {
1269 var validateFn, watch, validators = {},
1270 validateExpr = scope.$eval(attrs.uiValidate);
1271
1272 if (!validateExpr) return;
1273
1274 if (angular.isString(validateExpr)) {
1275 validateExpr = { validator: validateExpr };
1276 }
1277
1278 angular.forEach(validateExpr, function (expression, key) {
1279 validateFn = function (valueToValidate) {
1280 if (scope.$eval(expression, { '$value' : valueToValidate })) {
1281 ctrl.$setValidity(key, true);
1282 return valueToValidate;
1283 } else {
1284 ctrl.$setValidity(key, false);
1285 return undefined;
1286 }
1287 };
1288 validators[key] = validateFn;
1289 ctrl.$formatters.push(validateFn);
1290 ctrl.$parsers.push(validateFn);
1291 });
1292
1293 // Support for ui-validate-watch
1294 if (attrs.uiValidateWatch) {
1295 watch = scope.$eval(attrs.uiValidateWatch);
1296 if (angular.isString(watch)) {
1297 scope.$watch(watch, function(){
1298 angular.forEach(validators, function(validatorFn, key){
1299 validatorFn(ctrl.$modelValue);
1300 });
1301 });
1302 } else {
1303 angular.forEach(watch, function(expression, key){
1304 scope.$watch(expression, function(){
1305 validators[key](ctrl.$modelValue);
1306 });
1307 });
1308 }
1309 }
1310 }
1311 };
1312 });
1313
1314
1315 /**
1316 * A replacement utility for internationalization very similar to sprintf.
1317 *
1318 * @param replace {mixed} The tokens to replace depends on type
1319 * string: all instances of $0 will be replaced
1320 * array: each instance of $0, $1, $2 etc. will be placed with each array item in corresponding order
1321 * object: all attributes will be iterated through, with :key being replaced with its corresponding value
1322 * @return string
1323 *
1324 * @example: 'Hello :name, how are you :day'.format({ name:'John', day:'Today' })
1325 * @example: 'Records $0 to $1 out of $2 total'.format(['10', '20', '3000'])
1326 * @example: '$0 agrees to all mentions $0 makes in the event that $0 hits a tree while $0 is driving drunk'.format('Bob')
1327 */
1328 angular.module('ui.filters').filter('format', function(){
1329 return function(value, replace) {
1330 if (!value) {
1331 return value;
1332 }
1333 var target = value.toString(), token;
1334 if (replace === undefined) {
1335 return target;
1336 }
1337 if (!angular.isArray(replace) && !angular.isObject(replace)) {
1338 return target.split('$0').join(replace);
1339 }
1340 token = angular.isArray(replace) && '$' || ':';
1341
1342 angular.forEach(replace, function(value, key){
1343 target = target.split(token+key).join(value);
1344 });
1345 return target;
1346 };
1347 });
1348
1349 /**
1350 * Wraps the
1351 * @param text {string} haystack to search through
1352 * @param search {string} needle to search for
1353 * @param [caseSensitive] {boolean} optional boolean to use case-sensitive searching
1354 */
1355 angular.module('ui.filters').filter('highlight', function () {
1356 return function (text, search, caseSensitive) {
1357 if (search || angular.isNumber(search)) {
1358 text = text.toString();
1359 search = search.toString();
1360 if (caseSensitive) {
1361 return text.split(search).join('<span class="ui-match">' + search + '</span>');
1362 } else {
1363 return text.replace(new RegExp(search, 'gi'), '<span class="ui-match">$&</span>');
1364 }
1365 } else {
1366 return text;
1367 }
1368 };
1369 });
1370
1371 /**
1372 * Converts variable-esque naming conventions to something presentational, capitalized words separated by space.
1373 * @param {String} value The value to be parsed and prettified.
1374 * @param {String} [inflector] The inflector to use. Default: humanize.
1375 * @return {String}
1376 * @example {{ 'Here Is my_phoneNumber' | inflector:'humanize' }} => Here Is My Phone Number
1377 * {{ 'Here Is my_phoneNumber' | inflector:'underscore' }} => here_is_my_phone_number
1378 * {{ 'Here Is my_phoneNumber' | inflector:'variable' }} => hereIsMyPhoneNumber
1379 */
1380 angular.module('ui.filters').filter('inflector', function () {
1381 function ucwords(text) {
1382 return text.replace(/^([a-z])|\s+([a-z])/g, function ($1) {
1383 return $1.toUpperCase();
1384 });
1385 }
1386
1387 function breakup(text, separator) {
1388 return text.replace(/[A-Z]/g, function (match) {
1389 return separator + match;
1390 });
1391 }
1392
1393 var inflectors = {
1394 humanize: function (value) {
1395 return ucwords(breakup(value, ' ').split('_').join(' '));
1396 },
1397 underscore: function (value) {
1398 return value.substr(0, 1).toLowerCase() + breakup(value.substr(1), '_').toLowerCase().split(' ').join('_');
1399 },
1400 variable: function (value) {
1401 value = value.substr(0, 1).toLowerCase() + ucwords(value.split('_').join(' ')).substr(1).split(' ').join('');
1402 return value;
1403 }
1404 };
1405
1406 return function (text, inflector, separator) {
1407 if (inflector !== false && angular.isString(text)) {
1408 inflector = inflector || 'humanize';
1409 return inflectors[inflector](text);
1410 } else {
1411 return text;
1412 }
1413 };
1414 });
1415
1416 /**
1417 * Filters out all duplicate items from an array by checking the specified key
1418 * @param [key] {string} the name of the attribute of each object to compare for uniqueness
1419 if the key is empty, the entire object will be compared
1420 if the key === false then no filtering will be performed
1421 * @return {array}
1422 */
1423 angular.module('ui.filters').filter('unique', function () {
1424
1425 return function (items, filterOn) {
1426
1427 if (filterOn === false) {
1428 return items;
1429 }
1430
1431 if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
1432 var hashCheck = {}, newItems = [];
1433
1434 var extractValueToCompare = function (item) {
1435 if (angular.isObject(item) && angular.isString(filterOn)) {
1436 return item[filterOn];
1437 } else {
1438 return item;
1439 }
1440 };
1441
1442 angular.forEach(items, function (item) {
1443 var valueToCheck, isDuplicate = false;
1444
1445 for (var i = 0; i < newItems.length; i++) {
1446 if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {
1447 isDuplicate = true;
1448 break;
1449 }
1450 }
1451 if (!isDuplicate) {
1452 newItems.push(item);
1453 }
1454
1455 });
1456 items = newItems;
1457 }
1458 return items;
1459 };
1460 });
+0
-7
faraday/server/www/script/angular-ui.min.js less more
0 /**
1 * AngularUI - The companion suite for AngularJS
2 * @version v0.4.0 - 2013-02-15
3 * @link http://angular-ui.github.com
4 * @license MIT License, http://www.opensource.org/licenses/MIT
5 */
6 angular.module("ui.config",[]).value("ui.config",{}),angular.module("ui.filters",["ui.config"]),angular.module("ui.directives",["ui.config"]),angular.module("ui",["ui.filters","ui.directives","ui.config"]),angular.module("ui.directives").directive("uiAnimate",["ui.config","$timeout",function(e,t){var n={};return angular.isString(e.animate)?n["class"]=e.animate:e.animate&&(n=e.animate),{restrict:"A",link:function(e,r,i){var s={};i.uiAnimate&&(s=e.$eval(i.uiAnimate),angular.isString(s)&&(s={"class":s})),s=angular.extend({"class":"ui-animate"},n,s),r.addClass(s["class"]),t(function(){r.removeClass(s["class"])},20,!1)}}}]),angular.module("ui.directives").directive("uiCalendar",["ui.config","$parse",function(e,t){return e.uiCalendar=e.uiCalendar||{},{require:"ngModel",restrict:"A",link:function(t,n,r,i){function a(){t.calendar=n.html("");var i=t.calendar.fullCalendar("getView");i&&(i=i.name);var o,u={defaultView:i,eventSources:s};r.uiCalendar?o=t.$eval(r.uiCalendar):o={},angular.extend(u,e.uiCalendar,o),t.calendar.fullCalendar(u)}var s=t.$eval(r.ngModel),o=0,u=function(){var e=t.$eval(r.equalsTracker);return o=0,angular.forEach(s,function(e,t){angular.isArray(e)&&(o+=e.length)}),angular.isNumber(e)?o+s.length+e:o+s.length};a(),t.$watch(u,function(e,t){a()})}}}]),angular.module("ui.directives").directive("uiCodemirror",["ui.config","$timeout",function(e,t){"use strict";var n=["cursorActivity","viewportChange","gutterClick","focus","blur","scroll","update"];return{restrict:"A",require:"ngModel",link:function(r,i,s,o){var u,a,f,l,c;if(i[0].type!=="textarea")throw new Error("uiCodemirror3 can only be applied to a textarea element");u=e.codemirror||{},a=angular.extend({},u,r.$eval(s.uiCodemirror)),f=function(e){return function(t,n){var i=t.getValue();i!==o.$viewValue&&(o.$setViewValue(i),r.$apply()),typeof e=="function"&&e(t,n)}},l=function(){c=CodeMirror.fromTextArea(i[0],a),c.on("change",f(a.onChange));for(var e=0,u=n.length,l;e<u;++e){l=a["on"+n[e].charAt(0).toUpperCase()+n[e].slice(1)];if(l===void 0)continue;if(typeof l!="function")continue;c.on(n[e],l)}o.$formatters.push(function(e){if(angular.isUndefined(e)||e===null)return"";if(angular.isObject(e)||angular.isArray(e))throw new Error("ui-codemirror cannot use an object or an array as a model");return e}),o.$render=function(){c.setValue(o.$viewValue)},s.uiRefresh&&r.$watch(s.uiRefresh,function(e,n){e!==n&&t(c.refresh)})},t(l)}}}]),angular.module("ui.directives").directive("uiCurrency",["ui.config","currencyFilter",function(e,t){var n={pos:"ui-currency-pos",neg:"ui-currency-neg",zero:"ui-currency-zero"};return e.currency&&angular.extend(n,e.currency),{restrict:"EAC",require:"ngModel",link:function(e,r,i,s){var o,u,a;o=angular.extend({},n,e.$eval(i.uiCurrency)),u=function(e){var n;return n=e*1,r.toggleClass(o.pos,n>0),r.toggleClass(o.neg,n<0),r.toggleClass(o.zero,n===0),e===""?r.text(""):r.text(t(n,o.symbol)),!0},s.$render=function(){a=s.$viewValue,r.val(a),u(a)}}}}]),angular.module("ui.directives").directive("uiDate",["ui.config",function(e){"use strict";var t;return t={},angular.isObject(e.date)&&angular.extend(t,e.date),{require:"?ngModel",link:function(t,n,r,i){var s=function(){return angular.extend({},e.date,t.$eval(r.uiDate))},o=function(){var e=s();if(i){var r=function(){t.$apply(function(){var e=n.datepicker("getDate");n.datepicker("setDate",n.val()),i.$setViewValue(e),n.blur()})};if(e.onSelect){var o=e.onSelect;e.onSelect=function(e,n){r(),t.$apply(function(){o(e,n)})}}else e.onSelect=r;n.bind("change",r),i.$render=function(){var e=i.$viewValue;if(angular.isDefined(e)&&e!==null&&!angular.isDate(e))throw new Error("ng-Model value must be a Date object - currently it is a "+typeof e+" - use ui-date-format to convert it from a string");n.datepicker("setDate",e)}}n.datepicker("destroy"),n.datepicker(e),i&&i.$render()};t.$watch(s,o,!0)}}}]).directive("uiDateFormat",["ui.config",function(e){var t={require:"ngModel",link:function(t,n,r,i){var s=r.uiDateFormat||e.dateFormat;s?(i.$formatters.push(function(e){if(angular.isString(e))return $.datepicker.parseDate(s,e)}),i.$parsers.push(function(e){if(e)return $.datepicker.formatDate(s,e)})):(i.$formatters.push(function(e){if(angular.isString(e))return new Date(e)}),i.$parsers.push(function(e){if(e)return e.toISOString()}))}};return t}]),angular.module("ui.directives").directive("uiEvent",["$parse",function(e){return function(t,n,r){var i=t.$eval(r.uiEvent);angular.forEach(i,function(r,i){var s=e(r);n.bind(i,function(e){var n=Array.prototype.slice.call(arguments);n=n.splice(1),t.$apply(function(){s(t,{$event:e,$params:n})})})})}}]),angular.module("ui.directives").directive("uiIf",[function(){return{transclude:"element",priority:1e3,terminal:!0,restrict:"A",compile:function(e,t,n){return function(e,t,r){var i,s;e.$watch(r.uiIf,function(r){i&&(i.remove(),i=undefined),s&&(s.$destroy(),s=undefined),r&&(s=e.$new(),n(s,function(e){i=e,t.after(e)}))})}}}}]),angular.module("ui.directives").directive("uiJq",["ui.config","$timeout",function(t,n){return{restrict:"A",compile:function(r,i){if(!angular.isFunction(r[i.uiJq]))throw new Error('ui-jq: The "'+i.uiJq+'" function does not exist');var s=t.jq&&t.jq[i.uiJq];return function(t,r,i){function u(){n(function(){r[i.uiJq].apply(r,o)},0,!1)}var o=[];i.uiOptions?(o=t.$eval("["+i.uiOptions+"]"),angular.isObject(s)&&angular.isObject(o[0])&&(o[0]=angular.extend({},s,o[0]))):s&&(o=[s]),i.ngModel&&r.is("select,input,textarea")&&r.on("change",function(){r.trigger("input")}),i.uiRefresh&&t.$watch(i.uiRefresh,function(e){u()}),u()}}}}]),angular.module("ui.directives").factory("keypressHelper",["$parse",function(t){var n={8:"backspace",9:"tab",13:"enter",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"delete"},r=function(e){return e.charAt(0).toUpperCase()+e.slice(1)};return function(e,i,s,o){var u,a=[];u=i.$eval(o["ui"+r(e)]),angular.forEach(u,function(e,n){var r,i;i=t(e),angular.forEach(n.split(" "),function(e){r={expression:i,keys:{}},angular.forEach(e.split("-"),function(e){r.keys[e]=!0}),a.push(r)})}),s.bind(e,function(t){var r=t.metaKey||t.altKey,s=t.ctrlKey,o=t.shiftKey,u=t.keyCode;e==="keypress"&&!o&&u>=97&&u<=122&&(u-=32),angular.forEach(a,function(e){var u=e.keys[n[t.keyCode]]||e.keys[t.keyCode.toString()]||!1,a=e.keys.alt||!1,f=e.keys.ctrl||!1,l=e.keys.shift||!1;u&&a==r&&f==s&&l==o&&i.$apply(function(){e.expression(i,{$event:t})})})})}}]),angular.module("ui.directives").directive("uiKeydown",["keypressHelper",function(e){return{link:function(t,n,r){e("keydown",t,n,r)}}}]),angular.module("ui.directives").directive("uiKeypress",["keypressHelper",function(e){return{link:function(t,n,r){e("keypress",t,n,r)}}}]),angular.module("ui.directives").directive("uiKeyup",["keypressHelper",function(e){return{link:function(t,n,r){e("keyup",t,n,r)}}}]),function(){function t(e,t,n,r){angular.forEach(t.split(" "),function(t){var i={type:"map-"+t};google.maps.event.addListener(n,t,function(t){r.triggerHandler(angular.extend({},i,t)),e.$$phase||e.$apply()})})}function n(n,r){e.directive(n,[function(){return{restrict:"A",link:function(e,i,s){e.$watch(s[n],function(n){t(e,r,n,i)})}}}])}var e=angular.module("ui.directives");e.directive("uiMap",["ui.config","$parse",function(e,n){var r="bounds_changed center_changed click dblclick drag dragend dragstart heading_changed idle maptypeid_changed mousemove mouseout mouseover projection_changed resize rightclick tilesloaded tilt_changed zoom_changed",i=e.map||{};return{restrict:"A",link:function(e,s,o){var u=angular.extend({},i,e.$eval(o.uiOptions)),a=new google.maps.Map(s[0],u),f=n(o.uiMap);f.assign(e,a),t(e,r,a,s)}}}]),e.directive("uiMapInfoWindow",["ui.config","$parse","$compile",function(e,n,r){var i="closeclick content_change domready position_changed zindex_changed",s=e.mapInfoWindow||{};return{link:function(e,o,u){var a=angular.extend({},s,e.$eval(u.uiOptions));a.content=o[0];var f=n(u.uiMapInfoWindow),l=f(e);l||(l=new google.maps.InfoWindow(a),f.assign(e,l)),t(e,i,l,o),o.replaceWith("<div></div>");var c=l.open;l.open=function(n,i,s,u,a,f){r(o.contents())(e),c.call(l,n,i,s,u,a,f)}}}}]),n("uiMapMarker","animation_changed click clickable_changed cursor_changed dblclick drag dragend draggable_changed dragstart flat_changed icon_changed mousedown mouseout mouseover mouseup position_changed rightclick shadow_changed shape_changed title_changed visible_changed zindex_changed"),n("uiMapPolyline","click dblclick mousedown mousemove mouseout mouseover mouseup rightclick"),n("uiMapPolygon","click dblclick mousedown mousemove mouseout mouseover mouseup rightclick"),n("uiMapRectangle","bounds_changed click dblclick mousedown mousemove mouseout mouseover mouseup rightclick"),n("uiMapCircle","center_changed click dblclick mousedown mousemove mouseout mouseover mouseup radius_changed rightclick"),n("uiMapGroundOverlay","click dblclick")}(),angular.module("ui.directives").directive("uiMask",[function(){return{require:"ngModel",link:function(e,t,n,r){r.$render=function(){var i=r.$viewValue||"";t.val(i),t.mask(e.$eval(n.uiMask))},r.$parsers.push(function(e){var n=t.isMaskValid()||angular.isUndefined(t.isMaskValid())&&t.val().length>0;return r.$setValidity("mask",n),n?e:undefined}),t.bind("keyup",function(){e.$apply(function(){r.$setViewValue(t.mask())})})}}}]),angular.module("ui.directives").directive("uiReset",["ui.config",function(e){var t=null;return e.reset!==undefined&&(t=e.reset),{require:"ngModel",link:function(e,n,r,i){var s;s=angular.element('<a class="ui-reset" />'),n.wrap('<span class="ui-resetwrap" />').after(s),s.bind("click",function(n){n.preventDefault(),e.$apply(function(){r.uiReset?i.$setViewValue(e.$eval(r.uiReset)):i.$setViewValue(t),i.$render()})})}}}]),angular.module("ui.directives").directive("uiRoute",["$location","$parse",function(e,t){return{restrict:"AC",compile:function(n,r){var i;if(r.uiRoute)i="uiRoute";else if(r.ngHref)i="ngHref";else{if(!r.href)throw new Error("uiRoute missing a route or href property on "+n[0]);i="href"}return function(n,r,s){function a(t){(hash=t.indexOf("#"))>-1&&(t=t.substr(hash+1)),u=function(){o(n,e.path().indexOf(t)>-1)},u()}function f(t){(hash=t.indexOf("#"))>-1&&(t=t.substr(hash+1)),u=function(){var i=new RegExp("^"+t+"$",["i"]);o(n,i.test(e.path()))},u()}var o=t(s.ngModel||s.routeModel||"$uiRoute").assign,u=angular.noop;switch(i){case"uiRoute":s.uiRoute?f(s.uiRoute):s.$observe("uiRoute",f);break;case"ngHref":s.ngHref?a(s.ngHref):s.$observe("ngHref",a);break;case"href":a(s.href)}n.$on("$routeChangeSuccess",function(){u()})}}}}]),angular.module("ui.directives").directive("uiScrollfix",["$window",function(e){"use strict";return{link:function(t,n,r){var i=n.offset().top;r.uiScrollfix?r.uiScrollfix.charAt(0)==="-"?r.uiScrollfix=i-r.uiScrollfix.substr(1):r.uiScrollfix.charAt(0)==="+"&&(r.uiScrollfix=i+parseFloat(r.uiScrollfix.substr(1))):r.uiScrollfix=i,angular.element(e).on("scroll.ui-scrollfix",function(){var t;if(angular.isDefined(e.pageYOffset))t=e.pageYOffset;else{var i=document.compatMode&&document.compatMode!=="BackCompat"?document.documentElement:document.body;t=i.scrollTop}!n.hasClass("ui-scrollfix")&&t>r.uiScrollfix?n.addClass("ui-scrollfix"):n.hasClass("ui-scrollfix")&&t<r.uiScrollfix&&n.removeClass("ui-scrollfix")})}}}]),angular.module("ui.directives").directive("uiSelect2",["ui.config","$timeout",function(e,t){var n={};return e.select2&&angular.extend(n,e.select2),{require:"?ngModel",compile:function(e,r){var i,s,o,u=e.is("select"),a=r.multiple!==undefined;return e.is("select")&&(s=e.find("option[ng-repeat], option[data-ng-repeat]"),s.length&&(o=s.attr("ng-repeat")||s.attr("data-ng-repeat"),i=jQuery.trim(o.split("|")[0]).split(" ").pop())),function(e,r,s,o){var f=angular.extend({},n,e.$eval(s.uiSelect2));u?(delete f.multiple,delete f.initSelection):a&&(f.multiple=!0);if(o){o.$render=function(){u?r.select2("val",o.$modelValue):a?o.$modelValue?angular.isArray(o.$modelValue)?r.select2("data",o.$modelValue):r.select2("val",o.$modelValue):r.select2("data",[]):angular.isObject(o.$modelValue)?r.select2("data",o.$modelValue):r.select2("val",o.$modelValue)},i&&e.$watch(i,function(e,n,i){if(!e)return;t(function(){r.select2("val",o.$viewValue),r.trigger("change")})});if(!u){r.bind("change",function(){e.$apply(function(){o.$setViewValue(r.select2("data"))})});if(f.initSelection){var l=f.initSelection;f.initSelection=function(e,t){l(e,function(e){o.$setViewValue(e),t(e)})}}}}s.$observe("disabled",function(e){r.select2(e&&"disable"||"enable")}),s.ngMultiple&&e.$watch(s.ngMultiple,function(e){r.select2(f)}),r.val(e.$eval(s.ngModel)),t(function(){r.select2(f),!f.initSelection&&!u&&o.$setViewValue(r.select2("data"))})}}}}]),angular.module("ui.directives").directive("uiShow",[function(){return function(e,t,n){e.$watch(n.uiShow,function(e,n){e?t.addClass("ui-show"):t.removeClass("ui-show")})}}]).directive("uiHide",[function(){return function(e,t,n){e.$watch(n.uiHide,function(e,n){e?t.addClass("ui-hide"):t.removeClass("ui-hide")})}}]).directive("uiToggle",[function(){return function(e,t,n){e.$watch(n.uiToggle,function(e,n){e?t.removeClass("ui-hide").addClass("ui-show"):t.removeClass("ui-show").addClass("ui-hide")})}}]),angular.module("ui.directives").directive("uiSortable",["ui.config",function(e){return{require:"?ngModel",link:function(t,n,r,i){var s,o,u,a,f,l,c,h,p;f=angular.extend({},e.sortable,t.$eval(r.uiSortable)),i&&(i.$render=function(){n.sortable("refresh")},u=function(e,t){t.item.sortable={index:t.item.index()}},a=function(e,t){t.item.sortable.resort=i},s=function(e,t){t.item.sortable.relocate=!0,i.$modelValue.splice(t.item.index(),0,t.item.sortable.moved)},o=function(e,t){i.$modelValue.length===1?t.item.sortable.moved=i.$modelValue.splice(0,1)[0]:t.item.sortable.moved=i.$modelValue.splice(t.item.sortable.index,1)[0]},onStop=function(e,n){if(n.item.sortable.resort&&!n.item.sortable.relocate){var r,i;i=n.item.sortable.index,r=n.item.index(),i<r&&r--,n.item.sortable.resort.$modelValue.splice(r,0,n.item.sortable.resort.$modelValue.splice(i,1)[0])}(n.item.sortable.resort||n.item.sortable.relocate)&&t.$apply()},h=f.start,f.start=function(e,t){u(e,t),typeof h=="function"&&h(e,t)},_stop=f.stop,f.stop=function(e,t){onStop(e,t),typeof _stop=="function"&&_stop(e,t)},p=f.update,f.update=function(e,t){a(e,t),typeof p=="function"&&p(e,t)},l=f.receive,f.receive=function(e,t){s(e,t),typeof l=="function"&&l(e,t)},c=f.remove,f.remove=function(e,t){o(e,t),typeof c=="function"&&c(e,t)}),n.sortable(f)}}}]),angular.module("ui.directives").directive("uiTinymce",["ui.config",function(e){return e.tinymce=e.tinymce||{},{require:"ngModel",link:function(t,n,r,i){var s,o={onchange_callback:function(e){e.isDirty()&&(e.save(),i.$setViewValue(n.val()),t.$$phase||t.$apply())},handle_event_callback:function(e){return this.isDirty()&&(this.save(),i.$setViewValue(n.val()),t.$$phase||t.$apply()),!0},setup:function(e){e.onSetContent.add(function(e,r){e.isDirty()&&(e.save(),i.$setViewValue(n.val()),t.$$phase||t.$apply())})}};r.uiTinymce?s=t.$eval(r.uiTinymce):s={},angular.extend(o,e.tinymce,s),setTimeout(function(){n.tinymce(o)})}}}]),angular.module("ui.directives").directive("uiValidate",function(){return{restrict:"A",require:"ngModel",link:function(e,t,n,r){var i,s,o={},u=e.$eval(n.uiValidate);if(!u)return;angular.isString(u)&&(u={validator:u}),angular.forEach(u,function(t,n){i=function(i){return e.$eval(t,{$value:i})?(r.$setValidity(n,!0),i):(r.$setValidity(n,!1),undefined)},o[n]=i,r.$formatters.push(i),r.$parsers.push(i)}),n.uiValidateWatch&&(s=e.$eval(n.uiValidateWatch),angular.isString(s)?e.$watch(s,function(){angular.forEach(o,function(e,t){e(r.$modelValue)})}):angular.forEach(s,function(t,n){e.$watch(t,function(){o[n](r.$modelValue)})}))}}}),angular.module("ui.filters").filter("format",function(){return function(e,t){if(!e)return e;var n=e.toString(),r;return t===undefined?n:!angular.isArray(t)&&!angular.isObject(t)?n.split("$0").join(t):(r=angular.isArray(t)&&"$"||":",angular.forEach(t,function(e,t){n=n.split(r+t).join(e)}),n)}}),angular.module("ui.filters").filter("highlight",function(){return function(e,t,n){return t||angular.isNumber(t)?(e=e.toString(),t=t.toString(),n?e.split(t).join('<span class="ui-match">'+t+"</span>"):e.replace(new RegExp(t,"gi"),'<span class="ui-match">$&</span>')):e}}),angular.module("ui.filters").filter("inflector",function(){function e(e){return e.replace(/^([a-z])|\s+([a-z])/g,function(e){return e.toUpperCase()})}function t(e,t){return e.replace(/[A-Z]/g,function(e){return t+e})}var n={humanize:function(n){return e(t(n," ").split("_").join(" "))},underscore:function(e){return e.substr(0,1).toLowerCase()+t(e.substr(1),"_").toLowerCase().split(" ").join("_")},variable:function(t){return t=t.substr(0,1).toLowerCase()+e(t.split("_").join(" ")).substr(1).split(" ").join(""),t}};return function(e,t,r){return t!==!1&&angular.isString(e)?(t=t||"humanize",n[t](e)):e}}),angular.module("ui.filters").filter("unique",function(){return function(e,t){if(t===!1)return e;if((t||angular.isUndefined(t))&&angular.isArray(e)){var n={},r=[],i=function(e){return angular.isObject(e)&&angular.isString(t)?e[t]:e};angular.forEach(e,function(e){var t,n=!1;for(var s=0;s<r.length;s++)if(angular.equals(i(r[s]),i(e))){n=!0;break}n||r.push(e)}),e=r}return e}});
+0
-28364
faraday/server/www/script/angular.js less more
0 /**
1 * @license AngularJS v1.4.3
2 * (c) 2010-2015 Google, Inc. http://angularjs.org
3 * License: MIT
4 */
5 (function(window, document, undefined) {'use strict';
6
7 /**
8 * @description
9 *
10 * This object provides a utility for producing rich Error messages within
11 * Angular. It can be called as follows:
12 *
13 * var exampleMinErr = minErr('example');
14 * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
15 *
16 * The above creates an instance of minErr in the example namespace. The
17 * resulting error will have a namespaced error code of example.one. The
18 * resulting error will replace {0} with the value of foo, and {1} with the
19 * value of bar. The object is not restricted in the number of arguments it can
20 * take.
21 *
22 * If fewer arguments are specified than necessary for interpolation, the extra
23 * interpolation markers will be preserved in the final string.
24 *
25 * Since data will be parsed statically during a build step, some restrictions
26 * are applied with respect to how minErr instances are created and called.
27 * Instances should have names of the form namespaceMinErr for a minErr created
28 * using minErr('namespace') . Error codes, namespaces and template strings
29 * should all be static strings, not variables or general expressions.
30 *
31 * @param {string} module The namespace to use for the new minErr instance.
32 * @param {function} ErrorConstructor Custom error constructor to be instantiated when returning
33 * error from returned function, for cases when a particular type of error is useful.
34 * @returns {function(code:string, template:string, ...templateArgs): Error} minErr instance
35 */
36
37 function minErr(module, ErrorConstructor) {
38 ErrorConstructor = ErrorConstructor || Error;
39 return function() {
40 var SKIP_INDEXES = 2;
41
42 var templateArgs = arguments,
43 code = templateArgs[0],
44 message = '[' + (module ? module + ':' : '') + code + '] ',
45 template = templateArgs[1],
46 paramPrefix, i;
47
48 message += template.replace(/\{\d+\}/g, function(match) {
49 var index = +match.slice(1, -1),
50 shiftedIndex = index + SKIP_INDEXES;
51
52 if (shiftedIndex < templateArgs.length) {
53 return toDebugString(templateArgs[shiftedIndex]);
54 }
55
56 return match;
57 });
58
59 message += '\nhttp://errors.angularjs.org/1.4.3/' +
60 (module ? module + '/' : '') + code;
61
62 for (i = SKIP_INDEXES, paramPrefix = '?'; i < templateArgs.length; i++, paramPrefix = '&') {
63 message += paramPrefix + 'p' + (i - SKIP_INDEXES) + '=' +
64 encodeURIComponent(toDebugString(templateArgs[i]));
65 }
66
67 return new ErrorConstructor(message);
68 };
69 }
70
71 /* We need to tell jshint what variables are being exported */
72 /* global angular: true,
73 msie: true,
74 jqLite: true,
75 jQuery: true,
76 slice: true,
77 splice: true,
78 push: true,
79 toString: true,
80 ngMinErr: true,
81 angularModule: true,
82 uid: true,
83 REGEX_STRING_REGEXP: true,
84 VALIDITY_STATE_PROPERTY: true,
85
86 lowercase: true,
87 uppercase: true,
88 manualLowercase: true,
89 manualUppercase: true,
90 nodeName_: true,
91 isArrayLike: true,
92 forEach: true,
93 forEachSorted: true,
94 reverseParams: true,
95 nextUid: true,
96 setHashKey: true,
97 extend: true,
98 toInt: true,
99 inherit: true,
100 merge: true,
101 noop: true,
102 identity: true,
103 valueFn: true,
104 isUndefined: true,
105 isDefined: true,
106 isObject: true,
107 isBlankObject: true,
108 isString: true,
109 isNumber: true,
110 isDate: true,
111 isArray: true,
112 isFunction: true,
113 isRegExp: true,
114 isWindow: true,
115 isScope: true,
116 isFile: true,
117 isFormData: true,
118 isBlob: true,
119 isBoolean: true,
120 isPromiseLike: true,
121 trim: true,
122 escapeForRegexp: true,
123 isElement: true,
124 makeMap: true,
125 includes: true,
126 arrayRemove: true,
127 copy: true,
128 shallowCopy: true,
129 equals: true,
130 csp: true,
131 jq: true,
132 concat: true,
133 sliceArgs: true,
134 bind: true,
135 toJsonReplacer: true,
136 toJson: true,
137 fromJson: true,
138 convertTimezoneToLocal: true,
139 timezoneToOffset: true,
140 startingTag: true,
141 tryDecodeURIComponent: true,
142 parseKeyValue: true,
143 toKeyValue: true,
144 encodeUriSegment: true,
145 encodeUriQuery: true,
146 angularInit: true,
147 bootstrap: true,
148 getTestability: true,
149 snake_case: true,
150 bindJQuery: true,
151 assertArg: true,
152 assertArgFn: true,
153 assertNotHasOwnProperty: true,
154 getter: true,
155 getBlockNodes: true,
156 hasOwnProperty: true,
157 createMap: true,
158
159 NODE_TYPE_ELEMENT: true,
160 NODE_TYPE_ATTRIBUTE: true,
161 NODE_TYPE_TEXT: true,
162 NODE_TYPE_COMMENT: true,
163 NODE_TYPE_DOCUMENT: true,
164 NODE_TYPE_DOCUMENT_FRAGMENT: true,
165 */
166
167 ////////////////////////////////////
168
169 /**
170 * @ngdoc module
171 * @name ng
172 * @module ng
173 * @description
174 *
175 * # ng (core module)
176 * The ng module is loaded by default when an AngularJS application is started. The module itself
177 * contains the essential components for an AngularJS application to function. The table below
178 * lists a high level breakdown of each of the services/factories, filters, directives and testing
179 * components available within this core module.
180 *
181 * <div doc-module-components="ng"></div>
182 */
183
184 var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
185
186 // The name of a form control's ValidityState property.
187 // This is used so that it's possible for internal tests to create mock ValidityStates.
188 var VALIDITY_STATE_PROPERTY = 'validity';
189
190 /**
191 * @ngdoc function
192 * @name angular.lowercase
193 * @module ng
194 * @kind function
195 *
196 * @description Converts the specified string to lowercase.
197 * @param {string} string String to be converted to lowercase.
198 * @returns {string} Lowercased string.
199 */
200 var lowercase = function(string) {return isString(string) ? string.toLowerCase() : string;};
201 var hasOwnProperty = Object.prototype.hasOwnProperty;
202
203 /**
204 * @ngdoc function
205 * @name angular.uppercase
206 * @module ng
207 * @kind function
208 *
209 * @description Converts the specified string to uppercase.
210 * @param {string} string String to be converted to uppercase.
211 * @returns {string} Uppercased string.
212 */
213 var uppercase = function(string) {return isString(string) ? string.toUpperCase() : string;};
214
215
216 var manualLowercase = function(s) {
217 /* jshint bitwise: false */
218 return isString(s)
219 ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
220 : s;
221 };
222 var manualUppercase = function(s) {
223 /* jshint bitwise: false */
224 return isString(s)
225 ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
226 : s;
227 };
228
229
230 // String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
231 // locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
232 // with correct but slower alternatives.
233 if ('i' !== 'I'.toLowerCase()) {
234 lowercase = manualLowercase;
235 uppercase = manualUppercase;
236 }
237
238
239 var
240 msie, // holds major version number for IE, or NaN if UA is not IE.
241 jqLite, // delay binding since jQuery could be loaded after us.
242 jQuery, // delay binding
243 slice = [].slice,
244 splice = [].splice,
245 push = [].push,
246 toString = Object.prototype.toString,
247 getPrototypeOf = Object.getPrototypeOf,
248 ngMinErr = minErr('ng'),
249
250 /** @name angular */
251 angular = window.angular || (window.angular = {}),
252 angularModule,
253 uid = 0;
254
255 /**
256 * documentMode is an IE-only property
257 * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
258 */
259 msie = document.documentMode;
260
261
262 /**
263 * @private
264 * @param {*} obj
265 * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
266 * String ...)
267 */
268 function isArrayLike(obj) {
269 if (obj == null || isWindow(obj)) {
270 return false;
271 }
272
273 // Support: iOS 8.2 (not reproducible in simulator)
274 // "length" in obj used to prevent JIT error (gh-11508)
275 var length = "length" in Object(obj) && obj.length;
276
277 if (obj.nodeType === NODE_TYPE_ELEMENT && length) {
278 return true;
279 }
280
281 return isString(obj) || isArray(obj) || length === 0 ||
282 typeof length === 'number' && length > 0 && (length - 1) in obj;
283 }
284
285 /**
286 * @ngdoc function
287 * @name angular.forEach
288 * @module ng
289 * @kind function
290 *
291 * @description
292 * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
293 * object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
294 * is the value of an object property or an array element, `key` is the object property key or
295 * array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
296 *
297 * It is worth noting that `.forEach` does not iterate over inherited properties because it filters
298 * using the `hasOwnProperty` method.
299 *
300 * Unlike ES262's
301 * [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
302 * Providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
303 * return the value provided.
304 *
305 ```js
306 var values = {name: 'misko', gender: 'male'};
307 var log = [];
308 angular.forEach(values, function(value, key) {
309 this.push(key + ': ' + value);
310 }, log);
311 expect(log).toEqual(['name: misko', 'gender: male']);
312 ```
313 *
314 * @param {Object|Array} obj Object to iterate over.
315 * @param {Function} iterator Iterator function.
316 * @param {Object=} context Object to become context (`this`) for the iterator function.
317 * @returns {Object|Array} Reference to `obj`.
318 */
319
320 function forEach(obj, iterator, context) {
321 var key, length;
322 if (obj) {
323 if (isFunction(obj)) {
324 for (key in obj) {
325 // Need to check if hasOwnProperty exists,
326 // as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
327 if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
328 iterator.call(context, obj[key], key, obj);
329 }
330 }
331 } else if (isArray(obj) || isArrayLike(obj)) {
332 var isPrimitive = typeof obj !== 'object';
333 for (key = 0, length = obj.length; key < length; key++) {
334 if (isPrimitive || key in obj) {
335 iterator.call(context, obj[key], key, obj);
336 }
337 }
338 } else if (obj.forEach && obj.forEach !== forEach) {
339 obj.forEach(iterator, context, obj);
340 } else if (isBlankObject(obj)) {
341 // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
342 for (key in obj) {
343 iterator.call(context, obj[key], key, obj);
344 }
345 } else if (typeof obj.hasOwnProperty === 'function') {
346 // Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
347 for (key in obj) {
348 if (obj.hasOwnProperty(key)) {
349 iterator.call(context, obj[key], key, obj);
350 }
351 }
352 } else {
353 // Slow path for objects which do not have a method `hasOwnProperty`
354 for (key in obj) {
355 if (hasOwnProperty.call(obj, key)) {
356 iterator.call(context, obj[key], key, obj);
357 }
358 }
359 }
360 }
361 return obj;
362 }
363
364 function forEachSorted(obj, iterator, context) {
365 var keys = Object.keys(obj).sort();
366 for (var i = 0; i < keys.length; i++) {
367 iterator.call(context, obj[keys[i]], keys[i]);
368 }
369 return keys;
370 }
371
372
373 /**
374 * when using forEach the params are value, key, but it is often useful to have key, value.
375 * @param {function(string, *)} iteratorFn
376 * @returns {function(*, string)}
377 */
378 function reverseParams(iteratorFn) {
379 return function(value, key) { iteratorFn(key, value); };
380 }
381
382 /**
383 * A consistent way of creating unique IDs in angular.
384 *
385 * Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
386 * we hit number precision issues in JavaScript.
387 *
388 * Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
389 *
390 * @returns {number} an unique alpha-numeric string
391 */
392 function nextUid() {
393 return ++uid;
394 }
395
396
397 /**
398 * Set or clear the hashkey for an object.
399 * @param obj object
400 * @param h the hashkey (!truthy to delete the hashkey)
401 */
402 function setHashKey(obj, h) {
403 if (h) {
404 obj.$$hashKey = h;
405 } else {
406 delete obj.$$hashKey;
407 }
408 }
409
410
411 function baseExtend(dst, objs, deep) {
412 var h = dst.$$hashKey;
413
414 for (var i = 0, ii = objs.length; i < ii; ++i) {
415 var obj = objs[i];
416 if (!isObject(obj) && !isFunction(obj)) continue;
417 var keys = Object.keys(obj);
418 for (var j = 0, jj = keys.length; j < jj; j++) {
419 var key = keys[j];
420 var src = obj[key];
421
422 if (deep && isObject(src)) {
423 if (isDate(src)) {
424 dst[key] = new Date(src.valueOf());
425 } else {
426 if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
427 baseExtend(dst[key], [src], true);
428 }
429 } else {
430 dst[key] = src;
431 }
432 }
433 }
434
435 setHashKey(dst, h);
436 return dst;
437 }
438
439 /**
440 * @ngdoc function
441 * @name angular.extend
442 * @module ng
443 * @kind function
444 *
445 * @description
446 * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
447 * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
448 * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
449 *
450 * **Note:** Keep in mind that `angular.extend` does not support recursive merge (deep copy). Use
451 * {@link angular.merge} for this.
452 *
453 * @param {Object} dst Destination object.
454 * @param {...Object} src Source object(s).
455 * @returns {Object} Reference to `dst`.
456 */
457 function extend(dst) {
458 return baseExtend(dst, slice.call(arguments, 1), false);
459 }
460
461
462 /**
463 * @ngdoc function
464 * @name angular.merge
465 * @module ng
466 * @kind function
467 *
468 * @description
469 * Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
470 * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
471 * by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.
472 *
473 * Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
474 * objects, performing a deep copy.
475 *
476 * @param {Object} dst Destination object.
477 * @param {...Object} src Source object(s).
478 * @returns {Object} Reference to `dst`.
479 */
480 function merge(dst) {
481 return baseExtend(dst, slice.call(arguments, 1), true);
482 }
483
484
485
486 function toInt(str) {
487 return parseInt(str, 10);
488 }
489
490
491 function inherit(parent, extra) {
492 return extend(Object.create(parent), extra);
493 }
494
495 /**
496 * @ngdoc function
497 * @name angular.noop
498 * @module ng
499 * @kind function
500 *
501 * @description
502 * A function that performs no operations. This function can be useful when writing code in the
503 * functional style.
504 ```js
505 function foo(callback) {
506 var result = calculateResult();
507 (callback || angular.noop)(result);
508 }
509 ```
510 */
511 function noop() {}
512 noop.$inject = [];
513
514
515 /**
516 * @ngdoc function
517 * @name angular.identity
518 * @module ng
519 * @kind function
520 *
521 * @description
522 * A function that returns its first argument. This function is useful when writing code in the
523 * functional style.
524 *
525 ```js
526 function transformer(transformationFn, value) {
527 return (transformationFn || angular.identity)(value);
528 };
529 ```
530 * @param {*} value to be returned.
531 * @returns {*} the value passed in.
532 */
533 function identity($) {return $;}
534 identity.$inject = [];
535
536
537 function valueFn(value) {return function() {return value;};}
538
539 function hasCustomToString(obj) {
540 return isFunction(obj.toString) && obj.toString !== Object.prototype.toString;
541 }
542
543
544 /**
545 * @ngdoc function
546 * @name angular.isUndefined
547 * @module ng
548 * @kind function
549 *
550 * @description
551 * Determines if a reference is undefined.
552 *
553 * @param {*} value Reference to check.
554 * @returns {boolean} True if `value` is undefined.
555 */
556 function isUndefined(value) {return typeof value === 'undefined';}
557
558
559 /**
560 * @ngdoc function
561 * @name angular.isDefined
562 * @module ng
563 * @kind function
564 *
565 * @description
566 * Determines if a reference is defined.
567 *
568 * @param {*} value Reference to check.
569 * @returns {boolean} True if `value` is defined.
570 */
571 function isDefined(value) {return typeof value !== 'undefined';}
572
573
574 /**
575 * @ngdoc function
576 * @name angular.isObject
577 * @module ng
578 * @kind function
579 *
580 * @description
581 * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
582 * considered to be objects. Note that JavaScript arrays are objects.
583 *
584 * @param {*} value Reference to check.
585 * @returns {boolean} True if `value` is an `Object` but not `null`.
586 */
587 function isObject(value) {
588 // http://jsperf.com/isobject4
589 return value !== null && typeof value === 'object';
590 }
591
592
593 /**
594 * Determine if a value is an object with a null prototype
595 *
596 * @returns {boolean} True if `value` is an `Object` with a null prototype
597 */
598 function isBlankObject(value) {
599 return value !== null && typeof value === 'object' && !getPrototypeOf(value);
600 }
601
602
603 /**
604 * @ngdoc function
605 * @name angular.isString
606 * @module ng
607 * @kind function
608 *
609 * @description
610 * Determines if a reference is a `String`.
611 *
612 * @param {*} value Reference to check.
613 * @returns {boolean} True if `value` is a `String`.
614 */
615 function isString(value) {return typeof value === 'string';}
616
617
618 /**
619 * @ngdoc function
620 * @name angular.isNumber
621 * @module ng
622 * @kind function
623 *
624 * @description
625 * Determines if a reference is a `Number`.
626 *
627 * This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
628 *
629 * If you wish to exclude these then you can use the native
630 * [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
631 * method.
632 *
633 * @param {*} value Reference to check.
634 * @returns {boolean} True if `value` is a `Number`.
635 */
636 function isNumber(value) {return typeof value === 'number';}
637
638
639 /**
640 * @ngdoc function
641 * @name angular.isDate
642 * @module ng
643 * @kind function
644 *
645 * @description
646 * Determines if a value is a date.
647 *
648 * @param {*} value Reference to check.
649 * @returns {boolean} True if `value` is a `Date`.
650 */
651 function isDate(value) {
652 return toString.call(value) === '[object Date]';
653 }
654
655
656 /**
657 * @ngdoc function
658 * @name angular.isArray
659 * @module ng
660 * @kind function
661 *
662 * @description
663 * Determines if a reference is an `Array`.
664 *
665 * @param {*} value Reference to check.
666 * @returns {boolean} True if `value` is an `Array`.
667 */
668 var isArray = Array.isArray;
669
670 /**
671 * @ngdoc function
672 * @name angular.isFunction
673 * @module ng
674 * @kind function
675 *
676 * @description
677 * Determines if a reference is a `Function`.
678 *
679 * @param {*} value Reference to check.
680 * @returns {boolean} True if `value` is a `Function`.
681 */
682 function isFunction(value) {return typeof value === 'function';}
683
684
685 /**
686 * Determines if a value is a regular expression object.
687 *
688 * @private
689 * @param {*} value Reference to check.
690 * @returns {boolean} True if `value` is a `RegExp`.
691 */
692 function isRegExp(value) {
693 return toString.call(value) === '[object RegExp]';
694 }
695
696
697 /**
698 * Checks if `obj` is a window object.
699 *
700 * @private
701 * @param {*} obj Object to check
702 * @returns {boolean} True if `obj` is a window obj.
703 */
704 function isWindow(obj) {
705 return obj && obj.window === obj;
706 }
707
708
709 function isScope(obj) {
710 return obj && obj.$evalAsync && obj.$watch;
711 }
712
713
714 function isFile(obj) {
715 return toString.call(obj) === '[object File]';
716 }
717
718
719 function isFormData(obj) {
720 return toString.call(obj) === '[object FormData]';
721 }
722
723
724 function isBlob(obj) {
725 return toString.call(obj) === '[object Blob]';
726 }
727
728
729 function isBoolean(value) {
730 return typeof value === 'boolean';
731 }
732
733
734 function isPromiseLike(obj) {
735 return obj && isFunction(obj.then);
736 }
737
738
739 var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/;
740 function isTypedArray(value) {
741 return TYPED_ARRAY_REGEXP.test(toString.call(value));
742 }
743
744
745 var trim = function(value) {
746 return isString(value) ? value.trim() : value;
747 };
748
749 // Copied from:
750 // http://docs.closure-library.googlecode.com/git/local_closure_goog_string_string.js.source.html#line1021
751 // Prereq: s is a string.
752 var escapeForRegexp = function(s) {
753 return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
754 replace(/\x08/g, '\\x08');
755 };
756
757
758 /**
759 * @ngdoc function
760 * @name angular.isElement
761 * @module ng
762 * @kind function
763 *
764 * @description
765 * Determines if a reference is a DOM element (or wrapped jQuery element).
766 *
767 * @param {*} value Reference to check.
768 * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
769 */
770 function isElement(node) {
771 return !!(node &&
772 (node.nodeName // we are a direct element
773 || (node.prop && node.attr && node.find))); // we have an on and find method part of jQuery API
774 }
775
776 /**
777 * @param str 'key1,key2,...'
778 * @returns {object} in the form of {key1:true, key2:true, ...}
779 */
780 function makeMap(str) {
781 var obj = {}, items = str.split(","), i;
782 for (i = 0; i < items.length; i++) {
783 obj[items[i]] = true;
784 }
785 return obj;
786 }
787
788
789 function nodeName_(element) {
790 return lowercase(element.nodeName || (element[0] && element[0].nodeName));
791 }
792
793 function includes(array, obj) {
794 return Array.prototype.indexOf.call(array, obj) != -1;
795 }
796
797 function arrayRemove(array, value) {
798 var index = array.indexOf(value);
799 if (index >= 0) {
800 array.splice(index, 1);
801 }
802 return index;
803 }
804
805 /**
806 * @ngdoc function
807 * @name angular.copy
808 * @module ng
809 * @kind function
810 *
811 * @description
812 * Creates a deep copy of `source`, which should be an object or an array.
813 *
814 * * If no destination is supplied, a copy of the object or array is created.
815 * * If a destination is provided, all of its elements (for arrays) or properties (for objects)
816 * are deleted and then all elements/properties from the source are copied to it.
817 * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
818 * * If `source` is identical to 'destination' an exception will be thrown.
819 *
820 * @param {*} source The source that will be used to make a copy.
821 * Can be any type, including primitives, `null`, and `undefined`.
822 * @param {(Object|Array)=} destination Destination into which the source is copied. If
823 * provided, must be of the same type as `source`.
824 * @returns {*} The copy or updated `destination`, if `destination` was specified.
825 *
826 * @example
827 <example module="copyExample">
828 <file name="index.html">
829 <div ng-controller="ExampleController">
830 <form novalidate class="simple-form">
831 Name: <input type="text" ng-model="user.name" /><br />
832 E-mail: <input type="email" ng-model="user.email" /><br />
833 Gender: <input type="radio" ng-model="user.gender" value="male" />male
834 <input type="radio" ng-model="user.gender" value="female" />female<br />
835 <button ng-click="reset()">RESET</button>
836 <button ng-click="update(user)">SAVE</button>
837 </form>
838 <pre>form = {{user | json}}</pre>
839 <pre>master = {{master | json}}</pre>
840 </div>
841
842 <script>
843 angular.module('copyExample', [])
844 .controller('ExampleController', ['$scope', function($scope) {
845 $scope.master= {};
846
847 $scope.update = function(user) {
848 // Example with 1 argument
849 $scope.master= angular.copy(user);
850 };
851
852 $scope.reset = function() {
853 // Example with 2 arguments
854 angular.copy($scope.master, $scope.user);
855 };
856
857 $scope.reset();
858 }]);
859 </script>
860 </file>
861 </example>
862 */
863 function copy(source, destination, stackSource, stackDest) {
864 if (isWindow(source) || isScope(source)) {
865 throw ngMinErr('cpws',
866 "Can't copy! Making copies of Window or Scope instances is not supported.");
867 }
868 if (isTypedArray(destination)) {
869 throw ngMinErr('cpta',
870 "Can't copy! TypedArray destination cannot be mutated.");
871 }
872
873 if (!destination) {
874 destination = source;
875 if (isObject(source)) {
876 var index;
877 if (stackSource && (index = stackSource.indexOf(source)) !== -1) {
878 return stackDest[index];
879 }
880
881 // TypedArray, Date and RegExp have specific copy functionality and must be
882 // pushed onto the stack before returning.
883 // Array and other objects create the base object and recurse to copy child
884 // objects. The array/object will be pushed onto the stack when recursed.
885 if (isArray(source)) {
886 return copy(source, [], stackSource, stackDest);
887 } else if (isTypedArray(source)) {
888 destination = new source.constructor(source);
889 } else if (isDate(source)) {
890 destination = new Date(source.getTime());
891 } else if (isRegExp(source)) {
892 destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
893 destination.lastIndex = source.lastIndex;
894 } else {
895 var emptyObject = Object.create(getPrototypeOf(source));
896 return copy(source, emptyObject, stackSource, stackDest);
897 }
898
899 if (stackDest) {
900 stackSource.push(source);
901 stackDest.push(destination);
902 }
903 }
904 } else {
905 if (source === destination) throw ngMinErr('cpi',
906 "Can't copy! Source and destination are identical.");
907
908 stackSource = stackSource || [];
909 stackDest = stackDest || [];
910
911 if (isObject(source)) {
912 stackSource.push(source);
913 stackDest.push(destination);
914 }
915
916 var result, key;
917 if (isArray(source)) {
918 destination.length = 0;
919 for (var i = 0; i < source.length; i++) {
920 destination.push(copy(source[i], null, stackSource, stackDest));
921 }
922 } else {
923 var h = destination.$$hashKey;
924 if (isArray(destination)) {
925 destination.length = 0;
926 } else {
927 forEach(destination, function(value, key) {
928 delete destination[key];
929 });
930 }
931 if (isBlankObject(source)) {
932 // createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
933 for (key in source) {
934 destination[key] = copy(source[key], null, stackSource, stackDest);
935 }
936 } else if (source && typeof source.hasOwnProperty === 'function') {
937 // Slow path, which must rely on hasOwnProperty
938 for (key in source) {
939 if (source.hasOwnProperty(key)) {
940 destination[key] = copy(source[key], null, stackSource, stackDest);
941 }
942 }
943 } else {
944 // Slowest path --- hasOwnProperty can't be called as a method
945 for (key in source) {
946 if (hasOwnProperty.call(source, key)) {
947 destination[key] = copy(source[key], null, stackSource, stackDest);
948 }
949 }
950 }
951 setHashKey(destination,h);
952 }
953 }
954 return destination;
955 }
956
957 /**
958 * Creates a shallow copy of an object, an array or a primitive.
959 *
960 * Assumes that there are no proto properties for objects.
961 */
962 function shallowCopy(src, dst) {
963 if (isArray(src)) {
964 dst = dst || [];
965
966 for (var i = 0, ii = src.length; i < ii; i++) {
967 dst[i] = src[i];
968 }
969 } else if (isObject(src)) {
970 dst = dst || {};
971
972 for (var key in src) {
973 if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
974 dst[key] = src[key];
975 }
976 }
977 }
978
979 return dst || src;
980 }
981
982
983 /**
984 * @ngdoc function
985 * @name angular.equals
986 * @module ng
987 * @kind function
988 *
989 * @description
990 * Determines if two objects or two values are equivalent. Supports value types, regular
991 * expressions, arrays and objects.
992 *
993 * Two objects or values are considered equivalent if at least one of the following is true:
994 *
995 * * Both objects or values pass `===` comparison.
996 * * Both objects or values are of the same type and all of their properties are equal by
997 * comparing them with `angular.equals`.
998 * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
999 * * Both values represent the same regular expression (In JavaScript,
1000 * /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
1001 * representation matches).
1002 *
1003 * During a property comparison, properties of `function` type and properties with names
1004 * that begin with `$` are ignored.
1005 *
1006 * Scope and DOMWindow objects are being compared only by identify (`===`).
1007 *
1008 * @param {*} o1 Object or value to compare.
1009 * @param {*} o2 Object or value to compare.
1010 * @returns {boolean} True if arguments are equal.
1011 */
1012 function equals(o1, o2) {
1013 if (o1 === o2) return true;
1014 if (o1 === null || o2 === null) return false;
1015 if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
1016 var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
1017 if (t1 == t2) {
1018 if (t1 == 'object') {
1019 if (isArray(o1)) {
1020 if (!isArray(o2)) return false;
1021 if ((length = o1.length) == o2.length) {
1022 for (key = 0; key < length; key++) {
1023 if (!equals(o1[key], o2[key])) return false;
1024 }
1025 return true;
1026 }
1027 } else if (isDate(o1)) {
1028 if (!isDate(o2)) return false;
1029 return equals(o1.getTime(), o2.getTime());
1030 } else if (isRegExp(o1)) {
1031 return isRegExp(o2) ? o1.toString() == o2.toString() : false;
1032 } else {
1033 if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) ||
1034 isArray(o2) || isDate(o2) || isRegExp(o2)) return false;
1035 keySet = createMap();
1036 for (key in o1) {
1037 if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
1038 if (!equals(o1[key], o2[key])) return false;
1039 keySet[key] = true;
1040 }
1041 for (key in o2) {
1042 if (!(key in keySet) &&
1043 key.charAt(0) !== '$' &&
1044 o2[key] !== undefined &&
1045 !isFunction(o2[key])) return false;
1046 }
1047 return true;
1048 }
1049 }
1050 }
1051 return false;
1052 }
1053
1054 var csp = function() {
1055 if (isDefined(csp.isActive_)) return csp.isActive_;
1056
1057 var active = !!(document.querySelector('[ng-csp]') ||
1058 document.querySelector('[data-ng-csp]'));
1059
1060 if (!active) {
1061 try {
1062 /* jshint -W031, -W054 */
1063 new Function('');
1064 /* jshint +W031, +W054 */
1065 } catch (e) {
1066 active = true;
1067 }
1068 }
1069
1070 return (csp.isActive_ = active);
1071 };
1072
1073 /**
1074 * @ngdoc directive
1075 * @module ng
1076 * @name ngJq
1077 *
1078 * @element ANY
1079 * @param {string=} ngJq the name of the library available under `window`
1080 * to be used for angular.element
1081 * @description
1082 * Use this directive to force the angular.element library. This should be
1083 * used to force either jqLite by leaving ng-jq blank or setting the name of
1084 * the jquery variable under window (eg. jQuery).
1085 *
1086 * Since angular looks for this directive when it is loaded (doesn't wait for the
1087 * DOMContentLoaded event), it must be placed on an element that comes before the script
1088 * which loads angular. Also, only the first instance of `ng-jq` will be used and all
1089 * others ignored.
1090 *
1091 * @example
1092 * This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
1093 ```html
1094 <!doctype html>
1095 <html ng-app ng-jq>
1096 ...
1097 ...
1098 </html>
1099 ```
1100 * @example
1101 * This example shows how to use a jQuery based library of a different name.
1102 * The library name must be available at the top most 'window'.
1103 ```html
1104 <!doctype html>
1105 <html ng-app ng-jq="jQueryLib">
1106 ...
1107 ...
1108 </html>
1109 ```
1110 */
1111 var jq = function() {
1112 if (isDefined(jq.name_)) return jq.name_;
1113 var el;
1114 var i, ii = ngAttrPrefixes.length, prefix, name;
1115 for (i = 0; i < ii; ++i) {
1116 prefix = ngAttrPrefixes[i];
1117 if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
1118 name = el.getAttribute(prefix + 'jq');
1119 break;
1120 }
1121 }
1122
1123 return (jq.name_ = name);
1124 };
1125
1126 function concat(array1, array2, index) {
1127 return array1.concat(slice.call(array2, index));
1128 }
1129
1130 function sliceArgs(args, startIndex) {
1131 return slice.call(args, startIndex || 0);
1132 }
1133
1134
1135 /* jshint -W101 */
1136 /**
1137 * @ngdoc function
1138 * @name angular.bind
1139 * @module ng
1140 * @kind function
1141 *
1142 * @description
1143 * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
1144 * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
1145 * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
1146 * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
1147 *
1148 * @param {Object} self Context which `fn` should be evaluated in.
1149 * @param {function()} fn Function to be bound.
1150 * @param {...*} args Optional arguments to be prebound to the `fn` function call.
1151 * @returns {function()} Function that wraps the `fn` with all the specified bindings.
1152 */
1153 /* jshint +W101 */
1154 function bind(self, fn) {
1155 var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
1156 if (isFunction(fn) && !(fn instanceof RegExp)) {
1157 return curryArgs.length
1158 ? function() {
1159 return arguments.length
1160 ? fn.apply(self, concat(curryArgs, arguments, 0))
1161 : fn.apply(self, curryArgs);
1162 }
1163 : function() {
1164 return arguments.length
1165 ? fn.apply(self, arguments)
1166 : fn.call(self);
1167 };
1168 } else {
1169 // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
1170 return fn;
1171 }
1172 }
1173
1174
1175 function toJsonReplacer(key, value) {
1176 var val = value;
1177
1178 if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
1179 val = undefined;
1180 } else if (isWindow(value)) {
1181 val = '$WINDOW';
1182 } else if (value && document === value) {
1183 val = '$DOCUMENT';
1184 } else if (isScope(value)) {
1185 val = '$SCOPE';
1186 }
1187
1188 return val;
1189 }
1190
1191
1192 /**
1193 * @ngdoc function
1194 * @name angular.toJson
1195 * @module ng
1196 * @kind function
1197 *
1198 * @description
1199 * Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
1200 * stripped since angular uses this notation internally.
1201 *
1202 * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
1203 * @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
1204 * If set to an integer, the JSON output will contain that many spaces per indentation.
1205 * @returns {string|undefined} JSON-ified string representing `obj`.
1206 */
1207 function toJson(obj, pretty) {
1208 if (typeof obj === 'undefined') return undefined;
1209 if (!isNumber(pretty)) {
1210 pretty = pretty ? 2 : null;
1211 }
1212 return JSON.stringify(obj, toJsonReplacer, pretty);
1213 }
1214
1215
1216 /**
1217 * @ngdoc function
1218 * @name angular.fromJson
1219 * @module ng
1220 * @kind function
1221 *
1222 * @description
1223 * Deserializes a JSON string.
1224 *
1225 * @param {string} json JSON string to deserialize.
1226 * @returns {Object|Array|string|number} Deserialized JSON string.
1227 */
1228 function fromJson(json) {
1229 return isString(json)
1230 ? JSON.parse(json)
1231 : json;
1232 }
1233
1234
1235 function timezoneToOffset(timezone, fallback) {
1236 var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
1237 return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
1238 }
1239
1240
1241 function addDateMinutes(date, minutes) {
1242 date = new Date(date.getTime());
1243 date.setMinutes(date.getMinutes() + minutes);
1244 return date;
1245 }
1246
1247
1248 function convertTimezoneToLocal(date, timezone, reverse) {
1249 reverse = reverse ? -1 : 1;
1250 var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
1251 return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset()));
1252 }
1253
1254
1255 /**
1256 * @returns {string} Returns the string representation of the element.
1257 */
1258 function startingTag(element) {
1259 element = jqLite(element).clone();
1260 try {
1261 // turns out IE does not let you set .html() on elements which
1262 // are not allowed to have children. So we just ignore it.
1263 element.empty();
1264 } catch (e) {}
1265 var elemHtml = jqLite('<div>').append(element).html();
1266 try {
1267 return element[0].nodeType === NODE_TYPE_TEXT ? lowercase(elemHtml) :
1268 elemHtml.
1269 match(/^(<[^>]+>)/)[1].
1270 replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
1271 } catch (e) {
1272 return lowercase(elemHtml);
1273 }
1274
1275 }
1276
1277
1278 /////////////////////////////////////////////////
1279
1280 /**
1281 * Tries to decode the URI component without throwing an exception.
1282 *
1283 * @private
1284 * @param str value potential URI component to check.
1285 * @returns {boolean} True if `value` can be decoded
1286 * with the decodeURIComponent function.
1287 */
1288 function tryDecodeURIComponent(value) {
1289 try {
1290 return decodeURIComponent(value);
1291 } catch (e) {
1292 // Ignore any invalid uri component
1293 }
1294 }
1295
1296
1297 /**
1298 * Parses an escaped url query string into key-value pairs.
1299 * @returns {Object.<string,boolean|Array>}
1300 */
1301 function parseKeyValue(/**string*/keyValue) {
1302 var obj = {}, key_value, key;
1303 forEach((keyValue || "").split('&'), function(keyValue) {
1304 if (keyValue) {
1305 key_value = keyValue.replace(/\+/g,'%20').split('=');
1306 key = tryDecodeURIComponent(key_value[0]);
1307 if (isDefined(key)) {
1308 var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
1309 if (!hasOwnProperty.call(obj, key)) {
1310 obj[key] = val;
1311 } else if (isArray(obj[key])) {
1312 obj[key].push(val);
1313 } else {
1314 obj[key] = [obj[key],val];
1315 }
1316 }
1317 }
1318 });
1319 return obj;
1320 }
1321
1322 function toKeyValue(obj) {
1323 var parts = [];
1324 forEach(obj, function(value, key) {
1325 if (isArray(value)) {
1326 forEach(value, function(arrayValue) {
1327 parts.push(encodeUriQuery(key, true) +
1328 (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
1329 });
1330 } else {
1331 parts.push(encodeUriQuery(key, true) +
1332 (value === true ? '' : '=' + encodeUriQuery(value, true)));
1333 }
1334 });
1335 return parts.length ? parts.join('&') : '';
1336 }
1337
1338
1339 /**
1340 * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
1341 * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
1342 * segments:
1343 * segment = *pchar
1344 * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
1345 * pct-encoded = "%" HEXDIG HEXDIG
1346 * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1347 * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1348 * / "*" / "+" / "," / ";" / "="
1349 */
1350 function encodeUriSegment(val) {
1351 return encodeUriQuery(val, true).
1352 replace(/%26/gi, '&').
1353 replace(/%3D/gi, '=').
1354 replace(/%2B/gi, '+');
1355 }
1356
1357
1358 /**
1359 * This method is intended for encoding *key* or *value* parts of query component. We need a custom
1360 * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
1361 * encoded per http://tools.ietf.org/html/rfc3986:
1362 * query = *( pchar / "/" / "?" )
1363 * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
1364 * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
1365 * pct-encoded = "%" HEXDIG HEXDIG
1366 * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
1367 * / "*" / "+" / "," / ";" / "="
1368 */
1369 function encodeUriQuery(val, pctEncodeSpaces) {
1370 return encodeURIComponent(val).
1371 replace(/%40/gi, '@').
1372 replace(/%3A/gi, ':').
1373 replace(/%24/g, '$').
1374 replace(/%2C/gi, ',').
1375 replace(/%3B/gi, ';').
1376 replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
1377 }
1378
1379 var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
1380
1381 function getNgAttribute(element, ngAttr) {
1382 var attr, i, ii = ngAttrPrefixes.length;
1383 for (i = 0; i < ii; ++i) {
1384 attr = ngAttrPrefixes[i] + ngAttr;
1385 if (isString(attr = element.getAttribute(attr))) {
1386 return attr;
1387 }
1388 }
1389 return null;
1390 }
1391
1392 /**
1393 * @ngdoc directive
1394 * @name ngApp
1395 * @module ng
1396 *
1397 * @element ANY
1398 * @param {angular.Module} ngApp an optional application
1399 * {@link angular.module module} name to load.
1400 * @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
1401 * created in "strict-di" mode. This means that the application will fail to invoke functions which
1402 * do not use explicit function annotation (and are thus unsuitable for minification), as described
1403 * in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
1404 * tracking down the root of these bugs.
1405 *
1406 * @description
1407 *
1408 * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
1409 * designates the **root element** of the application and is typically placed near the root element
1410 * of the page - e.g. on the `<body>` or `<html>` tags.
1411 *
1412 * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
1413 * found in the document will be used to define the root element to auto-bootstrap as an
1414 * application. To run multiple applications in an HTML document you must manually bootstrap them using
1415 * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
1416 *
1417 * You can specify an **AngularJS module** to be used as the root module for the application. This
1418 * module will be loaded into the {@link auto.$injector} when the application is bootstrapped. It
1419 * should contain the application code needed or have dependencies on other modules that will
1420 * contain the code. See {@link angular.module} for more information.
1421 *
1422 * In the example below if the `ngApp` directive were not placed on the `html` element then the
1423 * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
1424 * would not be resolved to `3`.
1425 *
1426 * `ngApp` is the easiest, and most common way to bootstrap an application.
1427 *
1428 <example module="ngAppDemo">
1429 <file name="index.html">
1430 <div ng-controller="ngAppDemoController">
1431 I can add: {{a}} + {{b}} = {{ a+b }}
1432 </div>
1433 </file>
1434 <file name="script.js">
1435 angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
1436 $scope.a = 1;
1437 $scope.b = 2;
1438 });
1439 </file>
1440 </example>
1441 *
1442 * Using `ngStrictDi`, you would see something like this:
1443 *
1444 <example ng-app-included="true">
1445 <file name="index.html">
1446 <div ng-app="ngAppStrictDemo" ng-strict-di>
1447 <div ng-controller="GoodController1">
1448 I can add: {{a}} + {{b}} = {{ a+b }}
1449
1450 <p>This renders because the controller does not fail to
1451 instantiate, by using explicit annotation style (see
1452 script.js for details)
1453 </p>
1454 </div>
1455
1456 <div ng-controller="GoodController2">
1457 Name: <input ng-model="name"><br />
1458 Hello, {{name}}!
1459
1460 <p>This renders because the controller does not fail to
1461 instantiate, by using explicit annotation style
1462 (see script.js for details)
1463 </p>
1464 </div>
1465
1466 <div ng-controller="BadController">
1467 I can add: {{a}} + {{b}} = {{ a+b }}
1468
1469 <p>The controller could not be instantiated, due to relying
1470 on automatic function annotations (which are disabled in
1471 strict mode). As such, the content of this section is not
1472 interpolated, and there should be an error in your web console.
1473 </p>
1474 </div>
1475 </div>
1476 </file>
1477 <file name="script.js">
1478 angular.module('ngAppStrictDemo', [])
1479 // BadController will fail to instantiate, due to relying on automatic function annotation,
1480 // rather than an explicit annotation
1481 .controller('BadController', function($scope) {
1482 $scope.a = 1;
1483 $scope.b = 2;
1484 })
1485 // Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
1486 // due to using explicit annotations using the array style and $inject property, respectively.
1487 .controller('GoodController1', ['$scope', function($scope) {
1488 $scope.a = 1;
1489 $scope.b = 2;
1490 }])
1491 .controller('GoodController2', GoodController2);
1492 function GoodController2($scope) {
1493 $scope.name = "World";
1494 }
1495 GoodController2.$inject = ['$scope'];
1496 </file>
1497 <file name="style.css">
1498 div[ng-controller] {
1499 margin-bottom: 1em;
1500 -webkit-border-radius: 4px;
1501 border-radius: 4px;
1502 border: 1px solid;
1503 padding: .5em;
1504 }
1505 div[ng-controller^=Good] {
1506 border-color: #d6e9c6;
1507 background-color: #dff0d8;
1508 color: #3c763d;
1509 }
1510 div[ng-controller^=Bad] {
1511 border-color: #ebccd1;
1512 background-color: #f2dede;
1513 color: #a94442;
1514 margin-bottom: 0;
1515 }
1516 </file>
1517 </example>
1518 */
1519 function angularInit(element, bootstrap) {
1520 var appElement,
1521 module,
1522 config = {};
1523
1524 // The element `element` has priority over any other element
1525 forEach(ngAttrPrefixes, function(prefix) {
1526 var name = prefix + 'app';
1527
1528 if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
1529 appElement = element;
1530 module = element.getAttribute(name);
1531 }
1532 });
1533 forEach(ngAttrPrefixes, function(prefix) {
1534 var name = prefix + 'app';
1535 var candidate;
1536
1537 if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
1538 appElement = candidate;
1539 module = candidate.getAttribute(name);
1540 }
1541 });
1542 if (appElement) {
1543 config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
1544 bootstrap(appElement, module ? [module] : [], config);
1545 }
1546 }
1547
1548 /**
1549 * @ngdoc function
1550 * @name angular.bootstrap
1551 * @module ng
1552 * @description
1553 * Use this function to manually start up angular application.
1554 *
1555 * See: {@link guide/bootstrap Bootstrap}
1556 *
1557 * Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.
1558 * They must use {@link ng.directive:ngApp ngApp}.
1559 *
1560 * Angular will detect if it has been loaded into the browser more than once and only allow the
1561 * first loaded script to be bootstrapped and will report a warning to the browser console for
1562 * each of the subsequent scripts. This prevents strange results in applications, where otherwise
1563 * multiple instances of Angular try to work on the DOM.
1564 *
1565 * ```html
1566 * <!doctype html>
1567 * <html>
1568 * <body>
1569 * <div ng-controller="WelcomeController">
1570 * {{greeting}}
1571 * </div>
1572 *
1573 * <script src="angular.js"></script>
1574 * <script>
1575 * var app = angular.module('demo', [])
1576 * .controller('WelcomeController', function($scope) {
1577 * $scope.greeting = 'Welcome!';
1578 * });
1579 * angular.bootstrap(document, ['demo']);
1580 * </script>
1581 * </body>
1582 * </html>
1583 * ```
1584 *
1585 * @param {DOMElement} element DOM element which is the root of angular application.
1586 * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
1587 * Each item in the array should be the name of a predefined module or a (DI annotated)
1588 * function that will be invoked by the injector as a `config` block.
1589 * See: {@link angular.module modules}
1590 * @param {Object=} config an object for defining configuration options for the application. The
1591 * following keys are supported:
1592 *
1593 * * `strictDi` - disable automatic function annotation for the application. This is meant to
1594 * assist in finding bugs which break minified code. Defaults to `false`.
1595 *
1596 * @returns {auto.$injector} Returns the newly created injector for this app.
1597 */
1598 function bootstrap(element, modules, config) {
1599 if (!isObject(config)) config = {};
1600 var defaultConfig = {
1601 strictDi: false
1602 };
1603 config = extend(defaultConfig, config);
1604 var doBootstrap = function() {
1605 element = jqLite(element);
1606
1607 if (element.injector()) {
1608 var tag = (element[0] === document) ? 'document' : startingTag(element);
1609 //Encode angle brackets to prevent input from being sanitized to empty string #8683
1610 throw ngMinErr(
1611 'btstrpd',
1612 "App Already Bootstrapped with this Element '{0}'",
1613 tag.replace(/</,'&lt;').replace(/>/,'&gt;'));
1614 }
1615
1616 modules = modules || [];
1617 modules.unshift(['$provide', function($provide) {
1618 $provide.value('$rootElement', element);
1619 }]);
1620
1621 if (config.debugInfoEnabled) {
1622 // Pushing so that this overrides `debugInfoEnabled` setting defined in user's `modules`.
1623 modules.push(['$compileProvider', function($compileProvider) {
1624 $compileProvider.debugInfoEnabled(true);
1625 }]);
1626 }
1627
1628 modules.unshift('ng');
1629 var injector = createInjector(modules, config.strictDi);
1630 injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
1631 function bootstrapApply(scope, element, compile, injector) {
1632 scope.$apply(function() {
1633 element.data('$injector', injector);
1634 compile(element)(scope);
1635 });
1636 }]
1637 );
1638 return injector;
1639 };
1640
1641 var NG_ENABLE_DEBUG_INFO = /^NG_ENABLE_DEBUG_INFO!/;
1642 var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
1643
1644 if (window && NG_ENABLE_DEBUG_INFO.test(window.name)) {
1645 config.debugInfoEnabled = true;
1646 window.name = window.name.replace(NG_ENABLE_DEBUG_INFO, '');
1647 }
1648
1649 if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
1650 return doBootstrap();
1651 }
1652
1653 window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
1654 angular.resumeBootstrap = function(extraModules) {
1655 forEach(extraModules, function(module) {
1656 modules.push(module);
1657 });
1658 return doBootstrap();
1659 };
1660
1661 if (isFunction(angular.resumeDeferredBootstrap)) {
1662 angular.resumeDeferredBootstrap();
1663 }
1664 }
1665
1666 /**
1667 * @ngdoc function
1668 * @name angular.reloadWithDebugInfo
1669 * @module ng
1670 * @description
1671 * Use this function to reload the current application with debug information turned on.
1672 * This takes precedence over a call to `$compileProvider.debugInfoEnabled(false)`.
1673 *
1674 * See {@link ng.$compileProvider#debugInfoEnabled} for more.
1675 */
1676 function reloadWithDebugInfo() {
1677 window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
1678 window.location.reload();
1679 }
1680
1681 /**
1682 * @name angular.getTestability
1683 * @module ng
1684 * @description
1685 * Get the testability service for the instance of Angular on the given
1686 * element.
1687 * @param {DOMElement} element DOM element which is the root of angular application.
1688 */
1689 function getTestability(rootElement) {
1690 var injector = angular.element(rootElement).injector();
1691 if (!injector) {
1692 throw ngMinErr('test',
1693 'no injector found for element argument to getTestability');
1694 }
1695 return injector.get('$$testability');
1696 }
1697
1698 var SNAKE_CASE_REGEXP = /[A-Z]/g;
1699 function snake_case(name, separator) {
1700 separator = separator || '_';
1701 return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
1702 return (pos ? separator : '') + letter.toLowerCase();
1703 });
1704 }
1705
1706 var bindJQueryFired = false;
1707 var skipDestroyOnNextJQueryCleanData;
1708 function bindJQuery() {
1709 var originalCleanData;
1710
1711 if (bindJQueryFired) {
1712 return;
1713 }
1714
1715 // bind to jQuery if present;
1716 var jqName = jq();
1717 jQuery = window.jQuery; // use default jQuery.
1718 if (isDefined(jqName)) { // `ngJq` present
1719 jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`.
1720 }
1721
1722 // Use jQuery if it exists with proper functionality, otherwise default to us.
1723 // Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
1724 // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
1725 // versions. It will not work for sure with jQuery <1.7, though.
1726 if (jQuery && jQuery.fn.on) {
1727 jqLite = jQuery;
1728 extend(jQuery.fn, {
1729 scope: JQLitePrototype.scope,
1730 isolateScope: JQLitePrototype.isolateScope,
1731 controller: JQLitePrototype.controller,
1732 injector: JQLitePrototype.injector,
1733 inheritedData: JQLitePrototype.inheritedData
1734 });
1735
1736 // All nodes removed from the DOM via various jQuery APIs like .remove()
1737 // are passed through jQuery.cleanData. Monkey-patch this method to fire
1738 // the $destroy event on all removed nodes.
1739 originalCleanData = jQuery.cleanData;
1740 jQuery.cleanData = function(elems) {
1741 var events;
1742 if (!skipDestroyOnNextJQueryCleanData) {
1743 for (var i = 0, elem; (elem = elems[i]) != null; i++) {
1744 events = jQuery._data(elem, "events");
1745 if (events && events.$destroy) {
1746 jQuery(elem).triggerHandler('$destroy');
1747 }
1748 }
1749 } else {
1750 skipDestroyOnNextJQueryCleanData = false;
1751 }
1752 originalCleanData(elems);
1753 };
1754 } else {
1755 jqLite = JQLite;
1756 }
1757
1758 angular.element = jqLite;
1759
1760 // Prevent double-proxying.
1761 bindJQueryFired = true;
1762 }
1763
1764 /**
1765 * throw error if the argument is falsy.
1766 */
1767 function assertArg(arg, name, reason) {
1768 if (!arg) {
1769 throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
1770 }
1771 return arg;
1772 }
1773
1774 function assertArgFn(arg, name, acceptArrayAnnotation) {
1775 if (acceptArrayAnnotation && isArray(arg)) {
1776 arg = arg[arg.length - 1];
1777 }
1778
1779 assertArg(isFunction(arg), name, 'not a function, got ' +
1780 (arg && typeof arg === 'object' ? arg.constructor.name || 'Object' : typeof arg));
1781 return arg;
1782 }
1783
1784 /**
1785 * throw error if the name given is hasOwnProperty
1786 * @param {String} name the name to test
1787 * @param {String} context the context in which the name is used, such as module or directive
1788 */
1789 function assertNotHasOwnProperty(name, context) {
1790 if (name === 'hasOwnProperty') {
1791 throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
1792 }
1793 }
1794
1795 /**
1796 * Return the value accessible from the object by path. Any undefined traversals are ignored
1797 * @param {Object} obj starting object
1798 * @param {String} path path to traverse
1799 * @param {boolean} [bindFnToScope=true]
1800 * @returns {Object} value as accessible by path
1801 */
1802 //TODO(misko): this function needs to be removed
1803 function getter(obj, path, bindFnToScope) {
1804 if (!path) return obj;
1805 var keys = path.split('.');
1806 var key;
1807 var lastInstance = obj;
1808 var len = keys.length;
1809
1810 for (var i = 0; i < len; i++) {
1811 key = keys[i];
1812 if (obj) {
1813 obj = (lastInstance = obj)[key];
1814 }
1815 }
1816 if (!bindFnToScope && isFunction(obj)) {
1817 return bind(lastInstance, obj);
1818 }
1819 return obj;
1820 }
1821
1822 /**
1823 * Return the DOM siblings between the first and last node in the given array.
1824 * @param {Array} array like object
1825 * @returns {jqLite} jqLite collection containing the nodes
1826 */
1827 function getBlockNodes(nodes) {
1828 // TODO(perf): just check if all items in `nodes` are siblings and if they are return the original
1829 // collection, otherwise update the original collection.
1830 var node = nodes[0];
1831 var endNode = nodes[nodes.length - 1];
1832 var blockNodes = [node];
1833
1834 do {
1835 node = node.nextSibling;
1836 if (!node) break;
1837 blockNodes.push(node);
1838 } while (node !== endNode);
1839
1840 return jqLite(blockNodes);
1841 }
1842
1843
1844 /**
1845 * Creates a new object without a prototype. This object is useful for lookup without having to
1846 * guard against prototypically inherited properties via hasOwnProperty.
1847 *
1848 * Related micro-benchmarks:
1849 * - http://jsperf.com/object-create2
1850 * - http://jsperf.com/proto-map-lookup/2
1851 * - http://jsperf.com/for-in-vs-object-keys2
1852 *
1853 * @returns {Object}
1854 */
1855 function createMap() {
1856 return Object.create(null);
1857 }
1858
1859 var NODE_TYPE_ELEMENT = 1;
1860 var NODE_TYPE_ATTRIBUTE = 2;
1861 var NODE_TYPE_TEXT = 3;
1862 var NODE_TYPE_COMMENT = 8;
1863 var NODE_TYPE_DOCUMENT = 9;
1864 var NODE_TYPE_DOCUMENT_FRAGMENT = 11;
1865
1866 /**
1867 * @ngdoc type
1868 * @name angular.Module
1869 * @module ng
1870 * @description
1871 *
1872 * Interface for configuring angular {@link angular.module modules}.
1873 */
1874
1875 function setupModuleLoader(window) {
1876
1877 var $injectorMinErr = minErr('$injector');
1878 var ngMinErr = minErr('ng');
1879
1880 function ensure(obj, name, factory) {
1881 return obj[name] || (obj[name] = factory());
1882 }
1883
1884 var angular = ensure(window, 'angular', Object);
1885
1886 // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
1887 angular.$$minErr = angular.$$minErr || minErr;
1888
1889 return ensure(angular, 'module', function() {
1890 /** @type {Object.<string, angular.Module>} */
1891 var modules = {};
1892
1893 /**
1894 * @ngdoc function
1895 * @name angular.module
1896 * @module ng
1897 * @description
1898 *
1899 * The `angular.module` is a global place for creating, registering and retrieving Angular
1900 * modules.
1901 * All modules (angular core or 3rd party) that should be available to an application must be
1902 * registered using this mechanism.
1903 *
1904 * When passed two or more arguments, a new module is created. If passed only one argument, an
1905 * existing module (the name passed as the first argument to `module`) is retrieved.
1906 *
1907 *
1908 * # Module
1909 *
1910 * A module is a collection of services, directives, controllers, filters, and configuration information.
1911 * `angular.module` is used to configure the {@link auto.$injector $injector}.
1912 *
1913 * ```js
1914 * // Create a new module
1915 * var myModule = angular.module('myModule', []);
1916 *
1917 * // register a new service
1918 * myModule.value('appName', 'MyCoolApp');
1919 *
1920 * // configure existing services inside initialization blocks.
1921 * myModule.config(['$locationProvider', function($locationProvider) {
1922 * // Configure existing providers
1923 * $locationProvider.hashPrefix('!');
1924 * }]);
1925 * ```
1926 *
1927 * Then you can create an injector and load your modules like this:
1928 *
1929 * ```js
1930 * var injector = angular.injector(['ng', 'myModule'])
1931 * ```
1932 *
1933 * However it's more likely that you'll just use
1934 * {@link ng.directive:ngApp ngApp} or
1935 * {@link angular.bootstrap} to simplify this process for you.
1936 *
1937 * @param {!string} name The name of the module to create or retrieve.
1938 * @param {!Array.<string>=} requires If specified then new module is being created. If
1939 * unspecified then the module is being retrieved for further configuration.
1940 * @param {Function=} configFn Optional configuration function for the module. Same as
1941 * {@link angular.Module#config Module#config()}.
1942 * @returns {module} new module with the {@link angular.Module} api.
1943 */
1944 return function module(name, requires, configFn) {
1945 var assertNotHasOwnProperty = function(name, context) {
1946 if (name === 'hasOwnProperty') {
1947 throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
1948 }
1949 };
1950
1951 assertNotHasOwnProperty(name, 'module');
1952 if (requires && modules.hasOwnProperty(name)) {
1953 modules[name] = null;
1954 }
1955 return ensure(modules, name, function() {
1956 if (!requires) {
1957 throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
1958 "the module name or forgot to load it. If registering a module ensure that you " +
1959 "specify the dependencies as the second argument.", name);
1960 }
1961
1962 /** @type {!Array.<Array.<*>>} */
1963 var invokeQueue = [];
1964
1965 /** @type {!Array.<Function>} */
1966 var configBlocks = [];
1967
1968 /** @type {!Array.<Function>} */
1969 var runBlocks = [];
1970
1971 var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
1972
1973 /** @type {angular.Module} */
1974 var moduleInstance = {
1975 // Private state
1976 _invokeQueue: invokeQueue,
1977 _configBlocks: configBlocks,
1978 _runBlocks: runBlocks,
1979
1980 /**
1981 * @ngdoc property
1982 * @name angular.Module#requires
1983 * @module ng
1984 *
1985 * @description
1986 * Holds the list of modules which the injector will load before the current module is
1987 * loaded.
1988 */
1989 requires: requires,
1990
1991 /**
1992 * @ngdoc property
1993 * @name angular.Module#name
1994 * @module ng
1995 *
1996 * @description
1997 * Name of the module.
1998 */
1999 name: name,
2000
2001
2002 /**
2003 * @ngdoc method
2004 * @name angular.Module#provider
2005 * @module ng
2006 * @param {string} name service name
2007 * @param {Function} providerType Construction function for creating new instance of the
2008 * service.
2009 * @description
2010 * See {@link auto.$provide#provider $provide.provider()}.
2011 */
2012 provider: invokeLaterAndSetModuleName('$provide', 'provider'),
2013
2014 /**
2015 * @ngdoc method
2016 * @name angular.Module#factory
2017 * @module ng
2018 * @param {string} name service name
2019 * @param {Function} providerFunction Function for creating new instance of the service.
2020 * @description
2021 * See {@link auto.$provide#factory $provide.factory()}.
2022 */
2023 factory: invokeLaterAndSetModuleName('$provide', 'factory'),
2024
2025 /**
2026 * @ngdoc method
2027 * @name angular.Module#service
2028 * @module ng
2029 * @param {string} name service name
2030 * @param {Function} constructor A constructor function that will be instantiated.
2031 * @description
2032 * See {@link auto.$provide#service $provide.service()}.
2033 */
2034 service: invokeLaterAndSetModuleName('$provide', 'service'),
2035
2036 /**
2037 * @ngdoc method
2038 * @name angular.Module#value
2039 * @module ng
2040 * @param {string} name service name
2041 * @param {*} object Service instance object.
2042 * @description
2043 * See {@link auto.$provide#value $provide.value()}.
2044 */
2045 value: invokeLater('$provide', 'value'),
2046
2047 /**
2048 * @ngdoc method
2049 * @name angular.Module#constant
2050 * @module ng
2051 * @param {string} name constant name
2052 * @param {*} object Constant value.
2053 * @description
2054 * Because the constant are fixed, they get applied before other provide methods.
2055 * See {@link auto.$provide#constant $provide.constant()}.
2056 */
2057 constant: invokeLater('$provide', 'constant', 'unshift'),
2058
2059 /**
2060 * @ngdoc method
2061 * @name angular.Module#decorator
2062 * @module ng
2063 * @param {string} The name of the service to decorate.
2064 * @param {Function} This function will be invoked when the service needs to be
2065 * instantiated and should return the decorated service instance.
2066 * @description
2067 * See {@link auto.$provide#decorator $provide.decorator()}.
2068 */
2069 decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),
2070
2071 /**
2072 * @ngdoc method
2073 * @name angular.Module#animation
2074 * @module ng
2075 * @param {string} name animation name
2076 * @param {Function} animationFactory Factory function for creating new instance of an
2077 * animation.
2078 * @description
2079 *
2080 * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
2081 *
2082 *
2083 * Defines an animation hook that can be later used with
2084 * {@link $animate $animate} service and directives that use this service.
2085 *
2086 * ```js
2087 * module.animation('.animation-name', function($inject1, $inject2) {
2088 * return {
2089 * eventName : function(element, done) {
2090 * //code to run the animation
2091 * //once complete, then run done()
2092 * return function cancellationFunction(element) {
2093 * //code to cancel the animation
2094 * }
2095 * }
2096 * }
2097 * })
2098 * ```
2099 *
2100 * See {@link ng.$animateProvider#register $animateProvider.register()} and
2101 * {@link ngAnimate ngAnimate module} for more information.
2102 */
2103 animation: invokeLaterAndSetModuleName('$animateProvider', 'register'),
2104
2105 /**
2106 * @ngdoc method
2107 * @name angular.Module#filter
2108 * @module ng
2109 * @param {string} name Filter name - this must be a valid angular expression identifier
2110 * @param {Function} filterFactory Factory function for creating new instance of filter.
2111 * @description
2112 * See {@link ng.$filterProvider#register $filterProvider.register()}.
2113 *
2114 * <div class="alert alert-warning">
2115 * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
2116 * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
2117 * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
2118 * (`myapp_subsection_filterx`).
2119 * </div>
2120 */
2121 filter: invokeLaterAndSetModuleName('$filterProvider', 'register'),
2122
2123 /**
2124 * @ngdoc method
2125 * @name angular.Module#controller
2126 * @module ng
2127 * @param {string|Object} name Controller name, or an object map of controllers where the
2128 * keys are the names and the values are the constructors.
2129 * @param {Function} constructor Controller constructor function.
2130 * @description
2131 * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
2132 */
2133 controller: invokeLaterAndSetModuleName('$controllerProvider', 'register'),
2134
2135 /**
2136 * @ngdoc method
2137 * @name angular.Module#directive
2138 * @module ng
2139 * @param {string|Object} name Directive name, or an object map of directives where the
2140 * keys are the names and the values are the factories.
2141 * @param {Function} directiveFactory Factory function for creating new instance of
2142 * directives.
2143 * @description
2144 * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
2145 */
2146 directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),
2147
2148 /**
2149 * @ngdoc method
2150 * @name angular.Module#config
2151 * @module ng
2152 * @param {Function} configFn Execute this function on module load. Useful for service
2153 * configuration.
2154 * @description
2155 * Use this method to register work which needs to be performed on module loading.
2156 * For more about how to configure services, see
2157 * {@link providers#provider-recipe Provider Recipe}.
2158 */
2159 config: config,
2160
2161 /**
2162 * @ngdoc method
2163 * @name angular.Module#run
2164 * @module ng
2165 * @param {Function} initializationFn Execute this function after injector creation.
2166 * Useful for application initialization.
2167 * @description
2168 * Use this method to register work which should be performed when the injector is done
2169 * loading all modules.
2170 */
2171 run: function(block) {
2172 runBlocks.push(block);
2173 return this;
2174 }
2175 };
2176
2177 if (configFn) {
2178 config(configFn);
2179 }
2180
2181 return moduleInstance;
2182
2183 /**
2184 * @param {string} provider
2185 * @param {string} method
2186 * @param {String=} insertMethod
2187 * @returns {angular.Module}
2188 */
2189 function invokeLater(provider, method, insertMethod, queue) {
2190 if (!queue) queue = invokeQueue;
2191 return function() {
2192 queue[insertMethod || 'push']([provider, method, arguments]);
2193 return moduleInstance;
2194 };
2195 }
2196
2197 /**
2198 * @param {string} provider
2199 * @param {string} method
2200 * @returns {angular.Module}
2201 */
2202 function invokeLaterAndSetModuleName(provider, method) {
2203 return function(recipeName, factoryFunction) {
2204 if (factoryFunction && isFunction(factoryFunction)) factoryFunction.$$moduleName = name;
2205 invokeQueue.push([provider, method, arguments]);
2206 return moduleInstance;
2207 };
2208 }
2209 });
2210 };
2211 });
2212
2213 }
2214
2215 /* global: toDebugString: true */
2216
2217 function serializeObject(obj) {
2218 var seen = [];
2219
2220 return JSON.stringify(obj, function(key, val) {
2221 val = toJsonReplacer(key, val);
2222 if (isObject(val)) {
2223
2224 if (seen.indexOf(val) >= 0) return '<<already seen>>';
2225
2226 seen.push(val);
2227 }
2228 return val;
2229 });
2230 }
2231
2232 function toDebugString(obj) {
2233 if (typeof obj === 'function') {
2234 return obj.toString().replace(/ \{[\s\S]*$/, '');
2235 } else if (typeof obj === 'undefined') {
2236 return 'undefined';
2237 } else if (typeof obj !== 'string') {
2238 return serializeObject(obj);
2239 }
2240 return obj;
2241 }
2242
2243 /* global angularModule: true,
2244 version: true,
2245
2246 $LocaleProvider,
2247 $CompileProvider,
2248
2249 htmlAnchorDirective,
2250 inputDirective,
2251 inputDirective,
2252 formDirective,
2253 scriptDirective,
2254 selectDirective,
2255 styleDirective,
2256 optionDirective,
2257 ngBindDirective,
2258 ngBindHtmlDirective,
2259 ngBindTemplateDirective,
2260 ngClassDirective,
2261 ngClassEvenDirective,
2262 ngClassOddDirective,
2263 ngCspDirective,
2264 ngCloakDirective,
2265 ngControllerDirective,
2266 ngFormDirective,
2267 ngHideDirective,
2268 ngIfDirective,
2269 ngIncludeDirective,
2270 ngIncludeFillContentDirective,
2271 ngInitDirective,
2272 ngNonBindableDirective,
2273 ngPluralizeDirective,
2274 ngRepeatDirective,
2275 ngShowDirective,
2276 ngStyleDirective,
2277 ngSwitchDirective,
2278 ngSwitchWhenDirective,
2279 ngSwitchDefaultDirective,
2280 ngOptionsDirective,
2281 ngTranscludeDirective,
2282 ngModelDirective,
2283 ngListDirective,
2284 ngChangeDirective,
2285 patternDirective,
2286 patternDirective,
2287 requiredDirective,
2288 requiredDirective,
2289 minlengthDirective,
2290 minlengthDirective,
2291 maxlengthDirective,
2292 maxlengthDirective,
2293 ngValueDirective,
2294 ngModelOptionsDirective,
2295 ngAttributeAliasDirectives,
2296 ngEventDirectives,
2297
2298 $AnchorScrollProvider,
2299 $AnimateProvider,
2300 $$CoreAnimateQueueProvider,
2301 $$CoreAnimateRunnerProvider,
2302 $BrowserProvider,
2303 $CacheFactoryProvider,
2304 $ControllerProvider,
2305 $DocumentProvider,
2306 $ExceptionHandlerProvider,
2307 $FilterProvider,
2308 $InterpolateProvider,
2309 $IntervalProvider,
2310 $$HashMapProvider,
2311 $HttpProvider,
2312 $HttpParamSerializerProvider,
2313 $HttpParamSerializerJQLikeProvider,
2314 $HttpBackendProvider,
2315 $LocationProvider,
2316 $LogProvider,
2317 $ParseProvider,
2318 $RootScopeProvider,
2319 $QProvider,
2320 $$QProvider,
2321 $$SanitizeUriProvider,
2322 $SceProvider,
2323 $SceDelegateProvider,
2324 $SnifferProvider,
2325 $TemplateCacheProvider,
2326 $TemplateRequestProvider,
2327 $$TestabilityProvider,
2328 $TimeoutProvider,
2329 $$RAFProvider,
2330 $WindowProvider,
2331 $$jqLiteProvider,
2332 $$CookieReaderProvider
2333 */
2334
2335
2336 /**
2337 * @ngdoc object
2338 * @name angular.version
2339 * @module ng
2340 * @description
2341 * An object that contains information about the current AngularJS version. This object has the
2342 * following properties:
2343 *
2344 * - `full` – `{string}` – Full version string, such as "0.9.18".
2345 * - `major` – `{number}` – Major version number, such as "0".
2346 * - `minor` – `{number}` – Minor version number, such as "9".
2347 * - `dot` – `{number}` – Dot version number, such as "18".
2348 * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
2349 */
2350 var version = {
2351 full: '1.4.3', // all of these placeholder strings will be replaced by grunt's
2352 major: 1, // package task
2353 minor: 4,
2354 dot: 3,
2355 codeName: 'foam-acceleration'
2356 };
2357
2358
2359 function publishExternalAPI(angular) {
2360 extend(angular, {
2361 'bootstrap': bootstrap,
2362 'copy': copy,
2363 'extend': extend,
2364 'merge': merge,
2365 'equals': equals,
2366 'element': jqLite,
2367 'forEach': forEach,
2368 'injector': createInjector,
2369 'noop': noop,
2370 'bind': bind,
2371 'toJson': toJson,
2372 'fromJson': fromJson,
2373 'identity': identity,
2374 'isUndefined': isUndefined,
2375 'isDefined': isDefined,
2376 'isString': isString,
2377 'isFunction': isFunction,
2378 'isObject': isObject,
2379 'isNumber': isNumber,
2380 'isElement': isElement,
2381 'isArray': isArray,
2382 'version': version,
2383 'isDate': isDate,
2384 'lowercase': lowercase,
2385 'uppercase': uppercase,
2386 'callbacks': {counter: 0},
2387 'getTestability': getTestability,
2388 '$$minErr': minErr,
2389 '$$csp': csp,
2390 'reloadWithDebugInfo': reloadWithDebugInfo
2391 });
2392
2393 angularModule = setupModuleLoader(window);
2394 try {
2395 angularModule('ngLocale');
2396 } catch (e) {
2397 angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
2398 }
2399
2400 angularModule('ng', ['ngLocale'], ['$provide',
2401 function ngModule($provide) {
2402 // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
2403 $provide.provider({
2404 $$sanitizeUri: $$SanitizeUriProvider
2405 });
2406 $provide.provider('$compile', $CompileProvider).
2407 directive({
2408 a: htmlAnchorDirective,
2409 input: inputDirective,
2410 textarea: inputDirective,
2411 form: formDirective,
2412 script: scriptDirective,
2413 select: selectDirective,
2414 style: styleDirective,
2415 option: optionDirective,
2416 ngBind: ngBindDirective,
2417 ngBindHtml: ngBindHtmlDirective,
2418 ngBindTemplate: ngBindTemplateDirective,
2419 ngClass: ngClassDirective,
2420 ngClassEven: ngClassEvenDirective,
2421 ngClassOdd: ngClassOddDirective,
2422 ngCloak: ngCloakDirective,
2423 ngController: ngControllerDirective,
2424 ngForm: ngFormDirective,
2425 ngHide: ngHideDirective,
2426 ngIf: ngIfDirective,
2427 ngInclude: ngIncludeDirective,
2428 ngInit: ngInitDirective,
2429 ngNonBindable: ngNonBindableDirective,
2430 ngPluralize: ngPluralizeDirective,
2431 ngRepeat: ngRepeatDirective,
2432 ngShow: ngShowDirective,
2433 ngStyle: ngStyleDirective,
2434 ngSwitch: ngSwitchDirective,
2435 ngSwitchWhen: ngSwitchWhenDirective,
2436 ngSwitchDefault: ngSwitchDefaultDirective,
2437 ngOptions: ngOptionsDirective,
2438 ngTransclude: ngTranscludeDirective,
2439 ngModel: ngModelDirective,
2440 ngList: ngListDirective,
2441 ngChange: ngChangeDirective,
2442 pattern: patternDirective,
2443 ngPattern: patternDirective,
2444 required: requiredDirective,
2445 ngRequired: requiredDirective,
2446 minlength: minlengthDirective,
2447 ngMinlength: minlengthDirective,
2448 maxlength: maxlengthDirective,
2449 ngMaxlength: maxlengthDirective,
2450 ngValue: ngValueDirective,
2451 ngModelOptions: ngModelOptionsDirective
2452 }).
2453 directive({
2454 ngInclude: ngIncludeFillContentDirective
2455 }).
2456 directive(ngAttributeAliasDirectives).
2457 directive(ngEventDirectives);
2458 $provide.provider({
2459 $anchorScroll: $AnchorScrollProvider,
2460 $animate: $AnimateProvider,
2461 $$animateQueue: $$CoreAnimateQueueProvider,
2462 $$AnimateRunner: $$CoreAnimateRunnerProvider,
2463 $browser: $BrowserProvider,
2464 $cacheFactory: $CacheFactoryProvider,
2465 $controller: $ControllerProvider,
2466 $document: $DocumentProvider,
2467 $exceptionHandler: $ExceptionHandlerProvider,
2468 $filter: $FilterProvider,
2469 $interpolate: $InterpolateProvider,
2470 $interval: $IntervalProvider,
2471 $http: $HttpProvider,
2472 $httpParamSerializer: $HttpParamSerializerProvider,
2473 $httpParamSerializerJQLike: $HttpParamSerializerJQLikeProvider,
2474 $httpBackend: $HttpBackendProvider,
2475 $location: $LocationProvider,
2476 $log: $LogProvider,
2477 $parse: $ParseProvider,
2478 $rootScope: $RootScopeProvider,
2479 $q: $QProvider,
2480 $$q: $$QProvider,
2481 $sce: $SceProvider,
2482 $sceDelegate: $SceDelegateProvider,
2483 $sniffer: $SnifferProvider,
2484 $templateCache: $TemplateCacheProvider,
2485 $templateRequest: $TemplateRequestProvider,
2486 $$testability: $$TestabilityProvider,
2487 $timeout: $TimeoutProvider,
2488 $window: $WindowProvider,
2489 $$rAF: $$RAFProvider,
2490 $$jqLite: $$jqLiteProvider,
2491 $$HashMap: $$HashMapProvider,
2492 $$cookieReader: $$CookieReaderProvider
2493 });
2494 }
2495 ]);
2496 }
2497
2498 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2499 * Any commits to this file should be reviewed with security in mind. *
2500 * Changes to this file can potentially create security vulnerabilities. *
2501 * An approval from 2 Core members with history of modifying *
2502 * this file is required. *
2503 * *
2504 * Does the change somehow allow for arbitrary javascript to be executed? *
2505 * Or allows for someone to change the prototype of built-in objects? *
2506 * Or gives undesired access to variables likes document or window? *
2507 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2508
2509 /* global JQLitePrototype: true,
2510 addEventListenerFn: true,
2511 removeEventListenerFn: true,
2512 BOOLEAN_ATTR: true,
2513 ALIASED_ATTR: true,
2514 */
2515
2516 //////////////////////////////////
2517 //JQLite
2518 //////////////////////////////////
2519
2520 /**
2521 * @ngdoc function
2522 * @name angular.element
2523 * @module ng
2524 * @kind function
2525 *
2526 * @description
2527 * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
2528 *
2529 * If jQuery is available, `angular.element` is an alias for the
2530 * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
2531 * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
2532 *
2533 * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
2534 * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
2535 * commonly needed functionality with the goal of having a very small footprint.</div>
2536 *
2537 * To use `jQuery`, simply ensure it is loaded before the `angular.js` file.
2538 *
2539 * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
2540 * jqLite; they are never raw DOM references.</div>
2541 *
2542 * ## Angular's jqLite
2543 * jqLite provides only the following jQuery methods:
2544 *
2545 * - [`addClass()`](http://api.jquery.com/addClass/)
2546 * - [`after()`](http://api.jquery.com/after/)
2547 * - [`append()`](http://api.jquery.com/append/)
2548 * - [`attr()`](http://api.jquery.com/attr/) - Does not support functions as parameters
2549 * - [`bind()`](http://api.jquery.com/bind/) - Does not support namespaces, selectors or eventData
2550 * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
2551 * - [`clone()`](http://api.jquery.com/clone/)
2552 * - [`contents()`](http://api.jquery.com/contents/)
2553 * - [`css()`](http://api.jquery.com/css/) - Only retrieves inline-styles, does not call `getComputedStyle()`. As a setter, does not convert numbers to strings or append 'px'.
2554 * - [`data()`](http://api.jquery.com/data/)
2555 * - [`detach()`](http://api.jquery.com/detach/)
2556 * - [`empty()`](http://api.jquery.com/empty/)
2557 * - [`eq()`](http://api.jquery.com/eq/)
2558 * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
2559 * - [`hasClass()`](http://api.jquery.com/hasClass/)
2560 * - [`html()`](http://api.jquery.com/html/)
2561 * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
2562 * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
2563 * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
2564 * - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
2565 * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
2566 * - [`prepend()`](http://api.jquery.com/prepend/)
2567 * - [`prop()`](http://api.jquery.com/prop/)
2568 * - [`ready()`](http://api.jquery.com/ready/)
2569 * - [`remove()`](http://api.jquery.com/remove/)
2570 * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
2571 * - [`removeClass()`](http://api.jquery.com/removeClass/)
2572 * - [`removeData()`](http://api.jquery.com/removeData/)
2573 * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
2574 * - [`text()`](http://api.jquery.com/text/)
2575 * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
2576 * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
2577 * - [`unbind()`](http://api.jquery.com/unbind/) - Does not support namespaces
2578 * - [`val()`](http://api.jquery.com/val/)
2579 * - [`wrap()`](http://api.jquery.com/wrap/)
2580 *
2581 * ## jQuery/jqLite Extras
2582 * Angular also provides the following additional methods and events to both jQuery and jqLite:
2583 *
2584 * ### Events
2585 * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
2586 * on all DOM nodes being removed. This can be used to clean up any 3rd party bindings to the DOM
2587 * element before it is removed.
2588 *
2589 * ### Methods
2590 * - `controller(name)` - retrieves the controller of the current element or its parent. By default
2591 * retrieves controller associated with the `ngController` directive. If `name` is provided as
2592 * camelCase directive name, then the controller for this directive will be retrieved (e.g.
2593 * `'ngModel'`).
2594 * - `injector()` - retrieves the injector of the current element or its parent.
2595 * - `scope()` - retrieves the {@link ng.$rootScope.Scope scope} of the current
2596 * element or its parent. Requires {@link guide/production#disabling-debug-data Debug Data} to
2597 * be enabled.
2598 * - `isolateScope()` - retrieves an isolate {@link ng.$rootScope.Scope scope} if one is attached directly to the
2599 * current element. This getter should be used only on elements that contain a directive which starts a new isolate
2600 * scope. Calling `scope()` on this element always returns the original non-isolate scope.
2601 * Requires {@link guide/production#disabling-debug-data Debug Data} to be enabled.
2602 * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
2603 * parent element is reached.
2604 *
2605 * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
2606 * @returns {Object} jQuery object.
2607 */
2608
2609 JQLite.expando = 'ng339';
2610
2611 var jqCache = JQLite.cache = {},
2612 jqId = 1,
2613 addEventListenerFn = function(element, type, fn) {
2614 element.addEventListener(type, fn, false);
2615 },
2616 removeEventListenerFn = function(element, type, fn) {
2617 element.removeEventListener(type, fn, false);
2618 };
2619
2620 /*
2621 * !!! This is an undocumented "private" function !!!
2622 */
2623 JQLite._data = function(node) {
2624 //jQuery always returns an object on cache miss
2625 return this.cache[node[this.expando]] || {};
2626 };
2627
2628 function jqNextId() { return ++jqId; }
2629
2630
2631 var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
2632 var MOZ_HACK_REGEXP = /^moz([A-Z])/;
2633 var MOUSE_EVENT_MAP= { mouseleave: "mouseout", mouseenter: "mouseover"};
2634 var jqLiteMinErr = minErr('jqLite');
2635
2636 /**
2637 * Converts snake_case to camelCase.
2638 * Also there is special case for Moz prefix starting with upper case letter.
2639 * @param name Name to normalize
2640 */
2641 function camelCase(name) {
2642 return name.
2643 replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
2644 return offset ? letter.toUpperCase() : letter;
2645 }).
2646 replace(MOZ_HACK_REGEXP, 'Moz$1');
2647 }
2648
2649 var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
2650 var HTML_REGEXP = /<|&#?\w+;/;
2651 var TAG_NAME_REGEXP = /<([\w:]+)/;
2652 var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
2653
2654 var wrapMap = {
2655 'option': [1, '<select multiple="multiple">', '</select>'],
2656
2657 'thead': [1, '<table>', '</table>'],
2658 'col': [2, '<table><colgroup>', '</colgroup></table>'],
2659 'tr': [2, '<table><tbody>', '</tbody></table>'],
2660 'td': [3, '<table><tbody><tr>', '</tr></tbody></table>'],
2661 '_default': [0, "", ""]
2662 };
2663
2664 wrapMap.optgroup = wrapMap.option;
2665 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
2666 wrapMap.th = wrapMap.td;
2667
2668
2669 function jqLiteIsTextNode(html) {
2670 return !HTML_REGEXP.test(html);
2671 }
2672
2673 function jqLiteAcceptsData(node) {
2674 // The window object can accept data but has no nodeType
2675 // Otherwise we are only interested in elements (1) and documents (9)
2676 var nodeType = node.nodeType;
2677 return nodeType === NODE_TYPE_ELEMENT || !nodeType || nodeType === NODE_TYPE_DOCUMENT;
2678 }
2679
2680 function jqLiteHasData(node) {
2681 for (var key in jqCache[node.ng339]) {
2682 return true;
2683 }
2684 return false;
2685 }
2686
2687 function jqLiteBuildFragment(html, context) {
2688 var tmp, tag, wrap,
2689 fragment = context.createDocumentFragment(),
2690 nodes = [], i;
2691
2692 if (jqLiteIsTextNode(html)) {
2693 // Convert non-html into a text node
2694 nodes.push(context.createTextNode(html));
2695 } else {
2696 // Convert html into DOM nodes
2697 tmp = tmp || fragment.appendChild(context.createElement("div"));
2698 tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
2699 wrap = wrapMap[tag] || wrapMap._default;
2700 tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
2701
2702 // Descend through wrappers to the right content
2703 i = wrap[0];
2704 while (i--) {
2705 tmp = tmp.lastChild;
2706 }
2707
2708 nodes = concat(nodes, tmp.childNodes);
2709
2710 tmp = fragment.firstChild;
2711 tmp.textContent = "";
2712 }
2713
2714 // Remove wrapper from fragment
2715 fragment.textContent = "";
2716 fragment.innerHTML = ""; // Clear inner HTML
2717 forEach(nodes, function(node) {
2718 fragment.appendChild(node);
2719 });
2720
2721 return fragment;
2722 }
2723
2724 function jqLiteParseHTML(html, context) {
2725 context = context || document;
2726 var parsed;
2727
2728 if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
2729 return [context.createElement(parsed[1])];
2730 }
2731
2732 if ((parsed = jqLiteBuildFragment(html, context))) {
2733 return parsed.childNodes;
2734 }
2735
2736 return [];
2737 }
2738
2739 /////////////////////////////////////////////
2740 function JQLite(element) {
2741 if (element instanceof JQLite) {
2742 return element;
2743 }
2744
2745 var argIsString;
2746
2747 if (isString(element)) {
2748 element = trim(element);
2749 argIsString = true;
2750 }
2751 if (!(this instanceof JQLite)) {
2752 if (argIsString && element.charAt(0) != '<') {
2753 throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
2754 }
2755 return new JQLite(element);
2756 }
2757
2758 if (argIsString) {
2759 jqLiteAddNodes(this, jqLiteParseHTML(element));
2760 } else {
2761 jqLiteAddNodes(this, element);
2762 }
2763 }
2764
2765 function jqLiteClone(element) {
2766 return element.cloneNode(true);
2767 }
2768
2769 function jqLiteDealoc(element, onlyDescendants) {
2770 if (!onlyDescendants) jqLiteRemoveData(element);
2771
2772 if (element.querySelectorAll) {
2773 var descendants = element.querySelectorAll('*');
2774 for (var i = 0, l = descendants.length; i < l; i++) {
2775 jqLiteRemoveData(descendants[i]);
2776 }
2777 }
2778 }
2779
2780 function jqLiteOff(element, type, fn, unsupported) {
2781 if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
2782
2783 var expandoStore = jqLiteExpandoStore(element);
2784 var events = expandoStore && expandoStore.events;
2785 var handle = expandoStore && expandoStore.handle;
2786
2787 if (!handle) return; //no listeners registered
2788
2789 if (!type) {
2790 for (type in events) {
2791 if (type !== '$destroy') {
2792 removeEventListenerFn(element, type, handle);
2793 }
2794 delete events[type];
2795 }
2796 } else {
2797 forEach(type.split(' '), function(type) {
2798 if (isDefined(fn)) {
2799 var listenerFns = events[type];
2800 arrayRemove(listenerFns || [], fn);
2801 if (listenerFns && listenerFns.length > 0) {
2802 return;
2803 }
2804 }
2805
2806 removeEventListenerFn(element, type, handle);
2807 delete events[type];
2808 });
2809 }
2810 }
2811
2812 function jqLiteRemoveData(element, name) {
2813 var expandoId = element.ng339;
2814 var expandoStore = expandoId && jqCache[expandoId];
2815
2816 if (expandoStore) {
2817 if (name) {
2818 delete expandoStore.data[name];
2819 return;
2820 }
2821
2822 if (expandoStore.handle) {
2823 if (expandoStore.events.$destroy) {
2824 expandoStore.handle({}, '$destroy');
2825 }
2826 jqLiteOff(element);
2827 }
2828 delete jqCache[expandoId];
2829 element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
2830 }
2831 }
2832
2833
2834 function jqLiteExpandoStore(element, createIfNecessary) {
2835 var expandoId = element.ng339,
2836 expandoStore = expandoId && jqCache[expandoId];
2837
2838 if (createIfNecessary && !expandoStore) {
2839 element.ng339 = expandoId = jqNextId();
2840 expandoStore = jqCache[expandoId] = {events: {}, data: {}, handle: undefined};
2841 }
2842
2843 return expandoStore;
2844 }
2845
2846
2847 function jqLiteData(element, key, value) {
2848 if (jqLiteAcceptsData(element)) {
2849
2850 var isSimpleSetter = isDefined(value);
2851 var isSimpleGetter = !isSimpleSetter && key && !isObject(key);
2852 var massGetter = !key;
2853 var expandoStore = jqLiteExpandoStore(element, !isSimpleGetter);
2854 var data = expandoStore && expandoStore.data;
2855
2856 if (isSimpleSetter) { // data('key', value)
2857 data[key] = value;
2858 } else {
2859 if (massGetter) { // data()
2860 return data;
2861 } else {
2862 if (isSimpleGetter) { // data('key')
2863 // don't force creation of expandoStore if it doesn't exist yet
2864 return data && data[key];
2865 } else { // mass-setter: data({key1: val1, key2: val2})
2866 extend(data, key);
2867 }
2868 }
2869 }
2870 }
2871 }
2872
2873 function jqLiteHasClass(element, selector) {
2874 if (!element.getAttribute) return false;
2875 return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
2876 indexOf(" " + selector + " ") > -1);
2877 }
2878
2879 function jqLiteRemoveClass(element, cssClasses) {
2880 if (cssClasses && element.setAttribute) {
2881 forEach(cssClasses.split(' '), function(cssClass) {
2882 element.setAttribute('class', trim(
2883 (" " + (element.getAttribute('class') || '') + " ")
2884 .replace(/[\n\t]/g, " ")
2885 .replace(" " + trim(cssClass) + " ", " "))
2886 );
2887 });
2888 }
2889 }
2890
2891 function jqLiteAddClass(element, cssClasses) {
2892 if (cssClasses && element.setAttribute) {
2893 var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
2894 .replace(/[\n\t]/g, " ");
2895
2896 forEach(cssClasses.split(' '), function(cssClass) {
2897 cssClass = trim(cssClass);
2898 if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
2899 existingClasses += cssClass + ' ';
2900 }
2901 });
2902
2903 element.setAttribute('class', trim(existingClasses));
2904 }
2905 }
2906
2907
2908 function jqLiteAddNodes(root, elements) {
2909 // THIS CODE IS VERY HOT. Don't make changes without benchmarking.
2910
2911 if (elements) {
2912
2913 // if a Node (the most common case)
2914 if (elements.nodeType) {
2915 root[root.length++] = elements;
2916 } else {
2917 var length = elements.length;
2918
2919 // if an Array or NodeList and not a Window
2920 if (typeof length === 'number' && elements.window !== elements) {
2921 if (length) {
2922 for (var i = 0; i < length; i++) {
2923 root[root.length++] = elements[i];
2924 }
2925 }
2926 } else {
2927 root[root.length++] = elements;
2928 }
2929 }
2930 }
2931 }
2932
2933
2934 function jqLiteController(element, name) {
2935 return jqLiteInheritedData(element, '$' + (name || 'ngController') + 'Controller');
2936 }
2937
2938 function jqLiteInheritedData(element, name, value) {
2939 // if element is the document object work with the html element instead
2940 // this makes $(document).scope() possible
2941 if (element.nodeType == NODE_TYPE_DOCUMENT) {
2942 element = element.documentElement;
2943 }
2944 var names = isArray(name) ? name : [name];
2945
2946 while (element) {
2947 for (var i = 0, ii = names.length; i < ii; i++) {
2948 if ((value = jqLite.data(element, names[i])) !== undefined) return value;
2949 }
2950
2951 // If dealing with a document fragment node with a host element, and no parent, use the host
2952 // element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
2953 // to lookup parent controllers.
2954 element = element.parentNode || (element.nodeType === NODE_TYPE_DOCUMENT_FRAGMENT && element.host);
2955 }
2956 }
2957
2958 function jqLiteEmpty(element) {
2959 jqLiteDealoc(element, true);
2960 while (element.firstChild) {
2961 element.removeChild(element.firstChild);
2962 }
2963 }
2964
2965 function jqLiteRemove(element, keepData) {
2966 if (!keepData) jqLiteDealoc(element);
2967 var parent = element.parentNode;
2968 if (parent) parent.removeChild(element);
2969 }
2970
2971
2972 function jqLiteDocumentLoaded(action, win) {
2973 win = win || window;
2974 if (win.document.readyState === 'complete') {
2975 // Force the action to be run async for consistent behaviour
2976 // from the action's point of view
2977 // i.e. it will definitely not be in a $apply
2978 win.setTimeout(action);
2979 } else {
2980 // No need to unbind this handler as load is only ever called once
2981 jqLite(win).on('load', action);
2982 }
2983 }
2984
2985 //////////////////////////////////////////
2986 // Functions which are declared directly.
2987 //////////////////////////////////////////
2988 var JQLitePrototype = JQLite.prototype = {
2989 ready: function(fn) {
2990 var fired = false;
2991
2992 function trigger() {
2993 if (fired) return;
2994 fired = true;
2995 fn();
2996 }
2997
2998 // check if document is already loaded
2999 if (document.readyState === 'complete') {
3000 setTimeout(trigger);
3001 } else {
3002 this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
3003 // we can not use jqLite since we are not done loading and jQuery could be loaded later.
3004 // jshint -W064
3005 JQLite(window).on('load', trigger); // fallback to window.onload for others
3006 // jshint +W064
3007 }
3008 },
3009 toString: function() {
3010 var value = [];
3011 forEach(this, function(e) { value.push('' + e);});
3012 return '[' + value.join(', ') + ']';
3013 },
3014
3015 eq: function(index) {
3016 return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
3017 },
3018
3019 length: 0,
3020 push: push,
3021 sort: [].sort,
3022 splice: [].splice
3023 };
3024
3025 //////////////////////////////////////////
3026 // Functions iterating getter/setters.
3027 // these functions return self on setter and
3028 // value on get.
3029 //////////////////////////////////////////
3030 var BOOLEAN_ATTR = {};
3031 forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
3032 BOOLEAN_ATTR[lowercase(value)] = value;
3033 });
3034 var BOOLEAN_ELEMENTS = {};
3035 forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
3036 BOOLEAN_ELEMENTS[value] = true;
3037 });
3038 var ALIASED_ATTR = {
3039 'ngMinlength': 'minlength',
3040 'ngMaxlength': 'maxlength',
3041 'ngMin': 'min',
3042 'ngMax': 'max',
3043 'ngPattern': 'pattern'
3044 };
3045
3046 function getBooleanAttrName(element, name) {
3047 // check dom last since we will most likely fail on name
3048 var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
3049
3050 // booleanAttr is here twice to minimize DOM access
3051 return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
3052 }
3053
3054 function getAliasedAttrName(element, name) {
3055 var nodeName = element.nodeName;
3056 return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
3057 }
3058
3059 forEach({
3060 data: jqLiteData,
3061 removeData: jqLiteRemoveData,
3062 hasData: jqLiteHasData
3063 }, function(fn, name) {
3064 JQLite[name] = fn;
3065 });
3066
3067 forEach({
3068 data: jqLiteData,
3069 inheritedData: jqLiteInheritedData,
3070
3071 scope: function(element) {
3072 // Can't use jqLiteData here directly so we stay compatible with jQuery!
3073 return jqLite.data(element, '$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
3074 },
3075
3076 isolateScope: function(element) {
3077 // Can't use jqLiteData here directly so we stay compatible with jQuery!
3078 return jqLite.data(element, '$isolateScope') || jqLite.data(element, '$isolateScopeNoTemplate');
3079 },
3080
3081 controller: jqLiteController,
3082
3083 injector: function(element) {
3084 return jqLiteInheritedData(element, '$injector');
3085 },
3086
3087 removeAttr: function(element, name) {
3088 element.removeAttribute(name);
3089 },
3090
3091 hasClass: jqLiteHasClass,
3092
3093 css: function(element, name, value) {
3094 name = camelCase(name);
3095
3096 if (isDefined(value)) {
3097 element.style[name] = value;
3098 } else {
3099 return element.style[name];
3100 }
3101 },
3102
3103 attr: function(element, name, value) {
3104 var nodeType = element.nodeType;
3105 if (nodeType === NODE_TYPE_TEXT || nodeType === NODE_TYPE_ATTRIBUTE || nodeType === NODE_TYPE_COMMENT) {
3106 return;
3107 }
3108 var lowercasedName = lowercase(name);
3109 if (BOOLEAN_ATTR[lowercasedName]) {
3110 if (isDefined(value)) {
3111 if (!!value) {
3112 element[name] = true;
3113 element.setAttribute(name, lowercasedName);
3114 } else {
3115 element[name] = false;
3116 element.removeAttribute(lowercasedName);
3117 }
3118 } else {
3119 return (element[name] ||
3120 (element.attributes.getNamedItem(name) || noop).specified)
3121 ? lowercasedName
3122 : undefined;
3123 }
3124 } else if (isDefined(value)) {
3125 element.setAttribute(name, value);
3126 } else if (element.getAttribute) {
3127 // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
3128 // some elements (e.g. Document) don't have get attribute, so return undefined
3129 var ret = element.getAttribute(name, 2);
3130 // normalize non-existing attributes to undefined (as jQuery)
3131 return ret === null ? undefined : ret;
3132 }
3133 },
3134
3135 prop: function(element, name, value) {
3136 if (isDefined(value)) {
3137 element[name] = value;
3138 } else {
3139 return element[name];
3140 }
3141 },
3142
3143 text: (function() {
3144 getText.$dv = '';
3145 return getText;
3146
3147 function getText(element, value) {
3148 if (isUndefined(value)) {
3149 var nodeType = element.nodeType;
3150 return (nodeType === NODE_TYPE_ELEMENT || nodeType === NODE_TYPE_TEXT) ? element.textContent : '';
3151 }
3152 element.textContent = value;
3153 }
3154 })(),
3155
3156 val: function(element, value) {
3157 if (isUndefined(value)) {
3158 if (element.multiple && nodeName_(element) === 'select') {
3159 var result = [];
3160 forEach(element.options, function(option) {
3161 if (option.selected) {
3162 result.push(option.value || option.text);
3163 }
3164 });
3165 return result.length === 0 ? null : result;
3166 }
3167 return element.value;
3168 }
3169 element.value = value;
3170 },
3171
3172 html: function(element, value) {
3173 if (isUndefined(value)) {
3174 return element.innerHTML;
3175 }
3176 jqLiteDealoc(element, true);
3177 element.innerHTML = value;
3178 },
3179
3180 empty: jqLiteEmpty
3181 }, function(fn, name) {
3182 /**
3183 * Properties: writes return selection, reads return first value
3184 */
3185 JQLite.prototype[name] = function(arg1, arg2) {
3186 var i, key;
3187 var nodeCount = this.length;
3188
3189 // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
3190 // in a way that survives minification.
3191 // jqLiteEmpty takes no arguments but is a setter.
3192 if (fn !== jqLiteEmpty &&
3193 (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
3194 if (isObject(arg1)) {
3195
3196 // we are a write, but the object properties are the key/values
3197 for (i = 0; i < nodeCount; i++) {
3198 if (fn === jqLiteData) {
3199 // data() takes the whole object in jQuery
3200 fn(this[i], arg1);
3201 } else {
3202 for (key in arg1) {
3203 fn(this[i], key, arg1[key]);
3204 }
3205 }
3206 }
3207 // return self for chaining
3208 return this;
3209 } else {
3210 // we are a read, so read the first child.
3211 // TODO: do we still need this?
3212 var value = fn.$dv;
3213 // Only if we have $dv do we iterate over all, otherwise it is just the first element.
3214 var jj = (value === undefined) ? Math.min(nodeCount, 1) : nodeCount;
3215 for (var j = 0; j < jj; j++) {
3216 var nodeValue = fn(this[j], arg1, arg2);
3217 value = value ? value + nodeValue : nodeValue;
3218 }
3219 return value;
3220 }
3221 } else {
3222 // we are a write, so apply to all children
3223 for (i = 0; i < nodeCount; i++) {
3224 fn(this[i], arg1, arg2);
3225 }
3226 // return self for chaining
3227 return this;
3228 }
3229 };
3230 });
3231
3232 function createEventHandler(element, events) {
3233 var eventHandler = function(event, type) {
3234 // jQuery specific api
3235 event.isDefaultPrevented = function() {
3236 return event.defaultPrevented;
3237 };
3238
3239 var eventFns = events[type || event.type];
3240 var eventFnsLength = eventFns ? eventFns.length : 0;
3241
3242 if (!eventFnsLength) return;
3243
3244 if (isUndefined(event.immediatePropagationStopped)) {
3245 var originalStopImmediatePropagation = event.stopImmediatePropagation;
3246 event.stopImmediatePropagation = function() {
3247 event.immediatePropagationStopped = true;
3248
3249 if (event.stopPropagation) {
3250 event.stopPropagation();
3251 }
3252
3253 if (originalStopImmediatePropagation) {
3254 originalStopImmediatePropagation.call(event);
3255 }
3256 };
3257 }
3258
3259 event.isImmediatePropagationStopped = function() {
3260 return event.immediatePropagationStopped === true;
3261 };
3262
3263 // Copy event handlers in case event handlers array is modified during execution.
3264 if ((eventFnsLength > 1)) {
3265 eventFns = shallowCopy(eventFns);
3266 }
3267
3268 for (var i = 0; i < eventFnsLength; i++) {
3269 if (!event.isImmediatePropagationStopped()) {
3270 eventFns[i].call(element, event);
3271 }
3272 }
3273 };
3274
3275 // TODO: this is a hack for angularMocks/clearDataCache that makes it possible to deregister all
3276 // events on `element`
3277 eventHandler.elem = element;
3278 return eventHandler;
3279 }
3280
3281 //////////////////////////////////////////
3282 // Functions iterating traversal.
3283 // These functions chain results into a single
3284 // selector.
3285 //////////////////////////////////////////
3286 forEach({
3287 removeData: jqLiteRemoveData,
3288
3289 on: function jqLiteOn(element, type, fn, unsupported) {
3290 if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
3291
3292 // Do not add event handlers to non-elements because they will not be cleaned up.
3293 if (!jqLiteAcceptsData(element)) {
3294 return;
3295 }
3296
3297 var expandoStore = jqLiteExpandoStore(element, true);
3298 var events = expandoStore.events;
3299 var handle = expandoStore.handle;
3300
3301 if (!handle) {
3302 handle = expandoStore.handle = createEventHandler(element, events);
3303 }
3304
3305 // http://jsperf.com/string-indexof-vs-split
3306 var types = type.indexOf(' ') >= 0 ? type.split(' ') : [type];
3307 var i = types.length;
3308
3309 while (i--) {
3310 type = types[i];
3311 var eventFns = events[type];
3312
3313 if (!eventFns) {
3314 events[type] = [];
3315
3316 if (type === 'mouseenter' || type === 'mouseleave') {
3317 // Refer to jQuery's implementation of mouseenter & mouseleave
3318 // Read about mouseenter and mouseleave:
3319 // http://www.quirksmode.org/js/events_mouse.html#link8
3320
3321 jqLiteOn(element, MOUSE_EVENT_MAP[type], function(event) {
3322 var target = this, related = event.relatedTarget;
3323 // For mousenter/leave call the handler if related is outside the target.
3324 // NB: No relatedTarget if the mouse left/entered the browser window
3325 if (!related || (related !== target && !target.contains(related))) {
3326 handle(event, type);
3327 }
3328 });
3329
3330 } else {
3331 if (type !== '$destroy') {
3332 addEventListenerFn(element, type, handle);
3333 }
3334 }
3335 eventFns = events[type];
3336 }
3337 eventFns.push(fn);
3338 }
3339 },
3340
3341 off: jqLiteOff,
3342
3343 one: function(element, type, fn) {
3344 element = jqLite(element);
3345
3346 //add the listener twice so that when it is called
3347 //you can remove the original function and still be
3348 //able to call element.off(ev, fn) normally
3349 element.on(type, function onFn() {
3350 element.off(type, fn);
3351 element.off(type, onFn);
3352 });
3353 element.on(type, fn);
3354 },
3355
3356 replaceWith: function(element, replaceNode) {
3357 var index, parent = element.parentNode;
3358 jqLiteDealoc(element);
3359 forEach(new JQLite(replaceNode), function(node) {
3360 if (index) {
3361 parent.insertBefore(node, index.nextSibling);
3362 } else {
3363 parent.replaceChild(node, element);
3364 }
3365 index = node;
3366 });
3367 },
3368
3369 children: function(element) {
3370 var children = [];
3371 forEach(element.childNodes, function(element) {
3372 if (element.nodeType === NODE_TYPE_ELEMENT) {
3373 children.push(element);
3374 }
3375 });
3376 return children;
3377 },
3378
3379 contents: function(element) {
3380 return element.contentDocument || element.childNodes || [];
3381 },
3382
3383 append: function(element, node) {
3384 var nodeType = element.nodeType;
3385 if (nodeType !== NODE_TYPE_ELEMENT && nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT) return;
3386
3387 node = new JQLite(node);
3388
3389 for (var i = 0, ii = node.length; i < ii; i++) {
3390 var child = node[i];
3391 element.appendChild(child);
3392 }
3393 },
3394
3395 prepend: function(element, node) {
3396 if (element.nodeType === NODE_TYPE_ELEMENT) {
3397 var index = element.firstChild;
3398 forEach(new JQLite(node), function(child) {
3399 element.insertBefore(child, index);
3400 });
3401 }
3402 },
3403
3404 wrap: function(element, wrapNode) {
3405 wrapNode = jqLite(wrapNode).eq(0).clone()[0];
3406 var parent = element.parentNode;
3407 if (parent) {
3408 parent.replaceChild(wrapNode, element);
3409 }
3410 wrapNode.appendChild(element);
3411 },
3412
3413 remove: jqLiteRemove,
3414
3415 detach: function(element) {
3416 jqLiteRemove(element, true);
3417 },
3418
3419 after: function(element, newElement) {
3420 var index = element, parent = element.parentNode;
3421 newElement = new JQLite(newElement);
3422
3423 for (var i = 0, ii = newElement.length; i < ii; i++) {
3424 var node = newElement[i];
3425 parent.insertBefore(node, index.nextSibling);
3426 index = node;
3427 }
3428 },
3429
3430 addClass: jqLiteAddClass,
3431 removeClass: jqLiteRemoveClass,
3432
3433 toggleClass: function(element, selector, condition) {
3434 if (selector) {
3435 forEach(selector.split(' '), function(className) {
3436 var classCondition = condition;
3437 if (isUndefined(classCondition)) {
3438 classCondition = !jqLiteHasClass(element, className);
3439 }
3440 (classCondition ? jqLiteAddClass : jqLiteRemoveClass)(element, className);
3441 });
3442 }
3443 },
3444
3445 parent: function(element) {
3446 var parent = element.parentNode;
3447 return parent && parent.nodeType !== NODE_TYPE_DOCUMENT_FRAGMENT ? parent : null;
3448 },
3449
3450 next: function(element) {
3451 return element.nextElementSibling;
3452 },
3453
3454 find: function(element, selector) {
3455 if (element.getElementsByTagName) {
3456 return element.getElementsByTagName(selector);
3457 } else {
3458 return [];
3459 }
3460 },
3461
3462 clone: jqLiteClone,
3463
3464 triggerHandler: function(element, event, extraParameters) {
3465
3466 var dummyEvent, eventFnsCopy, handlerArgs;
3467 var eventName = event.type || event;
3468 var expandoStore = jqLiteExpandoStore(element);
3469 var events = expandoStore && expandoStore.events;
3470 var eventFns = events && events[eventName];
3471
3472 if (eventFns) {
3473 // Create a dummy event to pass to the handlers
3474 dummyEvent = {
3475 preventDefault: function() { this.defaultPrevented = true; },
3476 isDefaultPrevented: function() { return this.defaultPrevented === true; },
3477 stopImmediatePropagation: function() { this.immediatePropagationStopped = true; },
3478 isImmediatePropagationStopped: function() { return this.immediatePropagationStopped === true; },
3479 stopPropagation: noop,
3480 type: eventName,
3481 target: element
3482 };
3483
3484 // If a custom event was provided then extend our dummy event with it
3485 if (event.type) {
3486 dummyEvent = extend(dummyEvent, event);
3487 }
3488
3489 // Copy event handlers in case event handlers array is modified during execution.
3490 eventFnsCopy = shallowCopy(eventFns);
3491 handlerArgs = extraParameters ? [dummyEvent].concat(extraParameters) : [dummyEvent];
3492
3493 forEach(eventFnsCopy, function(fn) {
3494 if (!dummyEvent.isImmediatePropagationStopped()) {
3495 fn.apply(element, handlerArgs);
3496 }
3497 });
3498 }
3499 }
3500 }, function(fn, name) {
3501 /**
3502 * chaining functions
3503 */
3504 JQLite.prototype[name] = function(arg1, arg2, arg3) {
3505 var value;
3506
3507 for (var i = 0, ii = this.length; i < ii; i++) {
3508 if (isUndefined(value)) {
3509 value = fn(this[i], arg1, arg2, arg3);
3510 if (isDefined(value)) {
3511 // any function which returns a value needs to be wrapped
3512 value = jqLite(value);
3513 }
3514 } else {
3515 jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
3516 }
3517 }
3518 return isDefined(value) ? value : this;
3519 };
3520
3521 // bind legacy bind/unbind to on/off
3522 JQLite.prototype.bind = JQLite.prototype.on;
3523 JQLite.prototype.unbind = JQLite.prototype.off;
3524 });
3525
3526
3527 // Provider for private $$jqLite service
3528 function $$jqLiteProvider() {
3529 this.$get = function $$jqLite() {
3530 return extend(JQLite, {
3531 hasClass: function(node, classes) {
3532 if (node.attr) node = node[0];
3533 return jqLiteHasClass(node, classes);
3534 },
3535 addClass: function(node, classes) {
3536 if (node.attr) node = node[0];
3537 return jqLiteAddClass(node, classes);
3538 },
3539 removeClass: function(node, classes) {
3540 if (node.attr) node = node[0];
3541 return jqLiteRemoveClass(node, classes);
3542 }
3543 });
3544 };
3545 }
3546
3547 /**
3548 * Computes a hash of an 'obj'.
3549 * Hash of a:
3550 * string is string
3551 * number is number as string
3552 * object is either result of calling $$hashKey function on the object or uniquely generated id,
3553 * that is also assigned to the $$hashKey property of the object.
3554 *
3555 * @param obj
3556 * @returns {string} hash string such that the same input will have the same hash string.
3557 * The resulting string key is in 'type:hashKey' format.
3558 */
3559 function hashKey(obj, nextUidFn) {
3560 var key = obj && obj.$$hashKey;
3561
3562 if (key) {
3563 if (typeof key === 'function') {
3564 key = obj.$$hashKey();
3565 }
3566 return key;
3567 }
3568
3569 var objType = typeof obj;
3570 if (objType == 'function' || (objType == 'object' && obj !== null)) {
3571 key = obj.$$hashKey = objType + ':' + (nextUidFn || nextUid)();
3572 } else {
3573 key = objType + ':' + obj;
3574 }
3575
3576 return key;
3577 }
3578
3579 /**
3580 * HashMap which can use objects as keys
3581 */
3582 function HashMap(array, isolatedUid) {
3583 if (isolatedUid) {
3584 var uid = 0;
3585 this.nextUid = function() {
3586 return ++uid;
3587 };
3588 }
3589 forEach(array, this.put, this);
3590 }
3591 HashMap.prototype = {
3592 /**
3593 * Store key value pair
3594 * @param key key to store can be any type
3595 * @param value value to store can be any type
3596 */
3597 put: function(key, value) {
3598 this[hashKey(key, this.nextUid)] = value;
3599 },
3600
3601 /**
3602 * @param key
3603 * @returns {Object} the value for the key
3604 */
3605 get: function(key) {
3606 return this[hashKey(key, this.nextUid)];
3607 },
3608
3609 /**
3610 * Remove the key/value pair
3611 * @param key
3612 */
3613 remove: function(key) {
3614 var value = this[key = hashKey(key, this.nextUid)];
3615 delete this[key];
3616 return value;
3617 }
3618 };
3619
3620 var $$HashMapProvider = [function() {
3621 this.$get = [function() {
3622 return HashMap;
3623 }];
3624 }];
3625
3626 /**
3627 * @ngdoc function
3628 * @module ng
3629 * @name angular.injector
3630 * @kind function
3631 *
3632 * @description
3633 * Creates an injector object that can be used for retrieving services as well as for
3634 * dependency injection (see {@link guide/di dependency injection}).
3635 *
3636 * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
3637 * {@link angular.module}. The `ng` module must be explicitly added.
3638 * @param {boolean=} [strictDi=false] Whether the injector should be in strict mode, which
3639 * disallows argument name annotation inference.
3640 * @returns {injector} Injector object. See {@link auto.$injector $injector}.
3641 *
3642 * @example
3643 * Typical usage
3644 * ```js
3645 * // create an injector
3646 * var $injector = angular.injector(['ng']);
3647 *
3648 * // use the injector to kick off your application
3649 * // use the type inference to auto inject arguments, or use implicit injection
3650 * $injector.invoke(function($rootScope, $compile, $document) {
3651 * $compile($document)($rootScope);
3652 * $rootScope.$digest();
3653 * });
3654 * ```
3655 *
3656 * Sometimes you want to get access to the injector of a currently running Angular app
3657 * from outside Angular. Perhaps, you want to inject and compile some markup after the
3658 * application has been bootstrapped. You can do this using the extra `injector()` added
3659 * to JQuery/jqLite elements. See {@link angular.element}.
3660 *
3661 * *This is fairly rare but could be the case if a third party library is injecting the
3662 * markup.*
3663 *
3664 * In the following example a new block of HTML containing a `ng-controller`
3665 * directive is added to the end of the document body by JQuery. We then compile and link
3666 * it into the current AngularJS scope.
3667 *
3668 * ```js
3669 * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
3670 * $(document.body).append($div);
3671 *
3672 * angular.element(document).injector().invoke(function($compile) {
3673 * var scope = angular.element($div).scope();
3674 * $compile($div)(scope);
3675 * });
3676 * ```
3677 */
3678
3679
3680 /**
3681 * @ngdoc module
3682 * @name auto
3683 * @description
3684 *
3685 * Implicit module which gets automatically added to each {@link auto.$injector $injector}.
3686 */
3687
3688 var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
3689 var FN_ARG_SPLIT = /,/;
3690 var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
3691 var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
3692 var $injectorMinErr = minErr('$injector');
3693
3694 function anonFn(fn) {
3695 // For anonymous functions, showing at the very least the function signature can help in
3696 // debugging.
3697 var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
3698 args = fnText.match(FN_ARGS);
3699 if (args) {
3700 return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
3701 }
3702 return 'fn';
3703 }
3704
3705 function annotate(fn, strictDi, name) {
3706 var $inject,
3707 fnText,
3708 argDecl,
3709 last;
3710
3711 if (typeof fn === 'function') {
3712 if (!($inject = fn.$inject)) {
3713 $inject = [];
3714 if (fn.length) {
3715 if (strictDi) {
3716 if (!isString(name) || !name) {
3717 name = fn.name || anonFn(fn);
3718 }
3719 throw $injectorMinErr('strictdi',
3720 '{0} is not using explicit annotation and cannot be invoked in strict mode', name);
3721 }
3722 fnText = fn.toString().replace(STRIP_COMMENTS, '');
3723 argDecl = fnText.match(FN_ARGS);
3724 forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
3725 arg.replace(FN_ARG, function(all, underscore, name) {
3726 $inject.push(name);
3727 });
3728 });
3729 }
3730 fn.$inject = $inject;
3731 }
3732 } else if (isArray(fn)) {
3733 last = fn.length - 1;
3734 assertArgFn(fn[last], 'fn');
3735 $inject = fn.slice(0, last);
3736 } else {
3737 assertArgFn(fn, 'fn', true);
3738 }
3739 return $inject;
3740 }
3741
3742 ///////////////////////////////////////
3743
3744 /**
3745 * @ngdoc service
3746 * @name $injector
3747 *
3748 * @description
3749 *
3750 * `$injector` is used to retrieve object instances as defined by
3751 * {@link auto.$provide provider}, instantiate types, invoke methods,
3752 * and load modules.
3753 *
3754 * The following always holds true:
3755 *
3756 * ```js
3757 * var $injector = angular.injector();
3758 * expect($injector.get('$injector')).toBe($injector);
3759 * expect($injector.invoke(function($injector) {
3760 * return $injector;
3761 * })).toBe($injector);
3762 * ```
3763 *
3764 * # Injection Function Annotation
3765 *
3766 * JavaScript does not have annotations, and annotations are needed for dependency injection. The
3767 * following are all valid ways of annotating function with injection arguments and are equivalent.
3768 *
3769 * ```js
3770 * // inferred (only works if code not minified/obfuscated)
3771 * $injector.invoke(function(serviceA){});
3772 *
3773 * // annotated
3774 * function explicit(serviceA) {};
3775 * explicit.$inject = ['serviceA'];
3776 * $injector.invoke(explicit);
3777 *
3778 * // inline
3779 * $injector.invoke(['serviceA', function(serviceA){}]);
3780 * ```
3781 *
3782 * ## Inference
3783 *
3784 * In JavaScript calling `toString()` on a function returns the function definition. The definition
3785 * can then be parsed and the function arguments can be extracted. This method of discovering
3786 * annotations is disallowed when the injector is in strict mode.
3787 * *NOTE:* This does not work with minification, and obfuscation tools since these tools change the
3788 * argument names.
3789 *
3790 * ## `$inject` Annotation
3791 * By adding an `$inject` property onto a function the injection parameters can be specified.
3792 *
3793 * ## Inline
3794 * As an array of injection names, where the last item in the array is the function to call.
3795 */
3796
3797 /**
3798 * @ngdoc method
3799 * @name $injector#get
3800 *
3801 * @description
3802 * Return an instance of the service.
3803 *
3804 * @param {string} name The name of the instance to retrieve.
3805 * @param {string=} caller An optional string to provide the origin of the function call for error messages.
3806 * @return {*} The instance.
3807 */
3808
3809 /**
3810 * @ngdoc method
3811 * @name $injector#invoke
3812 *
3813 * @description
3814 * Invoke the method and supply the method arguments from the `$injector`.
3815 *
3816 * @param {Function|Array.<string|Function>} fn The injectable function to invoke. Function parameters are
3817 * injected according to the {@link guide/di $inject Annotation} rules.
3818 * @param {Object=} self The `this` for the invoked method.
3819 * @param {Object=} locals Optional object. If preset then any argument names are read from this
3820 * object first, before the `$injector` is consulted.
3821 * @returns {*} the value returned by the invoked `fn` function.
3822 */
3823
3824 /**
3825 * @ngdoc method
3826 * @name $injector#has
3827 *
3828 * @description
3829 * Allows the user to query if the particular service exists.
3830 *
3831 * @param {string} name Name of the service to query.
3832 * @returns {boolean} `true` if injector has given service.
3833 */
3834
3835 /**
3836 * @ngdoc method
3837 * @name $injector#instantiate
3838 * @description
3839 * Create a new instance of JS type. The method takes a constructor function, invokes the new
3840 * operator, and supplies all of the arguments to the constructor function as specified by the
3841 * constructor annotation.
3842 *
3843 * @param {Function} Type Annotated constructor function.
3844 * @param {Object=} locals Optional object. If preset then any argument names are read from this
3845 * object first, before the `$injector` is consulted.
3846 * @returns {Object} new instance of `Type`.
3847 */
3848
3849 /**
3850 * @ngdoc method
3851 * @name $injector#annotate
3852 *
3853 * @description
3854 * Returns an array of service names which the function is requesting for injection. This API is
3855 * used by the injector to determine which services need to be injected into the function when the
3856 * function is invoked. There are three ways in which the function can be annotated with the needed
3857 * dependencies.
3858 *
3859 * # Argument names
3860 *
3861 * The simplest form is to extract the dependencies from the arguments of the function. This is done
3862 * by converting the function into a string using `toString()` method and extracting the argument
3863 * names.
3864 * ```js
3865 * // Given
3866 * function MyController($scope, $route) {
3867 * // ...
3868 * }
3869 *
3870 * // Then
3871 * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
3872 * ```
3873 *
3874 * You can disallow this method by using strict injection mode.
3875 *
3876 * This method does not work with code minification / obfuscation. For this reason the following
3877 * annotation strategies are supported.
3878 *
3879 * # The `$inject` property
3880 *
3881 * If a function has an `$inject` property and its value is an array of strings, then the strings
3882 * represent names of services to be injected into the function.
3883 * ```js
3884 * // Given
3885 * var MyController = function(obfuscatedScope, obfuscatedRoute) {
3886 * // ...
3887 * }
3888 * // Define function dependencies
3889 * MyController['$inject'] = ['$scope', '$route'];
3890 *
3891 * // Then
3892 * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
3893 * ```
3894 *
3895 * # The array notation
3896 *
3897 * It is often desirable to inline Injected functions and that's when setting the `$inject` property
3898 * is very inconvenient. In these situations using the array notation to specify the dependencies in
3899 * a way that survives minification is a better choice:
3900 *
3901 * ```js
3902 * // We wish to write this (not minification / obfuscation safe)
3903 * injector.invoke(function($compile, $rootScope) {
3904 * // ...
3905 * });
3906 *
3907 * // We are forced to write break inlining
3908 * var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
3909 * // ...
3910 * };
3911 * tmpFn.$inject = ['$compile', '$rootScope'];
3912 * injector.invoke(tmpFn);
3913 *
3914 * // To better support inline function the inline annotation is supported
3915 * injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
3916 * // ...
3917 * }]);
3918 *
3919 * // Therefore
3920 * expect(injector.annotate(
3921 * ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
3922 * ).toEqual(['$compile', '$rootScope']);
3923 * ```
3924 *
3925 * @param {Function|Array.<string|Function>} fn Function for which dependent service names need to
3926 * be retrieved as described above.
3927 *
3928 * @param {boolean=} [strictDi=false] Disallow argument name annotation inference.
3929 *
3930 * @returns {Array.<string>} The names of the services which the function requires.
3931 */
3932
3933
3934
3935
3936 /**
3937 * @ngdoc service
3938 * @name $provide
3939 *
3940 * @description
3941 *
3942 * The {@link auto.$provide $provide} service has a number of methods for registering components
3943 * with the {@link auto.$injector $injector}. Many of these functions are also exposed on
3944 * {@link angular.Module}.
3945 *
3946 * An Angular **service** is a singleton object created by a **service factory**. These **service
3947 * factories** are functions which, in turn, are created by a **service provider**.
3948 * The **service providers** are constructor functions. When instantiated they must contain a
3949 * property called `$get`, which holds the **service factory** function.
3950 *
3951 * When you request a service, the {@link auto.$injector $injector} is responsible for finding the
3952 * correct **service provider**, instantiating it and then calling its `$get` **service factory**
3953 * function to get the instance of the **service**.
3954 *
3955 * Often services have no configuration options and there is no need to add methods to the service
3956 * provider. The provider will be no more than a constructor function with a `$get` property. For
3957 * these cases the {@link auto.$provide $provide} service has additional helper methods to register
3958 * services without specifying a provider.
3959 *
3960 * * {@link auto.$provide#provider provider(provider)} - registers a **service provider** with the
3961 * {@link auto.$injector $injector}
3962 * * {@link auto.$provide#constant constant(obj)} - registers a value/object that can be accessed by
3963 * providers and services.
3964 * * {@link auto.$provide#value value(obj)} - registers a value/object that can only be accessed by
3965 * services, not providers.
3966 * * {@link auto.$provide#factory factory(fn)} - registers a service **factory function**, `fn`,
3967 * that will be wrapped in a **service provider** object, whose `$get` property will contain the
3968 * given factory function.
3969 * * {@link auto.$provide#service service(class)} - registers a **constructor function**, `class`
3970 * that will be wrapped in a **service provider** object, whose `$get` property will instantiate
3971 * a new object using the given constructor function.
3972 *
3973 * See the individual methods for more information and examples.
3974 */
3975
3976 /**
3977 * @ngdoc method
3978 * @name $provide#provider
3979 * @description
3980 *
3981 * Register a **provider function** with the {@link auto.$injector $injector}. Provider functions
3982 * are constructor functions, whose instances are responsible for "providing" a factory for a
3983 * service.
3984 *
3985 * Service provider names start with the name of the service they provide followed by `Provider`.
3986 * For example, the {@link ng.$log $log} service has a provider called
3987 * {@link ng.$logProvider $logProvider}.
3988 *
3989 * Service provider objects can have additional methods which allow configuration of the provider
3990 * and its service. Importantly, you can configure what kind of service is created by the `$get`
3991 * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
3992 * method {@link ng.$logProvider#debugEnabled debugEnabled}
3993 * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
3994 * console or not.
3995 *
3996 * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
3997 'Provider'` key.
3998 * @param {(Object|function())} provider If the provider is:
3999 *
4000 * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
4001 * {@link auto.$injector#invoke $injector.invoke()} when an instance needs to be created.
4002 * - `Constructor`: a new instance of the provider will be created using
4003 * {@link auto.$injector#instantiate $injector.instantiate()}, then treated as `object`.
4004 *
4005 * @returns {Object} registered provider instance
4006
4007 * @example
4008 *
4009 * The following example shows how to create a simple event tracking service and register it using
4010 * {@link auto.$provide#provider $provide.provider()}.
4011 *
4012 * ```js
4013 * // Define the eventTracker provider
4014 * function EventTrackerProvider() {
4015 * var trackingUrl = '/track';
4016 *
4017 * // A provider method for configuring where the tracked events should been saved
4018 * this.setTrackingUrl = function(url) {
4019 * trackingUrl = url;
4020 * };
4021 *
4022 * // The service factory function
4023 * this.$get = ['$http', function($http) {
4024 * var trackedEvents = {};
4025 * return {
4026 * // Call this to track an event
4027 * event: function(event) {
4028 * var count = trackedEvents[event] || 0;
4029 * count += 1;
4030 * trackedEvents[event] = count;
4031 * return count;
4032 * },
4033 * // Call this to save the tracked events to the trackingUrl
4034 * save: function() {
4035 * $http.post(trackingUrl, trackedEvents);
4036 * }
4037 * };
4038 * }];
4039 * }
4040 *
4041 * describe('eventTracker', function() {
4042 * var postSpy;
4043 *
4044 * beforeEach(module(function($provide) {
4045 * // Register the eventTracker provider
4046 * $provide.provider('eventTracker', EventTrackerProvider);
4047 * }));
4048 *
4049 * beforeEach(module(function(eventTrackerProvider) {
4050 * // Configure eventTracker provider
4051 * eventTrackerProvider.setTrackingUrl('/custom-track');
4052 * }));
4053 *
4054 * it('tracks events', inject(function(eventTracker) {
4055 * expect(eventTracker.event('login')).toEqual(1);
4056 * expect(eventTracker.event('login')).toEqual(2);
4057 * }));
4058 *
4059 * it('saves to the tracking url', inject(function(eventTracker, $http) {
4060 * postSpy = spyOn($http, 'post');
4061 * eventTracker.event('login');
4062 * eventTracker.save();
4063 * expect(postSpy).toHaveBeenCalled();
4064 * expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
4065 * expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
4066 * expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
4067 * }));
4068 * });
4069 * ```
4070 */
4071
4072 /**
4073 * @ngdoc method
4074 * @name $provide#factory
4075 * @description
4076 *
4077 * Register a **service factory**, which will be called to return the service instance.
4078 * This is short for registering a service where its provider consists of only a `$get` property,
4079 * which is the given service factory function.
4080 * You should use {@link auto.$provide#factory $provide.factory(getFn)} if you do not need to
4081 * configure your service in a provider.
4082 *
4083 * @param {string} name The name of the instance.
4084 * @param {Function|Array.<string|Function>} $getFn The injectable $getFn for the instance creation.
4085 * Internally this is a short hand for `$provide.provider(name, {$get: $getFn})`.
4086 * @returns {Object} registered provider instance
4087 *
4088 * @example
4089 * Here is an example of registering a service
4090 * ```js
4091 * $provide.factory('ping', ['$http', function($http) {
4092 * return function ping() {
4093 * return $http.send('/ping');
4094 * };
4095 * }]);
4096 * ```
4097 * You would then inject and use this service like this:
4098 * ```js
4099 * someModule.controller('Ctrl', ['ping', function(ping) {
4100 * ping();
4101 * }]);
4102 * ```
4103 */
4104
4105
4106 /**
4107 * @ngdoc method
4108 * @name $provide#service
4109 * @description
4110 *
4111 * Register a **service constructor**, which will be invoked with `new` to create the service
4112 * instance.
4113 * This is short for registering a service where its provider's `$get` property is the service
4114 * constructor function that will be used to instantiate the service instance.
4115 *
4116 * You should use {@link auto.$provide#service $provide.service(class)} if you define your service
4117 * as a type/class.
4118 *
4119 * @param {string} name The name of the instance.
4120 * @param {Function|Array.<string|Function>} constructor An injectable class (constructor function)
4121 * that will be instantiated.
4122 * @returns {Object} registered provider instance
4123 *
4124 * @example
4125 * Here is an example of registering a service using
4126 * {@link auto.$provide#service $provide.service(class)}.
4127 * ```js
4128 * var Ping = function($http) {
4129 * this.$http = $http;
4130 * };
4131 *
4132 * Ping.$inject = ['$http'];
4133 *
4134 * Ping.prototype.send = function() {
4135 * return this.$http.get('/ping');
4136 * };
4137 * $provide.service('ping', Ping);
4138 * ```
4139 * You would then inject and use this service like this:
4140 * ```js
4141 * someModule.controller('Ctrl', ['ping', function(ping) {
4142 * ping.send();
4143 * }]);
4144 * ```
4145 */
4146
4147
4148 /**
4149 * @ngdoc method
4150 * @name $provide#value
4151 * @description
4152 *
4153 * Register a **value service** with the {@link auto.$injector $injector}, such as a string, a
4154 * number, an array, an object or a function. This is short for registering a service where its
4155 * provider's `$get` property is a factory function that takes no arguments and returns the **value
4156 * service**.
4157 *
4158 * Value services are similar to constant services, except that they cannot be injected into a
4159 * module configuration function (see {@link angular.Module#config}) but they can be overridden by
4160 * an Angular
4161 * {@link auto.$provide#decorator decorator}.
4162 *
4163 * @param {string} name The name of the instance.
4164 * @param {*} value The value.
4165 * @returns {Object} registered provider instance
4166 *
4167 * @example
4168 * Here are some examples of creating value services.
4169 * ```js
4170 * $provide.value('ADMIN_USER', 'admin');
4171 *
4172 * $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
4173 *
4174 * $provide.value('halfOf', function(value) {
4175 * return value / 2;
4176 * });
4177 * ```
4178 */
4179
4180
4181 /**
4182 * @ngdoc method
4183 * @name $provide#constant
4184 * @description
4185 *
4186 * Register a **constant service**, such as a string, a number, an array, an object or a function,
4187 * with the {@link auto.$injector $injector}. Unlike {@link auto.$provide#value value} it can be
4188 * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
4189 * be overridden by an Angular {@link auto.$provide#decorator decorator}.
4190 *
4191 * @param {string} name The name of the constant.
4192 * @param {*} value The constant value.
4193 * @returns {Object} registered instance
4194 *
4195 * @example
4196 * Here a some examples of creating constants:
4197 * ```js
4198 * $provide.constant('SHARD_HEIGHT', 306);
4199 *
4200 * $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
4201 *
4202 * $provide.constant('double', function(value) {
4203 * return value * 2;
4204 * });
4205 * ```
4206 */
4207
4208
4209 /**
4210 * @ngdoc method
4211 * @name $provide#decorator
4212 * @description
4213 *
4214 * Register a **service decorator** with the {@link auto.$injector $injector}. A service decorator
4215 * intercepts the creation of a service, allowing it to override or modify the behaviour of the
4216 * service. The object returned by the decorator may be the original service, or a new service
4217 * object which replaces or wraps and delegates to the original service.
4218 *
4219 * @param {string} name The name of the service to decorate.
4220 * @param {Function|Array.<string|Function>} decorator This function will be invoked when the service needs to be
4221 * instantiated and should return the decorated service instance. The function is called using
4222 * the {@link auto.$injector#invoke injector.invoke} method and is therefore fully injectable.
4223 * Local injection arguments:
4224 *
4225 * * `$delegate` - The original service instance, which can be monkey patched, configured,
4226 * decorated or delegated to.
4227 *
4228 * @example
4229 * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
4230 * calls to {@link ng.$log#error $log.warn()}.
4231 * ```js
4232 * $provide.decorator('$log', ['$delegate', function($delegate) {
4233 * $delegate.warn = $delegate.error;
4234 * return $delegate;
4235 * }]);
4236 * ```
4237 */
4238
4239
4240 function createInjector(modulesToLoad, strictDi) {
4241 strictDi = (strictDi === true);
4242 var INSTANTIATING = {},
4243 providerSuffix = 'Provider',
4244 path = [],
4245 loadedModules = new HashMap([], true),
4246 providerCache = {
4247 $provide: {
4248 provider: supportObject(provider),
4249 factory: supportObject(factory),
4250 service: supportObject(service),
4251 value: supportObject(value),
4252 constant: supportObject(constant),
4253 decorator: decorator
4254 }
4255 },
4256 providerInjector = (providerCache.$injector =
4257 createInternalInjector(providerCache, function(serviceName, caller) {
4258 if (angular.isString(caller)) {
4259 path.push(caller);
4260 }
4261 throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
4262 })),
4263 instanceCache = {},
4264 instanceInjector = (instanceCache.$injector =
4265 createInternalInjector(instanceCache, function(serviceName, caller) {
4266 var provider = providerInjector.get(serviceName + providerSuffix, caller);
4267 return instanceInjector.invoke(provider.$get, provider, undefined, serviceName);
4268 }));
4269
4270
4271 forEach(loadModules(modulesToLoad), function(fn) { if (fn) instanceInjector.invoke(fn); });
4272
4273 return instanceInjector;
4274
4275 ////////////////////////////////////
4276 // $provider
4277 ////////////////////////////////////
4278
4279 function supportObject(delegate) {
4280 return function(key, value) {
4281 if (isObject(key)) {
4282 forEach(key, reverseParams(delegate));
4283 } else {
4284 return delegate(key, value);
4285 }
4286 };
4287 }
4288
4289 function provider(name, provider_) {
4290 assertNotHasOwnProperty(name, 'service');
4291 if (isFunction(provider_) || isArray(provider_)) {
4292 provider_ = providerInjector.instantiate(provider_);
4293 }
4294 if (!provider_.$get) {
4295 throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
4296 }
4297 return providerCache[name + providerSuffix] = provider_;
4298 }
4299
4300 function enforceReturnValue(name, factory) {
4301 return function enforcedReturnValue() {
4302 var result = instanceInjector.invoke(factory, this);
4303 if (isUndefined(result)) {
4304 throw $injectorMinErr('undef', "Provider '{0}' must return a value from $get factory method.", name);
4305 }
4306 return result;
4307 };
4308 }
4309
4310 function factory(name, factoryFn, enforce) {
4311 return provider(name, {
4312 $get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
4313 });
4314 }
4315
4316 function service(name, constructor) {
4317 return factory(name, ['$injector', function($injector) {
4318 return $injector.instantiate(constructor);
4319 }]);
4320 }
4321
4322 function value(name, val) { return factory(name, valueFn(val), false); }
4323
4324 function constant(name, value) {
4325 assertNotHasOwnProperty(name, 'constant');
4326 providerCache[name] = value;
4327 instanceCache[name] = value;
4328 }
4329
4330 function decorator(serviceName, decorFn) {
4331 var origProvider = providerInjector.get(serviceName + providerSuffix),
4332 orig$get = origProvider.$get;
4333
4334 origProvider.$get = function() {
4335 var origInstance = instanceInjector.invoke(orig$get, origProvider);
4336 return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
4337 };
4338 }
4339
4340 ////////////////////////////////////
4341 // Module Loading
4342 ////////////////////////////////////
4343 function loadModules(modulesToLoad) {
4344 var runBlocks = [], moduleFn;
4345 forEach(modulesToLoad, function(module) {
4346 if (loadedModules.get(module)) return;
4347 loadedModules.put(module, true);
4348
4349 function runInvokeQueue(queue) {
4350 var i, ii;
4351 for (i = 0, ii = queue.length; i < ii; i++) {
4352 var invokeArgs = queue[i],
4353 provider = providerInjector.get(invokeArgs[0]);
4354
4355 provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
4356 }
4357 }
4358
4359 try {
4360 if (isString(module)) {
4361 moduleFn = angularModule(module);
4362 runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
4363 runInvokeQueue(moduleFn._invokeQueue);
4364 runInvokeQueue(moduleFn._configBlocks);
4365 } else if (isFunction(module)) {
4366 runBlocks.push(providerInjector.invoke(module));
4367 } else if (isArray(module)) {
4368 runBlocks.push(providerInjector.invoke(module));
4369 } else {
4370 assertArgFn(module, 'module');
4371 }
4372 } catch (e) {
4373 if (isArray(module)) {
4374 module = module[module.length - 1];
4375 }
4376 if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
4377 // Safari & FF's stack traces don't contain error.message content
4378 // unlike those of Chrome and IE
4379 // So if stack doesn't contain message, we create a new string that contains both.
4380 // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
4381 /* jshint -W022 */
4382 e = e.message + '\n' + e.stack;
4383 }
4384 throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
4385 module, e.stack || e.message || e);
4386 }
4387 });
4388 return runBlocks;
4389 }
4390
4391 ////////////////////////////////////
4392 // internal Injector
4393 ////////////////////////////////////
4394
4395 function createInternalInjector(cache, factory) {
4396
4397 function getService(serviceName, caller) {
4398 if (cache.hasOwnProperty(serviceName)) {
4399 if (cache[serviceName] === INSTANTIATING) {
4400 throw $injectorMinErr('cdep', 'Circular dependency found: {0}',
4401 serviceName + ' <- ' + path.join(' <- '));
4402 }
4403 return cache[serviceName];
4404 } else {
4405 try {
4406 path.unshift(serviceName);
4407 cache[serviceName] = INSTANTIATING;
4408 return cache[serviceName] = factory(serviceName, caller);
4409 } catch (err) {
4410 if (cache[serviceName] === INSTANTIATING) {
4411 delete cache[serviceName];
4412 }
4413 throw err;
4414 } finally {
4415 path.shift();
4416 }
4417 }
4418 }
4419
4420 function invoke(fn, self, locals, serviceName) {
4421 if (typeof locals === 'string') {
4422 serviceName = locals;
4423 locals = null;
4424 }
4425
4426 var args = [],
4427 $inject = createInjector.$$annotate(fn, strictDi, serviceName),
4428 length, i,
4429 key;
4430
4431 for (i = 0, length = $inject.length; i < length; i++) {
4432 key = $inject[i];
4433 if (typeof key !== 'string') {
4434 throw $injectorMinErr('itkn',
4435 'Incorrect injection token! Expected service name as string, got {0}', key);
4436 }
4437 args.push(
4438 locals && locals.hasOwnProperty(key)
4439 ? locals[key]
4440 : getService(key, serviceName)
4441 );
4442 }
4443 if (isArray(fn)) {
4444 fn = fn[length];
4445 }
4446
4447 // http://jsperf.com/angularjs-invoke-apply-vs-switch
4448 // #5388
4449 return fn.apply(self, args);
4450 }
4451
4452 function instantiate(Type, locals, serviceName) {
4453 // Check if Type is annotated and use just the given function at n-1 as parameter
4454 // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
4455 // Object creation: http://jsperf.com/create-constructor/2
4456 var instance = Object.create((isArray(Type) ? Type[Type.length - 1] : Type).prototype || null);
4457 var returnedValue = invoke(Type, instance, locals, serviceName);
4458
4459 return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
4460 }
4461
4462 return {
4463 invoke: invoke,
4464 instantiate: instantiate,
4465 get: getService,
4466 annotate: createInjector.$$annotate,
4467 has: function(name) {
4468 return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
4469 }
4470 };
4471 }
4472 }
4473
4474 createInjector.$$annotate = annotate;
4475
4476 /**
4477 * @ngdoc provider
4478 * @name $anchorScrollProvider
4479 *
4480 * @description
4481 * Use `$anchorScrollProvider` to disable automatic scrolling whenever
4482 * {@link ng.$location#hash $location.hash()} changes.
4483 */
4484 function $AnchorScrollProvider() {
4485
4486 var autoScrollingEnabled = true;
4487
4488 /**
4489 * @ngdoc method
4490 * @name $anchorScrollProvider#disableAutoScrolling
4491 *
4492 * @description
4493 * By default, {@link ng.$anchorScroll $anchorScroll()} will automatically detect changes to
4494 * {@link ng.$location#hash $location.hash()} and scroll to the element matching the new hash.<br />
4495 * Use this method to disable automatic scrolling.
4496 *
4497 * If automatic scrolling is disabled, one must explicitly call
4498 * {@link ng.$anchorScroll $anchorScroll()} in order to scroll to the element related to the
4499 * current hash.
4500 */
4501 this.disableAutoScrolling = function() {
4502 autoScrollingEnabled = false;
4503 };
4504
4505 /**
4506 * @ngdoc service
4507 * @name $anchorScroll
4508 * @kind function
4509 * @requires $window
4510 * @requires $location
4511 * @requires $rootScope
4512 *
4513 * @description
4514 * When called, it scrolls to the element related to the specified `hash` or (if omitted) to the
4515 * current value of {@link ng.$location#hash $location.hash()}, according to the rules specified
4516 * in the
4517 * [HTML5 spec](http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document).
4518 *
4519 * It also watches the {@link ng.$location#hash $location.hash()} and automatically scrolls to
4520 * match any anchor whenever it changes. This can be disabled by calling
4521 * {@link ng.$anchorScrollProvider#disableAutoScrolling $anchorScrollProvider.disableAutoScrolling()}.
4522 *
4523 * Additionally, you can use its {@link ng.$anchorScroll#yOffset yOffset} property to specify a
4524 * vertical scroll-offset (either fixed or dynamic).
4525 *
4526 * @param {string=} hash The hash specifying the element to scroll to. If omitted, the value of
4527 * {@link ng.$location#hash $location.hash()} will be used.
4528 *
4529 * @property {(number|function|jqLite)} yOffset
4530 * If set, specifies a vertical scroll-offset. This is often useful when there are fixed
4531 * positioned elements at the top of the page, such as navbars, headers etc.
4532 *
4533 * `yOffset` can be specified in various ways:
4534 * - **number**: A fixed number of pixels to be used as offset.<br /><br />
4535 * - **function**: A getter function called everytime `$anchorScroll()` is executed. Must return
4536 * a number representing the offset (in pixels).<br /><br />
4537 * - **jqLite**: A jqLite/jQuery element to be used for specifying the offset. The distance from
4538 * the top of the page to the element's bottom will be used as offset.<br />
4539 * **Note**: The element will be taken into account only as long as its `position` is set to
4540 * `fixed`. This option is useful, when dealing with responsive navbars/headers that adjust
4541 * their height and/or positioning according to the viewport's size.
4542 *
4543 * <br />
4544 * <div class="alert alert-warning">
4545 * In order for `yOffset` to work properly, scrolling should take place on the document's root and
4546 * not some child element.
4547 * </div>
4548 *
4549 * @example
4550 <example module="anchorScrollExample">
4551 <file name="index.html">
4552 <div id="scrollArea" ng-controller="ScrollController">
4553 <a ng-click="gotoBottom()">Go to bottom</a>
4554 <a id="bottom"></a> You're at the bottom!
4555 </div>
4556 </file>
4557 <file name="script.js">
4558 angular.module('anchorScrollExample', [])
4559 .controller('ScrollController', ['$scope', '$location', '$anchorScroll',
4560 function ($scope, $location, $anchorScroll) {
4561 $scope.gotoBottom = function() {
4562 // set the location.hash to the id of
4563 // the element you wish to scroll to.
4564 $location.hash('bottom');
4565
4566 // call $anchorScroll()
4567 $anchorScroll();
4568 };
4569 }]);
4570 </file>
4571 <file name="style.css">
4572 #scrollArea {
4573 height: 280px;
4574 overflow: auto;
4575 }
4576
4577 #bottom {
4578 display: block;
4579 margin-top: 2000px;
4580 }
4581 </file>
4582 </example>
4583 *
4584 * <hr />
4585 * The example below illustrates the use of a vertical scroll-offset (specified as a fixed value).
4586 * See {@link ng.$anchorScroll#yOffset $anchorScroll.yOffset} for more details.
4587 *
4588 * @example
4589 <example module="anchorScrollOffsetExample">
4590 <file name="index.html">
4591 <div class="fixed-header" ng-controller="headerCtrl">
4592 <a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
4593 Go to anchor {{x}}
4594 </a>
4595 </div>
4596 <div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
4597 Anchor {{x}} of 5
4598 </div>
4599 </file>
4600 <file name="script.js">
4601 angular.module('anchorScrollOffsetExample', [])
4602 .run(['$anchorScroll', function($anchorScroll) {
4603 $anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
4604 }])
4605 .controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
4606 function ($anchorScroll, $location, $scope) {
4607 $scope.gotoAnchor = function(x) {
4608 var newHash = 'anchor' + x;
4609 if ($location.hash() !== newHash) {
4610 // set the $location.hash to `newHash` and
4611 // $anchorScroll will automatically scroll to it
4612 $location.hash('anchor' + x);
4613 } else {
4614 // call $anchorScroll() explicitly,
4615 // since $location.hash hasn't changed
4616 $anchorScroll();
4617 }
4618 };
4619 }
4620 ]);
4621 </file>
4622 <file name="style.css">
4623 body {
4624 padding-top: 50px;
4625 }
4626
4627 .anchor {
4628 border: 2px dashed DarkOrchid;
4629 padding: 10px 10px 200px 10px;
4630 }
4631
4632 .fixed-header {
4633 background-color: rgba(0, 0, 0, 0.2);
4634 height: 50px;
4635 position: fixed;
4636 top: 0; left: 0; right: 0;
4637 }
4638
4639 .fixed-header > a {
4640 display: inline-block;
4641 margin: 5px 15px;
4642 }
4643 </file>
4644 </example>
4645 */
4646 this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
4647 var document = $window.document;
4648
4649 // Helper function to get first anchor from a NodeList
4650 // (using `Array#some()` instead of `angular#forEach()` since it's more performant
4651 // and working in all supported browsers.)
4652 function getFirstAnchor(list) {
4653 var result = null;
4654 Array.prototype.some.call(list, function(element) {
4655 if (nodeName_(element) === 'a') {
4656 result = element;
4657 return true;
4658 }
4659 });
4660 return result;
4661 }
4662
4663 function getYOffset() {
4664
4665 var offset = scroll.yOffset;
4666
4667 if (isFunction(offset)) {
4668 offset = offset();
4669 } else if (isElement(offset)) {
4670 var elem = offset[0];
4671 var style = $window.getComputedStyle(elem);
4672 if (style.position !== 'fixed') {
4673 offset = 0;
4674 } else {
4675 offset = elem.getBoundingClientRect().bottom;
4676 }
4677 } else if (!isNumber(offset)) {
4678 offset = 0;
4679 }
4680
4681 return offset;
4682 }
4683
4684 function scrollTo(elem) {
4685 if (elem) {
4686 elem.scrollIntoView();
4687
4688 var offset = getYOffset();
4689
4690 if (offset) {
4691 // `offset` is the number of pixels we should scroll UP in order to align `elem` properly.
4692 // This is true ONLY if the call to `elem.scrollIntoView()` initially aligns `elem` at the
4693 // top of the viewport.
4694 //
4695 // IF the number of pixels from the top of `elem` to the end of the page's content is less
4696 // than the height of the viewport, then `elem.scrollIntoView()` will align the `elem` some
4697 // way down the page.
4698 //
4699 // This is often the case for elements near the bottom of the page.
4700 //
4701 // In such cases we do not need to scroll the whole `offset` up, just the difference between
4702 // the top of the element and the offset, which is enough to align the top of `elem` at the
4703 // desired position.
4704 var elemTop = elem.getBoundingClientRect().top;
4705 $window.scrollBy(0, elemTop - offset);
4706 }
4707 } else {
4708 $window.scrollTo(0, 0);
4709 }
4710 }
4711
4712 function scroll(hash) {
4713 hash = isString(hash) ? hash : $location.hash();
4714 var elm;
4715
4716 // empty hash, scroll to the top of the page
4717 if (!hash) scrollTo(null);
4718
4719 // element with given id
4720 else if ((elm = document.getElementById(hash))) scrollTo(elm);
4721
4722 // first anchor with given name :-D
4723 else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) scrollTo(elm);
4724
4725 // no element and hash == 'top', scroll to the top of the page
4726 else if (hash === 'top') scrollTo(null);
4727 }
4728
4729 // does not scroll when user clicks on anchor link that is currently on
4730 // (no url change, no $location.hash() change), browser native does scroll
4731 if (autoScrollingEnabled) {
4732 $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
4733 function autoScrollWatchAction(newVal, oldVal) {
4734 // skip the initial scroll if $location.hash is empty
4735 if (newVal === oldVal && newVal === '') return;
4736
4737 jqLiteDocumentLoaded(function() {
4738 $rootScope.$evalAsync(scroll);
4739 });
4740 });
4741 }
4742
4743 return scroll;
4744 }];
4745 }
4746
4747 var $animateMinErr = minErr('$animate');
4748 var ELEMENT_NODE = 1;
4749 var NG_ANIMATE_CLASSNAME = 'ng-animate';
4750
4751 function mergeClasses(a,b) {
4752 if (!a && !b) return '';
4753 if (!a) return b;
4754 if (!b) return a;
4755 if (isArray(a)) a = a.join(' ');
4756 if (isArray(b)) b = b.join(' ');
4757 return a + ' ' + b;
4758 }
4759
4760 function extractElementNode(element) {
4761 for (var i = 0; i < element.length; i++) {
4762 var elm = element[i];
4763 if (elm.nodeType === ELEMENT_NODE) {
4764 return elm;
4765 }
4766 }
4767 }
4768
4769 function splitClasses(classes) {
4770 if (isString(classes)) {
4771 classes = classes.split(' ');
4772 }
4773
4774 // Use createMap() to prevent class assumptions involving property names in
4775 // Object.prototype
4776 var obj = createMap();
4777 forEach(classes, function(klass) {
4778 // sometimes the split leaves empty string values
4779 // incase extra spaces were applied to the options
4780 if (klass.length) {
4781 obj[klass] = true;
4782 }
4783 });
4784 return obj;
4785 }
4786
4787 // if any other type of options value besides an Object value is
4788 // passed into the $animate.method() animation then this helper code
4789 // will be run which will ignore it. While this patch is not the
4790 // greatest solution to this, a lot of existing plugins depend on
4791 // $animate to either call the callback (< 1.2) or return a promise
4792 // that can be changed. This helper function ensures that the options
4793 // are wiped clean incase a callback function is provided.
4794 function prepareAnimateOptions(options) {
4795 return isObject(options)
4796 ? options
4797 : {};
4798 }
4799
4800 var $$CoreAnimateRunnerProvider = function() {
4801 this.$get = ['$q', '$$rAF', function($q, $$rAF) {
4802 function AnimateRunner() {}
4803 AnimateRunner.all = noop;
4804 AnimateRunner.chain = noop;
4805 AnimateRunner.prototype = {
4806 end: noop,
4807 cancel: noop,
4808 resume: noop,
4809 pause: noop,
4810 complete: noop,
4811 then: function(pass, fail) {
4812 return $q(function(resolve) {
4813 $$rAF(function() {
4814 resolve();
4815 });
4816 }).then(pass, fail);
4817 }
4818 };
4819 return AnimateRunner;
4820 }];
4821 };
4822
4823 // this is prefixed with Core since it conflicts with
4824 // the animateQueueProvider defined in ngAnimate/animateQueue.js
4825 var $$CoreAnimateQueueProvider = function() {
4826 var postDigestQueue = new HashMap();
4827 var postDigestElements = [];
4828
4829 this.$get = ['$$AnimateRunner', '$rootScope',
4830 function($$AnimateRunner, $rootScope) {
4831 return {
4832 enabled: noop,
4833 on: noop,
4834 off: noop,
4835 pin: noop,
4836
4837 push: function(element, event, options, domOperation) {
4838 domOperation && domOperation();
4839
4840 options = options || {};
4841 options.from && element.css(options.from);
4842 options.to && element.css(options.to);
4843
4844 if (options.addClass || options.removeClass) {
4845 addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
4846 }
4847
4848 return new $$AnimateRunner(); // jshint ignore:line
4849 }
4850 };
4851
4852 function addRemoveClassesPostDigest(element, add, remove) {
4853 var data = postDigestQueue.get(element);
4854 var classVal;
4855
4856 if (!data) {
4857 postDigestQueue.put(element, data = {});
4858 postDigestElements.push(element);
4859 }
4860
4861 if (add) {
4862 forEach(add.split(' '), function(className) {
4863 if (className) {
4864 data[className] = true;
4865 }
4866 });
4867 }
4868
4869 if (remove) {
4870 forEach(remove.split(' '), function(className) {
4871 if (className) {
4872 data[className] = false;
4873 }
4874 });
4875 }
4876
4877 if (postDigestElements.length > 1) return;
4878
4879 $rootScope.$$postDigest(function() {
4880 forEach(postDigestElements, function(element) {
4881 var data = postDigestQueue.get(element);
4882 if (data) {
4883 var existing = splitClasses(element.attr('class'));
4884 var toAdd = '';
4885 var toRemove = '';
4886 forEach(data, function(status, className) {
4887 var hasClass = !!existing[className];
4888 if (status !== hasClass) {
4889 if (status) {
4890 toAdd += (toAdd.length ? ' ' : '') + className;
4891 } else {
4892 toRemove += (toRemove.length ? ' ' : '') + className;
4893 }
4894 }
4895 });
4896
4897 forEach(element, function(elm) {
4898 toAdd && jqLiteAddClass(elm, toAdd);
4899 toRemove && jqLiteRemoveClass(elm, toRemove);
4900 });
4901 postDigestQueue.remove(element);
4902 }
4903 });
4904
4905 postDigestElements.length = 0;
4906 });
4907 }
4908 }];
4909 };
4910
4911 /**
4912 * @ngdoc provider
4913 * @name $animateProvider
4914 *
4915 * @description
4916 * Default implementation of $animate that doesn't perform any animations, instead just
4917 * synchronously performs DOM updates and resolves the returned runner promise.
4918 *
4919 * In order to enable animations the `ngAnimate` module has to be loaded.
4920 *
4921 * To see the functional implementation check out `src/ngAnimate/animate.js`.
4922 */
4923 var $AnimateProvider = ['$provide', function($provide) {
4924 var provider = this;
4925
4926 this.$$registeredAnimations = Object.create(null);
4927
4928 /**
4929 * @ngdoc method
4930 * @name $animateProvider#register
4931 *
4932 * @description
4933 * Registers a new injectable animation factory function. The factory function produces the
4934 * animation object which contains callback functions for each event that is expected to be
4935 * animated.
4936 *
4937 * * `eventFn`: `function(element, ... , doneFunction, options)`
4938 * The element to animate, the `doneFunction` and the options fed into the animation. Depending
4939 * on the type of animation additional arguments will be injected into the animation function. The
4940 * list below explains the function signatures for the different animation methods:
4941 *
4942 * - setClass: function(element, addedClasses, removedClasses, doneFunction, options)
4943 * - addClass: function(element, addedClasses, doneFunction, options)
4944 * - removeClass: function(element, removedClasses, doneFunction, options)
4945 * - enter, leave, move: function(element, doneFunction, options)
4946 * - animate: function(element, fromStyles, toStyles, doneFunction, options)
4947 *
4948 * Make sure to trigger the `doneFunction` once the animation is fully complete.
4949 *
4950 * ```js
4951 * return {
4952 * //enter, leave, move signature
4953 * eventFn : function(element, done, options) {
4954 * //code to run the animation
4955 * //once complete, then run done()
4956 * return function endFunction(wasCancelled) {
4957 * //code to cancel the animation
4958 * }
4959 * }
4960 * }
4961 * ```
4962 *
4963 * @param {string} name The name of the animation (this is what the class-based CSS value will be compared to).
4964 * @param {Function} factory The factory function that will be executed to return the animation
4965 * object.
4966 */
4967 this.register = function(name, factory) {
4968 if (name && name.charAt(0) !== '.') {
4969 throw $animateMinErr('notcsel', "Expecting class selector starting with '.' got '{0}'.", name);
4970 }
4971
4972 var key = name + '-animation';
4973 provider.$$registeredAnimations[name.substr(1)] = key;
4974 $provide.factory(key, factory);
4975 };
4976
4977 /**
4978 * @ngdoc method
4979 * @name $animateProvider#classNameFilter
4980 *
4981 * @description
4982 * Sets and/or returns the CSS class regular expression that is checked when performing
4983 * an animation. Upon bootstrap the classNameFilter value is not set at all and will
4984 * therefore enable $animate to attempt to perform an animation on any element that is triggered.
4985 * When setting the `classNameFilter` value, animations will only be performed on elements
4986 * that successfully match the filter expression. This in turn can boost performance
4987 * for low-powered devices as well as applications containing a lot of structural operations.
4988 * @param {RegExp=} expression The className expression which will be checked against all animations
4989 * @return {RegExp} The current CSS className expression value. If null then there is no expression value
4990 */
4991 this.classNameFilter = function(expression) {
4992 if (arguments.length === 1) {
4993 this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
4994 if (this.$$classNameFilter) {
4995 var reservedRegex = new RegExp("(\\s+|\\/)" + NG_ANIMATE_CLASSNAME + "(\\s+|\\/)");
4996 if (reservedRegex.test(this.$$classNameFilter.toString())) {
4997 throw $animateMinErr('nongcls','$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.', NG_ANIMATE_CLASSNAME);
4998
4999 }
5000 }
5001 }
5002 return this.$$classNameFilter;
5003 };
5004
5005 this.$get = ['$$animateQueue', function($$animateQueue) {
5006 function domInsert(element, parentElement, afterElement) {
5007 // if for some reason the previous element was removed
5008 // from the dom sometime before this code runs then let's
5009 // just stick to using the parent element as the anchor
5010 if (afterElement) {
5011 var afterNode = extractElementNode(afterElement);
5012 if (afterNode && !afterNode.parentNode && !afterNode.previousElementSibling) {
5013 afterElement = null;
5014 }
5015 }
5016 afterElement ? afterElement.after(element) : parentElement.prepend(element);
5017 }
5018
5019 /**
5020 * @ngdoc service
5021 * @name $animate
5022 * @description The $animate service exposes a series of DOM utility methods that provide support
5023 * for animation hooks. The default behavior is the application of DOM operations, however,
5024 * when an animation is detected (and animations are enabled), $animate will do the heavy lifting
5025 * to ensure that animation runs with the triggered DOM operation.
5026 *
5027 * By default $animate doesn't trigger an animations. This is because the `ngAnimate` module isn't
5028 * included and only when it is active then the animation hooks that `$animate` triggers will be
5029 * functional. Once active then all structural `ng-` directives will trigger animations as they perform
5030 * their DOM-related operations (enter, leave and move). Other directives such as `ngClass`,
5031 * `ngShow`, `ngHide` and `ngMessages` also provide support for animations.
5032 *
5033 * It is recommended that the`$animate` service is always used when executing DOM-related procedures within directives.
5034 *
5035 * To learn more about enabling animation support, click here to visit the
5036 * {@link ngAnimate ngAnimate module page}.
5037 */
5038 return {
5039 // we don't call it directly since non-existant arguments may
5040 // be interpreted as null within the sub enabled function
5041
5042 /**
5043 *
5044 * @ngdoc method
5045 * @name $animate#on
5046 * @kind function
5047 * @description Sets up an event listener to fire whenever the animation event (enter, leave, move, etc...)
5048 * has fired on the given element or among any of its children. Once the listener is fired, the provided callback
5049 * is fired with the following params:
5050 *
5051 * ```js
5052 * $animate.on('enter', container,
5053 * function callback(element, phase) {
5054 * // cool we detected an enter animation within the container
5055 * }
5056 * );
5057 * ```
5058 *
5059 * @param {string} event the animation event that will be captured (e.g. enter, leave, move, addClass, removeClass, etc...)
5060 * @param {DOMElement} container the container element that will capture each of the animation events that are fired on itself
5061 * as well as among its children
5062 * @param {Function} callback the callback function that will be fired when the listener is triggered
5063 *
5064 * The arguments present in the callback function are:
5065 * * `element` - The captured DOM element that the animation was fired on.
5066 * * `phase` - The phase of the animation. The two possible phases are **start** (when the animation starts) and **close** (when it ends).
5067 */
5068 on: $$animateQueue.on,
5069
5070 /**
5071 *
5072 * @ngdoc method
5073 * @name $animate#off
5074 * @kind function
5075 * @description Deregisters an event listener based on the event which has been associated with the provided element. This method
5076 * can be used in three different ways depending on the arguments:
5077 *
5078 * ```js
5079 * // remove all the animation event listeners listening for `enter`
5080 * $animate.off('enter');
5081 *
5082 * // remove all the animation event listeners listening for `enter` on the given element and its children
5083 * $animate.off('enter', container);
5084 *
5085 * // remove the event listener function provided by `listenerFn` that is set
5086 * // to listen for `enter` on the given `element` as well as its children
5087 * $animate.off('enter', container, callback);
5088 * ```
5089 *
5090 * @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
5091 * @param {DOMElement=} container the container element the event listener was placed on
5092 * @param {Function=} callback the callback function that was registered as the listener
5093 */
5094 off: $$animateQueue.off,
5095
5096 /**
5097 * @ngdoc method
5098 * @name $animate#pin
5099 * @kind function
5100 * @description Associates the provided element with a host parent element to allow the element to be animated even if it exists
5101 * outside of the DOM structure of the Angular application. By doing so, any animation triggered via `$animate` can be issued on the
5102 * element despite being outside the realm of the application or within another application. Say for example if the application
5103 * was bootstrapped on an element that is somewhere inside of the `<body>` tag, but we wanted to allow for an element to be situated
5104 * as a direct child of `document.body`, then this can be achieved by pinning the element via `$animate.pin(element)`. Keep in mind
5105 * that calling `$animate.pin(element, parentElement)` will not actually insert into the DOM anywhere; it will just create the association.
5106 *
5107 * Note that this feature is only active when the `ngAnimate` module is used.
5108 *
5109 * @param {DOMElement} element the external element that will be pinned
5110 * @param {DOMElement} parentElement the host parent element that will be associated with the external element
5111 */
5112 pin: $$animateQueue.pin,
5113
5114 /**
5115 *
5116 * @ngdoc method
5117 * @name $animate#enabled
5118 * @kind function
5119 * @description Used to get and set whether animations are enabled or not on the entire application or on an element and its children. This
5120 * function can be called in four ways:
5121 *
5122 * ```js
5123 * // returns true or false
5124 * $animate.enabled();
5125 *
5126 * // changes the enabled state for all animations
5127 * $animate.enabled(false);
5128 * $animate.enabled(true);
5129 *
5130 * // returns true or false if animations are enabled for an element
5131 * $animate.enabled(element);
5132 *
5133 * // changes the enabled state for an element and its children
5134 * $animate.enabled(element, true);
5135 * $animate.enabled(element, false);
5136 * ```
5137 *
5138 * @param {DOMElement=} element the element that will be considered for checking/setting the enabled state
5139 * @param {boolean=} enabled whether or not the animations will be enabled for the element
5140 *
5141 * @return {boolean} whether or not animations are enabled
5142 */
5143 enabled: $$animateQueue.enabled,
5144
5145 /**
5146 * @ngdoc method
5147 * @name $animate#cancel
5148 * @kind function
5149 * @description Cancels the provided animation.
5150 *
5151 * @param {Promise} animationPromise The animation promise that is returned when an animation is started.
5152 */
5153 cancel: function(runner) {
5154 runner.end && runner.end();
5155 },
5156
5157 /**
5158 *
5159 * @ngdoc method
5160 * @name $animate#enter
5161 * @kind function
5162 * @description Inserts the element into the DOM either after the `after` element (if provided) or
5163 * as the first child within the `parent` element and then triggers an animation.
5164 * A promise is returned that will be resolved during the next digest once the animation
5165 * has completed.
5166 *
5167 * @param {DOMElement} element the element which will be inserted into the DOM
5168 * @param {DOMElement} parent the parent element which will append the element as
5169 * a child (so long as the after element is not present)
5170 * @param {DOMElement=} after the sibling element after which the element will be appended
5171 * @param {object=} options an optional collection of options/styles that will be applied to the element
5172 *
5173 * @return {Promise} the animation callback promise
5174 */
5175 enter: function(element, parent, after, options) {
5176 parent = parent && jqLite(parent);
5177 after = after && jqLite(after);
5178 parent = parent || after.parent();
5179 domInsert(element, parent, after);
5180 return $$animateQueue.push(element, 'enter', prepareAnimateOptions(options));
5181 },
5182
5183 /**
5184 *
5185 * @ngdoc method
5186 * @name $animate#move
5187 * @kind function
5188 * @description Inserts (moves) the element into its new position in the DOM either after
5189 * the `after` element (if provided) or as the first child within the `parent` element
5190 * and then triggers an animation. A promise is returned that will be resolved
5191 * during the next digest once the animation has completed.
5192 *
5193 * @param {DOMElement} element the element which will be moved into the new DOM position
5194 * @param {DOMElement} parent the parent element which will append the element as
5195 * a child (so long as the after element is not present)
5196 * @param {DOMElement=} after the sibling element after which the element will be appended
5197 * @param {object=} options an optional collection of options/styles that will be applied to the element
5198 *
5199 * @return {Promise} the animation callback promise
5200 */
5201 move: function(element, parent, after, options) {
5202 parent = parent && jqLite(parent);
5203 after = after && jqLite(after);
5204 parent = parent || after.parent();
5205 domInsert(element, parent, after);
5206 return $$animateQueue.push(element, 'move', prepareAnimateOptions(options));
5207 },
5208
5209 /**
5210 * @ngdoc method
5211 * @name $animate#leave
5212 * @kind function
5213 * @description Triggers an animation and then removes the element from the DOM.
5214 * When the function is called a promise is returned that will be resolved during the next
5215 * digest once the animation has completed.
5216 *
5217 * @param {DOMElement} element the element which will be removed from the DOM
5218 * @param {object=} options an optional collection of options/styles that will be applied to the element
5219 *
5220 * @return {Promise} the animation callback promise
5221 */
5222 leave: function(element, options) {
5223 return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() {
5224 element.remove();
5225 });
5226 },
5227
5228 /**
5229 * @ngdoc method
5230 * @name $animate#addClass
5231 * @kind function
5232 *
5233 * @description Triggers an addClass animation surrounding the addition of the provided CSS class(es). Upon
5234 * execution, the addClass operation will only be handled after the next digest and it will not trigger an
5235 * animation if element already contains the CSS class or if the class is removed at a later step.
5236 * Note that class-based animations are treated differently compared to structural animations
5237 * (like enter, move and leave) since the CSS classes may be added/removed at different points
5238 * depending if CSS or JavaScript animations are used.
5239 *
5240 * @param {DOMElement} element the element which the CSS classes will be applied to
5241 * @param {string} className the CSS class(es) that will be added (multiple classes are separated via spaces)
5242 * @param {object=} options an optional collection of options/styles that will be applied to the element
5243 *
5244 * @return {Promise} the animation callback promise
5245 */
5246 addClass: function(element, className, options) {
5247 options = prepareAnimateOptions(options);
5248 options.addClass = mergeClasses(options.addclass, className);
5249 return $$animateQueue.push(element, 'addClass', options);
5250 },
5251
5252 /**
5253 * @ngdoc method
5254 * @name $animate#removeClass
5255 * @kind function
5256 *
5257 * @description Triggers a removeClass animation surrounding the removal of the provided CSS class(es). Upon
5258 * execution, the removeClass operation will only be handled after the next digest and it will not trigger an
5259 * animation if element does not contain the CSS class or if the class is added at a later step.
5260 * Note that class-based animations are treated differently compared to structural animations
5261 * (like enter, move and leave) since the CSS classes may be added/removed at different points
5262 * depending if CSS or JavaScript animations are used.
5263 *
5264 * @param {DOMElement} element the element which the CSS classes will be applied to
5265 * @param {string} className the CSS class(es) that will be removed (multiple classes are separated via spaces)
5266 * @param {object=} options an optional collection of options/styles that will be applied to the element
5267 *
5268 * @return {Promise} the animation callback promise
5269 */
5270 removeClass: function(element, className, options) {
5271 options = prepareAnimateOptions(options);
5272 options.removeClass = mergeClasses(options.removeClass, className);
5273 return $$animateQueue.push(element, 'removeClass', options);
5274 },
5275
5276 /**
5277 * @ngdoc method
5278 * @name $animate#setClass
5279 * @kind function
5280 *
5281 * @description Performs both the addition and removal of a CSS classes on an element and (during the process)
5282 * triggers an animation surrounding the class addition/removal. Much like `$animate.addClass` and
5283 * `$animate.removeClass`, `setClass` will only evaluate the classes being added/removed once a digest has
5284 * passed. Note that class-based animations are treated differently compared to structural animations
5285 * (like enter, move and leave) since the CSS classes may be added/removed at different points
5286 * depending if CSS or JavaScript animations are used.
5287 *
5288 * @param {DOMElement} element the element which the CSS classes will be applied to
5289 * @param {string} add the CSS class(es) that will be added (multiple classes are separated via spaces)
5290 * @param {string} remove the CSS class(es) that will be removed (multiple classes are separated via spaces)
5291 * @param {object=} options an optional collection of options/styles that will be applied to the element
5292 *
5293 * @return {Promise} the animation callback promise
5294 */
5295 setClass: function(element, add, remove, options) {
5296 options = prepareAnimateOptions(options);
5297 options.addClass = mergeClasses(options.addClass, add);
5298 options.removeClass = mergeClasses(options.removeClass, remove);
5299 return $$animateQueue.push(element, 'setClass', options);
5300 },
5301
5302 /**
5303 * @ngdoc method
5304 * @name $animate#animate
5305 * @kind function
5306 *
5307 * @description Performs an inline animation on the element which applies the provided to and from CSS styles to the element.
5308 * If any detected CSS transition, keyframe or JavaScript matches the provided className value then the animation will take
5309 * on the provided styles. For example, if a transition animation is set for the given className then the provided from and
5310 * to styles will be applied alongside the given transition. If a JavaScript animation is detected then the provided styles
5311 * will be given in as function paramters into the `animate` method (or as apart of the `options` parameter).
5312 *
5313 * @param {DOMElement} element the element which the CSS styles will be applied to
5314 * @param {object} from the from (starting) CSS styles that will be applied to the element and across the animation.
5315 * @param {object} to the to (destination) CSS styles that will be applied to the element and across the animation.
5316 * @param {string=} className an optional CSS class that will be applied to the element for the duration of the animation. If
5317 * this value is left as empty then a CSS class of `ng-inline-animate` will be applied to the element.
5318 * (Note that if no animation is detected then this value will not be appplied to the element.)
5319 * @param {object=} options an optional collection of options/styles that will be applied to the element
5320 *
5321 * @return {Promise} the animation callback promise
5322 */
5323 animate: function(element, from, to, className, options) {
5324 options = prepareAnimateOptions(options);
5325 options.from = options.from ? extend(options.from, from) : from;
5326 options.to = options.to ? extend(options.to, to) : to;
5327
5328 className = className || 'ng-inline-animate';
5329 options.tempClasses = mergeClasses(options.tempClasses, className);
5330 return $$animateQueue.push(element, 'animate', options);
5331 }
5332 };
5333 }];
5334 }];
5335
5336 function $$AsyncCallbackProvider() {
5337 this.$get = ['$$rAF', '$timeout', function($$rAF, $timeout) {
5338 return $$rAF.supported
5339 ? function(fn) { return $$rAF(fn); }
5340 : function(fn) {
5341 return $timeout(fn, 0, false);
5342 };
5343 }];
5344 }
5345
5346 /* global stripHash: true */
5347
5348 /**
5349 * ! This is a private undocumented service !
5350 *
5351 * @name $browser
5352 * @requires $log
5353 * @description
5354 * This object has two goals:
5355 *
5356 * - hide all the global state in the browser caused by the window object
5357 * - abstract away all the browser specific features and inconsistencies
5358 *
5359 * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
5360 * service, which can be used for convenient testing of the application without the interaction with
5361 * the real browser apis.
5362 */
5363 /**
5364 * @param {object} window The global window object.
5365 * @param {object} document jQuery wrapped document.
5366 * @param {object} $log window.console or an object with the same interface.
5367 * @param {object} $sniffer $sniffer service
5368 */
5369 function Browser(window, document, $log, $sniffer) {
5370 var self = this,
5371 rawDocument = document[0],
5372 location = window.location,
5373 history = window.history,
5374 setTimeout = window.setTimeout,
5375 clearTimeout = window.clearTimeout,
5376 pendingDeferIds = {};
5377
5378 self.isMock = false;
5379
5380 var outstandingRequestCount = 0;
5381 var outstandingRequestCallbacks = [];
5382
5383 // TODO(vojta): remove this temporary api
5384 self.$$completeOutstandingRequest = completeOutstandingRequest;
5385 self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
5386
5387 /**
5388 * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
5389 * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
5390 */
5391 function completeOutstandingRequest(fn) {
5392 try {
5393 fn.apply(null, sliceArgs(arguments, 1));
5394 } finally {
5395 outstandingRequestCount--;
5396 if (outstandingRequestCount === 0) {
5397 while (outstandingRequestCallbacks.length) {
5398 try {
5399 outstandingRequestCallbacks.pop()();
5400 } catch (e) {
5401 $log.error(e);
5402 }
5403 }
5404 }
5405 }
5406 }
5407
5408 function getHash(url) {
5409 var index = url.indexOf('#');
5410 return index === -1 ? '' : url.substr(index);
5411 }
5412
5413 /**
5414 * @private
5415 * Note: this method is used only by scenario runner
5416 * TODO(vojta): prefix this method with $$ ?
5417 * @param {function()} callback Function that will be called when no outstanding request
5418 */
5419 self.notifyWhenNoOutstandingRequests = function(callback) {
5420 if (outstandingRequestCount === 0) {
5421 callback();
5422 } else {
5423 outstandingRequestCallbacks.push(callback);
5424 }
5425 };
5426
5427 //////////////////////////////////////////////////////////////
5428 // URL API
5429 //////////////////////////////////////////////////////////////
5430
5431 var cachedState, lastHistoryState,
5432 lastBrowserUrl = location.href,
5433 baseElement = document.find('base'),
5434 reloadLocation = null;
5435
5436 cacheState();
5437 lastHistoryState = cachedState;
5438
5439 /**
5440 * @name $browser#url
5441 *
5442 * @description
5443 * GETTER:
5444 * Without any argument, this method just returns current value of location.href.
5445 *
5446 * SETTER:
5447 * With at least one argument, this method sets url to new value.
5448 * If html5 history api supported, pushState/replaceState is used, otherwise
5449 * location.href/location.replace is used.
5450 * Returns its own instance to allow chaining
5451 *
5452 * NOTE: this api is intended for use only by the $location service. Please use the
5453 * {@link ng.$location $location service} to change url.
5454 *
5455 * @param {string} url New url (when used as setter)
5456 * @param {boolean=} replace Should new url replace current history record?
5457 * @param {object=} state object to use with pushState/replaceState
5458 */
5459 self.url = function(url, replace, state) {
5460 // In modern browsers `history.state` is `null` by default; treating it separately
5461 // from `undefined` would cause `$browser.url('/foo')` to change `history.state`
5462 // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
5463 if (isUndefined(state)) {
5464 state = null;
5465 }
5466
5467 // Android Browser BFCache causes location, history reference to become stale.
5468 if (location !== window.location) location = window.location;
5469 if (history !== window.history) history = window.history;
5470
5471 // setter
5472 if (url) {
5473 var sameState = lastHistoryState === state;
5474
5475 // Don't change anything if previous and current URLs and states match. This also prevents
5476 // IE<10 from getting into redirect loop when in LocationHashbangInHtml5Url mode.
5477 // See https://github.com/angular/angular.js/commit/ffb2701
5478 if (lastBrowserUrl === url && (!$sniffer.history || sameState)) {
5479 return self;
5480 }
5481 var sameBase = lastBrowserUrl && stripHash(lastBrowserUrl) === stripHash(url);
5482 lastBrowserUrl = url;
5483 lastHistoryState = state;
5484 // Don't use history API if only the hash changed
5485 // due to a bug in IE10/IE11 which leads
5486 // to not firing a `hashchange` nor `popstate` event
5487 // in some cases (see #9143).
5488 if ($sniffer.history && (!sameBase || !sameState)) {
5489 history[replace ? 'replaceState' : 'pushState'](state, '', url);
5490 cacheState();
5491 // Do the assignment again so that those two variables are referentially identical.
5492 lastHistoryState = cachedState;
5493 } else {
5494 if (!sameBase || reloadLocation) {
5495 reloadLocation = url;
5496 }
5497 if (replace) {
5498 location.replace(url);
5499 } else if (!sameBase) {
5500 location.href = url;
5501 } else {
5502 location.hash = getHash(url);
5503 }
5504 }
5505 return self;
5506 // getter
5507 } else {
5508 // - reloadLocation is needed as browsers don't allow to read out
5509 // the new location.href if a reload happened.
5510 // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
5511 return reloadLocation || location.href.replace(/%27/g,"'");
5512 }
5513 };
5514
5515 /**
5516 * @name $browser#state
5517 *
5518 * @description
5519 * This method is a getter.
5520 *
5521 * Return history.state or null if history.state is undefined.
5522 *
5523 * @returns {object} state
5524 */
5525 self.state = function() {
5526 return cachedState;
5527 };
5528
5529 var urlChangeListeners = [],
5530 urlChangeInit = false;
5531
5532 function cacheStateAndFireUrlChange() {
5533 cacheState();
5534 fireUrlChange();
5535 }
5536
5537 function getCurrentState() {
5538 try {
5539 return history.state;
5540 } catch (e) {
5541 // MSIE can reportedly throw when there is no state (UNCONFIRMED).
5542 }
5543 }
5544
5545 // This variable should be used *only* inside the cacheState function.
5546 var lastCachedState = null;
5547 function cacheState() {
5548 // This should be the only place in $browser where `history.state` is read.
5549 cachedState = getCurrentState();
5550 cachedState = isUndefined(cachedState) ? null : cachedState;
5551
5552 // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
5553 if (equals(cachedState, lastCachedState)) {
5554 cachedState = lastCachedState;
5555 }
5556 lastCachedState = cachedState;
5557 }
5558
5559 function fireUrlChange() {
5560 if (lastBrowserUrl === self.url() && lastHistoryState === cachedState) {
5561 return;
5562 }
5563
5564 lastBrowserUrl = self.url();
5565 lastHistoryState = cachedState;
5566 forEach(urlChangeListeners, function(listener) {
5567 listener(self.url(), cachedState);
5568 });
5569 }
5570
5571 /**
5572 * @name $browser#onUrlChange
5573 *
5574 * @description
5575 * Register callback function that will be called, when url changes.
5576 *
5577 * It's only called when the url is changed from outside of angular:
5578 * - user types different url into address bar
5579 * - user clicks on history (forward/back) button
5580 * - user clicks on a link
5581 *
5582 * It's not called when url is changed by $browser.url() method
5583 *
5584 * The listener gets called with new url as parameter.
5585 *
5586 * NOTE: this api is intended for use only by the $location service. Please use the
5587 * {@link ng.$location $location service} to monitor url changes in angular apps.
5588 *
5589 * @param {function(string)} listener Listener function to be called when url changes.
5590 * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
5591 */
5592 self.onUrlChange = function(callback) {
5593 // TODO(vojta): refactor to use node's syntax for events
5594 if (!urlChangeInit) {
5595 // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
5596 // don't fire popstate when user change the address bar and don't fire hashchange when url
5597 // changed by push/replaceState
5598
5599 // html5 history api - popstate event
5600 if ($sniffer.history) jqLite(window).on('popstate', cacheStateAndFireUrlChange);
5601 // hashchange event
5602 jqLite(window).on('hashchange', cacheStateAndFireUrlChange);
5603
5604 urlChangeInit = true;
5605 }
5606
5607 urlChangeListeners.push(callback);
5608 return callback;
5609 };
5610
5611 /**
5612 * @private
5613 * Remove popstate and hashchange handler from window.
5614 *
5615 * NOTE: this api is intended for use only by $rootScope.
5616 */
5617 self.$$applicationDestroyed = function() {
5618 jqLite(window).off('hashchange popstate', cacheStateAndFireUrlChange);
5619 };
5620
5621 /**
5622 * Checks whether the url has changed outside of Angular.
5623 * Needs to be exported to be able to check for changes that have been done in sync,
5624 * as hashchange/popstate events fire in async.
5625 */
5626 self.$$checkUrlChange = fireUrlChange;
5627
5628 //////////////////////////////////////////////////////////////
5629 // Misc API
5630 //////////////////////////////////////////////////////////////
5631
5632 /**
5633 * @name $browser#baseHref
5634 *
5635 * @description
5636 * Returns current <base href>
5637 * (always relative - without domain)
5638 *
5639 * @returns {string} The current base href
5640 */
5641 self.baseHref = function() {
5642 var href = baseElement.attr('href');
5643 return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
5644 };
5645
5646 /**
5647 * @name $browser#defer
5648 * @param {function()} fn A function, who's execution should be deferred.
5649 * @param {number=} [delay=0] of milliseconds to defer the function execution.
5650 * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
5651 *
5652 * @description
5653 * Executes a fn asynchronously via `setTimeout(fn, delay)`.
5654 *
5655 * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
5656 * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed
5657 * via `$browser.defer.flush()`.
5658 *
5659 */
5660 self.defer = function(fn, delay) {
5661 var timeoutId;
5662 outstandingRequestCount++;
5663 timeoutId = setTimeout(function() {
5664 delete pendingDeferIds[timeoutId];
5665 completeOutstandingRequest(fn);
5666 }, delay || 0);
5667 pendingDeferIds[timeoutId] = true;
5668 return timeoutId;
5669 };
5670
5671
5672 /**
5673 * @name $browser#defer.cancel
5674 *
5675 * @description
5676 * Cancels a deferred task identified with `deferId`.
5677 *
5678 * @param {*} deferId Token returned by the `$browser.defer` function.
5679 * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
5680 * canceled.
5681 */
5682 self.defer.cancel = function(deferId) {
5683 if (pendingDeferIds[deferId]) {
5684 delete pendingDeferIds[deferId];
5685 clearTimeout(deferId);
5686 completeOutstandingRequest(noop);
5687 return true;
5688 }
5689 return false;
5690 };
5691
5692 }
5693
5694 function $BrowserProvider() {
5695 this.$get = ['$window', '$log', '$sniffer', '$document',
5696 function($window, $log, $sniffer, $document) {
5697 return new Browser($window, $document, $log, $sniffer);
5698 }];
5699 }
5700
5701 /**
5702 * @ngdoc service
5703 * @name $cacheFactory
5704 *
5705 * @description
5706 * Factory that constructs {@link $cacheFactory.Cache Cache} objects and gives access to
5707 * them.
5708 *
5709 * ```js
5710 *
5711 * var cache = $cacheFactory('cacheId');
5712 * expect($cacheFactory.get('cacheId')).toBe(cache);
5713 * expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
5714 *
5715 * cache.put("key", "value");
5716 * cache.put("another key", "another value");
5717 *
5718 * // We've specified no options on creation
5719 * expect(cache.info()).toEqual({id: 'cacheId', size: 2});
5720 *
5721 * ```
5722 *
5723 *
5724 * @param {string} cacheId Name or id of the newly created cache.
5725 * @param {object=} options Options object that specifies the cache behavior. Properties:
5726 *
5727 * - `{number=}` `capacity` — turns the cache into LRU cache.
5728 *
5729 * @returns {object} Newly created cache object with the following set of methods:
5730 *
5731 * - `{object}` `info()` — Returns id, size, and options of cache.
5732 * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
5733 * it.
5734 * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
5735 * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
5736 * - `{void}` `removeAll()` — Removes all cached values.
5737 * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
5738 *
5739 * @example
5740 <example module="cacheExampleApp">
5741 <file name="index.html">
5742 <div ng-controller="CacheController">
5743 <input ng-model="newCacheKey" placeholder="Key">
5744 <input ng-model="newCacheValue" placeholder="Value">
5745 <button ng-click="put(newCacheKey, newCacheValue)">Cache</button>
5746
5747 <p ng-if="keys.length">Cached Values</p>
5748 <div ng-repeat="key in keys">
5749 <span ng-bind="key"></span>
5750 <span>: </span>
5751 <b ng-bind="cache.get(key)"></b>
5752 </div>
5753
5754 <p>Cache Info</p>
5755 <div ng-repeat="(key, value) in cache.info()">
5756 <span ng-bind="key"></span>
5757 <span>: </span>
5758 <b ng-bind="value"></b>
5759 </div>
5760 </div>
5761 </file>
5762 <file name="script.js">
5763 angular.module('cacheExampleApp', []).
5764 controller('CacheController', ['$scope', '$cacheFactory', function($scope, $cacheFactory) {
5765 $scope.keys = [];
5766 $scope.cache = $cacheFactory('cacheId');
5767 $scope.put = function(key, value) {
5768 if ($scope.cache.get(key) === undefined) {
5769 $scope.keys.push(key);
5770 }
5771 $scope.cache.put(key, value === undefined ? null : value);
5772 };
5773 }]);
5774 </file>
5775 <file name="style.css">
5776 p {
5777 margin: 10px 0 3px;
5778 }
5779 </file>
5780 </example>
5781 */
5782 function $CacheFactoryProvider() {
5783
5784 this.$get = function() {
5785 var caches = {};
5786
5787 function cacheFactory(cacheId, options) {
5788 if (cacheId in caches) {
5789 throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
5790 }
5791
5792 var size = 0,
5793 stats = extend({}, options, {id: cacheId}),
5794 data = {},
5795 capacity = (options && options.capacity) || Number.MAX_VALUE,
5796 lruHash = {},
5797 freshEnd = null,
5798 staleEnd = null;
5799
5800 /**
5801 * @ngdoc type
5802 * @name $cacheFactory.Cache
5803 *
5804 * @description
5805 * A cache object used to store and retrieve data, primarily used by
5806 * {@link $http $http} and the {@link ng.directive:script script} directive to cache
5807 * templates and other data.
5808 *
5809 * ```js
5810 * angular.module('superCache')
5811 * .factory('superCache', ['$cacheFactory', function($cacheFactory) {
5812 * return $cacheFactory('super-cache');
5813 * }]);
5814 * ```
5815 *
5816 * Example test:
5817 *
5818 * ```js
5819 * it('should behave like a cache', inject(function(superCache) {
5820 * superCache.put('key', 'value');
5821 * superCache.put('another key', 'another value');
5822 *
5823 * expect(superCache.info()).toEqual({
5824 * id: 'super-cache',
5825 * size: 2
5826 * });
5827 *
5828 * superCache.remove('another key');
5829 * expect(superCache.get('another key')).toBeUndefined();
5830 *
5831 * superCache.removeAll();
5832 * expect(superCache.info()).toEqual({
5833 * id: 'super-cache',
5834 * size: 0
5835 * });
5836 * }));
5837 * ```
5838 */
5839 return caches[cacheId] = {
5840
5841 /**
5842 * @ngdoc method
5843 * @name $cacheFactory.Cache#put
5844 * @kind function
5845 *
5846 * @description
5847 * Inserts a named entry into the {@link $cacheFactory.Cache Cache} object to be
5848 * retrieved later, and incrementing the size of the cache if the key was not already
5849 * present in the cache. If behaving like an LRU cache, it will also remove stale
5850 * entries from the set.
5851 *
5852 * It will not insert undefined values into the cache.
5853 *
5854 * @param {string} key the key under which the cached data is stored.
5855 * @param {*} value the value to store alongside the key. If it is undefined, the key
5856 * will not be stored.
5857 * @returns {*} the value stored.
5858 */
5859 put: function(key, value) {
5860 if (isUndefined(value)) return;
5861 if (capacity < Number.MAX_VALUE) {
5862 var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
5863
5864 refresh(lruEntry);
5865 }
5866
5867 if (!(key in data)) size++;
5868 data[key] = value;
5869
5870 if (size > capacity) {
5871 this.remove(staleEnd.key);
5872 }
5873
5874 return value;
5875 },
5876
5877 /**
5878 * @ngdoc method
5879 * @name $cacheFactory.Cache#get
5880 * @kind function
5881 *
5882 * @description
5883 * Retrieves named data stored in the {@link $cacheFactory.Cache Cache} object.
5884 *
5885 * @param {string} key the key of the data to be retrieved
5886 * @returns {*} the value stored.
5887 */
5888 get: function(key) {
5889 if (capacity < Number.MAX_VALUE) {
5890 var lruEntry = lruHash[key];
5891
5892 if (!lruEntry) return;
5893
5894 refresh(lruEntry);
5895 }
5896
5897 return data[key];
5898 },
5899
5900
5901 /**
5902 * @ngdoc method
5903 * @name $cacheFactory.Cache#remove
5904 * @kind function
5905 *
5906 * @description
5907 * Removes an entry from the {@link $cacheFactory.Cache Cache} object.
5908 *
5909 * @param {string} key the key of the entry to be removed
5910 */
5911 remove: function(key) {
5912 if (capacity < Number.MAX_VALUE) {
5913 var lruEntry = lruHash[key];
5914
5915 if (!lruEntry) return;
5916
5917 if (lruEntry == freshEnd) freshEnd = lruEntry.p;
5918 if (lruEntry == staleEnd) staleEnd = lruEntry.n;
5919 link(lruEntry.n,lruEntry.p);
5920
5921 delete lruHash[key];
5922 }
5923
5924 delete data[key];
5925 size--;
5926 },
5927
5928
5929 /**
5930 * @ngdoc method
5931 * @name $cacheFactory.Cache#removeAll
5932 * @kind function
5933 *
5934 * @description
5935 * Clears the cache object of any entries.
5936 */
5937 removeAll: function() {
5938 data = {};
5939 size = 0;
5940 lruHash = {};
5941 freshEnd = staleEnd = null;
5942 },
5943
5944
5945 /**
5946 * @ngdoc method
5947 * @name $cacheFactory.Cache#destroy
5948 * @kind function
5949 *
5950 * @description
5951 * Destroys the {@link $cacheFactory.Cache Cache} object entirely,
5952 * removing it from the {@link $cacheFactory $cacheFactory} set.
5953 */
5954 destroy: function() {
5955 data = null;
5956 stats = null;
5957 lruHash = null;
5958 delete caches[cacheId];
5959 },
5960
5961
5962 /**
5963 * @ngdoc method
5964 * @name $cacheFactory.Cache#info
5965 * @kind function
5966 *
5967 * @description
5968 * Retrieve information regarding a particular {@link $cacheFactory.Cache Cache}.
5969 *
5970 * @returns {object} an object with the following properties:
5971 * <ul>
5972 * <li>**id**: the id of the cache instance</li>
5973 * <li>**size**: the number of entries kept in the cache instance</li>
5974 * <li>**...**: any additional properties from the options object when creating the
5975 * cache.</li>
5976 * </ul>
5977 */
5978 info: function() {
5979 return extend({}, stats, {size: size});
5980 }
5981 };
5982
5983
5984 /**
5985 * makes the `entry` the freshEnd of the LRU linked list
5986 */
5987 function refresh(entry) {
5988 if (entry != freshEnd) {
5989 if (!staleEnd) {
5990 staleEnd = entry;
5991 } else if (staleEnd == entry) {
5992 staleEnd = entry.n;
5993 }
5994
5995 link(entry.n, entry.p);
5996 link(entry, freshEnd);
5997 freshEnd = entry;
5998 freshEnd.n = null;
5999 }
6000 }
6001
6002
6003 /**
6004 * bidirectionally links two entries of the LRU linked list
6005 */
6006 function link(nextEntry, prevEntry) {
6007 if (nextEntry != prevEntry) {
6008 if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
6009 if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
6010 }
6011 }
6012 }
6013
6014
6015 /**
6016 * @ngdoc method
6017 * @name $cacheFactory#info
6018 *
6019 * @description
6020 * Get information about all the caches that have been created
6021 *
6022 * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
6023 */
6024 cacheFactory.info = function() {
6025 var info = {};
6026 forEach(caches, function(cache, cacheId) {
6027 info[cacheId] = cache.info();
6028 });
6029 return info;
6030 };
6031
6032
6033 /**
6034 * @ngdoc method
6035 * @name $cacheFactory#get
6036 *
6037 * @description
6038 * Get access to a cache object by the `cacheId` used when it was created.
6039 *
6040 * @param {string} cacheId Name or id of a cache to access.
6041 * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
6042 */
6043 cacheFactory.get = function(cacheId) {
6044 return caches[cacheId];
6045 };
6046
6047
6048 return cacheFactory;
6049 };
6050 }
6051
6052 /**
6053 * @ngdoc service
6054 * @name $templateCache
6055 *
6056 * @description
6057 * The first time a template is used, it is loaded in the template cache for quick retrieval. You
6058 * can load templates directly into the cache in a `script` tag, or by consuming the
6059 * `$templateCache` service directly.
6060 *
6061 * Adding via the `script` tag:
6062 *
6063 * ```html
6064 * <script type="text/ng-template" id="templateId.html">
6065 * <p>This is the content of the template</p>
6066 * </script>
6067 * ```
6068 *
6069 * **Note:** the `script` tag containing the template does not need to be included in the `head` of
6070 * the document, but it must be a descendent of the {@link ng.$rootElement $rootElement} (IE,
6071 * element with ng-app attribute), otherwise the template will be ignored.
6072 *
6073 * Adding via the `$templateCache` service:
6074 *
6075 * ```js
6076 * var myApp = angular.module('myApp', []);
6077 * myApp.run(function($templateCache) {
6078 * $templateCache.put('templateId.html', 'This is the content of the template');
6079 * });
6080 * ```
6081 *
6082 * To retrieve the template later, simply use it in your HTML:
6083 * ```html
6084 * <div ng-include=" 'templateId.html' "></div>
6085 * ```
6086 *
6087 * or get it via Javascript:
6088 * ```js
6089 * $templateCache.get('templateId.html')
6090 * ```
6091 *
6092 * See {@link ng.$cacheFactory $cacheFactory}.
6093 *
6094 */
6095 function $TemplateCacheProvider() {
6096 this.$get = ['$cacheFactory', function($cacheFactory) {
6097 return $cacheFactory('templates');
6098 }];
6099 }
6100
6101 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
6102 * Any commits to this file should be reviewed with security in mind. *
6103 * Changes to this file can potentially create security vulnerabilities. *
6104 * An approval from 2 Core members with history of modifying *
6105 * this file is required. *
6106 * *
6107 * Does the change somehow allow for arbitrary javascript to be executed? *
6108 * Or allows for someone to change the prototype of built-in objects? *
6109 * Or gives undesired access to variables likes document or window? *
6110 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6111
6112 /* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
6113 *
6114 * DOM-related variables:
6115 *
6116 * - "node" - DOM Node
6117 * - "element" - DOM Element or Node
6118 * - "$node" or "$element" - jqLite-wrapped node or element
6119 *
6120 *
6121 * Compiler related stuff:
6122 *
6123 * - "linkFn" - linking fn of a single directive
6124 * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
6125 * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node
6126 * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
6127 */
6128
6129
6130 /**
6131 * @ngdoc service
6132 * @name $compile
6133 * @kind function
6134 *
6135 * @description
6136 * Compiles an HTML string or DOM into a template and produces a template function, which
6137 * can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
6138 *
6139 * The compilation is a process of walking the DOM tree and matching DOM elements to
6140 * {@link ng.$compileProvider#directive directives}.
6141 *
6142 * <div class="alert alert-warning">
6143 * **Note:** This document is an in-depth reference of all directive options.
6144 * For a gentle introduction to directives with examples of common use cases,
6145 * see the {@link guide/directive directive guide}.
6146 * </div>
6147 *
6148 * ## Comprehensive Directive API
6149 *
6150 * There are many different options for a directive.
6151 *
6152 * The difference resides in the return value of the factory function.
6153 * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
6154 * or just the `postLink` function (all other properties will have the default values).
6155 *
6156 * <div class="alert alert-success">
6157 * **Best Practice:** It's recommended to use the "directive definition object" form.
6158 * </div>
6159 *
6160 * Here's an example directive declared with a Directive Definition Object:
6161 *
6162 * ```js
6163 * var myModule = angular.module(...);
6164 *
6165 * myModule.directive('directiveName', function factory(injectables) {
6166 * var directiveDefinitionObject = {
6167 * priority: 0,
6168 * template: '<div></div>', // or // function(tElement, tAttrs) { ... },
6169 * // or
6170 * // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
6171 * transclude: false,
6172 * restrict: 'A',
6173 * templateNamespace: 'html',
6174 * scope: false,
6175 * controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
6176 * controllerAs: 'stringIdentifier',
6177 * bindToController: false,
6178 * require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
6179 * compile: function compile(tElement, tAttrs, transclude) {
6180 * return {
6181 * pre: function preLink(scope, iElement, iAttrs, controller) { ... },
6182 * post: function postLink(scope, iElement, iAttrs, controller) { ... }
6183 * }
6184 * // or
6185 * // return function postLink( ... ) { ... }
6186 * },
6187 * // or
6188 * // link: {
6189 * // pre: function preLink(scope, iElement, iAttrs, controller) { ... },
6190 * // post: function postLink(scope, iElement, iAttrs, controller) { ... }
6191 * // }
6192 * // or
6193 * // link: function postLink( ... ) { ... }
6194 * };
6195 * return directiveDefinitionObject;
6196 * });
6197 * ```
6198 *
6199 * <div class="alert alert-warning">
6200 * **Note:** Any unspecified options will use the default value. You can see the default values below.
6201 * </div>
6202 *
6203 * Therefore the above can be simplified as:
6204 *
6205 * ```js
6206 * var myModule = angular.module(...);
6207 *
6208 * myModule.directive('directiveName', function factory(injectables) {
6209 * var directiveDefinitionObject = {
6210 * link: function postLink(scope, iElement, iAttrs) { ... }
6211 * };
6212 * return directiveDefinitionObject;
6213 * // or
6214 * // return function postLink(scope, iElement, iAttrs) { ... }
6215 * });
6216 * ```
6217 *
6218 *
6219 *
6220 * ### Directive Definition Object
6221 *
6222 * The directive definition object provides instructions to the {@link ng.$compile
6223 * compiler}. The attributes are:
6224 *
6225 * #### `multiElement`
6226 * When this property is set to true, the HTML compiler will collect DOM nodes between
6227 * nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
6228 * together as the directive elements. It is recommended that this feature be used on directives
6229 * which are not strictly behavioural (such as {@link ngClick}), and which
6230 * do not manipulate or replace child nodes (such as {@link ngInclude}).
6231 *
6232 * #### `priority`
6233 * When there are multiple directives defined on a single DOM element, sometimes it
6234 * is necessary to specify the order in which the directives are applied. The `priority` is used
6235 * to sort the directives before their `compile` functions get called. Priority is defined as a
6236 * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
6237 * are also run in priority order, but post-link functions are run in reverse order. The order
6238 * of directives with the same priority is undefined. The default priority is `0`.
6239 *
6240 * #### `terminal`
6241 * If set to true then the current `priority` will be the last set of directives
6242 * which will execute (any directives at the current priority will still execute
6243 * as the order of execution on same `priority` is undefined). Note that expressions
6244 * and other directives used in the directive's template will also be excluded from execution.
6245 *
6246 * #### `scope`
6247 * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
6248 * same element request a new scope, only one new scope is created. The new scope rule does not
6249 * apply for the root of the template since the root of the template always gets a new scope.
6250 *
6251 * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
6252 * normal scope in that it does not prototypically inherit from the parent scope. This is useful
6253 * when creating reusable components, which should not accidentally read or modify data in the
6254 * parent scope.
6255 *
6256 * The 'isolate' scope takes an object hash which defines a set of local scope properties
6257 * derived from the parent scope. These local properties are useful for aliasing values for
6258 * templates. Locals definition is a hash of local scope property to its source:
6259 *
6260 * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
6261 * always a string since DOM attributes are strings. If no `attr` name is specified then the
6262 * attribute name is assumed to be the same as the local name.
6263 * Given `<widget my-attr="hello {{name}}">` and widget definition
6264 * of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
6265 * the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
6266 * `localName` property on the widget scope. The `name` is read from the parent scope (not
6267 * component scope).
6268 *
6269 * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
6270 * parent scope property of name defined via the value of the `attr` attribute. If no `attr`
6271 * name is specified then the attribute name is assumed to be the same as the local name.
6272 * Given `<widget my-attr="parentModel">` and widget definition of
6273 * `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
6274 * value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
6275 * in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
6276 * scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
6277 * can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional. If
6278 * you want to shallow watch for changes (i.e. $watchCollection instead of $watch) you can use
6279 * `=*` or `=*attr` (`=*?` or `=*?attr` if the property is optional).
6280 *
6281 * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
6282 * If no `attr` name is specified then the attribute name is assumed to be the same as the
6283 * local name. Given `<widget my-attr="count = count + value">` and widget definition of
6284 * `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
6285 * a function wrapper for the `count = count + value` expression. Often it's desirable to
6286 * pass data from the isolated scope via an expression to the parent scope, this can be
6287 * done by passing a map of local variable names and values into the expression wrapper fn.
6288 * For example, if the expression is `increment(amount)` then we can specify the amount value
6289 * by calling the `localFn` as `localFn({amount: 22})`.
6290 *
6291 *
6292 * #### `bindToController`
6293 * When an isolate scope is used for a component (see above), and `controllerAs` is used, `bindToController: true` will
6294 * allow a component to have its properties bound to the controller, rather than to scope. When the controller
6295 * is instantiated, the initial values of the isolate scope bindings are already available.
6296 *
6297 * #### `controller`
6298 * Controller constructor function. The controller is instantiated before the
6299 * pre-linking phase and it is shared with other directives (see
6300 * `require` attribute). This allows the directives to communicate with each other and augment
6301 * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
6302 *
6303 * * `$scope` - Current scope associated with the element
6304 * * `$element` - Current element
6305 * * `$attrs` - Current attributes object for the element
6306 * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
6307 * `function([scope], cloneLinkingFn, futureParentElement)`.
6308 * * `scope`: optional argument to override the scope.
6309 * * `cloneLinkingFn`: optional argument to create clones of the original transcluded content.
6310 * * `futureParentElement`:
6311 * * defines the parent to which the `cloneLinkingFn` will add the cloned elements.
6312 * * default: `$element.parent()` resp. `$element` for `transclude:'element'` resp. `transclude:true`.
6313 * * only needed for transcludes that are allowed to contain non html elements (e.g. SVG elements)
6314 * and when the `cloneLinkinFn` is passed,
6315 * as those elements need to created and cloned in a special way when they are defined outside their
6316 * usual containers (e.g. like `<svg>`).
6317 * * See also the `directive.templateNamespace` property.
6318 *
6319 *
6320 * #### `require`
6321 * Require another directive and inject its controller as the fourth argument to the linking function. The
6322 * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
6323 * injected argument will be an array in corresponding order. If no such directive can be
6324 * found, or if the directive does not have a controller, then an error is raised (unless no link function
6325 * is specified, in which case error checking is skipped). The name can be prefixed with:
6326 *
6327 * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
6328 * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
6329 * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found.
6330 * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found.
6331 * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass
6332 * `null` to the `link` fn if not found.
6333 * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass
6334 * `null` to the `link` fn if not found.
6335 *
6336 *
6337 * #### `controllerAs`
6338 * Identifier name for a reference to the controller in the directive's scope.
6339 * This allows the controller to be referenced from the directive template. The directive
6340 * needs to define a scope for this configuration to be used. Useful in the case when
6341 * directive is used as component.
6342 *
6343 *
6344 * #### `restrict`
6345 * String of subset of `EACM` which restricts the directive to a specific directive
6346 * declaration style. If omitted, the defaults (elements and attributes) are used.
6347 *
6348 * * `E` - Element name (default): `<my-directive></my-directive>`
6349 * * `A` - Attribute (default): `<div my-directive="exp"></div>`
6350 * * `C` - Class: `<div class="my-directive: exp;"></div>`
6351 * * `M` - Comment: `<!-- directive: my-directive exp -->`
6352 *
6353 *
6354 * #### `templateNamespace`
6355 * String representing the document type used by the markup in the template.
6356 * AngularJS needs this information as those elements need to be created and cloned
6357 * in a special way when they are defined outside their usual containers like `<svg>` and `<math>`.
6358 *
6359 * * `html` - All root nodes in the template are HTML. Root nodes may also be
6360 * top-level elements such as `<svg>` or `<math>`.
6361 * * `svg` - The root nodes in the template are SVG elements (excluding `<math>`).
6362 * * `math` - The root nodes in the template are MathML elements (excluding `<svg>`).
6363 *
6364 * If no `templateNamespace` is specified, then the namespace is considered to be `html`.
6365 *
6366 * #### `template`
6367 * HTML markup that may:
6368 * * Replace the contents of the directive's element (default).
6369 * * Replace the directive's element itself (if `replace` is true - DEPRECATED).
6370 * * Wrap the contents of the directive's element (if `transclude` is true).
6371 *
6372 * Value may be:
6373 *
6374 * * A string. For example `<div red-on-hover>{{delete_str}}</div>`.
6375 * * A function which takes two arguments `tElement` and `tAttrs` (described in the `compile`
6376 * function api below) and returns a string value.
6377 *
6378 *
6379 * #### `templateUrl`
6380 * This is similar to `template` but the template is loaded from the specified URL, asynchronously.
6381 *
6382 * Because template loading is asynchronous the compiler will suspend compilation of directives on that element
6383 * for later when the template has been resolved. In the meantime it will continue to compile and link
6384 * sibling and parent elements as though this element had not contained any directives.
6385 *
6386 * The compiler does not suspend the entire compilation to wait for templates to be loaded because this
6387 * would result in the whole app "stalling" until all templates are loaded asynchronously - even in the
6388 * case when only one deeply nested directive has `templateUrl`.
6389 *
6390 * Template loading is asynchronous even if the template has been preloaded into the {@link $templateCache}
6391 *
6392 * You can specify `templateUrl` as a string representing the URL or as a function which takes two
6393 * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
6394 * a string value representing the url. In either case, the template URL is passed through {@link
6395 * $sce#getTrustedResourceUrl $sce.getTrustedResourceUrl}.
6396 *
6397 *
6398 * #### `replace` ([*DEPRECATED*!], will be removed in next major release - i.e. v2.0)
6399 * specify what the template should replace. Defaults to `false`.
6400 *
6401 * * `true` - the template will replace the directive's element.
6402 * * `false` - the template will replace the contents of the directive's element.
6403 *
6404 * The replacement process migrates all of the attributes / classes from the old element to the new
6405 * one. See the {@link guide/directive#template-expanding-directive
6406 * Directives Guide} for an example.
6407 *
6408 * There are very few scenarios where element replacement is required for the application function,
6409 * the main one being reusable custom components that are used within SVG contexts
6410 * (because SVG doesn't work with custom elements in the DOM tree).
6411 *
6412 * #### `transclude`
6413 * Extract the contents of the element where the directive appears and make it available to the directive.
6414 * The contents are compiled and provided to the directive as a **transclusion function**. See the
6415 * {@link $compile#transclusion Transclusion} section below.
6416 *
6417 * There are two kinds of transclusion depending upon whether you want to transclude just the contents of the
6418 * directive's element or the entire element:
6419 *
6420 * * `true` - transclude the content (i.e. the child nodes) of the directive's element.
6421 * * `'element'` - transclude the whole of the directive's element including any directives on this
6422 * element that defined at a lower priority than this directive. When used, the `template`
6423 * property is ignored.
6424 *
6425 *
6426 * #### `compile`
6427 *
6428 * ```js
6429 * function compile(tElement, tAttrs, transclude) { ... }
6430 * ```
6431 *
6432 * The compile function deals with transforming the template DOM. Since most directives do not do
6433 * template transformation, it is not used often. The compile function takes the following arguments:
6434 *
6435 * * `tElement` - template element - The element where the directive has been declared. It is
6436 * safe to do template transformation on the element and child elements only.
6437 *
6438 * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
6439 * between all directive compile functions.
6440 *
6441 * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
6442 *
6443 * <div class="alert alert-warning">
6444 * **Note:** The template instance and the link instance may be different objects if the template has
6445 * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
6446 * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
6447 * should be done in a linking function rather than in a compile function.
6448 * </div>
6449
6450 * <div class="alert alert-warning">
6451 * **Note:** The compile function cannot handle directives that recursively use themselves in their
6452 * own templates or compile functions. Compiling these directives results in an infinite loop and a
6453 * stack overflow errors.
6454 *
6455 * This can be avoided by manually using $compile in the postLink function to imperatively compile
6456 * a directive's template instead of relying on automatic template compilation via `template` or
6457 * `templateUrl` declaration or manual compilation inside the compile function.
6458 * </div>
6459 *
6460 * <div class="alert alert-danger">
6461 * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
6462 * e.g. does not know about the right outer scope. Please use the transclude function that is passed
6463 * to the link function instead.
6464 * </div>
6465
6466 * A compile function can have a return value which can be either a function or an object.
6467 *
6468 * * returning a (post-link) function - is equivalent to registering the linking function via the
6469 * `link` property of the config object when the compile function is empty.
6470 *
6471 * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
6472 * control when a linking function should be called during the linking phase. See info about
6473 * pre-linking and post-linking functions below.
6474 *
6475 *
6476 * #### `link`
6477 * This property is used only if the `compile` property is not defined.
6478 *
6479 * ```js
6480 * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
6481 * ```
6482 *
6483 * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
6484 * executed after the template has been cloned. This is where most of the directive logic will be
6485 * put.
6486 *
6487 * * `scope` - {@link ng.$rootScope.Scope Scope} - The scope to be used by the
6488 * directive for registering {@link ng.$rootScope.Scope#$watch watches}.
6489 *
6490 * * `iElement` - instance element - The element where the directive is to be used. It is safe to
6491 * manipulate the children of the element only in `postLink` function since the children have
6492 * already been linked.
6493 *
6494 * * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
6495 * between all directive linking functions.
6496 *
6497 * * `controller` - the directive's required controller instance(s) - Instances are shared
6498 * among all directives, which allows the directives to use the controllers as a communication
6499 * channel. The exact value depends on the directive's `require` property:
6500 * * no controller(s) required: the directive's own controller, or `undefined` if it doesn't have one
6501 * * `string`: the controller instance
6502 * * `array`: array of controller instances
6503 *
6504 * If a required controller cannot be found, and it is optional, the instance is `null`,
6505 * otherwise the {@link error:$compile:ctreq Missing Required Controller} error is thrown.
6506 *
6507 * Note that you can also require the directive's own controller - it will be made available like
6508 * like any other controller.
6509 *
6510 * * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
6511 * This is the same as the `$transclude`
6512 * parameter of directive controllers, see there for details.
6513 * `function([scope], cloneLinkingFn, futureParentElement)`.
6514 *
6515 * #### Pre-linking function
6516 *
6517 * Executed before the child elements are linked. Not safe to do DOM transformation since the
6518 * compiler linking function will fail to locate the correct elements for linking.
6519 *
6520 * #### Post-linking function
6521 *
6522 * Executed after the child elements are linked.
6523 *
6524 * Note that child elements that contain `templateUrl` directives will not have been compiled
6525 * and linked since they are waiting for their template to load asynchronously and their own
6526 * compilation and linking has been suspended until that occurs.
6527 *
6528 * It is safe to do DOM transformation in the post-linking function on elements that are not waiting
6529 * for their async templates to be resolved.
6530 *
6531 *
6532 * ### Transclusion
6533 *
6534 * Transclusion is the process of extracting a collection of DOM element from one part of the DOM and
6535 * copying them to another part of the DOM, while maintaining their connection to the original AngularJS
6536 * scope from where they were taken.
6537 *
6538 * Transclusion is used (often with {@link ngTransclude}) to insert the
6539 * original contents of a directive's element into a specified place in the template of the directive.
6540 * The benefit of transclusion, over simply moving the DOM elements manually, is that the transcluded
6541 * content has access to the properties on the scope from which it was taken, even if the directive
6542 * has isolated scope.
6543 * See the {@link guide/directive#creating-a-directive-that-wraps-other-elements Directives Guide}.
6544 *
6545 * This makes it possible for the widget to have private state for its template, while the transcluded
6546 * content has access to its originating scope.
6547 *
6548 * <div class="alert alert-warning">
6549 * **Note:** When testing an element transclude directive you must not place the directive at the root of the
6550 * DOM fragment that is being compiled. See {@link guide/unit-testing#testing-transclusion-directives
6551 * Testing Transclusion Directives}.
6552 * </div>
6553 *
6554 * #### Transclusion Functions
6555 *
6556 * When a directive requests transclusion, the compiler extracts its contents and provides a **transclusion
6557 * function** to the directive's `link` function and `controller`. This transclusion function is a special
6558 * **linking function** that will return the compiled contents linked to a new transclusion scope.
6559 *
6560 * <div class="alert alert-info">
6561 * If you are just using {@link ngTransclude} then you don't need to worry about this function, since
6562 * ngTransclude will deal with it for us.
6563 * </div>
6564 *
6565 * If you want to manually control the insertion and removal of the transcluded content in your directive
6566 * then you must use this transclude function. When you call a transclude function it returns a a jqLite/JQuery
6567 * object that contains the compiled DOM, which is linked to the correct transclusion scope.
6568 *
6569 * When you call a transclusion function you can pass in a **clone attach function**. This function accepts
6570 * two parameters, `function(clone, scope) { ... }`, where the `clone` is a fresh compiled copy of your transcluded
6571 * content and the `scope` is the newly created transclusion scope, to which the clone is bound.
6572 *
6573 * <div class="alert alert-info">
6574 * **Best Practice**: Always provide a `cloneFn` (clone attach function) when you call a translude function
6575 * since you then get a fresh clone of the original DOM and also have access to the new transclusion scope.
6576 * </div>
6577 *
6578 * It is normal practice to attach your transcluded content (`clone`) to the DOM inside your **clone
6579 * attach function**:
6580 *
6581 * ```js
6582 * var transcludedContent, transclusionScope;
6583 *
6584 * $transclude(function(clone, scope) {
6585 * element.append(clone);
6586 * transcludedContent = clone;
6587 * transclusionScope = scope;
6588 * });
6589 * ```
6590 *
6591 * Later, if you want to remove the transcluded content from your DOM then you should also destroy the
6592 * associated transclusion scope:
6593 *
6594 * ```js
6595 * transcludedContent.remove();
6596 * transclusionScope.$destroy();
6597 * ```
6598 *
6599 * <div class="alert alert-info">
6600 * **Best Practice**: if you intend to add and remove transcluded content manually in your directive
6601 * (by calling the transclude function to get the DOM and calling `element.remove()` to remove it),
6602 * then you are also responsible for calling `$destroy` on the transclusion scope.
6603 * </div>
6604 *
6605 * The built-in DOM manipulation directives, such as {@link ngIf}, {@link ngSwitch} and {@link ngRepeat}
6606 * automatically destroy their transluded clones as necessary so you do not need to worry about this if
6607 * you are simply using {@link ngTransclude} to inject the transclusion into your directive.
6608 *
6609 *
6610 * #### Transclusion Scopes
6611 *
6612 * When you call a transclude function it returns a DOM fragment that is pre-bound to a **transclusion
6613 * scope**. This scope is special, in that it is a child of the directive's scope (and so gets destroyed
6614 * when the directive's scope gets destroyed) but it inherits the properties of the scope from which it
6615 * was taken.
6616 *
6617 * For example consider a directive that uses transclusion and isolated scope. The DOM hierarchy might look
6618 * like this:
6619 *
6620 * ```html
6621 * <div ng-app>
6622 * <div isolate>
6623 * <div transclusion>
6624 * </div>
6625 * </div>
6626 * </div>
6627 * ```
6628 *
6629 * The `$parent` scope hierarchy will look like this:
6630 *
6631 * ```
6632 * - $rootScope
6633 * - isolate
6634 * - transclusion
6635 * ```
6636 *
6637 * but the scopes will inherit prototypically from different scopes to their `$parent`.
6638 *
6639 * ```
6640 * - $rootScope
6641 * - transclusion
6642 * - isolate
6643 * ```
6644 *
6645 *
6646 * ### Attributes
6647 *
6648 * The {@link ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
6649 * `link()` or `compile()` functions. It has a variety of uses.
6650 *
6651 * accessing *Normalized attribute names:*
6652 * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
6653 * the attributes object allows for normalized access to
6654 * the attributes.
6655 *
6656 * * *Directive inter-communication:* All directives share the same instance of the attributes
6657 * object which allows the directives to use the attributes object as inter directive
6658 * communication.
6659 *
6660 * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
6661 * allowing other directives to read the interpolated value.
6662 *
6663 * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
6664 * that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
6665 * the only way to easily get the actual value because during the linking phase the interpolation
6666 * hasn't been evaluated yet and so the value is at this time set to `undefined`.
6667 *
6668 * ```js
6669 * function linkingFn(scope, elm, attrs, ctrl) {
6670 * // get the attribute value
6671 * console.log(attrs.ngModel);
6672 *
6673 * // change the attribute
6674 * attrs.$set('ngModel', 'new value');
6675 *
6676 * // observe changes to interpolated attribute
6677 * attrs.$observe('ngModel', function(value) {
6678 * console.log('ngModel has changed value to ' + value);
6679 * });
6680 * }
6681 * ```
6682 *
6683 * ## Example
6684 *
6685 * <div class="alert alert-warning">
6686 * **Note**: Typically directives are registered with `module.directive`. The example below is
6687 * to illustrate how `$compile` works.
6688 * </div>
6689 *
6690 <example module="compileExample">
6691 <file name="index.html">
6692 <script>
6693 angular.module('compileExample', [], function($compileProvider) {
6694 // configure new 'compile' directive by passing a directive
6695 // factory function. The factory function injects the '$compile'
6696 $compileProvider.directive('compile', function($compile) {
6697 // directive factory creates a link function
6698 return function(scope, element, attrs) {
6699 scope.$watch(
6700 function(scope) {
6701 // watch the 'compile' expression for changes
6702 return scope.$eval(attrs.compile);
6703 },
6704 function(value) {
6705 // when the 'compile' expression changes
6706 // assign it into the current DOM
6707 element.html(value);
6708
6709 // compile the new DOM and link it to the current
6710 // scope.
6711 // NOTE: we only compile .childNodes so that
6712 // we don't get into infinite loop compiling ourselves
6713 $compile(element.contents())(scope);
6714 }
6715 );
6716 };
6717 });
6718 })
6719 .controller('GreeterController', ['$scope', function($scope) {
6720 $scope.name = 'Angular';
6721 $scope.html = 'Hello {{name}}';
6722 }]);
6723 </script>
6724 <div ng-controller="GreeterController">
6725 <input ng-model="name"> <br/>
6726 <textarea ng-model="html"></textarea> <br/>
6727 <div compile="html"></div>
6728 </div>
6729 </file>
6730 <file name="protractor.js" type="protractor">
6731 it('should auto compile', function() {
6732 var textarea = $('textarea');
6733 var output = $('div[compile]');
6734 // The initial state reads 'Hello Angular'.
6735 expect(output.getText()).toBe('Hello Angular');
6736 textarea.clear();
6737 textarea.sendKeys('{{name}}!');
6738 expect(output.getText()).toBe('Angular!');
6739 });
6740 </file>
6741 </example>
6742
6743 *
6744 *
6745 * @param {string|DOMElement} element Element or HTML string to compile into a template function.
6746 * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED.
6747 *
6748 * <div class="alert alert-danger">
6749 * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it
6750 * e.g. will not use the right outer scope. Please pass the transclude function as a
6751 * `parentBoundTranscludeFn` to the link function instead.
6752 * </div>
6753 *
6754 * @param {number} maxPriority only apply directives lower than given priority (Only effects the
6755 * root element(s), not their children)
6756 * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template
6757 * (a DOM element/tree) to a scope. Where:
6758 *
6759 * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
6760 * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
6761 * `template` and call the `cloneAttachFn` function allowing the caller to attach the
6762 * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is
6763 * called as: <br/> `cloneAttachFn(clonedElement, scope)` where:
6764 *
6765 * * `clonedElement` - is a clone of the original `element` passed into the compiler.
6766 * * `scope` - is the current scope with which the linking function is working with.
6767 *
6768 * * `options` - An optional object hash with linking options. If `options` is provided, then the following
6769 * keys may be used to control linking behavior:
6770 *
6771 * * `parentBoundTranscludeFn` - the transclude function made available to
6772 * directives; if given, it will be passed through to the link functions of
6773 * directives found in `element` during compilation.
6774 * * `transcludeControllers` - an object hash with keys that map controller names
6775 * to controller instances; if given, it will make the controllers
6776 * available to directives.
6777 * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add
6778 * the cloned elements; only needed for transcludes that are allowed to contain non html
6779 * elements (e.g. SVG elements). See also the directive.controller property.
6780 *
6781 * Calling the linking function returns the element of the template. It is either the original
6782 * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
6783 *
6784 * After linking the view is not updated until after a call to $digest which typically is done by
6785 * Angular automatically.
6786 *
6787 * If you need access to the bound view, there are two ways to do it:
6788 *
6789 * - If you are not asking the linking function to clone the template, create the DOM element(s)
6790 * before you send them to the compiler and keep this reference around.
6791 * ```js
6792 * var element = $compile('<p>{{total}}</p>')(scope);
6793 * ```
6794 *
6795 * - if on the other hand, you need the element to be cloned, the view reference from the original
6796 * example would not point to the clone, but rather to the original template that was cloned. In
6797 * this case, you can access the clone via the cloneAttachFn:
6798 * ```js
6799 * var templateElement = angular.element('<p>{{total}}</p>'),
6800 * scope = ....;
6801 *
6802 * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
6803 * //attach the clone to DOM document at the right place
6804 * });
6805 *
6806 * //now we have reference to the cloned DOM via `clonedElement`
6807 * ```
6808 *
6809 *
6810 * For information on how the compiler works, see the
6811 * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
6812 */
6813
6814 var $compileMinErr = minErr('$compile');
6815
6816 /**
6817 * @ngdoc provider
6818 * @name $compileProvider
6819 *
6820 * @description
6821 */
6822 $CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
6823 function $CompileProvider($provide, $$sanitizeUriProvider) {
6824 var hasDirectives = {},
6825 Suffix = 'Directive',
6826 COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\w\-]+)\s+(.*)$/,
6827 CLASS_DIRECTIVE_REGEXP = /(([\w\-]+)(?:\:([^;]+))?;?)/,
6828 ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'),
6829 REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
6830
6831 // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
6832 // The assumption is that future DOM event attribute names will begin with
6833 // 'on' and be composed of only English letters.
6834 var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
6835
6836 function parseIsolateBindings(scope, directiveName, isController) {
6837 var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;
6838
6839 var bindings = {};
6840
6841 forEach(scope, function(definition, scopeName) {
6842 var match = definition.match(LOCAL_REGEXP);
6843
6844 if (!match) {
6845 throw $compileMinErr('iscp',
6846 "Invalid {3} for directive '{0}'." +
6847 " Definition: {... {1}: '{2}' ...}",
6848 directiveName, scopeName, definition,
6849 (isController ? "controller bindings definition" :
6850 "isolate scope definition"));
6851 }
6852
6853 bindings[scopeName] = {
6854 mode: match[1][0],
6855 collection: match[2] === '*',
6856 optional: match[3] === '?',
6857 attrName: match[4] || scopeName
6858 };
6859 });
6860
6861 return bindings;
6862 }
6863
6864 function parseDirectiveBindings(directive, directiveName) {
6865 var bindings = {
6866 isolateScope: null,
6867 bindToController: null
6868 };
6869 if (isObject(directive.scope)) {
6870 if (directive.bindToController === true) {
6871 bindings.bindToController = parseIsolateBindings(directive.scope,
6872 directiveName, true);
6873 bindings.isolateScope = {};
6874 } else {
6875 bindings.isolateScope = parseIsolateBindings(directive.scope,
6876 directiveName, false);
6877 }
6878 }
6879 if (isObject(directive.bindToController)) {
6880 bindings.bindToController =
6881 parseIsolateBindings(directive.bindToController, directiveName, true);
6882 }
6883 if (isObject(bindings.bindToController)) {
6884 var controller = directive.controller;
6885 var controllerAs = directive.controllerAs;
6886 if (!controller) {
6887 // There is no controller, there may or may not be a controllerAs property
6888 throw $compileMinErr('noctrl',
6889 "Cannot bind to controller without directive '{0}'s controller.",
6890 directiveName);
6891 } else if (!identifierForController(controller, controllerAs)) {
6892 // There is a controller, but no identifier or controllerAs property
6893 throw $compileMinErr('noident',
6894 "Cannot bind to controller without identifier for directive '{0}'.",
6895 directiveName);
6896 }
6897 }
6898 return bindings;
6899 }
6900
6901 function assertValidDirectiveName(name) {
6902 var letter = name.charAt(0);
6903 if (!letter || letter !== lowercase(letter)) {
6904 throw $compileMinErr('baddir', "Directive name '{0}' is invalid. The first character must be a lowercase letter", name);
6905 }
6906 if (name !== name.trim()) {
6907 throw $compileMinErr('baddir',
6908 "Directive name '{0}' is invalid. The name should not contain leading or trailing whitespaces",
6909 name);
6910 }
6911 }
6912
6913 /**
6914 * @ngdoc method
6915 * @name $compileProvider#directive
6916 * @kind function
6917 *
6918 * @description
6919 * Register a new directive with the compiler.
6920 *
6921 * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
6922 * will match as <code>ng-bind</code>), or an object map of directives where the keys are the
6923 * names and the values are the factories.
6924 * @param {Function|Array} directiveFactory An injectable directive factory function. See
6925 * {@link guide/directive} for more info.
6926 * @returns {ng.$compileProvider} Self for chaining.
6927 */
6928 this.directive = function registerDirective(name, directiveFactory) {
6929 assertNotHasOwnProperty(name, 'directive');
6930 if (isString(name)) {
6931 assertValidDirectiveName(name);
6932 assertArg(directiveFactory, 'directiveFactory');
6933 if (!hasDirectives.hasOwnProperty(name)) {
6934 hasDirectives[name] = [];
6935 $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
6936 function($injector, $exceptionHandler) {
6937 var directives = [];
6938 forEach(hasDirectives[name], function(directiveFactory, index) {
6939 try {
6940 var directive = $injector.invoke(directiveFactory);
6941 if (isFunction(directive)) {
6942 directive = { compile: valueFn(directive) };
6943 } else if (!directive.compile && directive.link) {
6944 directive.compile = valueFn(directive.link);
6945 }
6946 directive.priority = directive.priority || 0;
6947 directive.index = index;
6948 directive.name = directive.name || name;
6949 directive.require = directive.require || (directive.controller && directive.name);
6950 directive.restrict = directive.restrict || 'EA';
6951 var bindings = directive.$$bindings =
6952 parseDirectiveBindings(directive, directive.name);
6953 if (isObject(bindings.isolateScope)) {
6954 directive.$$isolateBindings = bindings.isolateScope;
6955 }
6956 directive.$$moduleName = directiveFactory.$$moduleName;
6957 directives.push(directive);
6958 } catch (e) {
6959 $exceptionHandler(e);
6960 }
6961 });
6962 return directives;
6963 }]);
6964 }
6965 hasDirectives[name].push(directiveFactory);
6966 } else {
6967 forEach(name, reverseParams(registerDirective));
6968 }
6969 return this;
6970 };
6971
6972
6973 /**
6974 * @ngdoc method
6975 * @name $compileProvider#aHrefSanitizationWhitelist
6976 * @kind function
6977 *
6978 * @description
6979 * Retrieves or overrides the default regular expression that is used for whitelisting of safe
6980 * urls during a[href] sanitization.
6981 *
6982 * The sanitization is a security measure aimed at preventing XSS attacks via html links.
6983 *
6984 * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
6985 * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
6986 * regular expression. If a match is found, the original url is written into the dom. Otherwise,
6987 * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
6988 *
6989 * @param {RegExp=} regexp New regexp to whitelist urls with.
6990 * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
6991 * chaining otherwise.
6992 */
6993 this.aHrefSanitizationWhitelist = function(regexp) {
6994 if (isDefined(regexp)) {
6995 $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
6996 return this;
6997 } else {
6998 return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
6999 }
7000 };
7001
7002
7003 /**
7004 * @ngdoc method
7005 * @name $compileProvider#imgSrcSanitizationWhitelist
7006 * @kind function
7007 *
7008 * @description
7009 * Retrieves or overrides the default regular expression that is used for whitelisting of safe
7010 * urls during img[src] sanitization.
7011 *
7012 * The sanitization is a security measure aimed at prevent XSS attacks via html links.
7013 *
7014 * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
7015 * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
7016 * regular expression. If a match is found, the original url is written into the dom. Otherwise,
7017 * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
7018 *
7019 * @param {RegExp=} regexp New regexp to whitelist urls with.
7020 * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
7021 * chaining otherwise.
7022 */
7023 this.imgSrcSanitizationWhitelist = function(regexp) {
7024 if (isDefined(regexp)) {
7025 $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
7026 return this;
7027 } else {
7028 return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
7029 }
7030 };
7031
7032 /**
7033 * @ngdoc method
7034 * @name $compileProvider#debugInfoEnabled
7035 *
7036 * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the
7037 * current debugInfoEnabled state
7038 * @returns {*} current value if used as getter or itself (chaining) if used as setter
7039 *
7040 * @kind function
7041 *
7042 * @description
7043 * Call this method to enable/disable various debug runtime information in the compiler such as adding
7044 * binding information and a reference to the current scope on to DOM elements.
7045 * If enabled, the compiler will add the following to DOM elements that have been bound to the scope
7046 * * `ng-binding` CSS class
7047 * * `$binding` data property containing an array of the binding expressions
7048 *
7049 * You may want to disable this in production for a significant performance boost. See
7050 * {@link guide/production#disabling-debug-data Disabling Debug Data} for more.
7051 *
7052 * The default value is true.
7053 */
7054 var debugInfoEnabled = true;
7055 this.debugInfoEnabled = function(enabled) {
7056 if (isDefined(enabled)) {
7057 debugInfoEnabled = enabled;
7058 return this;
7059 }
7060 return debugInfoEnabled;
7061 };
7062
7063 this.$get = [
7064 '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse',
7065 '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
7066 function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse,
7067 $controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
7068
7069 var Attributes = function(element, attributesToCopy) {
7070 if (attributesToCopy) {
7071 var keys = Object.keys(attributesToCopy);
7072 var i, l, key;
7073
7074 for (i = 0, l = keys.length; i < l; i++) {
7075 key = keys[i];
7076 this[key] = attributesToCopy[key];
7077 }
7078 } else {
7079 this.$attr = {};
7080 }
7081
7082 this.$$element = element;
7083 };
7084
7085 Attributes.prototype = {
7086 /**
7087 * @ngdoc method
7088 * @name $compile.directive.Attributes#$normalize
7089 * @kind function
7090 *
7091 * @description
7092 * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or
7093 * `data-`) to its normalized, camelCase form.
7094 *
7095 * Also there is special case for Moz prefix starting with upper case letter.
7096 *
7097 * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives}
7098 *
7099 * @param {string} name Name to normalize
7100 */
7101 $normalize: directiveNormalize,
7102
7103
7104 /**
7105 * @ngdoc method
7106 * @name $compile.directive.Attributes#$addClass
7107 * @kind function
7108 *
7109 * @description
7110 * Adds the CSS class value specified by the classVal parameter to the element. If animations
7111 * are enabled then an animation will be triggered for the class addition.
7112 *
7113 * @param {string} classVal The className value that will be added to the element
7114 */
7115 $addClass: function(classVal) {
7116 if (classVal && classVal.length > 0) {
7117 $animate.addClass(this.$$element, classVal);
7118 }
7119 },
7120
7121 /**
7122 * @ngdoc method
7123 * @name $compile.directive.Attributes#$removeClass
7124 * @kind function
7125 *
7126 * @description
7127 * Removes the CSS class value specified by the classVal parameter from the element. If
7128 * animations are enabled then an animation will be triggered for the class removal.
7129 *
7130 * @param {string} classVal The className value that will be removed from the element
7131 */
7132 $removeClass: function(classVal) {
7133 if (classVal && classVal.length > 0) {
7134 $animate.removeClass(this.$$element, classVal);
7135 }
7136 },
7137
7138 /**
7139 * @ngdoc method
7140 * @name $compile.directive.Attributes#$updateClass
7141 * @kind function
7142 *
7143 * @description
7144 * Adds and removes the appropriate CSS class values to the element based on the difference
7145 * between the new and old CSS class values (specified as newClasses and oldClasses).
7146 *
7147 * @param {string} newClasses The current CSS className value
7148 * @param {string} oldClasses The former CSS className value
7149 */
7150 $updateClass: function(newClasses, oldClasses) {
7151 var toAdd = tokenDifference(newClasses, oldClasses);
7152 if (toAdd && toAdd.length) {
7153 $animate.addClass(this.$$element, toAdd);
7154 }
7155
7156 var toRemove = tokenDifference(oldClasses, newClasses);
7157 if (toRemove && toRemove.length) {
7158 $animate.removeClass(this.$$element, toRemove);
7159 }
7160 },
7161
7162 /**
7163 * Set a normalized attribute on the element in a way such that all directives
7164 * can share the attribute. This function properly handles boolean attributes.
7165 * @param {string} key Normalized key. (ie ngAttribute)
7166 * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
7167 * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
7168 * Defaults to true.
7169 * @param {string=} attrName Optional none normalized name. Defaults to key.
7170 */
7171 $set: function(key, value, writeAttr, attrName) {
7172 // TODO: decide whether or not to throw an error if "class"
7173 //is set through this function since it may cause $updateClass to
7174 //become unstable.
7175
7176 var node = this.$$element[0],
7177 booleanKey = getBooleanAttrName(node, key),
7178 aliasedKey = getAliasedAttrName(node, key),
7179 observer = key,
7180 nodeName;
7181
7182 if (booleanKey) {
7183 this.$$element.prop(key, value);
7184 attrName = booleanKey;
7185 } else if (aliasedKey) {
7186 this[aliasedKey] = value;
7187 observer = aliasedKey;
7188 }
7189
7190 this[key] = value;
7191
7192 // translate normalized key to actual key
7193 if (attrName) {
7194 this.$attr[key] = attrName;
7195 } else {
7196 attrName = this.$attr[key];
7197 if (!attrName) {
7198 this.$attr[key] = attrName = snake_case(key, '-');
7199 }
7200 }
7201
7202 nodeName = nodeName_(this.$$element);
7203
7204 if ((nodeName === 'a' && key === 'href') ||
7205 (nodeName === 'img' && key === 'src')) {
7206 // sanitize a[href] and img[src] values
7207 this[key] = value = $$sanitizeUri(value, key === 'src');
7208 } else if (nodeName === 'img' && key === 'srcset') {
7209 // sanitize img[srcset] values
7210 var result = "";
7211
7212 // first check if there are spaces because it's not the same pattern
7213 var trimmedSrcset = trim(value);
7214 // ( 999x ,| 999w ,| ,|, )
7215 var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
7216 var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
7217
7218 // split srcset into tuple of uri and descriptor except for the last item
7219 var rawUris = trimmedSrcset.split(pattern);
7220
7221 // for each tuples
7222 var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
7223 for (var i = 0; i < nbrUrisWith2parts; i++) {
7224 var innerIdx = i * 2;
7225 // sanitize the uri
7226 result += $$sanitizeUri(trim(rawUris[innerIdx]), true);
7227 // add the descriptor
7228 result += (" " + trim(rawUris[innerIdx + 1]));
7229 }
7230
7231 // split the last item into uri and descriptor
7232 var lastTuple = trim(rawUris[i * 2]).split(/\s/);
7233
7234 // sanitize the last uri
7235 result += $$sanitizeUri(trim(lastTuple[0]), true);
7236
7237 // and add the last descriptor if any
7238 if (lastTuple.length === 2) {
7239 result += (" " + trim(lastTuple[1]));
7240 }
7241 this[key] = value = result;
7242 }
7243
7244 if (writeAttr !== false) {
7245 if (value === null || value === undefined) {
7246 this.$$element.removeAttr(attrName);
7247 } else {
7248 this.$$element.attr(attrName, value);
7249 }
7250 }
7251
7252 // fire observers
7253 var $$observers = this.$$observers;
7254 $$observers && forEach($$observers[observer], function(fn) {
7255 try {
7256 fn(value);
7257 } catch (e) {
7258 $exceptionHandler(e);
7259 }
7260 });
7261 },
7262
7263
7264 /**
7265 * @ngdoc method
7266 * @name $compile.directive.Attributes#$observe
7267 * @kind function
7268 *
7269 * @description
7270 * Observes an interpolated attribute.
7271 *
7272 * The observer function will be invoked once during the next `$digest` following
7273 * compilation. The observer is then invoked whenever the interpolated value
7274 * changes.
7275 *
7276 * @param {string} key Normalized key. (ie ngAttribute) .
7277 * @param {function(interpolatedValue)} fn Function that will be called whenever
7278 the interpolated value of the attribute changes.
7279 * See the {@link guide/directive#text-and-attribute-bindings Directives} guide for more info.
7280 * @returns {function()} Returns a deregistration function for this observer.
7281 */
7282 $observe: function(key, fn) {
7283 var attrs = this,
7284 $$observers = (attrs.$$observers || (attrs.$$observers = createMap())),
7285 listeners = ($$observers[key] || ($$observers[key] = []));
7286
7287 listeners.push(fn);
7288 $rootScope.$evalAsync(function() {
7289 if (!listeners.$$inter && attrs.hasOwnProperty(key)) {
7290 // no one registered attribute interpolation function, so lets call it manually
7291 fn(attrs[key]);
7292 }
7293 });
7294
7295 return function() {
7296 arrayRemove(listeners, fn);
7297 };
7298 }
7299 };
7300
7301
7302 function safeAddClass($element, className) {
7303 try {
7304 $element.addClass(className);
7305 } catch (e) {
7306 // ignore, since it means that we are trying to set class on
7307 // SVG element, where class name is read-only.
7308 }
7309 }
7310
7311
7312 var startSymbol = $interpolate.startSymbol(),
7313 endSymbol = $interpolate.endSymbol(),
7314 denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}')
7315 ? identity
7316 : function denormalizeTemplate(template) {
7317 return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
7318 },
7319 NG_ATTR_BINDING = /^ngAttr[A-Z]/;
7320
7321 compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) {
7322 var bindings = $element.data('$binding') || [];
7323
7324 if (isArray(binding)) {
7325 bindings = bindings.concat(binding);
7326 } else {
7327 bindings.push(binding);
7328 }
7329
7330 $element.data('$binding', bindings);
7331 } : noop;
7332
7333 compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) {
7334 safeAddClass($element, 'ng-binding');
7335 } : noop;
7336
7337 compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) {
7338 var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope';
7339 $element.data(dataName, scope);
7340 } : noop;
7341
7342 compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) {
7343 safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope');
7344 } : noop;
7345
7346 return compile;
7347
7348 //================================
7349
7350 function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
7351 previousCompileContext) {
7352 if (!($compileNodes instanceof jqLite)) {
7353 // jquery always rewraps, whereas we need to preserve the original selector so that we can
7354 // modify it.
7355 $compileNodes = jqLite($compileNodes);
7356 }
7357 // We can not compile top level text elements since text nodes can be merged and we will
7358 // not be able to attach scope data to them, so we will wrap them in <span>
7359 forEach($compileNodes, function(node, index) {
7360 if (node.nodeType == NODE_TYPE_TEXT && node.nodeValue.match(/\S+/) /* non-empty */ ) {
7361 $compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
7362 }
7363 });
7364 var compositeLinkFn =
7365 compileNodes($compileNodes, transcludeFn, $compileNodes,
7366 maxPriority, ignoreDirective, previousCompileContext);
7367 compile.$$addScopeClass($compileNodes);
7368 var namespace = null;
7369 return function publicLinkFn(scope, cloneConnectFn, options) {
7370 assertArg(scope, 'scope');
7371
7372 options = options || {};
7373 var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
7374 transcludeControllers = options.transcludeControllers,
7375 futureParentElement = options.futureParentElement;
7376
7377 // When `parentBoundTranscludeFn` is passed, it is a
7378 // `controllersBoundTransclude` function (it was previously passed
7379 // as `transclude` to directive.link) so we must unwrap it to get
7380 // its `boundTranscludeFn`
7381 if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) {
7382 parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude;
7383 }
7384
7385 if (!namespace) {
7386 namespace = detectNamespaceForChildElements(futureParentElement);
7387 }
7388 var $linkNode;
7389 if (namespace !== 'html') {
7390 // When using a directive with replace:true and templateUrl the $compileNodes
7391 // (or a child element inside of them)
7392 // might change, so we need to recreate the namespace adapted compileNodes
7393 // for call to the link function.
7394 // Note: This will already clone the nodes...
7395 $linkNode = jqLite(
7396 wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())
7397 );
7398 } else if (cloneConnectFn) {
7399 // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
7400 // and sometimes changes the structure of the DOM.
7401 $linkNode = JQLitePrototype.clone.call($compileNodes);
7402 } else {
7403 $linkNode = $compileNodes;
7404 }
7405
7406 if (transcludeControllers) {
7407 for (var controllerName in transcludeControllers) {
7408 $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance);
7409 }
7410 }
7411
7412 compile.$$addScopeInfo($linkNode, scope);
7413
7414 if (cloneConnectFn) cloneConnectFn($linkNode, scope);
7415 if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
7416 return $linkNode;
7417 };
7418 }
7419
7420 function detectNamespaceForChildElements(parentElement) {
7421 // TODO: Make this detect MathML as well...
7422 var node = parentElement && parentElement[0];
7423 if (!node) {
7424 return 'html';
7425 } else {
7426 return nodeName_(node) !== 'foreignobject' && node.toString().match(/SVG/) ? 'svg' : 'html';
7427 }
7428 }
7429
7430 /**
7431 * Compile function matches each node in nodeList against the directives. Once all directives
7432 * for a particular node are collected their compile functions are executed. The compile
7433 * functions return values - the linking functions - are combined into a composite linking
7434 * function, which is the a linking function for the node.
7435 *
7436 * @param {NodeList} nodeList an array of nodes or NodeList to compile
7437 * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
7438 * scope argument is auto-generated to the new child of the transcluded parent scope.
7439 * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
7440 * the rootElement must be set the jqLite collection of the compile root. This is
7441 * needed so that the jqLite collection items can be replaced with widgets.
7442 * @param {number=} maxPriority Max directive priority.
7443 * @returns {Function} A composite linking function of all of the matched directives or null.
7444 */
7445 function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
7446 previousCompileContext) {
7447 var linkFns = [],
7448 attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;
7449
7450 for (var i = 0; i < nodeList.length; i++) {
7451 attrs = new Attributes();
7452
7453 // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
7454 directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
7455 ignoreDirective);
7456
7457 nodeLinkFn = (directives.length)
7458 ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
7459 null, [], [], previousCompileContext)
7460 : null;
7461
7462 if (nodeLinkFn && nodeLinkFn.scope) {
7463 compile.$$addScopeClass(attrs.$$element);
7464 }
7465
7466 childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
7467 !(childNodes = nodeList[i].childNodes) ||
7468 !childNodes.length)
7469 ? null
7470 : compileNodes(childNodes,
7471 nodeLinkFn ? (
7472 (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement)
7473 && nodeLinkFn.transclude) : transcludeFn);
7474
7475 if (nodeLinkFn || childLinkFn) {
7476 linkFns.push(i, nodeLinkFn, childLinkFn);
7477 linkFnFound = true;
7478 nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
7479 }
7480
7481 //use the previous context only for the first element in the virtual group
7482 previousCompileContext = null;
7483 }
7484
7485 // return a linking function if we have found anything, null otherwise
7486 return linkFnFound ? compositeLinkFn : null;
7487
7488 function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
7489 var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;
7490 var stableNodeList;
7491
7492
7493 if (nodeLinkFnFound) {
7494 // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our
7495 // offsets don't get screwed up
7496 var nodeListLength = nodeList.length;
7497 stableNodeList = new Array(nodeListLength);
7498
7499 // create a sparse array by only copying the elements which have a linkFn
7500 for (i = 0; i < linkFns.length; i+=3) {
7501 idx = linkFns[i];
7502 stableNodeList[idx] = nodeList[idx];
7503 }
7504 } else {
7505 stableNodeList = nodeList;
7506 }
7507
7508 for (i = 0, ii = linkFns.length; i < ii;) {
7509 node = stableNodeList[linkFns[i++]];
7510 nodeLinkFn = linkFns[i++];
7511 childLinkFn = linkFns[i++];
7512
7513 if (nodeLinkFn) {
7514 if (nodeLinkFn.scope) {
7515 childScope = scope.$new();
7516 compile.$$addScopeInfo(jqLite(node), childScope);
7517 var destroyBindings = nodeLinkFn.$$destroyBindings;
7518 if (destroyBindings) {
7519 nodeLinkFn.$$destroyBindings = null;
7520 childScope.$on('$destroyed', destroyBindings);
7521 }
7522 } else {
7523 childScope = scope;
7524 }
7525
7526 if (nodeLinkFn.transcludeOnThisElement) {
7527 childBoundTranscludeFn = createBoundTranscludeFn(
7528 scope, nodeLinkFn.transclude, parentBoundTranscludeFn);
7529
7530 } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) {
7531 childBoundTranscludeFn = parentBoundTranscludeFn;
7532
7533 } else if (!parentBoundTranscludeFn && transcludeFn) {
7534 childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn);
7535
7536 } else {
7537 childBoundTranscludeFn = null;
7538 }
7539
7540 nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn,
7541 nodeLinkFn);
7542
7543 } else if (childLinkFn) {
7544 childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
7545 }
7546 }
7547 }
7548 }
7549
7550 function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
7551
7552 var boundTranscludeFn = function(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) {
7553
7554 if (!transcludedScope) {
7555 transcludedScope = scope.$new(false, containingScope);
7556 transcludedScope.$$transcluded = true;
7557 }
7558
7559 return transcludeFn(transcludedScope, cloneFn, {
7560 parentBoundTranscludeFn: previousBoundTranscludeFn,
7561 transcludeControllers: controllers,
7562 futureParentElement: futureParentElement
7563 });
7564 };
7565
7566 return boundTranscludeFn;
7567 }
7568
7569 /**
7570 * Looks for directives on the given node and adds them to the directive collection which is
7571 * sorted.
7572 *
7573 * @param node Node to search.
7574 * @param directives An array to which the directives are added to. This array is sorted before
7575 * the function returns.
7576 * @param attrs The shared attrs object which is used to populate the normalized attributes.
7577 * @param {number=} maxPriority Max directive priority.
7578 */
7579 function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
7580 var nodeType = node.nodeType,
7581 attrsMap = attrs.$attr,
7582 match,
7583 className;
7584
7585 switch (nodeType) {
7586 case NODE_TYPE_ELEMENT: /* Element */
7587 // use the node name: <directive>
7588 addDirective(directives,
7589 directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
7590
7591 // iterate over the attributes
7592 for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
7593 j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
7594 var attrStartName = false;
7595 var attrEndName = false;
7596
7597 attr = nAttrs[j];
7598 name = attr.name;
7599 value = trim(attr.value);
7600
7601 // support ngAttr attribute binding
7602 ngAttrName = directiveNormalize(name);
7603 if (isNgAttr = NG_ATTR_BINDING.test(ngAttrName)) {
7604 name = name.replace(PREFIX_REGEXP, '')
7605 .substr(8).replace(/_(.)/g, function(match, letter) {
7606 return letter.toUpperCase();
7607 });
7608 }
7609
7610 var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
7611 if (directiveIsMultiElement(directiveNName)) {
7612 if (ngAttrName === directiveNName + 'Start') {
7613 attrStartName = name;
7614 attrEndName = name.substr(0, name.length - 5) + 'end';
7615 name = name.substr(0, name.length - 6);
7616 }
7617 }
7618
7619 nName = directiveNormalize(name.toLowerCase());
7620 attrsMap[nName] = name;
7621 if (isNgAttr || !attrs.hasOwnProperty(nName)) {
7622 attrs[nName] = value;
7623 if (getBooleanAttrName(node, nName)) {
7624 attrs[nName] = true; // presence means true
7625 }
7626 }
7627 addAttrInterpolateDirective(node, directives, value, nName, isNgAttr);
7628 addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
7629 attrEndName);
7630 }
7631
7632 // use class as directive
7633 className = node.className;
7634 if (isObject(className)) {
7635 // Maybe SVGAnimatedString
7636 className = className.animVal;
7637 }
7638 if (isString(className) && className !== '') {
7639 while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
7640 nName = directiveNormalize(match[2]);
7641 if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
7642 attrs[nName] = trim(match[3]);
7643 }
7644 className = className.substr(match.index + match[0].length);
7645 }
7646 }
7647 break;
7648 case NODE_TYPE_TEXT: /* Text Node */
7649 if (msie === 11) {
7650 // Workaround for #11781
7651 while (node.parentNode && node.nextSibling && node.nextSibling.nodeType === NODE_TYPE_TEXT) {
7652 node.nodeValue = node.nodeValue + node.nextSibling.nodeValue;
7653 node.parentNode.removeChild(node.nextSibling);
7654 }
7655 }
7656 addTextInterpolateDirective(directives, node.nodeValue);
7657 break;
7658 case NODE_TYPE_COMMENT: /* Comment */
7659 try {
7660 match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
7661 if (match) {
7662 nName = directiveNormalize(match[1]);
7663 if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
7664 attrs[nName] = trim(match[2]);
7665 }
7666 }
7667 } catch (e) {
7668 // turns out that under some circumstances IE9 throws errors when one attempts to read
7669 // comment's node value.
7670 // Just ignore it and continue. (Can't seem to reproduce in test case.)
7671 }
7672 break;
7673 }
7674
7675 directives.sort(byPriority);
7676 return directives;
7677 }
7678
7679 /**
7680 * Given a node with an directive-start it collects all of the siblings until it finds
7681 * directive-end.
7682 * @param node
7683 * @param attrStart
7684 * @param attrEnd
7685 * @returns {*}
7686 */
7687 function groupScan(node, attrStart, attrEnd) {
7688 var nodes = [];
7689 var depth = 0;
7690 if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
7691 do {
7692 if (!node) {
7693 throw $compileMinErr('uterdir',
7694 "Unterminated attribute, found '{0}' but no matching '{1}' found.",
7695 attrStart, attrEnd);
7696 }
7697 if (node.nodeType == NODE_TYPE_ELEMENT) {
7698 if (node.hasAttribute(attrStart)) depth++;
7699 if (node.hasAttribute(attrEnd)) depth--;
7700 }
7701 nodes.push(node);
7702 node = node.nextSibling;
7703 } while (depth > 0);
7704 } else {
7705 nodes.push(node);
7706 }
7707
7708 return jqLite(nodes);
7709 }
7710
7711 /**
7712 * Wrapper for linking function which converts normal linking function into a grouped
7713 * linking function.
7714 * @param linkFn
7715 * @param attrStart
7716 * @param attrEnd
7717 * @returns {Function}
7718 */
7719 function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
7720 return function(scope, element, attrs, controllers, transcludeFn) {
7721 element = groupScan(element[0], attrStart, attrEnd);
7722 return linkFn(scope, element, attrs, controllers, transcludeFn);
7723 };
7724 }
7725
7726 /**
7727 * Once the directives have been collected, their compile functions are executed. This method
7728 * is responsible for inlining directive templates as well as terminating the application
7729 * of the directives if the terminal directive has been reached.
7730 *
7731 * @param {Array} directives Array of collected directives to execute their compile function.
7732 * this needs to be pre-sorted by priority order.
7733 * @param {Node} compileNode The raw DOM node to apply the compile functions to
7734 * @param {Object} templateAttrs The shared attribute function
7735 * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the
7736 * scope argument is auto-generated to the new
7737 * child of the transcluded parent scope.
7738 * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
7739 * argument has the root jqLite array so that we can replace nodes
7740 * on it.
7741 * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
7742 * compiling the transclusion.
7743 * @param {Array.<Function>} preLinkFns
7744 * @param {Array.<Function>} postLinkFns
7745 * @param {Object} previousCompileContext Context used for previous compilation of the current
7746 * node
7747 * @returns {Function} linkFn
7748 */
7749 function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
7750 jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
7751 previousCompileContext) {
7752 previousCompileContext = previousCompileContext || {};
7753
7754 var terminalPriority = -Number.MAX_VALUE,
7755 newScopeDirective = previousCompileContext.newScopeDirective,
7756 controllerDirectives = previousCompileContext.controllerDirectives,
7757 newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
7758 templateDirective = previousCompileContext.templateDirective,
7759 nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
7760 hasTranscludeDirective = false,
7761 hasTemplate = false,
7762 hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective,
7763 $compileNode = templateAttrs.$$element = jqLite(compileNode),
7764 directive,
7765 directiveName,
7766 $template,
7767 replaceDirective = originalReplaceDirective,
7768 childTranscludeFn = transcludeFn,
7769 linkFn,
7770 directiveValue;
7771
7772 // executes all directives on the current element
7773 for (var i = 0, ii = directives.length; i < ii; i++) {
7774 directive = directives[i];
7775 var attrStart = directive.$$start;
7776 var attrEnd = directive.$$end;
7777
7778 // collect multiblock sections
7779 if (attrStart) {
7780 $compileNode = groupScan(compileNode, attrStart, attrEnd);
7781 }
7782 $template = undefined;
7783
7784 if (terminalPriority > directive.priority) {
7785 break; // prevent further processing of directives
7786 }
7787
7788 if (directiveValue = directive.scope) {
7789
7790 // skip the check for directives with async templates, we'll check the derived sync
7791 // directive when the template arrives
7792 if (!directive.templateUrl) {
7793 if (isObject(directiveValue)) {
7794 // This directive is trying to add an isolated scope.
7795 // Check that there is no scope of any kind already
7796 assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,
7797 directive, $compileNode);
7798 newIsolateScopeDirective = directive;
7799 } else {
7800 // This directive is trying to add a child scope.
7801 // Check that there is no isolated scope already
7802 assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
7803 $compileNode);
7804 }
7805 }
7806
7807 newScopeDirective = newScopeDirective || directive;
7808 }
7809
7810 directiveName = directive.name;
7811
7812 if (!directive.templateUrl && directive.controller) {
7813 directiveValue = directive.controller;
7814 controllerDirectives = controllerDirectives || createMap();
7815 assertNoDuplicate("'" + directiveName + "' controller",
7816 controllerDirectives[directiveName], directive, $compileNode);
7817 controllerDirectives[directiveName] = directive;
7818 }
7819
7820 if (directiveValue = directive.transclude) {
7821 hasTranscludeDirective = true;
7822
7823 // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
7824 // This option should only be used by directives that know how to safely handle element transclusion,
7825 // where the transcluded nodes are added or replaced after linking.
7826 if (!directive.$$tlb) {
7827 assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
7828 nonTlbTranscludeDirective = directive;
7829 }
7830
7831 if (directiveValue == 'element') {
7832 hasElementTranscludeDirective = true;
7833 terminalPriority = directive.priority;
7834 $template = $compileNode;
7835 $compileNode = templateAttrs.$$element =
7836 jqLite(document.createComment(' ' + directiveName + ': ' +
7837 templateAttrs[directiveName] + ' '));
7838 compileNode = $compileNode[0];
7839 replaceWith(jqCollection, sliceArgs($template), compileNode);
7840
7841 childTranscludeFn = compile($template, transcludeFn, terminalPriority,
7842 replaceDirective && replaceDirective.name, {
7843 // Don't pass in:
7844 // - controllerDirectives - otherwise we'll create duplicates controllers
7845 // - newIsolateScopeDirective or templateDirective - combining templates with
7846 // element transclusion doesn't make sense.
7847 //
7848 // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
7849 // on the same element more than once.
7850 nonTlbTranscludeDirective: nonTlbTranscludeDirective
7851 });
7852 } else {
7853 $template = jqLite(jqLiteClone(compileNode)).contents();
7854 $compileNode.empty(); // clear contents
7855 childTranscludeFn = compile($template, transcludeFn);
7856 }
7857 }
7858
7859 if (directive.template) {
7860 hasTemplate = true;
7861 assertNoDuplicate('template', templateDirective, directive, $compileNode);
7862 templateDirective = directive;
7863
7864 directiveValue = (isFunction(directive.template))
7865 ? directive.template($compileNode, templateAttrs)
7866 : directive.template;
7867
7868 directiveValue = denormalizeTemplate(directiveValue);
7869
7870 if (directive.replace) {
7871 replaceDirective = directive;
7872 if (jqLiteIsTextNode(directiveValue)) {
7873 $template = [];
7874 } else {
7875 $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue)));
7876 }
7877 compileNode = $template[0];
7878
7879 if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
7880 throw $compileMinErr('tplrt',
7881 "Template for directive '{0}' must have exactly one root element. {1}",
7882 directiveName, '');
7883 }
7884
7885 replaceWith(jqCollection, $compileNode, compileNode);
7886
7887 var newTemplateAttrs = {$attr: {}};
7888
7889 // combine directives from the original node and from the template:
7890 // - take the array of directives for this element
7891 // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
7892 // - collect directives from the template and sort them by priority
7893 // - combine directives as: processed + template + unprocessed
7894 var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
7895 var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
7896
7897 if (newIsolateScopeDirective) {
7898 markDirectivesAsIsolate(templateDirectives);
7899 }
7900 directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
7901 mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
7902
7903 ii = directives.length;
7904 } else {
7905 $compileNode.html(directiveValue);
7906 }
7907 }
7908
7909 if (directive.templateUrl) {
7910 hasTemplate = true;
7911 assertNoDuplicate('template', templateDirective, directive, $compileNode);
7912 templateDirective = directive;
7913
7914 if (directive.replace) {
7915 replaceDirective = directive;
7916 }
7917
7918 nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
7919 templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
7920 controllerDirectives: controllerDirectives,
7921 newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,
7922 newIsolateScopeDirective: newIsolateScopeDirective,
7923 templateDirective: templateDirective,
7924 nonTlbTranscludeDirective: nonTlbTranscludeDirective
7925 });
7926 ii = directives.length;
7927 } else if (directive.compile) {
7928 try {
7929 linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
7930 if (isFunction(linkFn)) {
7931 addLinkFns(null, linkFn, attrStart, attrEnd);
7932 } else if (linkFn) {
7933 addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
7934 }
7935 } catch (e) {
7936 $exceptionHandler(e, startingTag($compileNode));
7937 }
7938 }
7939
7940 if (directive.terminal) {
7941 nodeLinkFn.terminal = true;
7942 terminalPriority = Math.max(terminalPriority, directive.priority);
7943 }
7944
7945 }
7946
7947 nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
7948 nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
7949 nodeLinkFn.templateOnThisElement = hasTemplate;
7950 nodeLinkFn.transclude = childTranscludeFn;
7951
7952 previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
7953
7954 // might be normal or delayed nodeLinkFn depending on if templateUrl is present
7955 return nodeLinkFn;
7956
7957 ////////////////////
7958
7959 function addLinkFns(pre, post, attrStart, attrEnd) {
7960 if (pre) {
7961 if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
7962 pre.require = directive.require;
7963 pre.directiveName = directiveName;
7964 if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
7965 pre = cloneAndAnnotateFn(pre, {isolateScope: true});
7966 }
7967 preLinkFns.push(pre);
7968 }
7969 if (post) {
7970 if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
7971 post.require = directive.require;
7972 post.directiveName = directiveName;
7973 if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
7974 post = cloneAndAnnotateFn(post, {isolateScope: true});
7975 }
7976 postLinkFns.push(post);
7977 }
7978 }
7979
7980
7981 function getControllers(directiveName, require, $element, elementControllers) {
7982 var value;
7983
7984 if (isString(require)) {
7985 var match = require.match(REQUIRE_PREFIX_REGEXP);
7986 var name = require.substring(match[0].length);
7987 var inheritType = match[1] || match[3];
7988 var optional = match[2] === '?';
7989
7990 //If only parents then start at the parent element
7991 if (inheritType === '^^') {
7992 $element = $element.parent();
7993 //Otherwise attempt getting the controller from elementControllers in case
7994 //the element is transcluded (and has no data) and to avoid .data if possible
7995 } else {
7996 value = elementControllers && elementControllers[name];
7997 value = value && value.instance;
7998 }
7999
8000 if (!value) {
8001 var dataName = '$' + name + 'Controller';
8002 value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName);
8003 }
8004
8005 if (!value && !optional) {
8006 throw $compileMinErr('ctreq',
8007 "Controller '{0}', required by directive '{1}', can't be found!",
8008 name, directiveName);
8009 }
8010 } else if (isArray(require)) {
8011 value = [];
8012 for (var i = 0, ii = require.length; i < ii; i++) {
8013 value[i] = getControllers(directiveName, require[i], $element, elementControllers);
8014 }
8015 }
8016
8017 return value || null;
8018 }
8019
8020 function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope) {
8021 var elementControllers = createMap();
8022 for (var controllerKey in controllerDirectives) {
8023 var directive = controllerDirectives[controllerKey];
8024 var locals = {
8025 $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
8026 $element: $element,
8027 $attrs: attrs,
8028 $transclude: transcludeFn
8029 };
8030
8031 var controller = directive.controller;
8032 if (controller == '@') {
8033 controller = attrs[directive.name];
8034 }
8035
8036 var controllerInstance = $controller(controller, locals, true, directive.controllerAs);
8037
8038 // For directives with element transclusion the element is a comment,
8039 // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
8040 // clean up (http://bugs.jquery.com/ticket/8335).
8041 // Instead, we save the controllers for the element in a local hash and attach to .data
8042 // later, once we have the actual element.
8043 elementControllers[directive.name] = controllerInstance;
8044 if (!hasElementTranscludeDirective) {
8045 $element.data('$' + directive.name + 'Controller', controllerInstance.instance);
8046 }
8047 }
8048 return elementControllers;
8049 }
8050
8051 function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn,
8052 thisLinkFn) {
8053 var i, ii, linkFn, controller, isolateScope, elementControllers, transcludeFn, $element,
8054 attrs;
8055
8056 if (compileNode === linkNode) {
8057 attrs = templateAttrs;
8058 $element = templateAttrs.$$element;
8059 } else {
8060 $element = jqLite(linkNode);
8061 attrs = new Attributes($element, templateAttrs);
8062 }
8063
8064 if (newIsolateScopeDirective) {
8065 isolateScope = scope.$new(true);
8066 }
8067
8068 if (boundTranscludeFn) {
8069 // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
8070 // is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
8071 transcludeFn = controllersBoundTransclude;
8072 transcludeFn.$$boundTransclude = boundTranscludeFn;
8073 }
8074
8075 if (controllerDirectives) {
8076 elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope);
8077 }
8078
8079 if (newIsolateScopeDirective) {
8080 // Initialize isolate scope bindings for new isolate scope directive.
8081 compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective ||
8082 templateDirective === newIsolateScopeDirective.$$originalDirective)));
8083 compile.$$addScopeClass($element, true);
8084 isolateScope.$$isolateBindings =
8085 newIsolateScopeDirective.$$isolateBindings;
8086 initializeDirectiveBindings(scope, attrs, isolateScope,
8087 isolateScope.$$isolateBindings,
8088 newIsolateScopeDirective, isolateScope);
8089 }
8090 if (elementControllers) {
8091 // Initialize bindToController bindings for new/isolate scopes
8092 var scopeDirective = newIsolateScopeDirective || newScopeDirective;
8093 var bindings;
8094 var controllerForBindings;
8095 if (scopeDirective && elementControllers[scopeDirective.name]) {
8096 bindings = scopeDirective.$$bindings.bindToController;
8097 controller = elementControllers[scopeDirective.name];
8098
8099 if (controller && controller.identifier && bindings) {
8100 controllerForBindings = controller;
8101 thisLinkFn.$$destroyBindings =
8102 initializeDirectiveBindings(scope, attrs, controller.instance,
8103 bindings, scopeDirective);
8104 }
8105 }
8106 for (i in elementControllers) {
8107 controller = elementControllers[i];
8108 var controllerResult = controller();
8109
8110 if (controllerResult !== controller.instance) {
8111 // If the controller constructor has a return value, overwrite the instance
8112 // from setupControllers and update the element data
8113 controller.instance = controllerResult;
8114 $element.data('$' + i + 'Controller', controllerResult);
8115 if (controller === controllerForBindings) {
8116 // Remove and re-install bindToController bindings
8117 thisLinkFn.$$destroyBindings();
8118 thisLinkFn.$$destroyBindings =
8119 initializeDirectiveBindings(scope, attrs, controllerResult, bindings, scopeDirective);
8120 }
8121 }
8122 }
8123 }
8124
8125 // PRELINKING
8126 for (i = 0, ii = preLinkFns.length; i < ii; i++) {
8127 linkFn = preLinkFns[i];
8128 invokeLinkFn(linkFn,
8129 linkFn.isolateScope ? isolateScope : scope,
8130 $element,
8131 attrs,
8132 linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
8133 transcludeFn
8134 );
8135 }
8136
8137 // RECURSION
8138 // We only pass the isolate scope, if the isolate directive has a template,
8139 // otherwise the child elements do not belong to the isolate directive.
8140 var scopeToChild = scope;
8141 if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
8142 scopeToChild = isolateScope;
8143 }
8144 childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
8145
8146 // POSTLINKING
8147 for (i = postLinkFns.length - 1; i >= 0; i--) {
8148 linkFn = postLinkFns[i];
8149 invokeLinkFn(linkFn,
8150 linkFn.isolateScope ? isolateScope : scope,
8151 $element,
8152 attrs,
8153 linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers),
8154 transcludeFn
8155 );
8156 }
8157
8158 // This is the function that is injected as `$transclude`.
8159 // Note: all arguments are optional!
8160 function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement) {
8161 var transcludeControllers;
8162
8163 // No scope passed in:
8164 if (!isScope(scope)) {
8165 futureParentElement = cloneAttachFn;
8166 cloneAttachFn = scope;
8167 scope = undefined;
8168 }
8169
8170 if (hasElementTranscludeDirective) {
8171 transcludeControllers = elementControllers;
8172 }
8173 if (!futureParentElement) {
8174 futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element;
8175 }
8176 return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild);
8177 }
8178 }
8179 }
8180
8181 function markDirectivesAsIsolate(directives) {
8182 // mark all directives as needing isolate scope.
8183 for (var j = 0, jj = directives.length; j < jj; j++) {
8184 directives[j] = inherit(directives[j], {$$isolateScope: true});
8185 }
8186 }
8187
8188 /**
8189 * looks up the directive and decorates it with exception handling and proper parameters. We
8190 * call this the boundDirective.
8191 *
8192 * @param {string} name name of the directive to look up.
8193 * @param {string} location The directive must be found in specific format.
8194 * String containing any of theses characters:
8195 *
8196 * * `E`: element name
8197 * * `A': attribute
8198 * * `C`: class
8199 * * `M`: comment
8200 * @returns {boolean} true if directive was added.
8201 */
8202 function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
8203 endAttrName) {
8204 if (name === ignoreDirective) return null;
8205 var match = null;
8206 if (hasDirectives.hasOwnProperty(name)) {
8207 for (var directive, directives = $injector.get(name + Suffix),
8208 i = 0, ii = directives.length; i < ii; i++) {
8209 try {
8210 directive = directives[i];
8211 if ((maxPriority === undefined || maxPriority > directive.priority) &&
8212 directive.restrict.indexOf(location) != -1) {
8213 if (startAttrName) {
8214 directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
8215 }
8216 tDirectives.push(directive);
8217 match = directive;
8218 }
8219 } catch (e) { $exceptionHandler(e); }
8220 }
8221 }
8222 return match;
8223 }
8224
8225
8226 /**
8227 * looks up the directive and returns true if it is a multi-element directive,
8228 * and therefore requires DOM nodes between -start and -end markers to be grouped
8229 * together.
8230 *
8231 * @param {string} name name of the directive to look up.
8232 * @returns true if directive was registered as multi-element.
8233 */
8234 function directiveIsMultiElement(name) {
8235 if (hasDirectives.hasOwnProperty(name)) {
8236 for (var directive, directives = $injector.get(name + Suffix),
8237 i = 0, ii = directives.length; i < ii; i++) {
8238 directive = directives[i];
8239 if (directive.multiElement) {
8240 return true;
8241 }
8242 }
8243 }
8244 return false;
8245 }
8246
8247 /**
8248 * When the element is replaced with HTML template then the new attributes
8249 * on the template need to be merged with the existing attributes in the DOM.
8250 * The desired effect is to have both of the attributes present.
8251 *
8252 * @param {object} dst destination attributes (original DOM)
8253 * @param {object} src source attributes (from the directive template)
8254 */
8255 function mergeTemplateAttributes(dst, src) {
8256 var srcAttr = src.$attr,
8257 dstAttr = dst.$attr,
8258 $element = dst.$$element;
8259
8260 // reapply the old attributes to the new element
8261 forEach(dst, function(value, key) {
8262 if (key.charAt(0) != '$') {
8263 if (src[key] && src[key] !== value) {
8264 value += (key === 'style' ? ';' : ' ') + src[key];
8265 }
8266 dst.$set(key, value, true, srcAttr[key]);
8267 }
8268 });
8269
8270 // copy the new attributes on the old attrs object
8271 forEach(src, function(value, key) {
8272 if (key == 'class') {
8273 safeAddClass($element, value);
8274 dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
8275 } else if (key == 'style') {
8276 $element.attr('style', $element.attr('style') + ';' + value);
8277 dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
8278 // `dst` will never contain hasOwnProperty as DOM parser won't let it.
8279 // You will get an "InvalidCharacterError: DOM Exception 5" error if you
8280 // have an attribute like "has-own-property" or "data-has-own-property", etc.
8281 } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
8282 dst[key] = value;
8283 dstAttr[key] = srcAttr[key];
8284 }
8285 });
8286 }
8287
8288
8289 function compileTemplateUrl(directives, $compileNode, tAttrs,
8290 $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
8291 var linkQueue = [],
8292 afterTemplateNodeLinkFn,
8293 afterTemplateChildLinkFn,
8294 beforeTemplateCompileNode = $compileNode[0],
8295 origAsyncDirective = directives.shift(),
8296 derivedSyncDirective = inherit(origAsyncDirective, {
8297 templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
8298 }),
8299 templateUrl = (isFunction(origAsyncDirective.templateUrl))
8300 ? origAsyncDirective.templateUrl($compileNode, tAttrs)
8301 : origAsyncDirective.templateUrl,
8302 templateNamespace = origAsyncDirective.templateNamespace;
8303
8304 $compileNode.empty();
8305
8306 $templateRequest(templateUrl)
8307 .then(function(content) {
8308 var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
8309
8310 content = denormalizeTemplate(content);
8311
8312 if (origAsyncDirective.replace) {
8313 if (jqLiteIsTextNode(content)) {
8314 $template = [];
8315 } else {
8316 $template = removeComments(wrapTemplate(templateNamespace, trim(content)));
8317 }
8318 compileNode = $template[0];
8319
8320 if ($template.length != 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) {
8321 throw $compileMinErr('tplrt',
8322 "Template for directive '{0}' must have exactly one root element. {1}",
8323 origAsyncDirective.name, templateUrl);
8324 }
8325
8326 tempTemplateAttrs = {$attr: {}};
8327 replaceWith($rootElement, $compileNode, compileNode);
8328 var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
8329
8330 if (isObject(origAsyncDirective.scope)) {
8331 markDirectivesAsIsolate(templateDirectives);
8332 }
8333 directives = templateDirectives.concat(directives);
8334 mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
8335 } else {
8336 compileNode = beforeTemplateCompileNode;
8337 $compileNode.html(content);
8338 }
8339
8340 directives.unshift(derivedSyncDirective);
8341
8342 afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
8343 childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
8344 previousCompileContext);
8345 forEach($rootElement, function(node, i) {
8346 if (node == compileNode) {
8347 $rootElement[i] = $compileNode[0];
8348 }
8349 });
8350 afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
8351
8352 while (linkQueue.length) {
8353 var scope = linkQueue.shift(),
8354 beforeTemplateLinkNode = linkQueue.shift(),
8355 linkRootElement = linkQueue.shift(),
8356 boundTranscludeFn = linkQueue.shift(),
8357 linkNode = $compileNode[0];
8358
8359 if (scope.$$destroyed) continue;
8360
8361 if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
8362 var oldClasses = beforeTemplateLinkNode.className;
8363
8364 if (!(previousCompileContext.hasElementTranscludeDirective &&
8365 origAsyncDirective.replace)) {
8366 // it was cloned therefore we have to clone as well.
8367 linkNode = jqLiteClone(compileNode);
8368 }
8369 replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
8370
8371 // Copy in CSS classes from original node
8372 safeAddClass(jqLite(linkNode), oldClasses);
8373 }
8374 if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
8375 childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
8376 } else {
8377 childBoundTranscludeFn = boundTranscludeFn;
8378 }
8379 afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
8380 childBoundTranscludeFn, afterTemplateNodeLinkFn);
8381 }
8382 linkQueue = null;
8383 });
8384
8385 return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
8386 var childBoundTranscludeFn = boundTranscludeFn;
8387 if (scope.$$destroyed) return;
8388 if (linkQueue) {
8389 linkQueue.push(scope,
8390 node,
8391 rootElement,
8392 childBoundTranscludeFn);
8393 } else {
8394 if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
8395 childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
8396 }
8397 afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn,
8398 afterTemplateNodeLinkFn);
8399 }
8400 };
8401 }
8402
8403
8404 /**
8405 * Sorting function for bound directives.
8406 */
8407 function byPriority(a, b) {
8408 var diff = b.priority - a.priority;
8409 if (diff !== 0) return diff;
8410 if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
8411 return a.index - b.index;
8412 }
8413
8414 function assertNoDuplicate(what, previousDirective, directive, element) {
8415
8416 function wrapModuleNameIfDefined(moduleName) {
8417 return moduleName ?
8418 (' (module: ' + moduleName + ')') :
8419 '';
8420 }
8421
8422 if (previousDirective) {
8423 throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}',
8424 previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName),
8425 directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element));
8426 }
8427 }
8428
8429
8430 function addTextInterpolateDirective(directives, text) {
8431 var interpolateFn = $interpolate(text, true);
8432 if (interpolateFn) {
8433 directives.push({
8434 priority: 0,
8435 compile: function textInterpolateCompileFn(templateNode) {
8436 var templateNodeParent = templateNode.parent(),
8437 hasCompileParent = !!templateNodeParent.length;
8438
8439 // When transcluding a template that has bindings in the root
8440 // we don't have a parent and thus need to add the class during linking fn.
8441 if (hasCompileParent) compile.$$addBindingClass(templateNodeParent);
8442
8443 return function textInterpolateLinkFn(scope, node) {
8444 var parent = node.parent();
8445 if (!hasCompileParent) compile.$$addBindingClass(parent);
8446 compile.$$addBindingInfo(parent, interpolateFn.expressions);
8447 scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
8448 node[0].nodeValue = value;
8449 });
8450 };
8451 }
8452 });
8453 }
8454 }
8455
8456
8457 function wrapTemplate(type, template) {
8458 type = lowercase(type || 'html');
8459 switch (type) {
8460 case 'svg':
8461 case 'math':
8462 var wrapper = document.createElement('div');
8463 wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
8464 return wrapper.childNodes[0].childNodes;
8465 default:
8466 return template;
8467 }
8468 }
8469
8470
8471 function getTrustedContext(node, attrNormalizedName) {
8472 if (attrNormalizedName == "srcdoc") {
8473 return $sce.HTML;
8474 }
8475 var tag = nodeName_(node);
8476 // maction[xlink:href] can source SVG. It's not limited to <maction>.
8477 if (attrNormalizedName == "xlinkHref" ||
8478 (tag == "form" && attrNormalizedName == "action") ||
8479 (tag != "img" && (attrNormalizedName == "src" ||
8480 attrNormalizedName == "ngSrc"))) {
8481 return $sce.RESOURCE_URL;
8482 }
8483 }
8484
8485
8486 function addAttrInterpolateDirective(node, directives, value, name, allOrNothing) {
8487 var trustedContext = getTrustedContext(node, name);
8488 allOrNothing = ALL_OR_NOTHING_ATTRS[name] || allOrNothing;
8489
8490 var interpolateFn = $interpolate(value, true, trustedContext, allOrNothing);
8491
8492 // no interpolation found -> ignore
8493 if (!interpolateFn) return;
8494
8495
8496 if (name === "multiple" && nodeName_(node) === "select") {
8497 throw $compileMinErr("selmulti",
8498 "Binding to the 'multiple' attribute is not supported. Element: {0}",
8499 startingTag(node));
8500 }
8501
8502 directives.push({
8503 priority: 100,
8504 compile: function() {
8505 return {
8506 pre: function attrInterpolatePreLinkFn(scope, element, attr) {
8507 var $$observers = (attr.$$observers || (attr.$$observers = {}));
8508
8509 if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
8510 throw $compileMinErr('nodomevents',
8511 "Interpolations for HTML DOM event attributes are disallowed. Please use the " +
8512 "ng- versions (such as ng-click instead of onclick) instead.");
8513 }
8514
8515 // If the attribute has changed since last $interpolate()ed
8516 var newValue = attr[name];
8517 if (newValue !== value) {
8518 // we need to interpolate again since the attribute value has been updated
8519 // (e.g. by another directive's compile function)
8520 // ensure unset/empty values make interpolateFn falsy
8521 interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing);
8522 value = newValue;
8523 }
8524
8525 // if attribute was updated so that there is no interpolation going on we don't want to
8526 // register any observers
8527 if (!interpolateFn) return;
8528
8529 // initialize attr object so that it's ready in case we need the value for isolate
8530 // scope initialization, otherwise the value would not be available from isolate
8531 // directive's linking fn during linking phase
8532 attr[name] = interpolateFn(scope);
8533
8534 ($$observers[name] || ($$observers[name] = [])).$$inter = true;
8535 (attr.$$observers && attr.$$observers[name].$$scope || scope).
8536 $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
8537 //special case for class attribute addition + removal
8538 //so that class changes can tap into the animation
8539 //hooks provided by the $animate service. Be sure to
8540 //skip animations when the first digest occurs (when
8541 //both the new and the old values are the same) since
8542 //the CSS classes are the non-interpolated values
8543 if (name === 'class' && newValue != oldValue) {
8544 attr.$updateClass(newValue, oldValue);
8545 } else {
8546 attr.$set(name, newValue);
8547 }
8548 });
8549 }
8550 };
8551 }
8552 });
8553 }
8554
8555
8556 /**
8557 * This is a special jqLite.replaceWith, which can replace items which
8558 * have no parents, provided that the containing jqLite collection is provided.
8559 *
8560 * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
8561 * in the root of the tree.
8562 * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
8563 * the shell, but replace its DOM node reference.
8564 * @param {Node} newNode The new DOM node.
8565 */
8566 function replaceWith($rootElement, elementsToRemove, newNode) {
8567 var firstElementToRemove = elementsToRemove[0],
8568 removeCount = elementsToRemove.length,
8569 parent = firstElementToRemove.parentNode,
8570 i, ii;
8571
8572 if ($rootElement) {
8573 for (i = 0, ii = $rootElement.length; i < ii; i++) {
8574 if ($rootElement[i] == firstElementToRemove) {
8575 $rootElement[i++] = newNode;
8576 for (var j = i, j2 = j + removeCount - 1,
8577 jj = $rootElement.length;
8578 j < jj; j++, j2++) {
8579 if (j2 < jj) {
8580 $rootElement[j] = $rootElement[j2];
8581 } else {
8582 delete $rootElement[j];
8583 }
8584 }
8585 $rootElement.length -= removeCount - 1;
8586
8587 // If the replaced element is also the jQuery .context then replace it
8588 // .context is a deprecated jQuery api, so we should set it only when jQuery set it
8589 // http://api.jquery.com/context/
8590 if ($rootElement.context === firstElementToRemove) {
8591 $rootElement.context = newNode;
8592 }
8593 break;
8594 }
8595 }
8596 }
8597
8598 if (parent) {
8599 parent.replaceChild(newNode, firstElementToRemove);
8600 }
8601
8602 // TODO(perf): what's this document fragment for? is it needed? can we at least reuse it?
8603 var fragment = document.createDocumentFragment();
8604 fragment.appendChild(firstElementToRemove);
8605
8606 if (jqLite.hasData(firstElementToRemove)) {
8607 // Copy over user data (that includes Angular's $scope etc.). Don't copy private
8608 // data here because there's no public interface in jQuery to do that and copying over
8609 // event listeners (which is the main use of private data) wouldn't work anyway.
8610 jqLite(newNode).data(jqLite(firstElementToRemove).data());
8611
8612 // Remove data of the replaced element. We cannot just call .remove()
8613 // on the element it since that would deallocate scope that is needed
8614 // for the new node. Instead, remove the data "manually".
8615 if (!jQuery) {
8616 delete jqLite.cache[firstElementToRemove[jqLite.expando]];
8617 } else {
8618 // jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after
8619 // the replaced element. The cleanData version monkey-patched by Angular would cause
8620 // the scope to be trashed and we do need the very same scope to work with the new
8621 // element. However, we cannot just cache the non-patched version and use it here as
8622 // that would break if another library patches the method after Angular does (one
8623 // example is jQuery UI). Instead, set a flag indicating scope destroying should be
8624 // skipped this one time.
8625 skipDestroyOnNextJQueryCleanData = true;
8626 jQuery.cleanData([firstElementToRemove]);
8627 }
8628 }
8629
8630 for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
8631 var element = elementsToRemove[k];
8632 jqLite(element).remove(); // must do this way to clean up expando
8633 fragment.appendChild(element);
8634 delete elementsToRemove[k];
8635 }
8636
8637 elementsToRemove[0] = newNode;
8638 elementsToRemove.length = 1;
8639 }
8640
8641
8642 function cloneAndAnnotateFn(fn, annotation) {
8643 return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
8644 }
8645
8646
8647 function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) {
8648 try {
8649 linkFn(scope, $element, attrs, controllers, transcludeFn);
8650 } catch (e) {
8651 $exceptionHandler(e, startingTag($element));
8652 }
8653 }
8654
8655
8656 // Set up $watches for isolate scope and controller bindings. This process
8657 // only occurs for isolate scopes and new scopes with controllerAs.
8658 function initializeDirectiveBindings(scope, attrs, destination, bindings,
8659 directive, newScope) {
8660 var onNewScopeDestroyed;
8661 forEach(bindings, function(definition, scopeName) {
8662 var attrName = definition.attrName,
8663 optional = definition.optional,
8664 mode = definition.mode, // @, =, or &
8665 lastValue,
8666 parentGet, parentSet, compare;
8667
8668 if (!hasOwnProperty.call(attrs, attrName)) {
8669 // In the case of user defined a binding with the same name as a method in Object.prototype but didn't set
8670 // the corresponding attribute. We need to make sure subsequent code won't access to the prototype function
8671 attrs[attrName] = undefined;
8672 }
8673
8674 switch (mode) {
8675
8676 case '@':
8677 if (!attrs[attrName] && !optional) {
8678 destination[scopeName] = undefined;
8679 }
8680
8681 attrs.$observe(attrName, function(value) {
8682 destination[scopeName] = value;
8683 });
8684 attrs.$$observers[attrName].$$scope = scope;
8685 if (attrs[attrName]) {
8686 // If the attribute has been provided then we trigger an interpolation to ensure
8687 // the value is there for use in the link fn
8688 destination[scopeName] = $interpolate(attrs[attrName])(scope);
8689 }
8690 break;
8691
8692 case '=':
8693 if (optional && !attrs[attrName]) {
8694 return;
8695 }
8696 parentGet = $parse(attrs[attrName]);
8697
8698 if (parentGet.literal) {
8699 compare = equals;
8700 } else {
8701 compare = function(a, b) { return a === b || (a !== a && b !== b); };
8702 }
8703 parentSet = parentGet.assign || function() {
8704 // reset the change, or we will throw this exception on every $digest
8705 lastValue = destination[scopeName] = parentGet(scope);
8706 throw $compileMinErr('nonassign',
8707 "Expression '{0}' used with directive '{1}' is non-assignable!",
8708 attrs[attrName], directive.name);
8709 };
8710 lastValue = destination[scopeName] = parentGet(scope);
8711 var parentValueWatch = function parentValueWatch(parentValue) {
8712 if (!compare(parentValue, destination[scopeName])) {
8713 // we are out of sync and need to copy
8714 if (!compare(parentValue, lastValue)) {
8715 // parent changed and it has precedence
8716 destination[scopeName] = parentValue;
8717 } else {
8718 // if the parent can be assigned then do so
8719 parentSet(scope, parentValue = destination[scopeName]);
8720 }
8721 }
8722 return lastValue = parentValue;
8723 };
8724 parentValueWatch.$stateful = true;
8725 var unwatch;
8726 if (definition.collection) {
8727 unwatch = scope.$watchCollection(attrs[attrName], parentValueWatch);
8728 } else {
8729 unwatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal);
8730 }
8731 onNewScopeDestroyed = (onNewScopeDestroyed || []);
8732 onNewScopeDestroyed.push(unwatch);
8733 break;
8734
8735 case '&':
8736 parentGet = $parse(attrs[attrName]);
8737
8738 // Don't assign noop to destination if expression is not valid
8739 if (parentGet === noop && optional) break;
8740
8741 destination[scopeName] = function(locals) {
8742 return parentGet(scope, locals);
8743 };
8744 break;
8745 }
8746 });
8747 var destroyBindings = onNewScopeDestroyed ? function destroyBindings() {
8748 for (var i = 0, ii = onNewScopeDestroyed.length; i < ii; ++i) {
8749 onNewScopeDestroyed[i]();
8750 }
8751 } : noop;
8752 if (newScope && destroyBindings !== noop) {
8753 newScope.$on('$destroy', destroyBindings);
8754 return noop;
8755 }
8756 return destroyBindings;
8757 }
8758 }];
8759 }
8760
8761 var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i;
8762 /**
8763 * Converts all accepted directives format into proper directive name.
8764 * @param name Name to normalize
8765 */
8766 function directiveNormalize(name) {
8767 return camelCase(name.replace(PREFIX_REGEXP, ''));
8768 }
8769
8770 /**
8771 * @ngdoc type
8772 * @name $compile.directive.Attributes
8773 *
8774 * @description
8775 * A shared object between directive compile / linking functions which contains normalized DOM
8776 * element attributes. The values reflect current binding state `{{ }}`. The normalization is
8777 * needed since all of these are treated as equivalent in Angular:
8778 *
8779 * ```
8780 * <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
8781 * ```
8782 */
8783
8784 /**
8785 * @ngdoc property
8786 * @name $compile.directive.Attributes#$attr
8787 *
8788 * @description
8789 * A map of DOM element attribute names to the normalized name. This is
8790 * needed to do reverse lookup from normalized name back to actual name.
8791 */
8792
8793
8794 /**
8795 * @ngdoc method
8796 * @name $compile.directive.Attributes#$set
8797 * @kind function
8798 *
8799 * @description
8800 * Set DOM element attribute value.
8801 *
8802 *
8803 * @param {string} name Normalized element attribute name of the property to modify. The name is
8804 * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
8805 * property to the original name.
8806 * @param {string} value Value to set the attribute to. The value can be an interpolated string.
8807 */
8808
8809
8810
8811 /**
8812 * Closure compiler type information
8813 */
8814
8815 function nodesetLinkingFn(
8816 /* angular.Scope */ scope,
8817 /* NodeList */ nodeList,
8818 /* Element */ rootElement,
8819 /* function(Function) */ boundTranscludeFn
8820 ) {}
8821
8822 function directiveLinkingFn(
8823 /* nodesetLinkingFn */ nodesetLinkingFn,
8824 /* angular.Scope */ scope,
8825 /* Node */ node,
8826 /* Element */ rootElement,
8827 /* function(Function) */ boundTranscludeFn
8828 ) {}
8829
8830 function tokenDifference(str1, str2) {
8831 var values = '',
8832 tokens1 = str1.split(/\s+/),
8833 tokens2 = str2.split(/\s+/);
8834
8835 outer:
8836 for (var i = 0; i < tokens1.length; i++) {
8837 var token = tokens1[i];
8838 for (var j = 0; j < tokens2.length; j++) {
8839 if (token == tokens2[j]) continue outer;
8840 }
8841 values += (values.length > 0 ? ' ' : '') + token;
8842 }
8843 return values;
8844 }
8845
8846 function removeComments(jqNodes) {
8847 jqNodes = jqLite(jqNodes);
8848 var i = jqNodes.length;
8849
8850 if (i <= 1) {
8851 return jqNodes;
8852 }
8853
8854 while (i--) {
8855 var node = jqNodes[i];
8856 if (node.nodeType === NODE_TYPE_COMMENT) {
8857 splice.call(jqNodes, i, 1);
8858 }
8859 }
8860 return jqNodes;
8861 }
8862
8863 var $controllerMinErr = minErr('$controller');
8864
8865
8866 var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
8867 function identifierForController(controller, ident) {
8868 if (ident && isString(ident)) return ident;
8869 if (isString(controller)) {
8870 var match = CNTRL_REG.exec(controller);
8871 if (match) return match[3];
8872 }
8873 }
8874
8875
8876 /**
8877 * @ngdoc provider
8878 * @name $controllerProvider
8879 * @description
8880 * The {@link ng.$controller $controller service} is used by Angular to create new
8881 * controllers.
8882 *
8883 * This provider allows controller registration via the
8884 * {@link ng.$controllerProvider#register register} method.
8885 */
8886 function $ControllerProvider() {
8887 var controllers = {},
8888 globals = false;
8889
8890 /**
8891 * @ngdoc method
8892 * @name $controllerProvider#register
8893 * @param {string|Object} name Controller name, or an object map of controllers where the keys are
8894 * the names and the values are the constructors.
8895 * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
8896 * annotations in the array notation).
8897 */
8898 this.register = function(name, constructor) {
8899 assertNotHasOwnProperty(name, 'controller');
8900 if (isObject(name)) {
8901 extend(controllers, name);
8902 } else {
8903 controllers[name] = constructor;
8904 }
8905 };
8906
8907 /**
8908 * @ngdoc method
8909 * @name $controllerProvider#allowGlobals
8910 * @description If called, allows `$controller` to find controller constructors on `window`
8911 */
8912 this.allowGlobals = function() {
8913 globals = true;
8914 };
8915
8916
8917 this.$get = ['$injector', '$window', function($injector, $window) {
8918
8919 /**
8920 * @ngdoc service
8921 * @name $controller
8922 * @requires $injector
8923 *
8924 * @param {Function|string} constructor If called with a function then it's considered to be the
8925 * controller constructor function. Otherwise it's considered to be a string which is used
8926 * to retrieve the controller constructor using the following steps:
8927 *
8928 * * check if a controller with given name is registered via `$controllerProvider`
8929 * * check if evaluating the string on the current scope returns a constructor
8930 * * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
8931 * `window` object (not recommended)
8932 *
8933 * The string can use the `controller as property` syntax, where the controller instance is published
8934 * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
8935 * to work correctly.
8936 *
8937 * @param {Object} locals Injection locals for Controller.
8938 * @return {Object} Instance of given controller.
8939 *
8940 * @description
8941 * `$controller` service is responsible for instantiating controllers.
8942 *
8943 * It's just a simple call to {@link auto.$injector $injector}, but extracted into
8944 * a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
8945 */
8946 return function(expression, locals, later, ident) {
8947 // PRIVATE API:
8948 // param `later` --- indicates that the controller's constructor is invoked at a later time.
8949 // If true, $controller will allocate the object with the correct
8950 // prototype chain, but will not invoke the controller until a returned
8951 // callback is invoked.
8952 // param `ident` --- An optional label which overrides the label parsed from the controller
8953 // expression, if any.
8954 var instance, match, constructor, identifier;
8955 later = later === true;
8956 if (ident && isString(ident)) {
8957 identifier = ident;
8958 }
8959
8960 if (isString(expression)) {
8961 match = expression.match(CNTRL_REG);
8962 if (!match) {
8963 throw $controllerMinErr('ctrlfmt',
8964 "Badly formed controller string '{0}'. " +
8965 "Must match `__name__ as __id__` or `__name__`.", expression);
8966 }
8967 constructor = match[1],
8968 identifier = identifier || match[3];
8969 expression = controllers.hasOwnProperty(constructor)
8970 ? controllers[constructor]
8971 : getter(locals.$scope, constructor, true) ||
8972 (globals ? getter($window, constructor, true) : undefined);
8973
8974 assertArgFn(expression, constructor, true);
8975 }
8976
8977 if (later) {
8978 // Instantiate controller later:
8979 // This machinery is used to create an instance of the object before calling the
8980 // controller's constructor itself.
8981 //
8982 // This allows properties to be added to the controller before the constructor is
8983 // invoked. Primarily, this is used for isolate scope bindings in $compile.
8984 //
8985 // This feature is not intended for use by applications, and is thus not documented
8986 // publicly.
8987 // Object creation: http://jsperf.com/create-constructor/2
8988 var controllerPrototype = (isArray(expression) ?
8989 expression[expression.length - 1] : expression).prototype;
8990 instance = Object.create(controllerPrototype || null);
8991
8992 if (identifier) {
8993 addIdentifier(locals, identifier, instance, constructor || expression.name);
8994 }
8995
8996 var instantiate;
8997 return instantiate = extend(function() {
8998 var result = $injector.invoke(expression, instance, locals, constructor);
8999 if (result !== instance && (isObject(result) || isFunction(result))) {
9000 instance = result;
9001 if (identifier) {
9002 // If result changed, re-assign controllerAs value to scope.
9003 addIdentifier(locals, identifier, instance, constructor || expression.name);
9004 }
9005 }
9006 return instance;
9007 }, {
9008 instance: instance,
9009 identifier: identifier
9010 });
9011 }
9012
9013 instance = $injector.instantiate(expression, locals, constructor);
9014
9015 if (identifier) {
9016 addIdentifier(locals, identifier, instance, constructor || expression.name);
9017 }
9018
9019 return instance;
9020 };
9021
9022 function addIdentifier(locals, identifier, instance, name) {
9023 if (!(locals && isObject(locals.$scope))) {
9024 throw minErr('$controller')('noscp',
9025 "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
9026 name, identifier);
9027 }
9028
9029 locals.$scope[identifier] = instance;
9030 }
9031 }];
9032 }
9033
9034 /**
9035 * @ngdoc service
9036 * @name $document
9037 * @requires $window
9038 *
9039 * @description
9040 * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object.
9041 *
9042 * @example
9043 <example module="documentExample">
9044 <file name="index.html">
9045 <div ng-controller="ExampleController">
9046 <p>$document title: <b ng-bind="title"></b></p>
9047 <p>window.document title: <b ng-bind="windowTitle"></b></p>
9048 </div>
9049 </file>
9050 <file name="script.js">
9051 angular.module('documentExample', [])
9052 .controller('ExampleController', ['$scope', '$document', function($scope, $document) {
9053 $scope.title = $document[0].title;
9054 $scope.windowTitle = angular.element(window.document)[0].title;
9055 }]);
9056 </file>
9057 </example>
9058 */
9059 function $DocumentProvider() {
9060 this.$get = ['$window', function(window) {
9061 return jqLite(window.document);
9062 }];
9063 }
9064
9065 /**
9066 * @ngdoc service
9067 * @name $exceptionHandler
9068 * @requires ng.$log
9069 *
9070 * @description
9071 * Any uncaught exception in angular expressions is delegated to this service.
9072 * The default implementation simply delegates to `$log.error` which logs it into
9073 * the browser console.
9074 *
9075 * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
9076 * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
9077 *
9078 * ## Example:
9079 *
9080 * ```js
9081 * angular.module('exceptionOverride', []).factory('$exceptionHandler', function() {
9082 * return function(exception, cause) {
9083 * exception.message += ' (caused by "' + cause + '")';
9084 * throw exception;
9085 * };
9086 * });
9087 * ```
9088 *
9089 * This example will override the normal action of `$exceptionHandler`, to make angular
9090 * exceptions fail hard when they happen, instead of just logging to the console.
9091 *
9092 * <hr />
9093 * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind`
9094 * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler}
9095 * (unless executed during a digest).
9096 *
9097 * If you wish, you can manually delegate exceptions, e.g.
9098 * `try { ... } catch(e) { $exceptionHandler(e); }`
9099 *
9100 * @param {Error} exception Exception associated with the error.
9101 * @param {string=} cause optional information about the context in which
9102 * the error was thrown.
9103 *
9104 */
9105 function $ExceptionHandlerProvider() {
9106 this.$get = ['$log', function($log) {
9107 return function(exception, cause) {
9108 $log.error.apply($log, arguments);
9109 };
9110 }];
9111 }
9112
9113 var APPLICATION_JSON = 'application/json';
9114 var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
9115 var JSON_START = /^\[|^\{(?!\{)/;
9116 var JSON_ENDS = {
9117 '[': /]$/,
9118 '{': /}$/
9119 };
9120 var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
9121
9122 function serializeValue(v) {
9123 if (isObject(v)) {
9124 return isDate(v) ? v.toISOString() : toJson(v);
9125 }
9126 return v;
9127 }
9128
9129
9130 function $HttpParamSerializerProvider() {
9131 /**
9132 * @ngdoc service
9133 * @name $httpParamSerializer
9134 * @description
9135 *
9136 * Default {@link $http `$http`} params serializer that converts objects to strings
9137 * according to the following rules:
9138 *
9139 * * `{'foo': 'bar'}` results in `foo=bar`
9140 * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)
9141 * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)
9142 * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
9143 *
9144 * Note that serializer will sort the request parameters alphabetically.
9145 * */
9146
9147 this.$get = function() {
9148 return function ngParamSerializer(params) {
9149 if (!params) return '';
9150 var parts = [];
9151 forEachSorted(params, function(value, key) {
9152 if (value === null || isUndefined(value)) return;
9153 if (isArray(value)) {
9154 forEach(value, function(v, k) {
9155 parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v)));
9156 });
9157 } else {
9158 parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value)));
9159 }
9160 });
9161
9162 return parts.join('&');
9163 };
9164 };
9165 }
9166
9167 function $HttpParamSerializerJQLikeProvider() {
9168 /**
9169 * @ngdoc service
9170 * @name $httpParamSerializerJQLike
9171 * @description
9172 *
9173 * Alternative {@link $http `$http`} params serializer that follows
9174 * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic.
9175 * The serializer will also sort the params alphabetically.
9176 *
9177 * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property:
9178 *
9179 * ```js
9180 * $http({
9181 * url: myUrl,
9182 * method: 'GET',
9183 * params: myParams,
9184 * paramSerializer: '$httpParamSerializerJQLike'
9185 * });
9186 * ```
9187 *
9188 * It is also possible to set it as the default `paramSerializer` in the
9189 * {@link $httpProvider#defaults `$httpProvider`}.
9190 *
9191 * Additionally, you can inject the serializer and use it explicitly, for example to serialize
9192 * form data for submission:
9193 *
9194 * ```js
9195 * .controller(function($http, $httpParamSerializerJQLike) {
9196 * //...
9197 *
9198 * $http({
9199 * url: myUrl,
9200 * method: 'POST',
9201 * data: $httpParamSerializerJQLike(myData),
9202 * headers: {
9203 * 'Content-Type': 'application/x-www-form-urlencoded'
9204 * }
9205 * });
9206 *
9207 * });
9208 * ```
9209 *
9210 * */
9211 this.$get = function() {
9212 return function jQueryLikeParamSerializer(params) {
9213 if (!params) return '';
9214 var parts = [];
9215 serialize(params, '', true);
9216 return parts.join('&');
9217
9218 function serialize(toSerialize, prefix, topLevel) {
9219 if (toSerialize === null || isUndefined(toSerialize)) return;
9220 if (isArray(toSerialize)) {
9221 forEach(toSerialize, function(value) {
9222 serialize(value, prefix + '[]');
9223 });
9224 } else if (isObject(toSerialize) && !isDate(toSerialize)) {
9225 forEachSorted(toSerialize, function(value, key) {
9226 serialize(value, prefix +
9227 (topLevel ? '' : '[') +
9228 key +
9229 (topLevel ? '' : ']'));
9230 });
9231 } else {
9232 parts.push(encodeUriQuery(prefix) + '=' + encodeUriQuery(serializeValue(toSerialize)));
9233 }
9234 }
9235 };
9236 };
9237 }
9238
9239 function defaultHttpResponseTransform(data, headers) {
9240 if (isString(data)) {
9241 // Strip json vulnerability protection prefix and trim whitespace
9242 var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();
9243
9244 if (tempData) {
9245 var contentType = headers('Content-Type');
9246 if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
9247 data = fromJson(tempData);
9248 }
9249 }
9250 }
9251
9252 return data;
9253 }
9254
9255 function isJsonLike(str) {
9256 var jsonStart = str.match(JSON_START);
9257 return jsonStart && JSON_ENDS[jsonStart[0]].test(str);
9258 }
9259
9260 /**
9261 * Parse headers into key value object
9262 *
9263 * @param {string} headers Raw headers as a string
9264 * @returns {Object} Parsed headers as key value object
9265 */
9266 function parseHeaders(headers) {
9267 var parsed = createMap(), i;
9268
9269 function fillInParsed(key, val) {
9270 if (key) {
9271 parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
9272 }
9273 }
9274
9275 if (isString(headers)) {
9276 forEach(headers.split('\n'), function(line) {
9277 i = line.indexOf(':');
9278 fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1)));
9279 });
9280 } else if (isObject(headers)) {
9281 forEach(headers, function(headerVal, headerKey) {
9282 fillInParsed(lowercase(headerKey), trim(headerVal));
9283 });
9284 }
9285
9286 return parsed;
9287 }
9288
9289
9290 /**
9291 * Returns a function that provides access to parsed headers.
9292 *
9293 * Headers are lazy parsed when first requested.
9294 * @see parseHeaders
9295 *
9296 * @param {(string|Object)} headers Headers to provide access to.
9297 * @returns {function(string=)} Returns a getter function which if called with:
9298 *
9299 * - if called with single an argument returns a single header value or null
9300 * - if called with no arguments returns an object containing all headers.
9301 */
9302 function headersGetter(headers) {
9303 var headersObj;
9304
9305 return function(name) {
9306 if (!headersObj) headersObj = parseHeaders(headers);
9307
9308 if (name) {
9309 var value = headersObj[lowercase(name)];
9310 if (value === void 0) {
9311 value = null;
9312 }
9313 return value;
9314 }
9315
9316 return headersObj;
9317 };
9318 }
9319
9320
9321 /**
9322 * Chain all given functions
9323 *
9324 * This function is used for both request and response transforming
9325 *
9326 * @param {*} data Data to transform.
9327 * @param {function(string=)} headers HTTP headers getter fn.
9328 * @param {number} status HTTP status code of the response.
9329 * @param {(Function|Array.<Function>)} fns Function or an array of functions.
9330 * @returns {*} Transformed data.
9331 */
9332 function transformData(data, headers, status, fns) {
9333 if (isFunction(fns)) {
9334 return fns(data, headers, status);
9335 }
9336
9337 forEach(fns, function(fn) {
9338 data = fn(data, headers, status);
9339 });
9340
9341 return data;
9342 }
9343
9344
9345 function isSuccess(status) {
9346 return 200 <= status && status < 300;
9347 }
9348
9349
9350 /**
9351 * @ngdoc provider
9352 * @name $httpProvider
9353 * @description
9354 * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
9355 * */
9356 function $HttpProvider() {
9357 /**
9358 * @ngdoc property
9359 * @name $httpProvider#defaults
9360 * @description
9361 *
9362 * Object containing default values for all {@link ng.$http $http} requests.
9363 *
9364 * - **`defaults.cache`** - {Object} - an object built with {@link ng.$cacheFactory `$cacheFactory`}
9365 * that will provide the cache for all requests who set their `cache` property to `true`.
9366 * If you set the `defaults.cache = false` then only requests that specify their own custom
9367 * cache object will be cached. See {@link $http#caching $http Caching} for more information.
9368 *
9369 * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token.
9370 * Defaults value is `'XSRF-TOKEN'`.
9371 *
9372 * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
9373 * XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
9374 *
9375 * - **`defaults.headers`** - {Object} - Default headers for all $http requests.
9376 * Refer to {@link ng.$http#setting-http-headers $http} for documentation on
9377 * setting default headers.
9378 * - **`defaults.headers.common`**
9379 * - **`defaults.headers.post`**
9380 * - **`defaults.headers.put`**
9381 * - **`defaults.headers.patch`**
9382 *
9383 *
9384 * - **`defaults.paramSerializer`** - `{string|function(Object<string,string>):string}` - A function
9385 * used to the prepare string representation of request parameters (specified as an object).
9386 * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
9387 * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
9388 *
9389 **/
9390 var defaults = this.defaults = {
9391 // transform incoming response data
9392 transformResponse: [defaultHttpResponseTransform],
9393
9394 // transform outgoing request data
9395 transformRequest: [function(d) {
9396 return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d;
9397 }],
9398
9399 // default headers
9400 headers: {
9401 common: {
9402 'Accept': 'application/json, text/plain, */*'
9403 },
9404 post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
9405 put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON),
9406 patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON)
9407 },
9408
9409 xsrfCookieName: 'XSRF-TOKEN',
9410 xsrfHeaderName: 'X-XSRF-TOKEN',
9411
9412 paramSerializer: '$httpParamSerializer'
9413 };
9414
9415 var useApplyAsync = false;
9416 /**
9417 * @ngdoc method
9418 * @name $httpProvider#useApplyAsync
9419 * @description
9420 *
9421 * Configure $http service to combine processing of multiple http responses received at around
9422 * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in
9423 * significant performance improvement for bigger applications that make many HTTP requests
9424 * concurrently (common during application bootstrap).
9425 *
9426 * Defaults to false. If no value is specified, returns the current configured value.
9427 *
9428 * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred
9429 * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window
9430 * to load and share the same digest cycle.
9431 *
9432 * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining.
9433 * otherwise, returns the current configured value.
9434 **/
9435 this.useApplyAsync = function(value) {
9436 if (isDefined(value)) {
9437 useApplyAsync = !!value;
9438 return this;
9439 }
9440 return useApplyAsync;
9441 };
9442
9443 /**
9444 * @ngdoc property
9445 * @name $httpProvider#interceptors
9446 * @description
9447 *
9448 * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http}
9449 * pre-processing of request or postprocessing of responses.
9450 *
9451 * These service factories are ordered by request, i.e. they are applied in the same order as the
9452 * array, on request, but reverse order, on response.
9453 *
9454 * {@link ng.$http#interceptors Interceptors detailed info}
9455 **/
9456 var interceptorFactories = this.interceptors = [];
9457
9458 this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
9459 function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
9460
9461 var defaultCache = $cacheFactory('$http');
9462
9463 /**
9464 * Make sure that default param serializer is exposed as a function
9465 */
9466 defaults.paramSerializer = isString(defaults.paramSerializer) ?
9467 $injector.get(defaults.paramSerializer) : defaults.paramSerializer;
9468
9469 /**
9470 * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
9471 * The reversal is needed so that we can build up the interception chain around the
9472 * server request.
9473 */
9474 var reversedInterceptors = [];
9475
9476 forEach(interceptorFactories, function(interceptorFactory) {
9477 reversedInterceptors.unshift(isString(interceptorFactory)
9478 ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
9479 });
9480
9481 /**
9482 * @ngdoc service
9483 * @kind function
9484 * @name $http
9485 * @requires ng.$httpBackend
9486 * @requires $cacheFactory
9487 * @requires $rootScope
9488 * @requires $q
9489 * @requires $injector
9490 *
9491 * @description
9492 * The `$http` service is a core Angular service that facilitates communication with the remote
9493 * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest)
9494 * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP).
9495 *
9496 * For unit testing applications that use `$http` service, see
9497 * {@link ngMock.$httpBackend $httpBackend mock}.
9498 *
9499 * For a higher level of abstraction, please check out the {@link ngResource.$resource
9500 * $resource} service.
9501 *
9502 * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
9503 * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
9504 * it is important to familiarize yourself with these APIs and the guarantees they provide.
9505 *
9506 *
9507 * ## General usage
9508 * The `$http` service is a function which takes a single argument — a configuration object —
9509 * that is used to generate an HTTP request and returns a {@link ng.$q promise}
9510 * with two $http specific methods: `success` and `error`.
9511 *
9512 * ```js
9513 * // Simple GET request example :
9514 * $http.get('/someUrl').
9515 * success(function(data, status, headers, config) {
9516 * // this callback will be called asynchronously
9517 * // when the response is available
9518 * }).
9519 * error(function(data, status, headers, config) {
9520 * // called asynchronously if an error occurs
9521 * // or server returns response with an error status.
9522 * });
9523 * ```
9524 *
9525 * ```js
9526 * // Simple POST request example (passing data) :
9527 * $http.post('/someUrl', {msg:'hello word!'}).
9528 * success(function(data, status, headers, config) {
9529 * // this callback will be called asynchronously
9530 * // when the response is available
9531 * }).
9532 * error(function(data, status, headers, config) {
9533 * // called asynchronously if an error occurs
9534 * // or server returns response with an error status.
9535 * });
9536 * ```
9537 *
9538 *
9539 * Since the returned value of calling the $http function is a `promise`, you can also use
9540 * the `then` method to register callbacks, and these callbacks will receive a single argument –
9541 * an object representing the response. See the API signature and type info below for more
9542 * details.
9543 *
9544 * A response status code between 200 and 299 is considered a success status and
9545 * will result in the success callback being called. Note that if the response is a redirect,
9546 * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
9547 * called for such responses.
9548 *
9549 * ## Writing Unit Tests that use $http
9550 * When unit testing (using {@link ngMock ngMock}), it is necessary to call
9551 * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending
9552 * request using trained responses.
9553 *
9554 * ```
9555 * $httpBackend.expectGET(...);
9556 * $http.get(...);
9557 * $httpBackend.flush();
9558 * ```
9559 *
9560 * ## Shortcut methods
9561 *
9562 * Shortcut methods are also available. All shortcut methods require passing in the URL, and
9563 * request data must be passed in for POST/PUT requests.
9564 *
9565 * ```js
9566 * $http.get('/someUrl').success(successCallback);
9567 * $http.post('/someUrl', data).success(successCallback);
9568 * ```
9569 *
9570 * Complete list of shortcut methods:
9571 *
9572 * - {@link ng.$http#get $http.get}
9573 * - {@link ng.$http#head $http.head}
9574 * - {@link ng.$http#post $http.post}
9575 * - {@link ng.$http#put $http.put}
9576 * - {@link ng.$http#delete $http.delete}
9577 * - {@link ng.$http#jsonp $http.jsonp}
9578 * - {@link ng.$http#patch $http.patch}
9579 *
9580 *
9581 * ## Setting HTTP Headers
9582 *
9583 * The $http service will automatically add certain HTTP headers to all requests. These defaults
9584 * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
9585 * object, which currently contains this default configuration:
9586 *
9587 * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
9588 * - `Accept: application/json, text/plain, * / *`
9589 * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
9590 * - `Content-Type: application/json`
9591 * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
9592 * - `Content-Type: application/json`
9593 *
9594 * To add or overwrite these defaults, simply add or remove a property from these configuration
9595 * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
9596 * with the lowercased HTTP method name as the key, e.g.
9597 * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`.
9598 *
9599 * The defaults can also be set at runtime via the `$http.defaults` object in the same
9600 * fashion. For example:
9601 *
9602 * ```
9603 * module.run(function($http) {
9604 * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'
9605 * });
9606 * ```
9607 *
9608 * In addition, you can supply a `headers` property in the config object passed when
9609 * calling `$http(config)`, which overrides the defaults without changing them globally.
9610 *
9611 * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis,
9612 * Use the `headers` property, setting the desired header to `undefined`. For example:
9613 *
9614 * ```js
9615 * var req = {
9616 * method: 'POST',
9617 * url: 'http://example.com',
9618 * headers: {
9619 * 'Content-Type': undefined
9620 * },
9621 * data: { test: 'test' }
9622 * }
9623 *
9624 * $http(req).success(function(){...}).error(function(){...});
9625 * ```
9626 *
9627 * ## Transforming Requests and Responses
9628 *
9629 * Both requests and responses can be transformed using transformation functions: `transformRequest`
9630 * and `transformResponse`. These properties can be a single function that returns
9631 * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions,
9632 * which allows you to `push` or `unshift` a new transformation function into the transformation chain.
9633 *
9634 * ### Default Transformations
9635 *
9636 * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and
9637 * `defaults.transformResponse` properties. If a request does not provide its own transformations
9638 * then these will be applied.
9639 *
9640 * You can augment or replace the default transformations by modifying these properties by adding to or
9641 * replacing the array.
9642 *
9643 * Angular provides the following default transformations:
9644 *
9645 * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`):
9646 *
9647 * - If the `data` property of the request configuration object contains an object, serialize it
9648 * into JSON format.
9649 *
9650 * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`):
9651 *
9652 * - If XSRF prefix is detected, strip it (see Security Considerations section below).
9653 * - If JSON response is detected, deserialize it using a JSON parser.
9654 *
9655 *
9656 * ### Overriding the Default Transformations Per Request
9657 *
9658 * If you wish override the request/response transformations only for a single request then provide
9659 * `transformRequest` and/or `transformResponse` properties on the configuration object passed
9660 * into `$http`.
9661 *
9662 * Note that if you provide these properties on the config object the default transformations will be
9663 * overwritten. If you wish to augment the default transformations then you must include them in your
9664 * local transformation array.
9665 *
9666 * The following code demonstrates adding a new response transformation to be run after the default response
9667 * transformations have been run.
9668 *
9669 * ```js
9670 * function appendTransform(defaults, transform) {
9671 *
9672 * // We can't guarantee that the default transformation is an array
9673 * defaults = angular.isArray(defaults) ? defaults : [defaults];
9674 *
9675 * // Append the new transformation to the defaults
9676 * return defaults.concat(transform);
9677 * }
9678 *
9679 * $http({
9680 * url: '...',
9681 * method: 'GET',
9682 * transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
9683 * return doTransform(value);
9684 * })
9685 * });
9686 * ```
9687 *
9688 *
9689 * ## Caching
9690 *
9691 * To enable caching, set the request configuration `cache` property to `true` (to use default
9692 * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
9693 * When the cache is enabled, `$http` stores the response from the server in the specified
9694 * cache. The next time the same request is made, the response is served from the cache without
9695 * sending a request to the server.
9696 *
9697 * Note that even if the response is served from cache, delivery of the data is asynchronous in
9698 * the same way that real requests are.
9699 *
9700 * If there are multiple GET requests for the same URL that should be cached using the same
9701 * cache, but the cache is not populated yet, only one request to the server will be made and
9702 * the remaining requests will be fulfilled using the response from the first request.
9703 *
9704 * You can change the default cache to a new object (built with
9705 * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
9706 * {@link ng.$http#defaults `$http.defaults.cache`} property. All requests who set
9707 * their `cache` property to `true` will now use this cache object.
9708 *
9709 * If you set the default cache to `false` then only requests that specify their own custom
9710 * cache object will be cached.
9711 *
9712 * ## Interceptors
9713 *
9714 * Before you start creating interceptors, be sure to understand the
9715 * {@link ng.$q $q and deferred/promise APIs}.
9716 *
9717 * For purposes of global error handling, authentication, or any kind of synchronous or
9718 * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
9719 * able to intercept requests before they are handed to the server and
9720 * responses before they are handed over to the application code that
9721 * initiated these requests. The interceptors leverage the {@link ng.$q
9722 * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
9723 *
9724 * The interceptors are service factories that are registered with the `$httpProvider` by
9725 * adding them to the `$httpProvider.interceptors` array. The factory is called and
9726 * injected with dependencies (if specified) and returns the interceptor.
9727 *
9728 * There are two kinds of interceptors (and two kinds of rejection interceptors):
9729 *
9730 * * `request`: interceptors get called with a http `config` object. The function is free to
9731 * modify the `config` object or create a new one. The function needs to return the `config`
9732 * object directly, or a promise containing the `config` or a new `config` object.
9733 * * `requestError`: interceptor gets called when a previous interceptor threw an error or
9734 * resolved with a rejection.
9735 * * `response`: interceptors get called with http `response` object. The function is free to
9736 * modify the `response` object or create a new one. The function needs to return the `response`
9737 * object directly, or as a promise containing the `response` or a new `response` object.
9738 * * `responseError`: interceptor gets called when a previous interceptor threw an error or
9739 * resolved with a rejection.
9740 *
9741 *
9742 * ```js
9743 * // register the interceptor as a service
9744 * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
9745 * return {
9746 * // optional method
9747 * 'request': function(config) {
9748 * // do something on success
9749 * return config;
9750 * },
9751 *
9752 * // optional method
9753 * 'requestError': function(rejection) {
9754 * // do something on error
9755 * if (canRecover(rejection)) {
9756 * return responseOrNewPromise
9757 * }
9758 * return $q.reject(rejection);
9759 * },
9760 *
9761 *
9762 *
9763 * // optional method
9764 * 'response': function(response) {
9765 * // do something on success
9766 * return response;
9767 * },
9768 *
9769 * // optional method
9770 * 'responseError': function(rejection) {
9771 * // do something on error
9772 * if (canRecover(rejection)) {
9773 * return responseOrNewPromise
9774 * }
9775 * return $q.reject(rejection);
9776 * }
9777 * };
9778 * });
9779 *
9780 * $httpProvider.interceptors.push('myHttpInterceptor');
9781 *
9782 *
9783 * // alternatively, register the interceptor via an anonymous factory
9784 * $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
9785 * return {
9786 * 'request': function(config) {
9787 * // same as above
9788 * },
9789 *
9790 * 'response': function(response) {
9791 * // same as above
9792 * }
9793 * };
9794 * });
9795 * ```
9796 *
9797 * ## Security Considerations
9798 *
9799 * When designing web applications, consider security threats from:
9800 *
9801 * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
9802 * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery)
9803 *
9804 * Both server and the client must cooperate in order to eliminate these threats. Angular comes
9805 * pre-configured with strategies that address these issues, but for this to work backend server
9806 * cooperation is required.
9807 *
9808 * ### JSON Vulnerability Protection
9809 *
9810 * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx)
9811 * allows third party website to turn your JSON resource URL into
9812 * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To
9813 * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
9814 * Angular will automatically strip the prefix before processing it as JSON.
9815 *
9816 * For example if your server needs to return:
9817 * ```js
9818 * ['one','two']
9819 * ```
9820 *
9821 * which is vulnerable to attack, your server can return:
9822 * ```js
9823 * )]}',
9824 * ['one','two']
9825 * ```
9826 *
9827 * Angular will strip the prefix, before processing the JSON.
9828 *
9829 *
9830 * ### Cross Site Request Forgery (XSRF) Protection
9831 *
9832 * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is a technique by which
9833 * an unauthorized site can gain your user's private data. Angular provides a mechanism
9834 * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
9835 * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
9836 * JavaScript that runs on your domain could read the cookie, your server can be assured that
9837 * the XHR came from JavaScript running on your domain. The header will not be set for
9838 * cross-domain requests.
9839 *
9840 * To take advantage of this, your server needs to set a token in a JavaScript readable session
9841 * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
9842 * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
9843 * that only JavaScript running on your domain could have sent the request. The token must be
9844 * unique for each user and must be verifiable by the server (to prevent the JavaScript from
9845 * making up its own tokens). We recommend that the token is a digest of your site's
9846 * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography&#41;)
9847 * for added security.
9848 *
9849 * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
9850 * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
9851 * or the per-request config object.
9852 *
9853 * In order to prevent collisions in environments where multiple Angular apps share the
9854 * same domain or subdomain, we recommend that each application uses unique cookie name.
9855 *
9856 *
9857 * @param {object} config Object describing the request to be made and how it should be
9858 * processed. The object has following properties:
9859 *
9860 * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
9861 * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
9862 * - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized
9863 * with the `paramSerializer` and appended as GET parameters.
9864 * - **data** – `{string|Object}` – Data to be sent as the request message data.
9865 * - **headers** – `{Object}` – Map of strings or functions which return strings representing
9866 * HTTP headers to send to the server. If the return value of a function is null, the
9867 * header will not be sent. Functions accept a config object as an argument.
9868 * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
9869 * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
9870 * - **transformRequest** –
9871 * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
9872 * transform function or an array of such functions. The transform function takes the http
9873 * request body and headers and returns its transformed (typically serialized) version.
9874 * See {@link ng.$http#overriding-the-default-transformations-per-request
9875 * Overriding the Default Transformations}
9876 * - **transformResponse** –
9877 * `{function(data, headersGetter, status)|Array.<function(data, headersGetter, status)>}` –
9878 * transform function or an array of such functions. The transform function takes the http
9879 * response body, headers and status and returns its transformed (typically deserialized) version.
9880 * See {@link ng.$http#overriding-the-default-transformations-per-request
9881 * Overriding the Default TransformationjqLiks}
9882 * - **paramSerializer** - `{string|function(Object<string,string>):string}` - A function used to
9883 * prepare the string representation of request parameters (specified as an object).
9884 * If specified as string, it is interpreted as function registered with the
9885 * {@link $injector $injector}, which means you can create your own serializer
9886 * by registering it as a {@link auto.$provide#service service}.
9887 * The default serializer is the {@link $httpParamSerializer $httpParamSerializer};
9888 * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike}
9889 * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
9890 * GET request, otherwise if a cache instance built with
9891 * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
9892 * caching.
9893 * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
9894 * that should abort the request when resolved.
9895 * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the
9896 * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials)
9897 * for more information.
9898 * - **responseType** - `{string}` - see
9899 * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype).
9900 *
9901 * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
9902 * standard `then` method and two http specific methods: `success` and `error`. The `then`
9903 * method takes two arguments a success and an error callback which will be called with a
9904 * response object. The `success` and `error` methods take a single argument - a function that
9905 * will be called when the request succeeds or fails respectively. The arguments passed into
9906 * these functions are destructured representation of the response object passed into the
9907 * `then` method. The response object has these properties:
9908 *
9909 * - **data** – `{string|Object}` – The response body transformed with the transform
9910 * functions.
9911 * - **status** – `{number}` – HTTP status code of the response.
9912 * - **headers** – `{function([headerName])}` – Header getter function.
9913 * - **config** – `{Object}` – The configuration object that was used to generate the request.
9914 * - **statusText** – `{string}` – HTTP status text of the response.
9915 *
9916 * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
9917 * requests. This is primarily meant to be used for debugging purposes.
9918 *
9919 *
9920 * @example
9921 <example module="httpExample">
9922 <file name="index.html">
9923 <div ng-controller="FetchController">
9924 <select ng-model="method" aria-label="Request method">
9925 <option>GET</option>
9926 <option>JSONP</option>
9927 </select>
9928 <input type="text" ng-model="url" size="80" aria-label="URL" />
9929 <button id="fetchbtn" ng-click="fetch()">fetch</button><br>
9930 <button id="samplegetbtn" ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
9931 <button id="samplejsonpbtn"
9932 ng-click="updateModel('JSONP',
9933 'https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
9934 Sample JSONP
9935 </button>
9936 <button id="invalidjsonpbtn"
9937 ng-click="updateModel('JSONP', 'https://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
9938 Invalid JSONP
9939 </button>
9940 <pre>http status code: {{status}}</pre>
9941 <pre>http response data: {{data}}</pre>
9942 </div>
9943 </file>
9944 <file name="script.js">
9945 angular.module('httpExample', [])
9946 .controller('FetchController', ['$scope', '$http', '$templateCache',
9947 function($scope, $http, $templateCache) {
9948 $scope.method = 'GET';
9949 $scope.url = 'http-hello.html';
9950
9951 $scope.fetch = function() {
9952 $scope.code = null;
9953 $scope.response = null;
9954
9955 $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
9956 success(function(data, status) {
9957 $scope.status = status;
9958 $scope.data = data;
9959 }).
9960 error(function(data, status) {
9961 $scope.data = data || "Request failed";
9962 $scope.status = status;
9963 });
9964 };
9965
9966 $scope.updateModel = function(method, url) {
9967 $scope.method = method;
9968 $scope.url = url;
9969 };
9970 }]);
9971 </file>
9972 <file name="http-hello.html">
9973 Hello, $http!
9974 </file>
9975 <file name="protractor.js" type="protractor">
9976 var status = element(by.binding('status'));
9977 var data = element(by.binding('data'));
9978 var fetchBtn = element(by.id('fetchbtn'));
9979 var sampleGetBtn = element(by.id('samplegetbtn'));
9980 var sampleJsonpBtn = element(by.id('samplejsonpbtn'));
9981 var invalidJsonpBtn = element(by.id('invalidjsonpbtn'));
9982
9983 it('should make an xhr GET request', function() {
9984 sampleGetBtn.click();
9985 fetchBtn.click();
9986 expect(status.getText()).toMatch('200');
9987 expect(data.getText()).toMatch(/Hello, \$http!/);
9988 });
9989
9990 // Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185
9991 // it('should make a JSONP request to angularjs.org', function() {
9992 // sampleJsonpBtn.click();
9993 // fetchBtn.click();
9994 // expect(status.getText()).toMatch('200');
9995 // expect(data.getText()).toMatch(/Super Hero!/);
9996 // });
9997
9998 it('should make JSONP request to invalid URL and invoke the error handler',
9999 function() {
10000 invalidJsonpBtn.click();
10001 fetchBtn.click();
10002 expect(status.getText()).toMatch('0');
10003 expect(data.getText()).toMatch('Request failed');
10004 });
10005 </file>
10006 </example>
10007 */
10008 function $http(requestConfig) {
10009
10010 if (!angular.isObject(requestConfig)) {
10011 throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig);
10012 }
10013
10014 var config = extend({
10015 method: 'get',
10016 transformRequest: defaults.transformRequest,
10017 transformResponse: defaults.transformResponse,
10018 paramSerializer: defaults.paramSerializer
10019 }, requestConfig);
10020
10021 config.headers = mergeHeaders(requestConfig);
10022 config.method = uppercase(config.method);
10023 config.paramSerializer = isString(config.paramSerializer) ?
10024 $injector.get(config.paramSerializer) : config.paramSerializer;
10025
10026 var serverRequest = function(config) {
10027 var headers = config.headers;
10028 var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest);
10029
10030 // strip content-type if data is undefined
10031 if (isUndefined(reqData)) {
10032 forEach(headers, function(value, header) {
10033 if (lowercase(header) === 'content-type') {
10034 delete headers[header];
10035 }
10036 });
10037 }
10038
10039 if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
10040 config.withCredentials = defaults.withCredentials;
10041 }
10042
10043 // send request
10044 return sendReq(config, reqData).then(transformResponse, transformResponse);
10045 };
10046
10047 var chain = [serverRequest, undefined];
10048 var promise = $q.when(config);
10049
10050 // apply interceptors
10051 forEach(reversedInterceptors, function(interceptor) {
10052 if (interceptor.request || interceptor.requestError) {
10053 chain.unshift(interceptor.request, interceptor.requestError);
10054 }
10055 if (interceptor.response || interceptor.responseError) {
10056 chain.push(interceptor.response, interceptor.responseError);
10057 }
10058 });
10059
10060 while (chain.length) {
10061 var thenFn = chain.shift();
10062 var rejectFn = chain.shift();
10063
10064 promise = promise.then(thenFn, rejectFn);
10065 }
10066
10067 promise.success = function(fn) {
10068 assertArgFn(fn, 'fn');
10069
10070 promise.then(function(response) {
10071 fn(response.data, response.status, response.headers, config);
10072 });
10073 return promise;
10074 };
10075
10076 promise.error = function(fn) {
10077 assertArgFn(fn, 'fn');
10078
10079 promise.then(null, function(response) {
10080 fn(response.data, response.status, response.headers, config);
10081 });
10082 return promise;
10083 };
10084
10085 return promise;
10086
10087 function transformResponse(response) {
10088 // make a copy since the response must be cacheable
10089 var resp = extend({}, response);
10090 if (!response.data) {
10091 resp.data = response.data;
10092 } else {
10093 resp.data = transformData(response.data, response.headers, response.status, config.transformResponse);
10094 }
10095 return (isSuccess(response.status))
10096 ? resp
10097 : $q.reject(resp);
10098 }
10099
10100 function executeHeaderFns(headers, config) {
10101 var headerContent, processedHeaders = {};
10102
10103 forEach(headers, function(headerFn, header) {
10104 if (isFunction(headerFn)) {
10105 headerContent = headerFn(config);
10106 if (headerContent != null) {
10107 processedHeaders[header] = headerContent;
10108 }
10109 } else {
10110 processedHeaders[header] = headerFn;
10111 }
10112 });
10113
10114 return processedHeaders;
10115 }
10116
10117 function mergeHeaders(config) {
10118 var defHeaders = defaults.headers,
10119 reqHeaders = extend({}, config.headers),
10120 defHeaderName, lowercaseDefHeaderName, reqHeaderName;
10121
10122 defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
10123
10124 // using for-in instead of forEach to avoid unecessary iteration after header has been found
10125 defaultHeadersIteration:
10126 for (defHeaderName in defHeaders) {
10127 lowercaseDefHeaderName = lowercase(defHeaderName);
10128
10129 for (reqHeaderName in reqHeaders) {
10130 if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
10131 continue defaultHeadersIteration;
10132 }
10133 }
10134
10135 reqHeaders[defHeaderName] = defHeaders[defHeaderName];
10136 }
10137
10138 // execute if header value is a function for merged headers
10139 return executeHeaderFns(reqHeaders, shallowCopy(config));
10140 }
10141 }
10142
10143 $http.pendingRequests = [];
10144
10145 /**
10146 * @ngdoc method
10147 * @name $http#get
10148 *
10149 * @description
10150 * Shortcut method to perform `GET` request.
10151 *
10152 * @param {string} url Relative or absolute URL specifying the destination of the request
10153 * @param {Object=} config Optional configuration object
10154 * @returns {HttpPromise} Future object
10155 */
10156
10157 /**
10158 * @ngdoc method
10159 * @name $http#delete
10160 *
10161 * @description
10162 * Shortcut method to perform `DELETE` request.
10163 *
10164 * @param {string} url Relative or absolute URL specifying the destination of the request
10165 * @param {Object=} config Optional configuration object
10166 * @returns {HttpPromise} Future object
10167 */
10168
10169 /**
10170 * @ngdoc method
10171 * @name $http#head
10172 *
10173 * @description
10174 * Shortcut method to perform `HEAD` request.
10175 *
10176 * @param {string} url Relative or absolute URL specifying the destination of the request
10177 * @param {Object=} config Optional configuration object
10178 * @returns {HttpPromise} Future object
10179 */
10180
10181 /**
10182 * @ngdoc method
10183 * @name $http#jsonp
10184 *
10185 * @description
10186 * Shortcut method to perform `JSONP` request.
10187 *
10188 * @param {string} url Relative or absolute URL specifying the destination of the request.
10189 * The name of the callback should be the string `JSON_CALLBACK`.
10190 * @param {Object=} config Optional configuration object
10191 * @returns {HttpPromise} Future object
10192 */
10193 createShortMethods('get', 'delete', 'head', 'jsonp');
10194
10195 /**
10196 * @ngdoc method
10197 * @name $http#post
10198 *
10199 * @description
10200 * Shortcut method to perform `POST` request.
10201 *
10202 * @param {string} url Relative or absolute URL specifying the destination of the request
10203 * @param {*} data Request content
10204 * @param {Object=} config Optional configuration object
10205 * @returns {HttpPromise} Future object
10206 */
10207
10208 /**
10209 * @ngdoc method
10210 * @name $http#put
10211 *
10212 * @description
10213 * Shortcut method to perform `PUT` request.
10214 *
10215 * @param {string} url Relative or absolute URL specifying the destination of the request
10216 * @param {*} data Request content
10217 * @param {Object=} config Optional configuration object
10218 * @returns {HttpPromise} Future object
10219 */
10220
10221 /**
10222 * @ngdoc method
10223 * @name $http#patch
10224 *
10225 * @description
10226 * Shortcut method to perform `PATCH` request.
10227 *
10228 * @param {string} url Relative or absolute URL specifying the destination of the request
10229 * @param {*} data Request content
10230 * @param {Object=} config Optional configuration object
10231 * @returns {HttpPromise} Future object
10232 */
10233 createShortMethodsWithData('post', 'put', 'patch');
10234
10235 /**
10236 * @ngdoc property
10237 * @name $http#defaults
10238 *
10239 * @description
10240 * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
10241 * default headers, withCredentials as well as request and response transformations.
10242 *
10243 * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
10244 */
10245 $http.defaults = defaults;
10246
10247
10248 return $http;
10249
10250
10251 function createShortMethods(names) {
10252 forEach(arguments, function(name) {
10253 $http[name] = function(url, config) {
10254 return $http(extend({}, config || {}, {
10255 method: name,
10256 url: url
10257 }));
10258 };
10259 });
10260 }
10261
10262
10263 function createShortMethodsWithData(name) {
10264 forEach(arguments, function(name) {
10265 $http[name] = function(url, data, config) {
10266 return $http(extend({}, config || {}, {
10267 method: name,
10268 url: url,
10269 data: data
10270 }));
10271 };
10272 });
10273 }
10274
10275
10276 /**
10277 * Makes the request.
10278 *
10279 * !!! ACCESSES CLOSURE VARS:
10280 * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
10281 */
10282 function sendReq(config, reqData) {
10283 var deferred = $q.defer(),
10284 promise = deferred.promise,
10285 cache,
10286 cachedResp,
10287 reqHeaders = config.headers,
10288 url = buildUrl(config.url, config.paramSerializer(config.params));
10289
10290 $http.pendingRequests.push(config);
10291 promise.then(removePendingReq, removePendingReq);
10292
10293
10294 if ((config.cache || defaults.cache) && config.cache !== false &&
10295 (config.method === 'GET' || config.method === 'JSONP')) {
10296 cache = isObject(config.cache) ? config.cache
10297 : isObject(defaults.cache) ? defaults.cache
10298 : defaultCache;
10299 }
10300
10301 if (cache) {
10302 cachedResp = cache.get(url);
10303 if (isDefined(cachedResp)) {
10304 if (isPromiseLike(cachedResp)) {
10305 // cached request has already been sent, but there is no response yet
10306 cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult);
10307 } else {
10308 // serving from cache
10309 if (isArray(cachedResp)) {
10310 resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3]);
10311 } else {
10312 resolvePromise(cachedResp, 200, {}, 'OK');
10313 }
10314 }
10315 } else {
10316 // put the promise for the non-transformed response into cache as a placeholder
10317 cache.put(url, promise);
10318 }
10319 }
10320
10321
10322 // if we won't have the response in cache, set the xsrf headers and
10323 // send the request to the backend
10324 if (isUndefined(cachedResp)) {
10325 var xsrfValue = urlIsSameOrigin(config.url)
10326 ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
10327 : undefined;
10328 if (xsrfValue) {
10329 reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
10330 }
10331
10332 $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
10333 config.withCredentials, config.responseType);
10334 }
10335
10336 return promise;
10337
10338
10339 /**
10340 * Callback registered to $httpBackend():
10341 * - caches the response if desired
10342 * - resolves the raw $http promise
10343 * - calls $apply
10344 */
10345 function done(status, response, headersString, statusText) {
10346 if (cache) {
10347 if (isSuccess(status)) {
10348 cache.put(url, [status, response, parseHeaders(headersString), statusText]);
10349 } else {
10350 // remove promise from the cache
10351 cache.remove(url);
10352 }
10353 }
10354
10355 function resolveHttpPromise() {
10356 resolvePromise(response, status, headersString, statusText);
10357 }
10358
10359 if (useApplyAsync) {
10360 $rootScope.$applyAsync(resolveHttpPromise);
10361 } else {
10362 resolveHttpPromise();
10363 if (!$rootScope.$$phase) $rootScope.$apply();
10364 }
10365 }
10366
10367
10368 /**
10369 * Resolves the raw $http promise.
10370 */
10371 function resolvePromise(response, status, headers, statusText) {
10372 // normalize internal statuses to 0
10373 status = Math.max(status, 0);
10374
10375 (isSuccess(status) ? deferred.resolve : deferred.reject)({
10376 data: response,
10377 status: status,
10378 headers: headersGetter(headers),
10379 config: config,
10380 statusText: statusText
10381 });
10382 }
10383
10384 function resolvePromiseWithResult(result) {
10385 resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText);
10386 }
10387
10388 function removePendingReq() {
10389 var idx = $http.pendingRequests.indexOf(config);
10390 if (idx !== -1) $http.pendingRequests.splice(idx, 1);
10391 }
10392 }
10393
10394
10395 function buildUrl(url, serializedParams) {
10396 if (serializedParams.length > 0) {
10397 url += ((url.indexOf('?') == -1) ? '?' : '&') + serializedParams;
10398 }
10399 return url;
10400 }
10401 }];
10402 }
10403
10404 function createXhr() {
10405 return new window.XMLHttpRequest();
10406 }
10407
10408 /**
10409 * @ngdoc service
10410 * @name $httpBackend
10411 * @requires $window
10412 * @requires $document
10413 *
10414 * @description
10415 * HTTP backend used by the {@link ng.$http service} that delegates to
10416 * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
10417 *
10418 * You should never need to use this service directly, instead use the higher-level abstractions:
10419 * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
10420 *
10421 * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
10422 * $httpBackend} which can be trained with responses.
10423 */
10424 function $HttpBackendProvider() {
10425 this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
10426 return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]);
10427 }];
10428 }
10429
10430 function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) {
10431 // TODO(vojta): fix the signature
10432 return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
10433 $browser.$$incOutstandingRequestCount();
10434 url = url || $browser.url();
10435
10436 if (lowercase(method) == 'jsonp') {
10437 var callbackId = '_' + (callbacks.counter++).toString(36);
10438 callbacks[callbackId] = function(data) {
10439 callbacks[callbackId].data = data;
10440 callbacks[callbackId].called = true;
10441 };
10442
10443 var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
10444 callbackId, function(status, text) {
10445 completeRequest(callback, status, callbacks[callbackId].data, "", text);
10446 callbacks[callbackId] = noop;
10447 });
10448 } else {
10449
10450 var xhr = createXhr();
10451
10452 xhr.open(method, url, true);
10453 forEach(headers, function(value, key) {
10454 if (isDefined(value)) {
10455 xhr.setRequestHeader(key, value);
10456 }
10457 });
10458
10459 xhr.onload = function requestLoaded() {
10460 var statusText = xhr.statusText || '';
10461
10462 // responseText is the old-school way of retrieving response (supported by IE8 & 9)
10463 // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
10464 var response = ('response' in xhr) ? xhr.response : xhr.responseText;
10465
10466 // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
10467 var status = xhr.status === 1223 ? 204 : xhr.status;
10468
10469 // fix status code when it is 0 (0 status is undocumented).
10470 // Occurs when accessing file resources or on Android 4.1 stock browser
10471 // while retrieving files from application cache.
10472 if (status === 0) {
10473 status = response ? 200 : urlResolve(url).protocol == 'file' ? 404 : 0;
10474 }
10475
10476 completeRequest(callback,
10477 status,
10478 response,
10479 xhr.getAllResponseHeaders(),
10480 statusText);
10481 };
10482
10483 var requestError = function() {
10484 // The response is always empty
10485 // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error
10486 completeRequest(callback, -1, null, null, '');
10487 };
10488
10489 xhr.onerror = requestError;
10490 xhr.onabort = requestError;
10491
10492 if (withCredentials) {
10493 xhr.withCredentials = true;
10494 }
10495
10496 if (responseType) {
10497 try {
10498 xhr.responseType = responseType;
10499 } catch (e) {
10500 // WebKit added support for the json responseType value on 09/03/2013
10501 // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are
10502 // known to throw when setting the value "json" as the response type. Other older
10503 // browsers implementing the responseType
10504 //
10505 // The json response type can be ignored if not supported, because JSON payloads are
10506 // parsed on the client-side regardless.
10507 if (responseType !== 'json') {
10508 throw e;
10509 }
10510 }
10511 }
10512
10513 xhr.send(post);
10514 }
10515
10516 if (timeout > 0) {
10517 var timeoutId = $browserDefer(timeoutRequest, timeout);
10518 } else if (isPromiseLike(timeout)) {
10519 timeout.then(timeoutRequest);
10520 }
10521
10522
10523 function timeoutRequest() {
10524 jsonpDone && jsonpDone();
10525 xhr && xhr.abort();
10526 }
10527
10528 function completeRequest(callback, status, response, headersString, statusText) {
10529 // cancel timeout and subsequent timeout promise resolution
10530 if (timeoutId !== undefined) {
10531 $browserDefer.cancel(timeoutId);
10532 }
10533 jsonpDone = xhr = null;
10534
10535 callback(status, response, headersString, statusText);
10536 $browser.$$completeOutstandingRequest(noop);
10537 }
10538 };
10539
10540 function jsonpReq(url, callbackId, done) {
10541 // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.:
10542 // - fetches local scripts via XHR and evals them
10543 // - adds and immediately removes script elements from the document
10544 var script = rawDocument.createElement('script'), callback = null;
10545 script.type = "text/javascript";
10546 script.src = url;
10547 script.async = true;
10548
10549 callback = function(event) {
10550 removeEventListenerFn(script, "load", callback);
10551 removeEventListenerFn(script, "error", callback);
10552 rawDocument.body.removeChild(script);
10553 script = null;
10554 var status = -1;
10555 var text = "unknown";
10556
10557 if (event) {
10558 if (event.type === "load" && !callbacks[callbackId].called) {
10559 event = { type: "error" };
10560 }
10561 text = event.type;
10562 status = event.type === "error" ? 404 : 200;
10563 }
10564
10565 if (done) {
10566 done(status, text);
10567 }
10568 };
10569
10570 addEventListenerFn(script, "load", callback);
10571 addEventListenerFn(script, "error", callback);
10572 rawDocument.body.appendChild(script);
10573 return callback;
10574 }
10575 }
10576
10577 var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate');
10578 $interpolateMinErr.throwNoconcat = function(text) {
10579 throw $interpolateMinErr('noconcat',
10580 "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
10581 "interpolations that concatenate multiple expressions when a trusted value is " +
10582 "required. See http://docs.angularjs.org/api/ng.$sce", text);
10583 };
10584
10585 $interpolateMinErr.interr = function(text, err) {
10586 return $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString());
10587 };
10588
10589 /**
10590 * @ngdoc provider
10591 * @name $interpolateProvider
10592 *
10593 * @description
10594 *
10595 * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
10596 *
10597 * @example
10598 <example module="customInterpolationApp">
10599 <file name="index.html">
10600 <script>
10601 var customInterpolationApp = angular.module('customInterpolationApp', []);
10602
10603 customInterpolationApp.config(function($interpolateProvider) {
10604 $interpolateProvider.startSymbol('//');
10605 $interpolateProvider.endSymbol('//');
10606 });
10607
10608
10609 customInterpolationApp.controller('DemoController', function() {
10610 this.label = "This binding is brought you by // interpolation symbols.";
10611 });
10612 </script>
10613 <div ng-app="App" ng-controller="DemoController as demo">
10614 //demo.label//
10615 </div>
10616 </file>
10617 <file name="protractor.js" type="protractor">
10618 it('should interpolate binding with custom symbols', function() {
10619 expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.');
10620 });
10621 </file>
10622 </example>
10623 */
10624 function $InterpolateProvider() {
10625 var startSymbol = '{{';
10626 var endSymbol = '}}';
10627
10628 /**
10629 * @ngdoc method
10630 * @name $interpolateProvider#startSymbol
10631 * @description
10632 * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
10633 *
10634 * @param {string=} value new value to set the starting symbol to.
10635 * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
10636 */
10637 this.startSymbol = function(value) {
10638 if (value) {
10639 startSymbol = value;
10640 return this;
10641 } else {
10642 return startSymbol;
10643 }
10644 };
10645
10646 /**
10647 * @ngdoc method
10648 * @name $interpolateProvider#endSymbol
10649 * @description
10650 * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
10651 *
10652 * @param {string=} value new value to set the ending symbol to.
10653 * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
10654 */
10655 this.endSymbol = function(value) {
10656 if (value) {
10657 endSymbol = value;
10658 return this;
10659 } else {
10660 return endSymbol;
10661 }
10662 };
10663
10664
10665 this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
10666 var startSymbolLength = startSymbol.length,
10667 endSymbolLength = endSymbol.length,
10668 escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),
10669 escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');
10670
10671 function escape(ch) {
10672 return '\\\\\\' + ch;
10673 }
10674
10675 function unescapeText(text) {
10676 return text.replace(escapedStartRegexp, startSymbol).
10677 replace(escapedEndRegexp, endSymbol);
10678 }
10679
10680 function stringify(value) {
10681 if (value == null) { // null || undefined
10682 return '';
10683 }
10684 switch (typeof value) {
10685 case 'string':
10686 break;
10687 case 'number':
10688 value = '' + value;
10689 break;
10690 default:
10691 value = toJson(value);
10692 }
10693
10694 return value;
10695 }
10696
10697 /**
10698 * @ngdoc service
10699 * @name $interpolate
10700 * @kind function
10701 *
10702 * @requires $parse
10703 * @requires $sce
10704 *
10705 * @description
10706 *
10707 * Compiles a string with markup into an interpolation function. This service is used by the
10708 * HTML {@link ng.$compile $compile} service for data binding. See
10709 * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
10710 * interpolation markup.
10711 *
10712 *
10713 * ```js
10714 * var $interpolate = ...; // injected
10715 * var exp = $interpolate('Hello {{name | uppercase}}!');
10716 * expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
10717 * ```
10718 *
10719 * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
10720 * `true`, the interpolation function will return `undefined` unless all embedded expressions
10721 * evaluate to a value other than `undefined`.
10722 *
10723 * ```js
10724 * var $interpolate = ...; // injected
10725 * var context = {greeting: 'Hello', name: undefined };
10726 *
10727 * // default "forgiving" mode
10728 * var exp = $interpolate('{{greeting}} {{name}}!');
10729 * expect(exp(context)).toEqual('Hello !');
10730 *
10731 * // "allOrNothing" mode
10732 * exp = $interpolate('{{greeting}} {{name}}!', false, null, true);
10733 * expect(exp(context)).toBeUndefined();
10734 * context.name = 'Angular';
10735 * expect(exp(context)).toEqual('Hello Angular!');
10736 * ```
10737 *
10738 * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.
10739 *
10740 * ####Escaped Interpolation
10741 * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers
10742 * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).
10743 * It will be rendered as a regular start/end marker, and will not be interpreted as an expression
10744 * or binding.
10745 *
10746 * This enables web-servers to prevent script injection attacks and defacing attacks, to some
10747 * degree, while also enabling code examples to work without relying on the
10748 * {@link ng.directive:ngNonBindable ngNonBindable} directive.
10749 *
10750 * **For security purposes, it is strongly encouraged that web servers escape user-supplied data,
10751 * replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all
10752 * interpolation start/end markers with their escaped counterparts.**
10753 *
10754 * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered
10755 * output when the $interpolate service processes the text. So, for HTML elements interpolated
10756 * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter
10757 * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,
10758 * this is typically useful only when user-data is used in rendering a template from the server, or
10759 * when otherwise untrusted data is used by a directive.
10760 *
10761 * <example>
10762 * <file name="index.html">
10763 * <div ng-init="username='A user'">
10764 * <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\}
10765 * </p>
10766 * <p><strong>{{username}}</strong> attempts to inject code which will deface the
10767 * application, but fails to accomplish their task, because the server has correctly
10768 * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)
10769 * characters.</p>
10770 * <p>Instead, the result of the attempted script injection is visible, and can be removed
10771 * from the database by an administrator.</p>
10772 * </div>
10773 * </file>
10774 * </example>
10775 *
10776 * @param {string} text The text with markup to interpolate.
10777 * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
10778 * embedded expression in order to return an interpolation function. Strings with no
10779 * embedded expression will return null for the interpolation function.
10780 * @param {string=} trustedContext when provided, the returned function passes the interpolated
10781 * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
10782 * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
10783 * provides Strict Contextual Escaping for details.
10784 * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined
10785 * unless all embedded expressions evaluate to a value other than `undefined`.
10786 * @returns {function(context)} an interpolation function which is used to compute the
10787 * interpolated string. The function has these parameters:
10788 *
10789 * - `context`: evaluation context for all expressions embedded in the interpolated text
10790 */
10791 function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
10792 allOrNothing = !!allOrNothing;
10793 var startIndex,
10794 endIndex,
10795 index = 0,
10796 expressions = [],
10797 parseFns = [],
10798 textLength = text.length,
10799 exp,
10800 concat = [],
10801 expressionPositions = [];
10802
10803 while (index < textLength) {
10804 if (((startIndex = text.indexOf(startSymbol, index)) != -1) &&
10805 ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1)) {
10806 if (index !== startIndex) {
10807 concat.push(unescapeText(text.substring(index, startIndex)));
10808 }
10809 exp = text.substring(startIndex + startSymbolLength, endIndex);
10810 expressions.push(exp);
10811 parseFns.push($parse(exp, parseStringifyInterceptor));
10812 index = endIndex + endSymbolLength;
10813 expressionPositions.push(concat.length);
10814 concat.push('');
10815 } else {
10816 // we did not find an interpolation, so we have to add the remainder to the separators array
10817 if (index !== textLength) {
10818 concat.push(unescapeText(text.substring(index)));
10819 }
10820 break;
10821 }
10822 }
10823
10824 // Concatenating expressions makes it hard to reason about whether some combination of
10825 // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a
10826 // single expression be used for iframe[src], object[src], etc., we ensure that the value
10827 // that's used is assigned or constructed by some JS code somewhere that is more testable or
10828 // make it obvious that you bound the value to some user controlled value. This helps reduce
10829 // the load when auditing for XSS issues.
10830 if (trustedContext && concat.length > 1) {
10831 $interpolateMinErr.throwNoconcat(text);
10832 }
10833
10834 if (!mustHaveExpression || expressions.length) {
10835 var compute = function(values) {
10836 for (var i = 0, ii = expressions.length; i < ii; i++) {
10837 if (allOrNothing && isUndefined(values[i])) return;
10838 concat[expressionPositions[i]] = values[i];
10839 }
10840 return concat.join('');
10841 };
10842
10843 var getValue = function(value) {
10844 return trustedContext ?
10845 $sce.getTrusted(trustedContext, value) :
10846 $sce.valueOf(value);
10847 };
10848
10849 return extend(function interpolationFn(context) {
10850 var i = 0;
10851 var ii = expressions.length;
10852 var values = new Array(ii);
10853
10854 try {
10855 for (; i < ii; i++) {
10856 values[i] = parseFns[i](context);
10857 }
10858
10859 return compute(values);
10860 } catch (err) {
10861 $exceptionHandler($interpolateMinErr.interr(text, err));
10862 }
10863
10864 }, {
10865 // all of these properties are undocumented for now
10866 exp: text, //just for compatibility with regular watchers created via $watch
10867 expressions: expressions,
10868 $$watchDelegate: function(scope, listener) {
10869 var lastValue;
10870 return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
10871 var currValue = compute(values);
10872 if (isFunction(listener)) {
10873 listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
10874 }
10875 lastValue = currValue;
10876 });
10877 }
10878 });
10879 }
10880
10881 function parseStringifyInterceptor(value) {
10882 try {
10883 value = getValue(value);
10884 return allOrNothing && !isDefined(value) ? value : stringify(value);
10885 } catch (err) {
10886 $exceptionHandler($interpolateMinErr.interr(text, err));
10887 }
10888 }
10889 }
10890
10891
10892 /**
10893 * @ngdoc method
10894 * @name $interpolate#startSymbol
10895 * @description
10896 * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
10897 *
10898 * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change
10899 * the symbol.
10900 *
10901 * @returns {string} start symbol.
10902 */
10903 $interpolate.startSymbol = function() {
10904 return startSymbol;
10905 };
10906
10907
10908 /**
10909 * @ngdoc method
10910 * @name $interpolate#endSymbol
10911 * @description
10912 * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
10913 *
10914 * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change
10915 * the symbol.
10916 *
10917 * @returns {string} end symbol.
10918 */
10919 $interpolate.endSymbol = function() {
10920 return endSymbol;
10921 };
10922
10923 return $interpolate;
10924 }];
10925 }
10926
10927 function $IntervalProvider() {
10928 this.$get = ['$rootScope', '$window', '$q', '$$q',
10929 function($rootScope, $window, $q, $$q) {
10930 var intervals = {};
10931
10932
10933 /**
10934 * @ngdoc service
10935 * @name $interval
10936 *
10937 * @description
10938 * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
10939 * milliseconds.
10940 *
10941 * The return value of registering an interval function is a promise. This promise will be
10942 * notified upon each tick of the interval, and will be resolved after `count` iterations, or
10943 * run indefinitely if `count` is not defined. The value of the notification will be the
10944 * number of iterations that have run.
10945 * To cancel an interval, call `$interval.cancel(promise)`.
10946 *
10947 * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to
10948 * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
10949 * time.
10950 *
10951 * <div class="alert alert-warning">
10952 * **Note**: Intervals created by this service must be explicitly destroyed when you are finished
10953 * with them. In particular they are not automatically destroyed when a controller's scope or a
10954 * directive's element are destroyed.
10955 * You should take this into consideration and make sure to always cancel the interval at the
10956 * appropriate moment. See the example below for more details on how and when to do this.
10957 * </div>
10958 *
10959 * @param {function()} fn A function that should be called repeatedly.
10960 * @param {number} delay Number of milliseconds between each function call.
10961 * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
10962 * indefinitely.
10963 * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
10964 * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
10965 * @param {...*=} Pass additional parameters to the executed function.
10966 * @returns {promise} A promise which will be notified on each iteration.
10967 *
10968 * @example
10969 * <example module="intervalExample">
10970 * <file name="index.html">
10971 * <script>
10972 * angular.module('intervalExample', [])
10973 * .controller('ExampleController', ['$scope', '$interval',
10974 * function($scope, $interval) {
10975 * $scope.format = 'M/d/yy h:mm:ss a';
10976 * $scope.blood_1 = 100;
10977 * $scope.blood_2 = 120;
10978 *
10979 * var stop;
10980 * $scope.fight = function() {
10981 * // Don't start a new fight if we are already fighting
10982 * if ( angular.isDefined(stop) ) return;
10983 *
10984 * stop = $interval(function() {
10985 * if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
10986 * $scope.blood_1 = $scope.blood_1 - 3;
10987 * $scope.blood_2 = $scope.blood_2 - 4;
10988 * } else {
10989 * $scope.stopFight();
10990 * }
10991 * }, 100);
10992 * };
10993 *
10994 * $scope.stopFight = function() {
10995 * if (angular.isDefined(stop)) {
10996 * $interval.cancel(stop);
10997 * stop = undefined;
10998 * }
10999 * };
11000 *
11001 * $scope.resetFight = function() {
11002 * $scope.blood_1 = 100;
11003 * $scope.blood_2 = 120;
11004 * };
11005 *
11006 * $scope.$on('$destroy', function() {
11007 * // Make sure that the interval is destroyed too
11008 * $scope.stopFight();
11009 * });
11010 * }])
11011 * // Register the 'myCurrentTime' directive factory method.
11012 * // We inject $interval and dateFilter service since the factory method is DI.
11013 * .directive('myCurrentTime', ['$interval', 'dateFilter',
11014 * function($interval, dateFilter) {
11015 * // return the directive link function. (compile function not needed)
11016 * return function(scope, element, attrs) {
11017 * var format, // date format
11018 * stopTime; // so that we can cancel the time updates
11019 *
11020 * // used to update the UI
11021 * function updateTime() {
11022 * element.text(dateFilter(new Date(), format));
11023 * }
11024 *
11025 * // watch the expression, and update the UI on change.
11026 * scope.$watch(attrs.myCurrentTime, function(value) {
11027 * format = value;
11028 * updateTime();
11029 * });
11030 *
11031 * stopTime = $interval(updateTime, 1000);
11032 *
11033 * // listen on DOM destroy (removal) event, and cancel the next UI update
11034 * // to prevent updating time after the DOM element was removed.
11035 * element.on('$destroy', function() {
11036 * $interval.cancel(stopTime);
11037 * });
11038 * }
11039 * }]);
11040 * </script>
11041 *
11042 * <div>
11043 * <div ng-controller="ExampleController">
11044 * <label>Date format: <input ng-model="format"></label> <hr/>
11045 * Current time is: <span my-current-time="format"></span>
11046 * <hr/>
11047 * Blood 1 : <font color='red'>{{blood_1}}</font>
11048 * Blood 2 : <font color='red'>{{blood_2}}</font>
11049 * <button type="button" data-ng-click="fight()">Fight</button>
11050 * <button type="button" data-ng-click="stopFight()">StopFight</button>
11051 * <button type="button" data-ng-click="resetFight()">resetFight</button>
11052 * </div>
11053 * </div>
11054 *
11055 * </file>
11056 * </example>
11057 */
11058 function interval(fn, delay, count, invokeApply) {
11059 var hasParams = arguments.length > 4,
11060 args = hasParams ? sliceArgs(arguments, 4) : [],
11061 setInterval = $window.setInterval,
11062 clearInterval = $window.clearInterval,
11063 iteration = 0,
11064 skipApply = (isDefined(invokeApply) && !invokeApply),
11065 deferred = (skipApply ? $$q : $q).defer(),
11066 promise = deferred.promise;
11067
11068 count = isDefined(count) ? count : 0;
11069
11070 promise.then(null, null, (!hasParams) ? fn : function() {
11071 fn.apply(null, args);
11072 });
11073
11074 promise.$$intervalId = setInterval(function tick() {
11075 deferred.notify(iteration++);
11076
11077 if (count > 0 && iteration >= count) {
11078 deferred.resolve(iteration);
11079 clearInterval(promise.$$intervalId);
11080 delete intervals[promise.$$intervalId];
11081 }
11082
11083 if (!skipApply) $rootScope.$apply();
11084
11085 }, delay);
11086
11087 intervals[promise.$$intervalId] = deferred;
11088
11089 return promise;
11090 }
11091
11092
11093 /**
11094 * @ngdoc method
11095 * @name $interval#cancel
11096 *
11097 * @description
11098 * Cancels a task associated with the `promise`.
11099 *
11100 * @param {promise} promise returned by the `$interval` function.
11101 * @returns {boolean} Returns `true` if the task was successfully canceled.
11102 */
11103 interval.cancel = function(promise) {
11104 if (promise && promise.$$intervalId in intervals) {
11105 intervals[promise.$$intervalId].reject('canceled');
11106 $window.clearInterval(promise.$$intervalId);
11107 delete intervals[promise.$$intervalId];
11108 return true;
11109 }
11110 return false;
11111 };
11112
11113 return interval;
11114 }];
11115 }
11116
11117 /**
11118 * @ngdoc service
11119 * @name $locale
11120 *
11121 * @description
11122 * $locale service provides localization rules for various Angular components. As of right now the
11123 * only public api is:
11124 *
11125 * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
11126 */
11127 function $LocaleProvider() {
11128 this.$get = function() {
11129 return {
11130 id: 'en-us',
11131
11132 NUMBER_FORMATS: {
11133 DECIMAL_SEP: '.',
11134 GROUP_SEP: ',',
11135 PATTERNS: [
11136 { // Decimal Pattern
11137 minInt: 1,
11138 minFrac: 0,
11139 maxFrac: 3,
11140 posPre: '',
11141 posSuf: '',
11142 negPre: '-',
11143 negSuf: '',
11144 gSize: 3,
11145 lgSize: 3
11146 },{ //Currency Pattern
11147 minInt: 1,
11148 minFrac: 2,
11149 maxFrac: 2,
11150 posPre: '\u00A4',
11151 posSuf: '',
11152 negPre: '(\u00A4',
11153 negSuf: ')',
11154 gSize: 3,
11155 lgSize: 3
11156 }
11157 ],
11158 CURRENCY_SYM: '$'
11159 },
11160
11161 DATETIME_FORMATS: {
11162 MONTH:
11163 'January,February,March,April,May,June,July,August,September,October,November,December'
11164 .split(','),
11165 SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
11166 DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
11167 SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
11168 AMPMS: ['AM','PM'],
11169 medium: 'MMM d, y h:mm:ss a',
11170 'short': 'M/d/yy h:mm a',
11171 fullDate: 'EEEE, MMMM d, y',
11172 longDate: 'MMMM d, y',
11173 mediumDate: 'MMM d, y',
11174 shortDate: 'M/d/yy',
11175 mediumTime: 'h:mm:ss a',
11176 shortTime: 'h:mm a',
11177 ERANAMES: [
11178 "Before Christ",
11179 "Anno Domini"
11180 ],
11181 ERAS: [
11182 "BC",
11183 "AD"
11184 ]
11185 },
11186
11187 pluralCat: function(num) {
11188 if (num === 1) {
11189 return 'one';
11190 }
11191 return 'other';
11192 }
11193 };
11194 };
11195 }
11196
11197 var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
11198 DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
11199 var $locationMinErr = minErr('$location');
11200
11201
11202 /**
11203 * Encode path using encodeUriSegment, ignoring forward slashes
11204 *
11205 * @param {string} path Path to encode
11206 * @returns {string}
11207 */
11208 function encodePath(path) {
11209 var segments = path.split('/'),
11210 i = segments.length;
11211
11212 while (i--) {
11213 segments[i] = encodeUriSegment(segments[i]);
11214 }
11215
11216 return segments.join('/');
11217 }
11218
11219 function parseAbsoluteUrl(absoluteUrl, locationObj) {
11220 var parsedUrl = urlResolve(absoluteUrl);
11221
11222 locationObj.$$protocol = parsedUrl.protocol;
11223 locationObj.$$host = parsedUrl.hostname;
11224 locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
11225 }
11226
11227
11228 function parseAppUrl(relativeUrl, locationObj) {
11229 var prefixed = (relativeUrl.charAt(0) !== '/');
11230 if (prefixed) {
11231 relativeUrl = '/' + relativeUrl;
11232 }
11233 var match = urlResolve(relativeUrl);
11234 locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
11235 match.pathname.substring(1) : match.pathname);
11236 locationObj.$$search = parseKeyValue(match.search);
11237 locationObj.$$hash = decodeURIComponent(match.hash);
11238
11239 // make sure path starts with '/';
11240 if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
11241 locationObj.$$path = '/' + locationObj.$$path;
11242 }
11243 }
11244
11245
11246 /**
11247 *
11248 * @param {string} begin
11249 * @param {string} whole
11250 * @returns {string} returns text from whole after begin or undefined if it does not begin with
11251 * expected string.
11252 */
11253 function beginsWith(begin, whole) {
11254 if (whole.indexOf(begin) === 0) {
11255 return whole.substr(begin.length);
11256 }
11257 }
11258
11259
11260 function stripHash(url) {
11261 var index = url.indexOf('#');
11262 return index == -1 ? url : url.substr(0, index);
11263 }
11264
11265 function trimEmptyHash(url) {
11266 return url.replace(/(#.+)|#$/, '$1');
11267 }
11268
11269
11270 function stripFile(url) {
11271 return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
11272 }
11273
11274 /* return the server only (scheme://host:port) */
11275 function serverBase(url) {
11276 return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
11277 }
11278
11279
11280 /**
11281 * LocationHtml5Url represents an url
11282 * This object is exposed as $location service when HTML5 mode is enabled and supported
11283 *
11284 * @constructor
11285 * @param {string} appBase application base URL
11286 * @param {string} basePrefix url path prefix
11287 */
11288 function LocationHtml5Url(appBase, basePrefix) {
11289 this.$$html5 = true;
11290 basePrefix = basePrefix || '';
11291 var appBaseNoFile = stripFile(appBase);
11292 parseAbsoluteUrl(appBase, this);
11293
11294
11295 /**
11296 * Parse given html5 (regular) url string into properties
11297 * @param {string} url HTML5 url
11298 * @private
11299 */
11300 this.$$parse = function(url) {
11301 var pathUrl = beginsWith(appBaseNoFile, url);
11302 if (!isString(pathUrl)) {
11303 throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
11304 appBaseNoFile);
11305 }
11306
11307 parseAppUrl(pathUrl, this);
11308
11309 if (!this.$$path) {
11310 this.$$path = '/';
11311 }
11312
11313 this.$$compose();
11314 };
11315
11316 /**
11317 * Compose url and update `absUrl` property
11318 * @private
11319 */
11320 this.$$compose = function() {
11321 var search = toKeyValue(this.$$search),
11322 hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
11323
11324 this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
11325 this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
11326 };
11327
11328 this.$$parseLinkUrl = function(url, relHref) {
11329 if (relHref && relHref[0] === '#') {
11330 // special case for links to hash fragments:
11331 // keep the old url and only replace the hash fragment
11332 this.hash(relHref.slice(1));
11333 return true;
11334 }
11335 var appUrl, prevAppUrl;
11336 var rewrittenUrl;
11337
11338 if ((appUrl = beginsWith(appBase, url)) !== undefined) {
11339 prevAppUrl = appUrl;
11340 if ((appUrl = beginsWith(basePrefix, appUrl)) !== undefined) {
11341 rewrittenUrl = appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
11342 } else {
11343 rewrittenUrl = appBase + prevAppUrl;
11344 }
11345 } else if ((appUrl = beginsWith(appBaseNoFile, url)) !== undefined) {
11346 rewrittenUrl = appBaseNoFile + appUrl;
11347 } else if (appBaseNoFile == url + '/') {
11348 rewrittenUrl = appBaseNoFile;
11349 }
11350 if (rewrittenUrl) {
11351 this.$$parse(rewrittenUrl);
11352 }
11353 return !!rewrittenUrl;
11354 };
11355 }
11356
11357
11358 /**
11359 * LocationHashbangUrl represents url
11360 * This object is exposed as $location service when developer doesn't opt into html5 mode.
11361 * It also serves as the base class for html5 mode fallback on legacy browsers.
11362 *
11363 * @constructor
11364 * @param {string} appBase application base URL
11365 * @param {string} hashPrefix hashbang prefix
11366 */
11367 function LocationHashbangUrl(appBase, hashPrefix) {
11368 var appBaseNoFile = stripFile(appBase);
11369
11370 parseAbsoluteUrl(appBase, this);
11371
11372
11373 /**
11374 * Parse given hashbang url into properties
11375 * @param {string} url Hashbang url
11376 * @private
11377 */
11378 this.$$parse = function(url) {
11379 var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
11380 var withoutHashUrl;
11381
11382 if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
11383
11384 // The rest of the url starts with a hash so we have
11385 // got either a hashbang path or a plain hash fragment
11386 withoutHashUrl = beginsWith(hashPrefix, withoutBaseUrl);
11387 if (isUndefined(withoutHashUrl)) {
11388 // There was no hashbang prefix so we just have a hash fragment
11389 withoutHashUrl = withoutBaseUrl;
11390 }
11391
11392 } else {
11393 // There was no hashbang path nor hash fragment:
11394 // If we are in HTML5 mode we use what is left as the path;
11395 // Otherwise we ignore what is left
11396 if (this.$$html5) {
11397 withoutHashUrl = withoutBaseUrl;
11398 } else {
11399 withoutHashUrl = '';
11400 if (isUndefined(withoutBaseUrl)) {
11401 appBase = url;
11402 this.replace();
11403 }
11404 }
11405 }
11406
11407 parseAppUrl(withoutHashUrl, this);
11408
11409 this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
11410
11411 this.$$compose();
11412
11413 /*
11414 * In Windows, on an anchor node on documents loaded from
11415 * the filesystem, the browser will return a pathname
11416 * prefixed with the drive name ('/C:/path') when a
11417 * pathname without a drive is set:
11418 * * a.setAttribute('href', '/foo')
11419 * * a.pathname === '/C:/foo' //true
11420 *
11421 * Inside of Angular, we're always using pathnames that
11422 * do not include drive names for routing.
11423 */
11424 function removeWindowsDriveName(path, url, base) {
11425 /*
11426 Matches paths for file protocol on windows,
11427 such as /C:/foo/bar, and captures only /foo/bar.
11428 */
11429 var windowsFilePathExp = /^\/[A-Z]:(\/.*)/;
11430
11431 var firstPathSegmentMatch;
11432
11433 //Get the relative path from the input URL.
11434 if (url.indexOf(base) === 0) {
11435 url = url.replace(base, '');
11436 }
11437
11438 // The input URL intentionally contains a first path segment that ends with a colon.
11439 if (windowsFilePathExp.exec(url)) {
11440 return path;
11441 }
11442
11443 firstPathSegmentMatch = windowsFilePathExp.exec(path);
11444 return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
11445 }
11446 };
11447
11448 /**
11449 * Compose hashbang url and update `absUrl` property
11450 * @private
11451 */
11452 this.$$compose = function() {
11453 var search = toKeyValue(this.$$search),
11454 hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
11455
11456 this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
11457 this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
11458 };
11459
11460 this.$$parseLinkUrl = function(url, relHref) {
11461 if (stripHash(appBase) == stripHash(url)) {
11462 this.$$parse(url);
11463 return true;
11464 }
11465 return false;
11466 };
11467 }
11468
11469
11470 /**
11471 * LocationHashbangUrl represents url
11472 * This object is exposed as $location service when html5 history api is enabled but the browser
11473 * does not support it.
11474 *
11475 * @constructor
11476 * @param {string} appBase application base URL
11477 * @param {string} hashPrefix hashbang prefix
11478 */
11479 function LocationHashbangInHtml5Url(appBase, hashPrefix) {
11480 this.$$html5 = true;
11481 LocationHashbangUrl.apply(this, arguments);
11482
11483 var appBaseNoFile = stripFile(appBase);
11484
11485 this.$$parseLinkUrl = function(url, relHref) {
11486 if (relHref && relHref[0] === '#') {
11487 // special case for links to hash fragments:
11488 // keep the old url and only replace the hash fragment
11489 this.hash(relHref.slice(1));
11490 return true;
11491 }
11492
11493 var rewrittenUrl;
11494 var appUrl;
11495
11496 if (appBase == stripHash(url)) {
11497 rewrittenUrl = url;
11498 } else if ((appUrl = beginsWith(appBaseNoFile, url))) {
11499 rewrittenUrl = appBase + hashPrefix + appUrl;
11500 } else if (appBaseNoFile === url + '/') {
11501 rewrittenUrl = appBaseNoFile;
11502 }
11503 if (rewrittenUrl) {
11504 this.$$parse(rewrittenUrl);
11505 }
11506 return !!rewrittenUrl;
11507 };
11508
11509 this.$$compose = function() {
11510 var search = toKeyValue(this.$$search),
11511 hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
11512
11513 this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
11514 // include hashPrefix in $$absUrl when $$url is empty so IE8 & 9 do not reload page because of removal of '#'
11515 this.$$absUrl = appBase + hashPrefix + this.$$url;
11516 };
11517
11518 }
11519
11520
11521 var locationPrototype = {
11522
11523 /**
11524 * Are we in html5 mode?
11525 * @private
11526 */
11527 $$html5: false,
11528
11529 /**
11530 * Has any change been replacing?
11531 * @private
11532 */
11533 $$replace: false,
11534
11535 /**
11536 * @ngdoc method
11537 * @name $location#absUrl
11538 *
11539 * @description
11540 * This method is getter only.
11541 *
11542 * Return full url representation with all segments encoded according to rules specified in
11543 * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
11544 *
11545 *
11546 * ```js
11547 * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11548 * var absUrl = $location.absUrl();
11549 * // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
11550 * ```
11551 *
11552 * @return {string} full url
11553 */
11554 absUrl: locationGetter('$$absUrl'),
11555
11556 /**
11557 * @ngdoc method
11558 * @name $location#url
11559 *
11560 * @description
11561 * This method is getter / setter.
11562 *
11563 * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
11564 *
11565 * Change path, search and hash, when called with parameter and return `$location`.
11566 *
11567 *
11568 * ```js
11569 * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11570 * var url = $location.url();
11571 * // => "/some/path?foo=bar&baz=xoxo"
11572 * ```
11573 *
11574 * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
11575 * @return {string} url
11576 */
11577 url: function(url) {
11578 if (isUndefined(url)) {
11579 return this.$$url;
11580 }
11581
11582 var match = PATH_MATCH.exec(url);
11583 if (match[1] || url === '') this.path(decodeURIComponent(match[1]));
11584 if (match[2] || match[1] || url === '') this.search(match[3] || '');
11585 this.hash(match[5] || '');
11586
11587 return this;
11588 },
11589
11590 /**
11591 * @ngdoc method
11592 * @name $location#protocol
11593 *
11594 * @description
11595 * This method is getter only.
11596 *
11597 * Return protocol of current url.
11598 *
11599 *
11600 * ```js
11601 * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11602 * var protocol = $location.protocol();
11603 * // => "http"
11604 * ```
11605 *
11606 * @return {string} protocol of current url
11607 */
11608 protocol: locationGetter('$$protocol'),
11609
11610 /**
11611 * @ngdoc method
11612 * @name $location#host
11613 *
11614 * @description
11615 * This method is getter only.
11616 *
11617 * Return host of current url.
11618 *
11619 * Note: compared to the non-angular version `location.host` which returns `hostname:port`, this returns the `hostname` portion only.
11620 *
11621 *
11622 * ```js
11623 * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11624 * var host = $location.host();
11625 * // => "example.com"
11626 *
11627 * // given url http://user:[email protected]:8080/#/some/path?foo=bar&baz=xoxo
11628 * host = $location.host();
11629 * // => "example.com"
11630 * host = location.host;
11631 * // => "example.com:8080"
11632 * ```
11633 *
11634 * @return {string} host of current url.
11635 */
11636 host: locationGetter('$$host'),
11637
11638 /**
11639 * @ngdoc method
11640 * @name $location#port
11641 *
11642 * @description
11643 * This method is getter only.
11644 *
11645 * Return port of current url.
11646 *
11647 *
11648 * ```js
11649 * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11650 * var port = $location.port();
11651 * // => 80
11652 * ```
11653 *
11654 * @return {Number} port
11655 */
11656 port: locationGetter('$$port'),
11657
11658 /**
11659 * @ngdoc method
11660 * @name $location#path
11661 *
11662 * @description
11663 * This method is getter / setter.
11664 *
11665 * Return path of current url when called without any parameter.
11666 *
11667 * Change path when called with parameter and return `$location`.
11668 *
11669 * Note: Path should always begin with forward slash (/), this method will add the forward slash
11670 * if it is missing.
11671 *
11672 *
11673 * ```js
11674 * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11675 * var path = $location.path();
11676 * // => "/some/path"
11677 * ```
11678 *
11679 * @param {(string|number)=} path New path
11680 * @return {string} path
11681 */
11682 path: locationGetterSetter('$$path', function(path) {
11683 path = path !== null ? path.toString() : '';
11684 return path.charAt(0) == '/' ? path : '/' + path;
11685 }),
11686
11687 /**
11688 * @ngdoc method
11689 * @name $location#search
11690 *
11691 * @description
11692 * This method is getter / setter.
11693 *
11694 * Return search part (as object) of current url when called without any parameter.
11695 *
11696 * Change search part when called with parameter and return `$location`.
11697 *
11698 *
11699 * ```js
11700 * // given url http://example.com/#/some/path?foo=bar&baz=xoxo
11701 * var searchObject = $location.search();
11702 * // => {foo: 'bar', baz: 'xoxo'}
11703 *
11704 * // set foo to 'yipee'
11705 * $location.search('foo', 'yipee');
11706 * // $location.search() => {foo: 'yipee', baz: 'xoxo'}
11707 * ```
11708 *
11709 * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
11710 * hash object.
11711 *
11712 * When called with a single argument the method acts as a setter, setting the `search` component
11713 * of `$location` to the specified value.
11714 *
11715 * If the argument is a hash object containing an array of values, these values will be encoded
11716 * as duplicate search parameters in the url.
11717 *
11718 * @param {(string|Number|Array<string>|boolean)=} paramValue If `search` is a string or number, then `paramValue`
11719 * will override only a single search property.
11720 *
11721 * If `paramValue` is an array, it will override the property of the `search` component of
11722 * `$location` specified via the first argument.
11723 *
11724 * If `paramValue` is `null`, the property specified via the first argument will be deleted.
11725 *
11726 * If `paramValue` is `true`, the property specified via the first argument will be added with no
11727 * value nor trailing equal sign.
11728 *
11729 * @return {Object} If called with no arguments returns the parsed `search` object. If called with
11730 * one or more arguments returns `$location` object itself.
11731 */
11732 search: function(search, paramValue) {
11733 switch (arguments.length) {
11734 case 0:
11735 return this.$$search;
11736 case 1:
11737 if (isString(search) || isNumber(search)) {
11738 search = search.toString();
11739 this.$$search = parseKeyValue(search);
11740 } else if (isObject(search)) {
11741 search = copy(search, {});
11742 // remove object undefined or null properties
11743 forEach(search, function(value, key) {
11744 if (value == null) delete search[key];
11745 });
11746
11747 this.$$search = search;
11748 } else {
11749 throw $locationMinErr('isrcharg',
11750 'The first argument of the `$location#search()` call must be a string or an object.');
11751 }
11752 break;
11753 default:
11754 if (isUndefined(paramValue) || paramValue === null) {
11755 delete this.$$search[search];
11756 } else {
11757 this.$$search[search] = paramValue;
11758 }
11759 }
11760
11761 this.$$compose();
11762 return this;
11763 },
11764
11765 /**
11766 * @ngdoc method
11767 * @name $location#hash
11768 *
11769 * @description
11770 * This method is getter / setter.
11771 *
11772 * Return hash fragment when called without any parameter.
11773 *
11774 * Change hash fragment when called with parameter and return `$location`.
11775 *
11776 *
11777 * ```js
11778 * // given url http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue
11779 * var hash = $location.hash();
11780 * // => "hashValue"
11781 * ```
11782 *
11783 * @param {(string|number)=} hash New hash fragment
11784 * @return {string} hash
11785 */
11786 hash: locationGetterSetter('$$hash', function(hash) {
11787 return hash !== null ? hash.toString() : '';
11788 }),
11789
11790 /**
11791 * @ngdoc method
11792 * @name $location#replace
11793 *
11794 * @description
11795 * If called, all changes to $location during current `$digest` will be replacing current history
11796 * record, instead of adding new one.
11797 */
11798 replace: function() {
11799 this.$$replace = true;
11800 return this;
11801 }
11802 };
11803
11804 forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) {
11805 Location.prototype = Object.create(locationPrototype);
11806
11807 /**
11808 * @ngdoc method
11809 * @name $location#state
11810 *
11811 * @description
11812 * This method is getter / setter.
11813 *
11814 * Return the history state object when called without any parameter.
11815 *
11816 * Change the history state object when called with one parameter and return `$location`.
11817 * The state object is later passed to `pushState` or `replaceState`.
11818 *
11819 * NOTE: This method is supported only in HTML5 mode and only in browsers supporting
11820 * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support
11821 * older browsers (like IE9 or Android < 4.0), don't use this method.
11822 *
11823 * @param {object=} state State object for pushState or replaceState
11824 * @return {object} state
11825 */
11826 Location.prototype.state = function(state) {
11827 if (!arguments.length) {
11828 return this.$$state;
11829 }
11830
11831 if (Location !== LocationHtml5Url || !this.$$html5) {
11832 throw $locationMinErr('nostate', 'History API state support is available only ' +
11833 'in HTML5 mode and only in browsers supporting HTML5 History API');
11834 }
11835 // The user might modify `stateObject` after invoking `$location.state(stateObject)`
11836 // but we're changing the $$state reference to $browser.state() during the $digest
11837 // so the modification window is narrow.
11838 this.$$state = isUndefined(state) ? null : state;
11839
11840 return this;
11841 };
11842 });
11843
11844
11845 function locationGetter(property) {
11846 return function() {
11847 return this[property];
11848 };
11849 }
11850
11851
11852 function locationGetterSetter(property, preprocess) {
11853 return function(value) {
11854 if (isUndefined(value)) {
11855 return this[property];
11856 }
11857
11858 this[property] = preprocess(value);
11859 this.$$compose();
11860
11861 return this;
11862 };
11863 }
11864
11865
11866 /**
11867 * @ngdoc service
11868 * @name $location
11869 *
11870 * @requires $rootElement
11871 *
11872 * @description
11873 * The $location service parses the URL in the browser address bar (based on the
11874 * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL
11875 * available to your application. Changes to the URL in the address bar are reflected into
11876 * $location service and changes to $location are reflected into the browser address bar.
11877 *
11878 * **The $location service:**
11879 *
11880 * - Exposes the current URL in the browser address bar, so you can
11881 * - Watch and observe the URL.
11882 * - Change the URL.
11883 * - Synchronizes the URL with the browser when the user
11884 * - Changes the address bar.
11885 * - Clicks the back or forward button (or clicks a History link).
11886 * - Clicks on a link.
11887 * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
11888 *
11889 * For more information see {@link guide/$location Developer Guide: Using $location}
11890 */
11891
11892 /**
11893 * @ngdoc provider
11894 * @name $locationProvider
11895 * @description
11896 * Use the `$locationProvider` to configure how the application deep linking paths are stored.
11897 */
11898 function $LocationProvider() {
11899 var hashPrefix = '',
11900 html5Mode = {
11901 enabled: false,
11902 requireBase: true,
11903 rewriteLinks: true
11904 };
11905
11906 /**
11907 * @ngdoc method
11908 * @name $locationProvider#hashPrefix
11909 * @description
11910 * @param {string=} prefix Prefix for hash part (containing path and search)
11911 * @returns {*} current value if used as getter or itself (chaining) if used as setter
11912 */
11913 this.hashPrefix = function(prefix) {
11914 if (isDefined(prefix)) {
11915 hashPrefix = prefix;
11916 return this;
11917 } else {
11918 return hashPrefix;
11919 }
11920 };
11921
11922 /**
11923 * @ngdoc method
11924 * @name $locationProvider#html5Mode
11925 * @description
11926 * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
11927 * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported
11928 * properties:
11929 * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to
11930 * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not
11931 * support `pushState`.
11932 * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
11933 * whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
11934 * true, and a base tag is not present, an error will be thrown when `$location` is injected.
11935 * See the {@link guide/$location $location guide for more information}
11936 * - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,
11937 * enables/disables url rewriting for relative links.
11938 *
11939 * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
11940 */
11941 this.html5Mode = function(mode) {
11942 if (isBoolean(mode)) {
11943 html5Mode.enabled = mode;
11944 return this;
11945 } else if (isObject(mode)) {
11946
11947 if (isBoolean(mode.enabled)) {
11948 html5Mode.enabled = mode.enabled;
11949 }
11950
11951 if (isBoolean(mode.requireBase)) {
11952 html5Mode.requireBase = mode.requireBase;
11953 }
11954
11955 if (isBoolean(mode.rewriteLinks)) {
11956 html5Mode.rewriteLinks = mode.rewriteLinks;
11957 }
11958
11959 return this;
11960 } else {
11961 return html5Mode;
11962 }
11963 };
11964
11965 /**
11966 * @ngdoc event
11967 * @name $location#$locationChangeStart
11968 * @eventType broadcast on root scope
11969 * @description
11970 * Broadcasted before a URL will change.
11971 *
11972 * This change can be prevented by calling
11973 * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
11974 * details about event object. Upon successful change
11975 * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
11976 *
11977 * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
11978 * the browser supports the HTML5 History API.
11979 *
11980 * @param {Object} angularEvent Synthetic event object.
11981 * @param {string} newUrl New URL
11982 * @param {string=} oldUrl URL that was before it was changed.
11983 * @param {string=} newState New history state object
11984 * @param {string=} oldState History state object that was before it was changed.
11985 */
11986
11987 /**
11988 * @ngdoc event
11989 * @name $location#$locationChangeSuccess
11990 * @eventType broadcast on root scope
11991 * @description
11992 * Broadcasted after a URL was changed.
11993 *
11994 * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when
11995 * the browser supports the HTML5 History API.
11996 *
11997 * @param {Object} angularEvent Synthetic event object.
11998 * @param {string} newUrl New URL
11999 * @param {string=} oldUrl URL that was before it was changed.
12000 * @param {string=} newState New history state object
12001 * @param {string=} oldState History state object that was before it was changed.
12002 */
12003
12004 this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window',
12005 function($rootScope, $browser, $sniffer, $rootElement, $window) {
12006 var $location,
12007 LocationMode,
12008 baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
12009 initialUrl = $browser.url(),
12010 appBase;
12011
12012 if (html5Mode.enabled) {
12013 if (!baseHref && html5Mode.requireBase) {
12014 throw $locationMinErr('nobase',
12015 "$location in HTML5 mode requires a <base> tag to be present!");
12016 }
12017 appBase = serverBase(initialUrl) + (baseHref || '/');
12018 LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
12019 } else {
12020 appBase = stripHash(initialUrl);
12021 LocationMode = LocationHashbangUrl;
12022 }
12023 $location = new LocationMode(appBase, '#' + hashPrefix);
12024 $location.$$parseLinkUrl(initialUrl, initialUrl);
12025
12026 $location.$$state = $browser.state();
12027
12028 var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
12029
12030 function setBrowserUrlWithFallback(url, replace, state) {
12031 var oldUrl = $location.url();
12032 var oldState = $location.$$state;
12033 try {
12034 $browser.url(url, replace, state);
12035
12036 // Make sure $location.state() returns referentially identical (not just deeply equal)
12037 // state object; this makes possible quick checking if the state changed in the digest
12038 // loop. Checking deep equality would be too expensive.
12039 $location.$$state = $browser.state();
12040 } catch (e) {
12041 // Restore old values if pushState fails
12042 $location.url(oldUrl);
12043 $location.$$state = oldState;
12044
12045 throw e;
12046 }
12047 }
12048
12049 $rootElement.on('click', function(event) {
12050 // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
12051 // currently we open nice url link and redirect then
12052
12053 if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which == 2 || event.button == 2) return;
12054
12055 var elm = jqLite(event.target);
12056
12057 // traverse the DOM up to find first A tag
12058 while (nodeName_(elm[0]) !== 'a') {
12059 // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
12060 if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
12061 }
12062
12063 var absHref = elm.prop('href');
12064 // get the actual href attribute - see
12065 // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
12066 var relHref = elm.attr('href') || elm.attr('xlink:href');
12067
12068 if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') {
12069 // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during
12070 // an animation.
12071 absHref = urlResolve(absHref.animVal).href;
12072 }
12073
12074 // Ignore when url is started with javascript: or mailto:
12075 if (IGNORE_URI_REGEXP.test(absHref)) return;
12076
12077 if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) {
12078 if ($location.$$parseLinkUrl(absHref, relHref)) {
12079 // We do a preventDefault for all urls that are part of the angular application,
12080 // in html5mode and also without, so that we are able to abort navigation without
12081 // getting double entries in the location history.
12082 event.preventDefault();
12083 // update location manually
12084 if ($location.absUrl() != $browser.url()) {
12085 $rootScope.$apply();
12086 // hack to work around FF6 bug 684208 when scenario runner clicks on links
12087 $window.angular['ff-684208-preventDefault'] = true;
12088 }
12089 }
12090 }
12091 });
12092
12093
12094 // rewrite hashbang url <> html5 url
12095 if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
12096 $browser.url($location.absUrl(), true);
12097 }
12098
12099 var initializing = true;
12100
12101 // update $location when $browser url changes
12102 $browser.onUrlChange(function(newUrl, newState) {
12103 $rootScope.$evalAsync(function() {
12104 var oldUrl = $location.absUrl();
12105 var oldState = $location.$$state;
12106 var defaultPrevented;
12107
12108 $location.$$parse(newUrl);
12109 $location.$$state = newState;
12110
12111 defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
12112 newState, oldState).defaultPrevented;
12113
12114 // if the location was changed by a `$locationChangeStart` handler then stop
12115 // processing this location change
12116 if ($location.absUrl() !== newUrl) return;
12117
12118 if (defaultPrevented) {
12119 $location.$$parse(oldUrl);
12120 $location.$$state = oldState;
12121 setBrowserUrlWithFallback(oldUrl, false, oldState);
12122 } else {
12123 initializing = false;
12124 afterLocationChange(oldUrl, oldState);
12125 }
12126 });
12127 if (!$rootScope.$$phase) $rootScope.$digest();
12128 });
12129
12130 // update browser
12131 $rootScope.$watch(function $locationWatch() {
12132 var oldUrl = trimEmptyHash($browser.url());
12133 var newUrl = trimEmptyHash($location.absUrl());
12134 var oldState = $browser.state();
12135 var currentReplace = $location.$$replace;
12136 var urlOrStateChanged = oldUrl !== newUrl ||
12137 ($location.$$html5 && $sniffer.history && oldState !== $location.$$state);
12138
12139 if (initializing || urlOrStateChanged) {
12140 initializing = false;
12141
12142 $rootScope.$evalAsync(function() {
12143 var newUrl = $location.absUrl();
12144 var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl,
12145 $location.$$state, oldState).defaultPrevented;
12146
12147 // if the location was changed by a `$locationChangeStart` handler then stop
12148 // processing this location change
12149 if ($location.absUrl() !== newUrl) return;
12150
12151 if (defaultPrevented) {
12152 $location.$$parse(oldUrl);
12153 $location.$$state = oldState;
12154 } else {
12155 if (urlOrStateChanged) {
12156 setBrowserUrlWithFallback(newUrl, currentReplace,
12157 oldState === $location.$$state ? null : $location.$$state);
12158 }
12159 afterLocationChange(oldUrl, oldState);
12160 }
12161 });
12162 }
12163
12164 $location.$$replace = false;
12165
12166 // we don't need to return anything because $evalAsync will make the digest loop dirty when
12167 // there is a change
12168 });
12169
12170 return $location;
12171
12172 function afterLocationChange(oldUrl, oldState) {
12173 $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl,
12174 $location.$$state, oldState);
12175 }
12176 }];
12177 }
12178
12179 /**
12180 * @ngdoc service
12181 * @name $log
12182 * @requires $window
12183 *
12184 * @description
12185 * Simple service for logging. Default implementation safely writes the message
12186 * into the browser's console (if present).
12187 *
12188 * The main purpose of this service is to simplify debugging and troubleshooting.
12189 *
12190 * The default is to log `debug` messages. You can use
12191 * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
12192 *
12193 * @example
12194 <example module="logExample">
12195 <file name="script.js">
12196 angular.module('logExample', [])
12197 .controller('LogController', ['$scope', '$log', function($scope, $log) {
12198 $scope.$log = $log;
12199 $scope.message = 'Hello World!';
12200 }]);
12201 </file>
12202 <file name="index.html">
12203 <div ng-controller="LogController">
12204 <p>Reload this page with open console, enter text and hit the log button...</p>
12205 <label>Message:
12206 <input type="text" ng-model="message" /></label>
12207 <button ng-click="$log.log(message)">log</button>
12208 <button ng-click="$log.warn(message)">warn</button>
12209 <button ng-click="$log.info(message)">info</button>
12210 <button ng-click="$log.error(message)">error</button>
12211 <button ng-click="$log.debug(message)">debug</button>
12212 </div>
12213 </file>
12214 </example>
12215 */
12216
12217 /**
12218 * @ngdoc provider
12219 * @name $logProvider
12220 * @description
12221 * Use the `$logProvider` to configure how the application logs messages
12222 */
12223 function $LogProvider() {
12224 var debug = true,
12225 self = this;
12226
12227 /**
12228 * @ngdoc method
12229 * @name $logProvider#debugEnabled
12230 * @description
12231 * @param {boolean=} flag enable or disable debug level messages
12232 * @returns {*} current value if used as getter or itself (chaining) if used as setter
12233 */
12234 this.debugEnabled = function(flag) {
12235 if (isDefined(flag)) {
12236 debug = flag;
12237 return this;
12238 } else {
12239 return debug;
12240 }
12241 };
12242
12243 this.$get = ['$window', function($window) {
12244 return {
12245 /**
12246 * @ngdoc method
12247 * @name $log#log
12248 *
12249 * @description
12250 * Write a log message
12251 */
12252 log: consoleLog('log'),
12253
12254 /**
12255 * @ngdoc method
12256 * @name $log#info
12257 *
12258 * @description
12259 * Write an information message
12260 */
12261 info: consoleLog('info'),
12262
12263 /**
12264 * @ngdoc method
12265 * @name $log#warn
12266 *
12267 * @description
12268 * Write a warning message
12269 */
12270 warn: consoleLog('warn'),
12271
12272 /**
12273 * @ngdoc method
12274 * @name $log#error
12275 *
12276 * @description
12277 * Write an error message
12278 */
12279 error: consoleLog('error'),
12280
12281 /**
12282 * @ngdoc method
12283 * @name $log#debug
12284 *
12285 * @description
12286 * Write a debug message
12287 */
12288 debug: (function() {
12289 var fn = consoleLog('debug');
12290
12291 return function() {
12292 if (debug) {
12293 fn.apply(self, arguments);
12294 }
12295 };
12296 }())
12297 };
12298
12299 function formatError(arg) {
12300 if (arg instanceof Error) {
12301 if (arg.stack) {
12302 arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
12303 ? 'Error: ' + arg.message + '\n' + arg.stack
12304 : arg.stack;
12305 } else if (arg.sourceURL) {
12306 arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
12307 }
12308 }
12309 return arg;
12310 }
12311
12312 function consoleLog(type) {
12313 var console = $window.console || {},
12314 logFn = console[type] || console.log || noop,
12315 hasApply = false;
12316
12317 // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
12318 // The reason behind this is that console.log has type "object" in IE8...
12319 try {
12320 hasApply = !!logFn.apply;
12321 } catch (e) {}
12322
12323 if (hasApply) {
12324 return function() {
12325 var args = [];
12326 forEach(arguments, function(arg) {
12327 args.push(formatError(arg));
12328 });
12329 return logFn.apply(console, args);
12330 };
12331 }
12332
12333 // we are IE which either doesn't have window.console => this is noop and we do nothing,
12334 // or we are IE where console.log doesn't have apply so we log at least first 2 args
12335 return function(arg1, arg2) {
12336 logFn(arg1, arg2 == null ? '' : arg2);
12337 };
12338 }
12339 }];
12340 }
12341
12342 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
12343 * Any commits to this file should be reviewed with security in mind. *
12344 * Changes to this file can potentially create security vulnerabilities. *
12345 * An approval from 2 Core members with history of modifying *
12346 * this file is required. *
12347 * *
12348 * Does the change somehow allow for arbitrary javascript to be executed? *
12349 * Or allows for someone to change the prototype of built-in objects? *
12350 * Or gives undesired access to variables likes document or window? *
12351 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12352
12353 var $parseMinErr = minErr('$parse');
12354
12355 // Sandboxing Angular Expressions
12356 // ------------------------------
12357 // Angular expressions are generally considered safe because these expressions only have direct
12358 // access to `$scope` and locals. However, one can obtain the ability to execute arbitrary JS code by
12359 // obtaining a reference to native JS functions such as the Function constructor.
12360 //
12361 // As an example, consider the following Angular expression:
12362 //
12363 // {}.toString.constructor('alert("evil JS code")')
12364 //
12365 // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
12366 // against the expression language, but not to prevent exploits that were enabled by exposing
12367 // sensitive JavaScript or browser APIs on Scope. Exposing such objects on a Scope is never a good
12368 // practice and therefore we are not even trying to protect against interaction with an object
12369 // explicitly exposed in this way.
12370 //
12371 // In general, it is not possible to access a Window object from an angular expression unless a
12372 // window or some DOM object that has a reference to window is published onto a Scope.
12373 // Similarly we prevent invocations of function known to be dangerous, as well as assignments to
12374 // native objects.
12375 //
12376 // See https://docs.angularjs.org/guide/security
12377
12378
12379 function ensureSafeMemberName(name, fullExpression) {
12380 if (name === "__defineGetter__" || name === "__defineSetter__"
12381 || name === "__lookupGetter__" || name === "__lookupSetter__"
12382 || name === "__proto__") {
12383 throw $parseMinErr('isecfld',
12384 'Attempting to access a disallowed field in Angular expressions! '
12385 + 'Expression: {0}', fullExpression);
12386 }
12387 return name;
12388 }
12389
12390 function ensureSafeObject(obj, fullExpression) {
12391 // nifty check if obj is Function that is fast and works across iframes and other contexts
12392 if (obj) {
12393 if (obj.constructor === obj) {
12394 throw $parseMinErr('isecfn',
12395 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
12396 fullExpression);
12397 } else if (// isWindow(obj)
12398 obj.window === obj) {
12399 throw $parseMinErr('isecwindow',
12400 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
12401 fullExpression);
12402 } else if (// isElement(obj)
12403 obj.children && (obj.nodeName || (obj.prop && obj.attr && obj.find))) {
12404 throw $parseMinErr('isecdom',
12405 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
12406 fullExpression);
12407 } else if (// block Object so that we can't get hold of dangerous Object.* methods
12408 obj === Object) {
12409 throw $parseMinErr('isecobj',
12410 'Referencing Object in Angular expressions is disallowed! Expression: {0}',
12411 fullExpression);
12412 }
12413 }
12414 return obj;
12415 }
12416
12417 var CALL = Function.prototype.call;
12418 var APPLY = Function.prototype.apply;
12419 var BIND = Function.prototype.bind;
12420
12421 function ensureSafeFunction(obj, fullExpression) {
12422 if (obj) {
12423 if (obj.constructor === obj) {
12424 throw $parseMinErr('isecfn',
12425 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
12426 fullExpression);
12427 } else if (obj === CALL || obj === APPLY || obj === BIND) {
12428 throw $parseMinErr('isecff',
12429 'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
12430 fullExpression);
12431 }
12432 }
12433 }
12434
12435 var OPERATORS = createMap();
12436 forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; });
12437 var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
12438
12439
12440 /////////////////////////////////////////
12441
12442
12443 /**
12444 * @constructor
12445 */
12446 var Lexer = function(options) {
12447 this.options = options;
12448 };
12449
12450 Lexer.prototype = {
12451 constructor: Lexer,
12452
12453 lex: function(text) {
12454 this.text = text;
12455 this.index = 0;
12456 this.tokens = [];
12457
12458 while (this.index < this.text.length) {
12459 var ch = this.text.charAt(this.index);
12460 if (ch === '"' || ch === "'") {
12461 this.readString(ch);
12462 } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) {
12463 this.readNumber();
12464 } else if (this.isIdent(ch)) {
12465 this.readIdent();
12466 } else if (this.is(ch, '(){}[].,;:?')) {
12467 this.tokens.push({index: this.index, text: ch});
12468 this.index++;
12469 } else if (this.isWhitespace(ch)) {
12470 this.index++;
12471 } else {
12472 var ch2 = ch + this.peek();
12473 var ch3 = ch2 + this.peek(2);
12474 var op1 = OPERATORS[ch];
12475 var op2 = OPERATORS[ch2];
12476 var op3 = OPERATORS[ch3];
12477 if (op1 || op2 || op3) {
12478 var token = op3 ? ch3 : (op2 ? ch2 : ch);
12479 this.tokens.push({index: this.index, text: token, operator: true});
12480 this.index += token.length;
12481 } else {
12482 this.throwError('Unexpected next character ', this.index, this.index + 1);
12483 }
12484 }
12485 }
12486 return this.tokens;
12487 },
12488
12489 is: function(ch, chars) {
12490 return chars.indexOf(ch) !== -1;
12491 },
12492
12493 peek: function(i) {
12494 var num = i || 1;
12495 return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
12496 },
12497
12498 isNumber: function(ch) {
12499 return ('0' <= ch && ch <= '9') && typeof ch === "string";
12500 },
12501
12502 isWhitespace: function(ch) {
12503 // IE treats non-breaking space as \u00A0
12504 return (ch === ' ' || ch === '\r' || ch === '\t' ||
12505 ch === '\n' || ch === '\v' || ch === '\u00A0');
12506 },
12507
12508 isIdent: function(ch) {
12509 return ('a' <= ch && ch <= 'z' ||
12510 'A' <= ch && ch <= 'Z' ||
12511 '_' === ch || ch === '$');
12512 },
12513
12514 isExpOperator: function(ch) {
12515 return (ch === '-' || ch === '+' || this.isNumber(ch));
12516 },
12517
12518 throwError: function(error, start, end) {
12519 end = end || this.index;
12520 var colStr = (isDefined(start)
12521 ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']'
12522 : ' ' + end);
12523 throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
12524 error, colStr, this.text);
12525 },
12526
12527 readNumber: function() {
12528 var number = '';
12529 var start = this.index;
12530 while (this.index < this.text.length) {
12531 var ch = lowercase(this.text.charAt(this.index));
12532 if (ch == '.' || this.isNumber(ch)) {
12533 number += ch;
12534 } else {
12535 var peekCh = this.peek();
12536 if (ch == 'e' && this.isExpOperator(peekCh)) {
12537 number += ch;
12538 } else if (this.isExpOperator(ch) &&
12539 peekCh && this.isNumber(peekCh) &&
12540 number.charAt(number.length - 1) == 'e') {
12541 number += ch;
12542 } else if (this.isExpOperator(ch) &&
12543 (!peekCh || !this.isNumber(peekCh)) &&
12544 number.charAt(number.length - 1) == 'e') {
12545 this.throwError('Invalid exponent');
12546 } else {
12547 break;
12548 }
12549 }
12550 this.index++;
12551 }
12552 this.tokens.push({
12553 index: start,
12554 text: number,
12555 constant: true,
12556 value: Number(number)
12557 });
12558 },
12559
12560 readIdent: function() {
12561 var start = this.index;
12562 while (this.index < this.text.length) {
12563 var ch = this.text.charAt(this.index);
12564 if (!(this.isIdent(ch) || this.isNumber(ch))) {
12565 break;
12566 }
12567 this.index++;
12568 }
12569 this.tokens.push({
12570 index: start,
12571 text: this.text.slice(start, this.index),
12572 identifier: true
12573 });
12574 },
12575
12576 readString: function(quote) {
12577 var start = this.index;
12578 this.index++;
12579 var string = '';
12580 var rawString = quote;
12581 var escape = false;
12582 while (this.index < this.text.length) {
12583 var ch = this.text.charAt(this.index);
12584 rawString += ch;
12585 if (escape) {
12586 if (ch === 'u') {
12587 var hex = this.text.substring(this.index + 1, this.index + 5);
12588 if (!hex.match(/[\da-f]{4}/i)) {
12589 this.throwError('Invalid unicode escape [\\u' + hex + ']');
12590 }
12591 this.index += 4;
12592 string += String.fromCharCode(parseInt(hex, 16));
12593 } else {
12594 var rep = ESCAPE[ch];
12595 string = string + (rep || ch);
12596 }
12597 escape = false;
12598 } else if (ch === '\\') {
12599 escape = true;
12600 } else if (ch === quote) {
12601 this.index++;
12602 this.tokens.push({
12603 index: start,
12604 text: rawString,
12605 constant: true,
12606 value: string
12607 });
12608 return;
12609 } else {
12610 string += ch;
12611 }
12612 this.index++;
12613 }
12614 this.throwError('Unterminated quote', start);
12615 }
12616 };
12617
12618 var AST = function(lexer, options) {
12619 this.lexer = lexer;
12620 this.options = options;
12621 };
12622
12623 AST.Program = 'Program';
12624 AST.ExpressionStatement = 'ExpressionStatement';
12625 AST.AssignmentExpression = 'AssignmentExpression';
12626 AST.ConditionalExpression = 'ConditionalExpression';
12627 AST.LogicalExpression = 'LogicalExpression';
12628 AST.BinaryExpression = 'BinaryExpression';
12629 AST.UnaryExpression = 'UnaryExpression';
12630 AST.CallExpression = 'CallExpression';
12631 AST.MemberExpression = 'MemberExpression';
12632 AST.Identifier = 'Identifier';
12633 AST.Literal = 'Literal';
12634 AST.ArrayExpression = 'ArrayExpression';
12635 AST.Property = 'Property';
12636 AST.ObjectExpression = 'ObjectExpression';
12637 AST.ThisExpression = 'ThisExpression';
12638
12639 // Internal use only
12640 AST.NGValueParameter = 'NGValueParameter';
12641
12642 AST.prototype = {
12643 ast: function(text) {
12644 this.text = text;
12645 this.tokens = this.lexer.lex(text);
12646
12647 var value = this.program();
12648
12649 if (this.tokens.length !== 0) {
12650 this.throwError('is an unexpected token', this.tokens[0]);
12651 }
12652
12653 return value;
12654 },
12655
12656 program: function() {
12657 var body = [];
12658 while (true) {
12659 if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
12660 body.push(this.expressionStatement());
12661 if (!this.expect(';')) {
12662 return { type: AST.Program, body: body};
12663 }
12664 }
12665 },
12666
12667 expressionStatement: function() {
12668 return { type: AST.ExpressionStatement, expression: this.filterChain() };
12669 },
12670
12671 filterChain: function() {
12672 var left = this.expression();
12673 var token;
12674 while ((token = this.expect('|'))) {
12675 left = this.filter(left);
12676 }
12677 return left;
12678 },
12679
12680 expression: function() {
12681 return this.assignment();
12682 },
12683
12684 assignment: function() {
12685 var result = this.ternary();
12686 if (this.expect('=')) {
12687 result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='};
12688 }
12689 return result;
12690 },
12691
12692 ternary: function() {
12693 var test = this.logicalOR();
12694 var alternate;
12695 var consequent;
12696 if (this.expect('?')) {
12697 alternate = this.expression();
12698 if (this.consume(':')) {
12699 consequent = this.expression();
12700 return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent};
12701 }
12702 }
12703 return test;
12704 },
12705
12706 logicalOR: function() {
12707 var left = this.logicalAND();
12708 while (this.expect('||')) {
12709 left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() };
12710 }
12711 return left;
12712 },
12713
12714 logicalAND: function() {
12715 var left = this.equality();
12716 while (this.expect('&&')) {
12717 left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()};
12718 }
12719 return left;
12720 },
12721
12722 equality: function() {
12723 var left = this.relational();
12724 var token;
12725 while ((token = this.expect('==','!=','===','!=='))) {
12726 left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() };
12727 }
12728 return left;
12729 },
12730
12731 relational: function() {
12732 var left = this.additive();
12733 var token;
12734 while ((token = this.expect('<', '>', '<=', '>='))) {
12735 left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() };
12736 }
12737 return left;
12738 },
12739
12740 additive: function() {
12741 var left = this.multiplicative();
12742 var token;
12743 while ((token = this.expect('+','-'))) {
12744 left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() };
12745 }
12746 return left;
12747 },
12748
12749 multiplicative: function() {
12750 var left = this.unary();
12751 var token;
12752 while ((token = this.expect('*','/','%'))) {
12753 left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() };
12754 }
12755 return left;
12756 },
12757
12758 unary: function() {
12759 var token;
12760 if ((token = this.expect('+', '-', '!'))) {
12761 return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() };
12762 } else {
12763 return this.primary();
12764 }
12765 },
12766
12767 primary: function() {
12768 var primary;
12769 if (this.expect('(')) {
12770 primary = this.filterChain();
12771 this.consume(')');
12772 } else if (this.expect('[')) {
12773 primary = this.arrayDeclaration();
12774 } else if (this.expect('{')) {
12775 primary = this.object();
12776 } else if (this.constants.hasOwnProperty(this.peek().text)) {
12777 primary = copy(this.constants[this.consume().text]);
12778 } else if (this.peek().identifier) {
12779 primary = this.identifier();
12780 } else if (this.peek().constant) {
12781 primary = this.constant();
12782 } else {
12783 this.throwError('not a primary expression', this.peek());
12784 }
12785
12786 var next;
12787 while ((next = this.expect('(', '[', '.'))) {
12788 if (next.text === '(') {
12789 primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() };
12790 this.consume(')');
12791 } else if (next.text === '[') {
12792 primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true };
12793 this.consume(']');
12794 } else if (next.text === '.') {
12795 primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false };
12796 } else {
12797 this.throwError('IMPOSSIBLE');
12798 }
12799 }
12800 return primary;
12801 },
12802
12803 filter: function(baseExpression) {
12804 var args = [baseExpression];
12805 var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true};
12806
12807 while (this.expect(':')) {
12808 args.push(this.expression());
12809 }
12810
12811 return result;
12812 },
12813
12814 parseArguments: function() {
12815 var args = [];
12816 if (this.peekToken().text !== ')') {
12817 do {
12818 args.push(this.expression());
12819 } while (this.expect(','));
12820 }
12821 return args;
12822 },
12823
12824 identifier: function() {
12825 var token = this.consume();
12826 if (!token.identifier) {
12827 this.throwError('is not a valid identifier', token);
12828 }
12829 return { type: AST.Identifier, name: token.text };
12830 },
12831
12832 constant: function() {
12833 // TODO check that it is a constant
12834 return { type: AST.Literal, value: this.consume().value };
12835 },
12836
12837 arrayDeclaration: function() {
12838 var elements = [];
12839 if (this.peekToken().text !== ']') {
12840 do {
12841 if (this.peek(']')) {
12842 // Support trailing commas per ES5.1.
12843 break;
12844 }
12845 elements.push(this.expression());
12846 } while (this.expect(','));
12847 }
12848 this.consume(']');
12849
12850 return { type: AST.ArrayExpression, elements: elements };
12851 },
12852
12853 object: function() {
12854 var properties = [], property;
12855 if (this.peekToken().text !== '}') {
12856 do {
12857 if (this.peek('}')) {
12858 // Support trailing commas per ES5.1.
12859 break;
12860 }
12861 property = {type: AST.Property, kind: 'init'};
12862 if (this.peek().constant) {
12863 property.key = this.constant();
12864 } else if (this.peek().identifier) {
12865 property.key = this.identifier();
12866 } else {
12867 this.throwError("invalid key", this.peek());
12868 }
12869 this.consume(':');
12870 property.value = this.expression();
12871 properties.push(property);
12872 } while (this.expect(','));
12873 }
12874 this.consume('}');
12875
12876 return {type: AST.ObjectExpression, properties: properties };
12877 },
12878
12879 throwError: function(msg, token) {
12880 throw $parseMinErr('syntax',
12881 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
12882 token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
12883 },
12884
12885 consume: function(e1) {
12886 if (this.tokens.length === 0) {
12887 throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
12888 }
12889
12890 var token = this.expect(e1);
12891 if (!token) {
12892 this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
12893 }
12894 return token;
12895 },
12896
12897 peekToken: function() {
12898 if (this.tokens.length === 0) {
12899 throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
12900 }
12901 return this.tokens[0];
12902 },
12903
12904 peek: function(e1, e2, e3, e4) {
12905 return this.peekAhead(0, e1, e2, e3, e4);
12906 },
12907
12908 peekAhead: function(i, e1, e2, e3, e4) {
12909 if (this.tokens.length > i) {
12910 var token = this.tokens[i];
12911 var t = token.text;
12912 if (t === e1 || t === e2 || t === e3 || t === e4 ||
12913 (!e1 && !e2 && !e3 && !e4)) {
12914 return token;
12915 }
12916 }
12917 return false;
12918 },
12919
12920 expect: function(e1, e2, e3, e4) {
12921 var token = this.peek(e1, e2, e3, e4);
12922 if (token) {
12923 this.tokens.shift();
12924 return token;
12925 }
12926 return false;
12927 },
12928
12929
12930 /* `undefined` is not a constant, it is an identifier,
12931 * but using it as an identifier is not supported
12932 */
12933 constants: {
12934 'true': { type: AST.Literal, value: true },
12935 'false': { type: AST.Literal, value: false },
12936 'null': { type: AST.Literal, value: null },
12937 'undefined': {type: AST.Literal, value: undefined },
12938 'this': {type: AST.ThisExpression }
12939 }
12940 };
12941
12942 function ifDefined(v, d) {
12943 return typeof v !== 'undefined' ? v : d;
12944 }
12945
12946 function plusFn(l, r) {
12947 if (typeof l === 'undefined') return r;
12948 if (typeof r === 'undefined') return l;
12949 return l + r;
12950 }
12951
12952 function isStateless($filter, filterName) {
12953 var fn = $filter(filterName);
12954 return !fn.$stateful;
12955 }
12956
12957 function findConstantAndWatchExpressions(ast, $filter) {
12958 var allConstants;
12959 var argsToWatch;
12960 switch (ast.type) {
12961 case AST.Program:
12962 allConstants = true;
12963 forEach(ast.body, function(expr) {
12964 findConstantAndWatchExpressions(expr.expression, $filter);
12965 allConstants = allConstants && expr.expression.constant;
12966 });
12967 ast.constant = allConstants;
12968 break;
12969 case AST.Literal:
12970 ast.constant = true;
12971 ast.toWatch = [];
12972 break;
12973 case AST.UnaryExpression:
12974 findConstantAndWatchExpressions(ast.argument, $filter);
12975 ast.constant = ast.argument.constant;
12976 ast.toWatch = ast.argument.toWatch;
12977 break;
12978 case AST.BinaryExpression:
12979 findConstantAndWatchExpressions(ast.left, $filter);
12980 findConstantAndWatchExpressions(ast.right, $filter);
12981 ast.constant = ast.left.constant && ast.right.constant;
12982 ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch);
12983 break;
12984 case AST.LogicalExpression:
12985 findConstantAndWatchExpressions(ast.left, $filter);
12986 findConstantAndWatchExpressions(ast.right, $filter);
12987 ast.constant = ast.left.constant && ast.right.constant;
12988 ast.toWatch = ast.constant ? [] : [ast];
12989 break;
12990 case AST.ConditionalExpression:
12991 findConstantAndWatchExpressions(ast.test, $filter);
12992 findConstantAndWatchExpressions(ast.alternate, $filter);
12993 findConstantAndWatchExpressions(ast.consequent, $filter);
12994 ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant;
12995 ast.toWatch = ast.constant ? [] : [ast];
12996 break;
12997 case AST.Identifier:
12998 ast.constant = false;
12999 ast.toWatch = [ast];
13000 break;
13001 case AST.MemberExpression:
13002 findConstantAndWatchExpressions(ast.object, $filter);
13003 if (ast.computed) {
13004 findConstantAndWatchExpressions(ast.property, $filter);
13005 }
13006 ast.constant = ast.object.constant && (!ast.computed || ast.property.constant);
13007 ast.toWatch = [ast];
13008 break;
13009 case AST.CallExpression:
13010 allConstants = ast.filter ? isStateless($filter, ast.callee.name) : false;
13011 argsToWatch = [];
13012 forEach(ast.arguments, function(expr) {
13013 findConstantAndWatchExpressions(expr, $filter);
13014 allConstants = allConstants && expr.constant;
13015 if (!expr.constant) {
13016 argsToWatch.push.apply(argsToWatch, expr.toWatch);
13017 }
13018 });
13019 ast.constant = allConstants;
13020 ast.toWatch = ast.filter && isStateless($filter, ast.callee.name) ? argsToWatch : [ast];
13021 break;
13022 case AST.AssignmentExpression:
13023 findConstantAndWatchExpressions(ast.left, $filter);
13024 findConstantAndWatchExpressions(ast.right, $filter);
13025 ast.constant = ast.left.constant && ast.right.constant;
13026 ast.toWatch = [ast];
13027 break;
13028 case AST.ArrayExpression:
13029 allConstants = true;
13030 argsToWatch = [];
13031 forEach(ast.elements, function(expr) {
13032 findConstantAndWatchExpressions(expr, $filter);
13033 allConstants = allConstants && expr.constant;
13034 if (!expr.constant) {
13035 argsToWatch.push.apply(argsToWatch, expr.toWatch);
13036 }
13037 });
13038 ast.constant = allConstants;
13039 ast.toWatch = argsToWatch;
13040 break;
13041 case AST.ObjectExpression:
13042 allConstants = true;
13043 argsToWatch = [];
13044 forEach(ast.properties, function(property) {
13045 findConstantAndWatchExpressions(property.value, $filter);
13046 allConstants = allConstants && property.value.constant;
13047 if (!property.value.constant) {
13048 argsToWatch.push.apply(argsToWatch, property.value.toWatch);
13049 }
13050 });
13051 ast.constant = allConstants;
13052 ast.toWatch = argsToWatch;
13053 break;
13054 case AST.ThisExpression:
13055 ast.constant = false;
13056 ast.toWatch = [];
13057 break;
13058 }
13059 }
13060
13061 function getInputs(body) {
13062 if (body.length != 1) return;
13063 var lastExpression = body[0].expression;
13064 var candidate = lastExpression.toWatch;
13065 if (candidate.length !== 1) return candidate;
13066 return candidate[0] !== lastExpression ? candidate : undefined;
13067 }
13068
13069 function isAssignable(ast) {
13070 return ast.type === AST.Identifier || ast.type === AST.MemberExpression;
13071 }
13072
13073 function assignableAST(ast) {
13074 if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) {
13075 return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='};
13076 }
13077 }
13078
13079 function isLiteral(ast) {
13080 return ast.body.length === 0 ||
13081 ast.body.length === 1 && (
13082 ast.body[0].expression.type === AST.Literal ||
13083 ast.body[0].expression.type === AST.ArrayExpression ||
13084 ast.body[0].expression.type === AST.ObjectExpression);
13085 }
13086
13087 function isConstant(ast) {
13088 return ast.constant;
13089 }
13090
13091 function ASTCompiler(astBuilder, $filter) {
13092 this.astBuilder = astBuilder;
13093 this.$filter = $filter;
13094 }
13095
13096 ASTCompiler.prototype = {
13097 compile: function(expression, expensiveChecks) {
13098 var self = this;
13099 var ast = this.astBuilder.ast(expression);
13100 this.state = {
13101 nextId: 0,
13102 filters: {},
13103 expensiveChecks: expensiveChecks,
13104 fn: {vars: [], body: [], own: {}},
13105 assign: {vars: [], body: [], own: {}},
13106 inputs: []
13107 };
13108 findConstantAndWatchExpressions(ast, self.$filter);
13109 var extra = '';
13110 var assignable;
13111 this.stage = 'assign';
13112 if ((assignable = assignableAST(ast))) {
13113 this.state.computing = 'assign';
13114 var result = this.nextId();
13115 this.recurse(assignable, result);
13116 extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l');
13117 }
13118 var toWatch = getInputs(ast.body);
13119 self.stage = 'inputs';
13120 forEach(toWatch, function(watch, key) {
13121 var fnKey = 'fn' + key;
13122 self.state[fnKey] = {vars: [], body: [], own: {}};
13123 self.state.computing = fnKey;
13124 var intoId = self.nextId();
13125 self.recurse(watch, intoId);
13126 self.return_(intoId);
13127 self.state.inputs.push(fnKey);
13128 watch.watchId = key;
13129 });
13130 this.state.computing = 'fn';
13131 this.stage = 'main';
13132 this.recurse(ast);
13133 var fnString =
13134 // The build and minification steps remove the string "use strict" from the code, but this is done using a regex.
13135 // This is a workaround for this until we do a better job at only removing the prefix only when we should.
13136 '"' + this.USE + ' ' + this.STRICT + '";\n' +
13137 this.filterPrefix() +
13138 'var fn=' + this.generateFunction('fn', 's,l,a,i') +
13139 extra +
13140 this.watchFns() +
13141 'return fn;';
13142
13143 /* jshint -W054 */
13144 var fn = (new Function('$filter',
13145 'ensureSafeMemberName',
13146 'ensureSafeObject',
13147 'ensureSafeFunction',
13148 'ifDefined',
13149 'plus',
13150 'text',
13151 fnString))(
13152 this.$filter,
13153 ensureSafeMemberName,
13154 ensureSafeObject,
13155 ensureSafeFunction,
13156 ifDefined,
13157 plusFn,
13158 expression);
13159 /* jshint +W054 */
13160 this.state = this.stage = undefined;
13161 fn.literal = isLiteral(ast);
13162 fn.constant = isConstant(ast);
13163 return fn;
13164 },
13165
13166 USE: 'use',
13167
13168 STRICT: 'strict',
13169
13170 watchFns: function() {
13171 var result = [];
13172 var fns = this.state.inputs;
13173 var self = this;
13174 forEach(fns, function(name) {
13175 result.push('var ' + name + '=' + self.generateFunction(name, 's'));
13176 });
13177 if (fns.length) {
13178 result.push('fn.inputs=[' + fns.join(',') + '];');
13179 }
13180 return result.join('');
13181 },
13182
13183 generateFunction: function(name, params) {
13184 return 'function(' + params + '){' +
13185 this.varsPrefix(name) +
13186 this.body(name) +
13187 '};';
13188 },
13189
13190 filterPrefix: function() {
13191 var parts = [];
13192 var self = this;
13193 forEach(this.state.filters, function(id, filter) {
13194 parts.push(id + '=$filter(' + self.escape(filter) + ')');
13195 });
13196 if (parts.length) return 'var ' + parts.join(',') + ';';
13197 return '';
13198 },
13199
13200 varsPrefix: function(section) {
13201 return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : '';
13202 },
13203
13204 body: function(section) {
13205 return this.state[section].body.join('');
13206 },
13207
13208 recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
13209 var left, right, self = this, args, expression;
13210 recursionFn = recursionFn || noop;
13211 if (!skipWatchIdCheck && isDefined(ast.watchId)) {
13212 intoId = intoId || this.nextId();
13213 this.if_('i',
13214 this.lazyAssign(intoId, this.computedMember('i', ast.watchId)),
13215 this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true)
13216 );
13217 return;
13218 }
13219 switch (ast.type) {
13220 case AST.Program:
13221 forEach(ast.body, function(expression, pos) {
13222 self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; });
13223 if (pos !== ast.body.length - 1) {
13224 self.current().body.push(right, ';');
13225 } else {
13226 self.return_(right);
13227 }
13228 });
13229 break;
13230 case AST.Literal:
13231 expression = this.escape(ast.value);
13232 this.assign(intoId, expression);
13233 recursionFn(expression);
13234 break;
13235 case AST.UnaryExpression:
13236 this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; });
13237 expression = ast.operator + '(' + this.ifDefined(right, 0) + ')';
13238 this.assign(intoId, expression);
13239 recursionFn(expression);
13240 break;
13241 case AST.BinaryExpression:
13242 this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; });
13243 this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; });
13244 if (ast.operator === '+') {
13245 expression = this.plus(left, right);
13246 } else if (ast.operator === '-') {
13247 expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0);
13248 } else {
13249 expression = '(' + left + ')' + ast.operator + '(' + right + ')';
13250 }
13251 this.assign(intoId, expression);
13252 recursionFn(expression);
13253 break;
13254 case AST.LogicalExpression:
13255 intoId = intoId || this.nextId();
13256 self.recurse(ast.left, intoId);
13257 self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId));
13258 recursionFn(intoId);
13259 break;
13260 case AST.ConditionalExpression:
13261 intoId = intoId || this.nextId();
13262 self.recurse(ast.test, intoId);
13263 self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId));
13264 recursionFn(intoId);
13265 break;
13266 case AST.Identifier:
13267 intoId = intoId || this.nextId();
13268 if (nameId) {
13269 nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s');
13270 nameId.computed = false;
13271 nameId.name = ast.name;
13272 }
13273 ensureSafeMemberName(ast.name);
13274 self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)),
13275 function() {
13276 self.if_(self.stage === 'inputs' || 's', function() {
13277 if (create && create !== 1) {
13278 self.if_(
13279 self.not(self.nonComputedMember('s', ast.name)),
13280 self.lazyAssign(self.nonComputedMember('s', ast.name), '{}'));
13281 }
13282 self.assign(intoId, self.nonComputedMember('s', ast.name));
13283 });
13284 }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name))
13285 );
13286 if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.name)) {
13287 self.addEnsureSafeObject(intoId);
13288 }
13289 recursionFn(intoId);
13290 break;
13291 case AST.MemberExpression:
13292 left = nameId && (nameId.context = this.nextId()) || this.nextId();
13293 intoId = intoId || this.nextId();
13294 self.recurse(ast.object, left, undefined, function() {
13295 self.if_(self.notNull(left), function() {
13296 if (ast.computed) {
13297 right = self.nextId();
13298 self.recurse(ast.property, right);
13299 self.addEnsureSafeMemberName(right);
13300 if (create && create !== 1) {
13301 self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}'));
13302 }
13303 expression = self.ensureSafeObject(self.computedMember(left, right));
13304 self.assign(intoId, expression);
13305 if (nameId) {
13306 nameId.computed = true;
13307 nameId.name = right;
13308 }
13309 } else {
13310 ensureSafeMemberName(ast.property.name);
13311 if (create && create !== 1) {
13312 self.if_(self.not(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}'));
13313 }
13314 expression = self.nonComputedMember(left, ast.property.name);
13315 if (self.state.expensiveChecks || isPossiblyDangerousMemberName(ast.property.name)) {
13316 expression = self.ensureSafeObject(expression);
13317 }
13318 self.assign(intoId, expression);
13319 if (nameId) {
13320 nameId.computed = false;
13321 nameId.name = ast.property.name;
13322 }
13323 }
13324 }, function() {
13325 self.assign(intoId, 'undefined');
13326 });
13327 recursionFn(intoId);
13328 }, !!create);
13329 break;
13330 case AST.CallExpression:
13331 intoId = intoId || this.nextId();
13332 if (ast.filter) {
13333 right = self.filter(ast.callee.name);
13334 args = [];
13335 forEach(ast.arguments, function(expr) {
13336 var argument = self.nextId();
13337 self.recurse(expr, argument);
13338 args.push(argument);
13339 });
13340 expression = right + '(' + args.join(',') + ')';
13341 self.assign(intoId, expression);
13342 recursionFn(intoId);
13343 } else {
13344 right = self.nextId();
13345 left = {};
13346 args = [];
13347 self.recurse(ast.callee, right, left, function() {
13348 self.if_(self.notNull(right), function() {
13349 self.addEnsureSafeFunction(right);
13350 forEach(ast.arguments, function(expr) {
13351 self.recurse(expr, self.nextId(), undefined, function(argument) {
13352 args.push(self.ensureSafeObject(argument));
13353 });
13354 });
13355 if (left.name) {
13356 if (!self.state.expensiveChecks) {
13357 self.addEnsureSafeObject(left.context);
13358 }
13359 expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')';
13360 } else {
13361 expression = right + '(' + args.join(',') + ')';
13362 }
13363 expression = self.ensureSafeObject(expression);
13364 self.assign(intoId, expression);
13365 }, function() {
13366 self.assign(intoId, 'undefined');
13367 });
13368 recursionFn(intoId);
13369 });
13370 }
13371 break;
13372 case AST.AssignmentExpression:
13373 right = this.nextId();
13374 left = {};
13375 if (!isAssignable(ast.left)) {
13376 throw $parseMinErr('lval', 'Trying to assing a value to a non l-value');
13377 }
13378 this.recurse(ast.left, undefined, left, function() {
13379 self.if_(self.notNull(left.context), function() {
13380 self.recurse(ast.right, right);
13381 self.addEnsureSafeObject(self.member(left.context, left.name, left.computed));
13382 expression = self.member(left.context, left.name, left.computed) + ast.operator + right;
13383 self.assign(intoId, expression);
13384 recursionFn(intoId || expression);
13385 });
13386 }, 1);
13387 break;
13388 case AST.ArrayExpression:
13389 args = [];
13390 forEach(ast.elements, function(expr) {
13391 self.recurse(expr, self.nextId(), undefined, function(argument) {
13392 args.push(argument);
13393 });
13394 });
13395 expression = '[' + args.join(',') + ']';
13396 this.assign(intoId, expression);
13397 recursionFn(expression);
13398 break;
13399 case AST.ObjectExpression:
13400 args = [];
13401 forEach(ast.properties, function(property) {
13402 self.recurse(property.value, self.nextId(), undefined, function(expr) {
13403 args.push(self.escape(
13404 property.key.type === AST.Identifier ? property.key.name :
13405 ('' + property.key.value)) +
13406 ':' + expr);
13407 });
13408 });
13409 expression = '{' + args.join(',') + '}';
13410 this.assign(intoId, expression);
13411 recursionFn(expression);
13412 break;
13413 case AST.ThisExpression:
13414 this.assign(intoId, 's');
13415 recursionFn('s');
13416 break;
13417 case AST.NGValueParameter:
13418 this.assign(intoId, 'v');
13419 recursionFn('v');
13420 break;
13421 }
13422 },
13423
13424 getHasOwnProperty: function(element, property) {
13425 var key = element + '.' + property;
13426 var own = this.current().own;
13427 if (!own.hasOwnProperty(key)) {
13428 own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')');
13429 }
13430 return own[key];
13431 },
13432
13433 assign: function(id, value) {
13434 if (!id) return;
13435 this.current().body.push(id, '=', value, ';');
13436 return id;
13437 },
13438
13439 filter: function(filterName) {
13440 if (!this.state.filters.hasOwnProperty(filterName)) {
13441 this.state.filters[filterName] = this.nextId(true);
13442 }
13443 return this.state.filters[filterName];
13444 },
13445
13446 ifDefined: function(id, defaultValue) {
13447 return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')';
13448 },
13449
13450 plus: function(left, right) {
13451 return 'plus(' + left + ',' + right + ')';
13452 },
13453
13454 return_: function(id) {
13455 this.current().body.push('return ', id, ';');
13456 },
13457
13458 if_: function(test, alternate, consequent) {
13459 if (test === true) {
13460 alternate();
13461 } else {
13462 var body = this.current().body;
13463 body.push('if(', test, '){');
13464 alternate();
13465 body.push('}');
13466 if (consequent) {
13467 body.push('else{');
13468 consequent();
13469 body.push('}');
13470 }
13471 }
13472 },
13473
13474 not: function(expression) {
13475 return '!(' + expression + ')';
13476 },
13477
13478 notNull: function(expression) {
13479 return expression + '!=null';
13480 },
13481
13482 nonComputedMember: function(left, right) {
13483 return left + '.' + right;
13484 },
13485
13486 computedMember: function(left, right) {
13487 return left + '[' + right + ']';
13488 },
13489
13490 member: function(left, right, computed) {
13491 if (computed) return this.computedMember(left, right);
13492 return this.nonComputedMember(left, right);
13493 },
13494
13495 addEnsureSafeObject: function(item) {
13496 this.current().body.push(this.ensureSafeObject(item), ';');
13497 },
13498
13499 addEnsureSafeMemberName: function(item) {
13500 this.current().body.push(this.ensureSafeMemberName(item), ';');
13501 },
13502
13503 addEnsureSafeFunction: function(item) {
13504 this.current().body.push(this.ensureSafeFunction(item), ';');
13505 },
13506
13507 ensureSafeObject: function(item) {
13508 return 'ensureSafeObject(' + item + ',text)';
13509 },
13510
13511 ensureSafeMemberName: function(item) {
13512 return 'ensureSafeMemberName(' + item + ',text)';
13513 },
13514
13515 ensureSafeFunction: function(item) {
13516 return 'ensureSafeFunction(' + item + ',text)';
13517 },
13518
13519 lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) {
13520 var self = this;
13521 return function() {
13522 self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck);
13523 };
13524 },
13525
13526 lazyAssign: function(id, value) {
13527 var self = this;
13528 return function() {
13529 self.assign(id, value);
13530 };
13531 },
13532
13533 stringEscapeRegex: /[^ a-zA-Z0-9]/g,
13534
13535 stringEscapeFn: function(c) {
13536 return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4);
13537 },
13538
13539 escape: function(value) {
13540 if (isString(value)) return "'" + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + "'";
13541 if (isNumber(value)) return value.toString();
13542 if (value === true) return 'true';
13543 if (value === false) return 'false';
13544 if (value === null) return 'null';
13545 if (typeof value === 'undefined') return 'undefined';
13546
13547 throw $parseMinErr('esc', 'IMPOSSIBLE');
13548 },
13549
13550 nextId: function(skip, init) {
13551 var id = 'v' + (this.state.nextId++);
13552 if (!skip) {
13553 this.current().vars.push(id + (init ? '=' + init : ''));
13554 }
13555 return id;
13556 },
13557
13558 current: function() {
13559 return this.state[this.state.computing];
13560 }
13561 };
13562
13563
13564 function ASTInterpreter(astBuilder, $filter) {
13565 this.astBuilder = astBuilder;
13566 this.$filter = $filter;
13567 }
13568
13569 ASTInterpreter.prototype = {
13570 compile: function(expression, expensiveChecks) {
13571 var self = this;
13572 var ast = this.astBuilder.ast(expression);
13573 this.expression = expression;
13574 this.expensiveChecks = expensiveChecks;
13575 findConstantAndWatchExpressions(ast, self.$filter);
13576 var assignable;
13577 var assign;
13578 if ((assignable = assignableAST(ast))) {
13579 assign = this.recurse(assignable);
13580 }
13581 var toWatch = getInputs(ast.body);
13582 var inputs;
13583 if (toWatch) {
13584 inputs = [];
13585 forEach(toWatch, function(watch, key) {
13586 var input = self.recurse(watch);
13587 watch.input = input;
13588 inputs.push(input);
13589 watch.watchId = key;
13590 });
13591 }
13592 var expressions = [];
13593 forEach(ast.body, function(expression) {
13594 expressions.push(self.recurse(expression.expression));
13595 });
13596 var fn = ast.body.length === 0 ? function() {} :
13597 ast.body.length === 1 ? expressions[0] :
13598 function(scope, locals) {
13599 var lastValue;
13600 forEach(expressions, function(exp) {
13601 lastValue = exp(scope, locals);
13602 });
13603 return lastValue;
13604 };
13605 if (assign) {
13606 fn.assign = function(scope, value, locals) {
13607 return assign(scope, locals, value);
13608 };
13609 }
13610 if (inputs) {
13611 fn.inputs = inputs;
13612 }
13613 fn.literal = isLiteral(ast);
13614 fn.constant = isConstant(ast);
13615 return fn;
13616 },
13617
13618 recurse: function(ast, context, create) {
13619 var left, right, self = this, args, expression;
13620 if (ast.input) {
13621 return this.inputs(ast.input, ast.watchId);
13622 }
13623 switch (ast.type) {
13624 case AST.Literal:
13625 return this.value(ast.value, context);
13626 case AST.UnaryExpression:
13627 right = this.recurse(ast.argument);
13628 return this['unary' + ast.operator](right, context);
13629 case AST.BinaryExpression:
13630 left = this.recurse(ast.left);
13631 right = this.recurse(ast.right);
13632 return this['binary' + ast.operator](left, right, context);
13633 case AST.LogicalExpression:
13634 left = this.recurse(ast.left);
13635 right = this.recurse(ast.right);
13636 return this['binary' + ast.operator](left, right, context);
13637 case AST.ConditionalExpression:
13638 return this['ternary?:'](
13639 this.recurse(ast.test),
13640 this.recurse(ast.alternate),
13641 this.recurse(ast.consequent),
13642 context
13643 );
13644 case AST.Identifier:
13645 ensureSafeMemberName(ast.name, self.expression);
13646 return self.identifier(ast.name,
13647 self.expensiveChecks || isPossiblyDangerousMemberName(ast.name),
13648 context, create, self.expression);
13649 case AST.MemberExpression:
13650 left = this.recurse(ast.object, false, !!create);
13651 if (!ast.computed) {
13652 ensureSafeMemberName(ast.property.name, self.expression);
13653 right = ast.property.name;
13654 }
13655 if (ast.computed) right = this.recurse(ast.property);
13656 return ast.computed ?
13657 this.computedMember(left, right, context, create, self.expression) :
13658 this.nonComputedMember(left, right, self.expensiveChecks, context, create, self.expression);
13659 case AST.CallExpression:
13660 args = [];
13661 forEach(ast.arguments, function(expr) {
13662 args.push(self.recurse(expr));
13663 });
13664 if (ast.filter) right = this.$filter(ast.callee.name);
13665 if (!ast.filter) right = this.recurse(ast.callee, true);
13666 return ast.filter ?
13667 function(scope, locals, assign, inputs) {
13668 var values = [];
13669 for (var i = 0; i < args.length; ++i) {
13670 values.push(args[i](scope, locals, assign, inputs));
13671 }
13672 var value = right.apply(undefined, values, inputs);
13673 return context ? {context: undefined, name: undefined, value: value} : value;
13674 } :
13675 function(scope, locals, assign, inputs) {
13676 var rhs = right(scope, locals, assign, inputs);
13677 var value;
13678 if (rhs.value != null) {
13679 ensureSafeObject(rhs.context, self.expression);
13680 ensureSafeFunction(rhs.value, self.expression);
13681 var values = [];
13682 for (var i = 0; i < args.length; ++i) {
13683 values.push(ensureSafeObject(args[i](scope, locals, assign, inputs), self.expression));
13684 }
13685 value = ensureSafeObject(rhs.value.apply(rhs.context, values), self.expression);
13686 }
13687 return context ? {value: value} : value;
13688 };
13689 case AST.AssignmentExpression:
13690 left = this.recurse(ast.left, true, 1);
13691 right = this.recurse(ast.right);
13692 return function(scope, locals, assign, inputs) {
13693 var lhs = left(scope, locals, assign, inputs);
13694 var rhs = right(scope, locals, assign, inputs);
13695 ensureSafeObject(lhs.value, self.expression);
13696 lhs.context[lhs.name] = rhs;
13697 return context ? {value: rhs} : rhs;
13698 };
13699 case AST.ArrayExpression:
13700 args = [];
13701 forEach(ast.elements, function(expr) {
13702 args.push(self.recurse(expr));
13703 });
13704 return function(scope, locals, assign, inputs) {
13705 var value = [];
13706 for (var i = 0; i < args.length; ++i) {
13707 value.push(args[i](scope, locals, assign, inputs));
13708 }
13709 return context ? {value: value} : value;
13710 };
13711 case AST.ObjectExpression:
13712 args = [];
13713 forEach(ast.properties, function(property) {
13714 args.push({key: property.key.type === AST.Identifier ?
13715 property.key.name :
13716 ('' + property.key.value),
13717 value: self.recurse(property.value)
13718 });
13719 });
13720 return function(scope, locals, assign, inputs) {
13721 var value = {};
13722 for (var i = 0; i < args.length; ++i) {
13723 value[args[i].key] = args[i].value(scope, locals, assign, inputs);
13724 }
13725 return context ? {value: value} : value;
13726 };
13727 case AST.ThisExpression:
13728 return function(scope) {
13729 return context ? {value: scope} : scope;
13730 };
13731 case AST.NGValueParameter:
13732 return function(scope, locals, assign, inputs) {
13733 return context ? {value: assign} : assign;
13734 };
13735 }
13736 },
13737
13738 'unary+': function(argument, context) {
13739 return function(scope, locals, assign, inputs) {
13740 var arg = argument(scope, locals, assign, inputs);
13741 if (isDefined(arg)) {
13742 arg = +arg;
13743 } else {
13744 arg = 0;
13745 }
13746 return context ? {value: arg} : arg;
13747 };
13748 },
13749 'unary-': function(argument, context) {
13750 return function(scope, locals, assign, inputs) {
13751 var arg = argument(scope, locals, assign, inputs);
13752 if (isDefined(arg)) {
13753 arg = -arg;
13754 } else {
13755 arg = 0;
13756 }
13757 return context ? {value: arg} : arg;
13758 };
13759 },
13760 'unary!': function(argument, context) {
13761 return function(scope, locals, assign, inputs) {
13762 var arg = !argument(scope, locals, assign, inputs);
13763 return context ? {value: arg} : arg;
13764 };
13765 },
13766 'binary+': function(left, right, context) {
13767 return function(scope, locals, assign, inputs) {
13768 var lhs = left(scope, locals, assign, inputs);
13769 var rhs = right(scope, locals, assign, inputs);
13770 var arg = plusFn(lhs, rhs);
13771 return context ? {value: arg} : arg;
13772 };
13773 },
13774 'binary-': function(left, right, context) {
13775 return function(scope, locals, assign, inputs) {
13776 var lhs = left(scope, locals, assign, inputs);
13777 var rhs = right(scope, locals, assign, inputs);
13778 var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0);
13779 return context ? {value: arg} : arg;
13780 };
13781 },
13782 'binary*': function(left, right, context) {
13783 return function(scope, locals, assign, inputs) {
13784 var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs);
13785 return context ? {value: arg} : arg;
13786 };
13787 },
13788 'binary/': function(left, right, context) {
13789 return function(scope, locals, assign, inputs) {
13790 var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs);
13791 return context ? {value: arg} : arg;
13792 };
13793 },
13794 'binary%': function(left, right, context) {
13795 return function(scope, locals, assign, inputs) {
13796 var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs);
13797 return context ? {value: arg} : arg;
13798 };
13799 },
13800 'binary===': function(left, right, context) {
13801 return function(scope, locals, assign, inputs) {
13802 var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs);
13803 return context ? {value: arg} : arg;
13804 };
13805 },
13806 'binary!==': function(left, right, context) {
13807 return function(scope, locals, assign, inputs) {
13808 var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs);
13809 return context ? {value: arg} : arg;
13810 };
13811 },
13812 'binary==': function(left, right, context) {
13813 return function(scope, locals, assign, inputs) {
13814 var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs);
13815 return context ? {value: arg} : arg;
13816 };
13817 },
13818 'binary!=': function(left, right, context) {
13819 return function(scope, locals, assign, inputs) {
13820 var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs);
13821 return context ? {value: arg} : arg;
13822 };
13823 },
13824 'binary<': function(left, right, context) {
13825 return function(scope, locals, assign, inputs) {
13826 var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs);
13827 return context ? {value: arg} : arg;
13828 };
13829 },
13830 'binary>': function(left, right, context) {
13831 return function(scope, locals, assign, inputs) {
13832 var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs);
13833 return context ? {value: arg} : arg;
13834 };
13835 },
13836 'binary<=': function(left, right, context) {
13837 return function(scope, locals, assign, inputs) {
13838 var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs);
13839 return context ? {value: arg} : arg;
13840 };
13841 },
13842 'binary>=': function(left, right, context) {
13843 return function(scope, locals, assign, inputs) {
13844 var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs);
13845 return context ? {value: arg} : arg;
13846 };
13847 },
13848 'binary&&': function(left, right, context) {
13849 return function(scope, locals, assign, inputs) {
13850 var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs);
13851 return context ? {value: arg} : arg;
13852 };
13853 },
13854 'binary||': function(left, right, context) {
13855 return function(scope, locals, assign, inputs) {
13856 var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs);
13857 return context ? {value: arg} : arg;
13858 };
13859 },
13860 'ternary?:': function(test, alternate, consequent, context) {
13861 return function(scope, locals, assign, inputs) {
13862 var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs);
13863 return context ? {value: arg} : arg;
13864 };
13865 },
13866 value: function(value, context) {
13867 return function() { return context ? {context: undefined, name: undefined, value: value} : value; };
13868 },
13869 identifier: function(name, expensiveChecks, context, create, expression) {
13870 return function(scope, locals, assign, inputs) {
13871 var base = locals && (name in locals) ? locals : scope;
13872 if (create && create !== 1 && base && !(base[name])) {
13873 base[name] = {};
13874 }
13875 var value = base ? base[name] : undefined;
13876 if (expensiveChecks) {
13877 ensureSafeObject(value, expression);
13878 }
13879 if (context) {
13880 return {context: base, name: name, value: value};
13881 } else {
13882 return value;
13883 }
13884 };
13885 },
13886 computedMember: function(left, right, context, create, expression) {
13887 return function(scope, locals, assign, inputs) {
13888 var lhs = left(scope, locals, assign, inputs);
13889 var rhs;
13890 var value;
13891 if (lhs != null) {
13892 rhs = right(scope, locals, assign, inputs);
13893 ensureSafeMemberName(rhs, expression);
13894 if (create && create !== 1 && lhs && !(lhs[rhs])) {
13895 lhs[rhs] = {};
13896 }
13897 value = lhs[rhs];
13898 ensureSafeObject(value, expression);
13899 }
13900 if (context) {
13901 return {context: lhs, name: rhs, value: value};
13902 } else {
13903 return value;
13904 }
13905 };
13906 },
13907 nonComputedMember: function(left, right, expensiveChecks, context, create, expression) {
13908 return function(scope, locals, assign, inputs) {
13909 var lhs = left(scope, locals, assign, inputs);
13910 if (create && create !== 1 && lhs && !(lhs[right])) {
13911 lhs[right] = {};
13912 }
13913 var value = lhs != null ? lhs[right] : undefined;
13914 if (expensiveChecks || isPossiblyDangerousMemberName(right)) {
13915 ensureSafeObject(value, expression);
13916 }
13917 if (context) {
13918 return {context: lhs, name: right, value: value};
13919 } else {
13920 return value;
13921 }
13922 };
13923 },
13924 inputs: function(input, watchId) {
13925 return function(scope, value, locals, inputs) {
13926 if (inputs) return inputs[watchId];
13927 return input(scope, value, locals);
13928 };
13929 }
13930 };
13931
13932 /**
13933 * @constructor
13934 */
13935 var Parser = function(lexer, $filter, options) {
13936 this.lexer = lexer;
13937 this.$filter = $filter;
13938 this.options = options;
13939 this.ast = new AST(this.lexer);
13940 this.astCompiler = options.csp ? new ASTInterpreter(this.ast, $filter) :
13941 new ASTCompiler(this.ast, $filter);
13942 };
13943
13944 Parser.prototype = {
13945 constructor: Parser,
13946
13947 parse: function(text) {
13948 return this.astCompiler.compile(text, this.options.expensiveChecks);
13949 }
13950 };
13951
13952 //////////////////////////////////////////////////
13953 // Parser helper functions
13954 //////////////////////////////////////////////////
13955
13956 function setter(obj, path, setValue, fullExp) {
13957 ensureSafeObject(obj, fullExp);
13958
13959 var element = path.split('.'), key;
13960 for (var i = 0; element.length > 1; i++) {
13961 key = ensureSafeMemberName(element.shift(), fullExp);
13962 var propertyObj = ensureSafeObject(obj[key], fullExp);
13963 if (!propertyObj) {
13964 propertyObj = {};
13965 obj[key] = propertyObj;
13966 }
13967 obj = propertyObj;
13968 }
13969 key = ensureSafeMemberName(element.shift(), fullExp);
13970 ensureSafeObject(obj[key], fullExp);
13971 obj[key] = setValue;
13972 return setValue;
13973 }
13974
13975 var getterFnCacheDefault = createMap();
13976 var getterFnCacheExpensive = createMap();
13977
13978 function isPossiblyDangerousMemberName(name) {
13979 return name == 'constructor';
13980 }
13981
13982 var objectValueOf = Object.prototype.valueOf;
13983
13984 function getValueOf(value) {
13985 return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value);
13986 }
13987
13988 ///////////////////////////////////
13989
13990 /**
13991 * @ngdoc service
13992 * @name $parse
13993 * @kind function
13994 *
13995 * @description
13996 *
13997 * Converts Angular {@link guide/expression expression} into a function.
13998 *
13999 * ```js
14000 * var getter = $parse('user.name');
14001 * var setter = getter.assign;
14002 * var context = {user:{name:'angular'}};
14003 * var locals = {user:{name:'local'}};
14004 *
14005 * expect(getter(context)).toEqual('angular');
14006 * setter(context, 'newValue');
14007 * expect(context.user.name).toEqual('newValue');
14008 * expect(getter(context, locals)).toEqual('local');
14009 * ```
14010 *
14011 *
14012 * @param {string} expression String expression to compile.
14013 * @returns {function(context, locals)} a function which represents the compiled expression:
14014 *
14015 * * `context` – `{object}` – an object against which any expressions embedded in the strings
14016 * are evaluated against (typically a scope object).
14017 * * `locals` – `{object=}` – local variables context object, useful for overriding values in
14018 * `context`.
14019 *
14020 * The returned function also has the following properties:
14021 * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
14022 * literal.
14023 * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
14024 * constant literals.
14025 * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
14026 * set to a function to change its value on the given context.
14027 *
14028 */
14029
14030
14031 /**
14032 * @ngdoc provider
14033 * @name $parseProvider
14034 *
14035 * @description
14036 * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
14037 * service.
14038 */
14039 function $ParseProvider() {
14040 var cacheDefault = createMap();
14041 var cacheExpensive = createMap();
14042
14043 this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
14044 var $parseOptions = {
14045 csp: $sniffer.csp,
14046 expensiveChecks: false
14047 },
14048 $parseOptionsExpensive = {
14049 csp: $sniffer.csp,
14050 expensiveChecks: true
14051 };
14052
14053 return function $parse(exp, interceptorFn, expensiveChecks) {
14054 var parsedExpression, oneTime, cacheKey;
14055
14056 switch (typeof exp) {
14057 case 'string':
14058 exp = exp.trim();
14059 cacheKey = exp;
14060
14061 var cache = (expensiveChecks ? cacheExpensive : cacheDefault);
14062 parsedExpression = cache[cacheKey];
14063
14064 if (!parsedExpression) {
14065 if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
14066 oneTime = true;
14067 exp = exp.substring(2);
14068 }
14069 var parseOptions = expensiveChecks ? $parseOptionsExpensive : $parseOptions;
14070 var lexer = new Lexer(parseOptions);
14071 var parser = new Parser(lexer, $filter, parseOptions);
14072 parsedExpression = parser.parse(exp);
14073 if (parsedExpression.constant) {
14074 parsedExpression.$$watchDelegate = constantWatchDelegate;
14075 } else if (oneTime) {
14076 parsedExpression.$$watchDelegate = parsedExpression.literal ?
14077 oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
14078 } else if (parsedExpression.inputs) {
14079 parsedExpression.$$watchDelegate = inputsWatchDelegate;
14080 }
14081 cache[cacheKey] = parsedExpression;
14082 }
14083 return addInterceptor(parsedExpression, interceptorFn);
14084
14085 case 'function':
14086 return addInterceptor(exp, interceptorFn);
14087
14088 default:
14089 return noop;
14090 }
14091 };
14092
14093 function expressionInputDirtyCheck(newValue, oldValueOfValue) {
14094
14095 if (newValue == null || oldValueOfValue == null) { // null/undefined
14096 return newValue === oldValueOfValue;
14097 }
14098
14099 if (typeof newValue === 'object') {
14100
14101 // attempt to convert the value to a primitive type
14102 // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
14103 // be cheaply dirty-checked
14104 newValue = getValueOf(newValue);
14105
14106 if (typeof newValue === 'object') {
14107 // objects/arrays are not supported - deep-watching them would be too expensive
14108 return false;
14109 }
14110
14111 // fall-through to the primitive equality check
14112 }
14113
14114 //Primitive or NaN
14115 return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);
14116 }
14117
14118 function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
14119 var inputExpressions = parsedExpression.inputs;
14120 var lastResult;
14121
14122 if (inputExpressions.length === 1) {
14123 var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails
14124 inputExpressions = inputExpressions[0];
14125 return scope.$watch(function expressionInputWatch(scope) {
14126 var newInputValue = inputExpressions(scope);
14127 if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf)) {
14128 lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
14129 oldInputValueOf = newInputValue && getValueOf(newInputValue);
14130 }
14131 return lastResult;
14132 }, listener, objectEquality, prettyPrintExpression);
14133 }
14134
14135 var oldInputValueOfValues = [];
14136 var oldInputValues = [];
14137 for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
14138 oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
14139 oldInputValues[i] = null;
14140 }
14141
14142 return scope.$watch(function expressionInputsWatch(scope) {
14143 var changed = false;
14144
14145 for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
14146 var newInputValue = inputExpressions[i](scope);
14147 if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i]))) {
14148 oldInputValues[i] = newInputValue;
14149 oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
14150 }
14151 }
14152
14153 if (changed) {
14154 lastResult = parsedExpression(scope, undefined, undefined, oldInputValues);
14155 }
14156
14157 return lastResult;
14158 }, listener, objectEquality, prettyPrintExpression);
14159 }
14160
14161 function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {
14162 var unwatch, lastValue;
14163 return unwatch = scope.$watch(function oneTimeWatch(scope) {
14164 return parsedExpression(scope);
14165 }, function oneTimeListener(value, old, scope) {
14166 lastValue = value;
14167 if (isFunction(listener)) {
14168 listener.apply(this, arguments);
14169 }
14170 if (isDefined(value)) {
14171 scope.$$postDigest(function() {
14172 if (isDefined(lastValue)) {
14173 unwatch();
14174 }
14175 });
14176 }
14177 }, objectEquality);
14178 }
14179
14180 function oneTimeLiteralWatchDelegate(scope, listener, objectEquality, parsedExpression) {
14181 var unwatch, lastValue;
14182 return unwatch = scope.$watch(function oneTimeWatch(scope) {
14183 return parsedExpression(scope);
14184 }, function oneTimeListener(value, old, scope) {
14185 lastValue = value;
14186 if (isFunction(listener)) {
14187 listener.call(this, value, old, scope);
14188 }
14189 if (isAllDefined(value)) {
14190 scope.$$postDigest(function() {
14191 if (isAllDefined(lastValue)) unwatch();
14192 });
14193 }
14194 }, objectEquality);
14195
14196 function isAllDefined(value) {
14197 var allDefined = true;
14198 forEach(value, function(val) {
14199 if (!isDefined(val)) allDefined = false;
14200 });
14201 return allDefined;
14202 }
14203 }
14204
14205 function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
14206 var unwatch;
14207 return unwatch = scope.$watch(function constantWatch(scope) {
14208 return parsedExpression(scope);
14209 }, function constantListener(value, old, scope) {
14210 if (isFunction(listener)) {
14211 listener.apply(this, arguments);
14212 }
14213 unwatch();
14214 }, objectEquality);
14215 }
14216
14217 function addInterceptor(parsedExpression, interceptorFn) {
14218 if (!interceptorFn) return parsedExpression;
14219 var watchDelegate = parsedExpression.$$watchDelegate;
14220
14221 var regularWatch =
14222 watchDelegate !== oneTimeLiteralWatchDelegate &&
14223 watchDelegate !== oneTimeWatchDelegate;
14224
14225 var fn = regularWatch ? function regularInterceptedExpression(scope, locals, assign, inputs) {
14226 var value = parsedExpression(scope, locals, assign, inputs);
14227 return interceptorFn(value, scope, locals);
14228 } : function oneTimeInterceptedExpression(scope, locals, assign, inputs) {
14229 var value = parsedExpression(scope, locals, assign, inputs);
14230 var result = interceptorFn(value, scope, locals);
14231 // we only return the interceptor's result if the
14232 // initial value is defined (for bind-once)
14233 return isDefined(value) ? result : value;
14234 };
14235
14236 // Propagate $$watchDelegates other then inputsWatchDelegate
14237 if (parsedExpression.$$watchDelegate &&
14238 parsedExpression.$$watchDelegate !== inputsWatchDelegate) {
14239 fn.$$watchDelegate = parsedExpression.$$watchDelegate;
14240 } else if (!interceptorFn.$stateful) {
14241 // If there is an interceptor, but no watchDelegate then treat the interceptor like
14242 // we treat filters - it is assumed to be a pure function unless flagged with $stateful
14243 fn.$$watchDelegate = inputsWatchDelegate;
14244 fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];
14245 }
14246
14247 return fn;
14248 }
14249 }];
14250 }
14251
14252 /**
14253 * @ngdoc service
14254 * @name $q
14255 * @requires $rootScope
14256 *
14257 * @description
14258 * A service that helps you run functions asynchronously, and use their return values (or exceptions)
14259 * when they are done processing.
14260 *
14261 * This is an implementation of promises/deferred objects inspired by
14262 * [Kris Kowal's Q](https://github.com/kriskowal/q).
14263 *
14264 * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred
14265 * implementations, and the other which resembles ES6 promises to some degree.
14266 *
14267 * # $q constructor
14268 *
14269 * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`
14270 * function as the first argument. This is similar to the native Promise implementation from ES6 Harmony,
14271 * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
14272 *
14273 * While the constructor-style use is supported, not all of the supporting methods from ES6 Harmony promises are
14274 * available yet.
14275 *
14276 * It can be used like so:
14277 *
14278 * ```js
14279 * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
14280 * // are available in the current lexical scope (they could have been injected or passed in).
14281 *
14282 * function asyncGreet(name) {
14283 * // perform some asynchronous operation, resolve or reject the promise when appropriate.
14284 * return $q(function(resolve, reject) {
14285 * setTimeout(function() {
14286 * if (okToGreet(name)) {
14287 * resolve('Hello, ' + name + '!');
14288 * } else {
14289 * reject('Greeting ' + name + ' is not allowed.');
14290 * }
14291 * }, 1000);
14292 * });
14293 * }
14294 *
14295 * var promise = asyncGreet('Robin Hood');
14296 * promise.then(function(greeting) {
14297 * alert('Success: ' + greeting);
14298 * }, function(reason) {
14299 * alert('Failed: ' + reason);
14300 * });
14301 * ```
14302 *
14303 * Note: progress/notify callbacks are not currently supported via the ES6-style interface.
14304 *
14305 * However, the more traditional CommonJS-style usage is still available, and documented below.
14306 *
14307 * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
14308 * interface for interacting with an object that represents the result of an action that is
14309 * performed asynchronously, and may or may not be finished at any given point in time.
14310 *
14311 * From the perspective of dealing with error handling, deferred and promise APIs are to
14312 * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
14313 *
14314 * ```js
14315 * // for the purpose of this example let's assume that variables `$q` and `okToGreet`
14316 * // are available in the current lexical scope (they could have been injected or passed in).
14317 *
14318 * function asyncGreet(name) {
14319 * var deferred = $q.defer();
14320 *
14321 * setTimeout(function() {
14322 * deferred.notify('About to greet ' + name + '.');
14323 *
14324 * if (okToGreet(name)) {
14325 * deferred.resolve('Hello, ' + name + '!');
14326 * } else {
14327 * deferred.reject('Greeting ' + name + ' is not allowed.');
14328 * }
14329 * }, 1000);
14330 *
14331 * return deferred.promise;
14332 * }
14333 *
14334 * var promise = asyncGreet('Robin Hood');
14335 * promise.then(function(greeting) {
14336 * alert('Success: ' + greeting);
14337 * }, function(reason) {
14338 * alert('Failed: ' + reason);
14339 * }, function(update) {
14340 * alert('Got notification: ' + update);
14341 * });
14342 * ```
14343 *
14344 * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
14345 * comes in the way of guarantees that promise and deferred APIs make, see
14346 * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
14347 *
14348 * Additionally the promise api allows for composition that is very hard to do with the
14349 * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
14350 * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
14351 * section on serial or parallel joining of promises.
14352 *
14353 * # The Deferred API
14354 *
14355 * A new instance of deferred is constructed by calling `$q.defer()`.
14356 *
14357 * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
14358 * that can be used for signaling the successful or unsuccessful completion, as well as the status
14359 * of the task.
14360 *
14361 * **Methods**
14362 *
14363 * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
14364 * constructed via `$q.reject`, the promise will be rejected instead.
14365 * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
14366 * resolving it with a rejection constructed via `$q.reject`.
14367 * - `notify(value)` - provides updates on the status of the promise's execution. This may be called
14368 * multiple times before the promise is either resolved or rejected.
14369 *
14370 * **Properties**
14371 *
14372 * - promise – `{Promise}` – promise object associated with this deferred.
14373 *
14374 *
14375 * # The Promise API
14376 *
14377 * A new promise instance is created when a deferred instance is created and can be retrieved by
14378 * calling `deferred.promise`.
14379 *
14380 * The purpose of the promise object is to allow for interested parties to get access to the result
14381 * of the deferred task when it completes.
14382 *
14383 * **Methods**
14384 *
14385 * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
14386 * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
14387 * as soon as the result is available. The callbacks are called with a single argument: the result
14388 * or rejection reason. Additionally, the notify callback may be called zero or more times to
14389 * provide a progress indication, before the promise is resolved or rejected.
14390 *
14391 * This method *returns a new promise* which is resolved or rejected via the return value of the
14392 * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved
14393 * with the value which is resolved in that promise using
14394 * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)).
14395 * It also notifies via the return value of the `notifyCallback` method. The promise cannot be
14396 * resolved or rejected from the notifyCallback method.
14397 *
14398 * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
14399 *
14400 * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise,
14401 * but to do so without modifying the final value. This is useful to release resources or do some
14402 * clean-up that needs to be done whether the promise was rejected or resolved. See the [full
14403 * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
14404 * more information.
14405 *
14406 * # Chaining promises
14407 *
14408 * Because calling the `then` method of a promise returns a new derived promise, it is easily
14409 * possible to create a chain of promises:
14410 *
14411 * ```js
14412 * promiseB = promiseA.then(function(result) {
14413 * return result + 1;
14414 * });
14415 *
14416 * // promiseB will be resolved immediately after promiseA is resolved and its value
14417 * // will be the result of promiseA incremented by 1
14418 * ```
14419 *
14420 * It is possible to create chains of any length and since a promise can be resolved with another
14421 * promise (which will defer its resolution further), it is possible to pause/defer resolution of
14422 * the promises at any point in the chain. This makes it possible to implement powerful APIs like
14423 * $http's response interceptors.
14424 *
14425 *
14426 * # Differences between Kris Kowal's Q and $q
14427 *
14428 * There are two main differences:
14429 *
14430 * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
14431 * mechanism in angular, which means faster propagation of resolution or rejection into your
14432 * models and avoiding unnecessary browser repaints, which would result in flickering UI.
14433 * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
14434 * all the important functionality needed for common async tasks.
14435 *
14436 * # Testing
14437 *
14438 * ```js
14439 * it('should simulate promise', inject(function($q, $rootScope) {
14440 * var deferred = $q.defer();
14441 * var promise = deferred.promise;
14442 * var resolvedValue;
14443 *
14444 * promise.then(function(value) { resolvedValue = value; });
14445 * expect(resolvedValue).toBeUndefined();
14446 *
14447 * // Simulate resolving of promise
14448 * deferred.resolve(123);
14449 * // Note that the 'then' function does not get called synchronously.
14450 * // This is because we want the promise API to always be async, whether or not
14451 * // it got called synchronously or asynchronously.
14452 * expect(resolvedValue).toBeUndefined();
14453 *
14454 * // Propagate promise resolution to 'then' functions using $apply().
14455 * $rootScope.$apply();
14456 * expect(resolvedValue).toEqual(123);
14457 * }));
14458 * ```
14459 *
14460 * @param {function(function, function)} resolver Function which is responsible for resolving or
14461 * rejecting the newly created promise. The first parameter is a function which resolves the
14462 * promise, the second parameter is a function which rejects the promise.
14463 *
14464 * @returns {Promise} The newly created promise.
14465 */
14466 function $QProvider() {
14467
14468 this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
14469 return qFactory(function(callback) {
14470 $rootScope.$evalAsync(callback);
14471 }, $exceptionHandler);
14472 }];
14473 }
14474
14475 function $$QProvider() {
14476 this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
14477 return qFactory(function(callback) {
14478 $browser.defer(callback);
14479 }, $exceptionHandler);
14480 }];
14481 }
14482
14483 /**
14484 * Constructs a promise manager.
14485 *
14486 * @param {function(function)} nextTick Function for executing functions in the next turn.
14487 * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
14488 * debugging purposes.
14489 * @returns {object} Promise manager.
14490 */
14491 function qFactory(nextTick, exceptionHandler) {
14492 var $qMinErr = minErr('$q', TypeError);
14493 function callOnce(self, resolveFn, rejectFn) {
14494 var called = false;
14495 function wrap(fn) {
14496 return function(value) {
14497 if (called) return;
14498 called = true;
14499 fn.call(self, value);
14500 };
14501 }
14502
14503 return [wrap(resolveFn), wrap(rejectFn)];
14504 }
14505
14506 /**
14507 * @ngdoc method
14508 * @name ng.$q#defer
14509 * @kind function
14510 *
14511 * @description
14512 * Creates a `Deferred` object which represents a task which will finish in the future.
14513 *
14514 * @returns {Deferred} Returns a new instance of deferred.
14515 */
14516 var defer = function() {
14517 return new Deferred();
14518 };
14519
14520 function Promise() {
14521 this.$$state = { status: 0 };
14522 }
14523
14524 Promise.prototype = {
14525 then: function(onFulfilled, onRejected, progressBack) {
14526 var result = new Deferred();
14527
14528 this.$$state.pending = this.$$state.pending || [];
14529 this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]);
14530 if (this.$$state.status > 0) scheduleProcessQueue(this.$$state);
14531
14532 return result.promise;
14533 },
14534
14535 "catch": function(callback) {
14536 return this.then(null, callback);
14537 },
14538
14539 "finally": function(callback, progressBack) {
14540 return this.then(function(value) {
14541 return handleCallback(value, true, callback);
14542 }, function(error) {
14543 return handleCallback(error, false, callback);
14544 }, progressBack);
14545 }
14546 };
14547
14548 //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
14549 function simpleBind(context, fn) {
14550 return function(value) {
14551 fn.call(context, value);
14552 };
14553 }
14554
14555 function processQueue(state) {
14556 var fn, deferred, pending;
14557
14558 pending = state.pending;
14559 state.processScheduled = false;
14560 state.pending = undefined;
14561 for (var i = 0, ii = pending.length; i < ii; ++i) {
14562 deferred = pending[i][0];
14563 fn = pending[i][state.status];
14564 try {
14565 if (isFunction(fn)) {
14566 deferred.resolve(fn(state.value));
14567 } else if (state.status === 1) {
14568 deferred.resolve(state.value);
14569 } else {
14570 deferred.reject(state.value);
14571 }
14572 } catch (e) {
14573 deferred.reject(e);
14574 exceptionHandler(e);
14575 }
14576 }
14577 }
14578
14579 function scheduleProcessQueue(state) {
14580 if (state.processScheduled || !state.pending) return;
14581 state.processScheduled = true;
14582 nextTick(function() { processQueue(state); });
14583 }
14584
14585 function Deferred() {
14586 this.promise = new Promise();
14587 //Necessary to support unbound execution :/
14588 this.resolve = simpleBind(this, this.resolve);
14589 this.reject = simpleBind(this, this.reject);
14590 this.notify = simpleBind(this, this.notify);
14591 }
14592
14593 Deferred.prototype = {
14594 resolve: function(val) {
14595 if (this.promise.$$state.status) return;
14596 if (val === this.promise) {
14597 this.$$reject($qMinErr(
14598 'qcycle',
14599 "Expected promise to be resolved with value other than itself '{0}'",
14600 val));
14601 } else {
14602 this.$$resolve(val);
14603 }
14604
14605 },
14606
14607 $$resolve: function(val) {
14608 var then, fns;
14609
14610 fns = callOnce(this, this.$$resolve, this.$$reject);
14611 try {
14612 if ((isObject(val) || isFunction(val))) then = val && val.then;
14613 if (isFunction(then)) {
14614 this.promise.$$state.status = -1;
14615 then.call(val, fns[0], fns[1], this.notify);
14616 } else {
14617 this.promise.$$state.value = val;
14618 this.promise.$$state.status = 1;
14619 scheduleProcessQueue(this.promise.$$state);
14620 }
14621 } catch (e) {
14622 fns[1](e);
14623 exceptionHandler(e);
14624 }
14625 },
14626
14627 reject: function(reason) {
14628 if (this.promise.$$state.status) return;
14629 this.$$reject(reason);
14630 },
14631
14632 $$reject: function(reason) {
14633 this.promise.$$state.value = reason;
14634 this.promise.$$state.status = 2;
14635 scheduleProcessQueue(this.promise.$$state);
14636 },
14637
14638 notify: function(progress) {
14639 var callbacks = this.promise.$$state.pending;
14640
14641 if ((this.promise.$$state.status <= 0) && callbacks && callbacks.length) {
14642 nextTick(function() {
14643 var callback, result;
14644 for (var i = 0, ii = callbacks.length; i < ii; i++) {
14645 result = callbacks[i][0];
14646 callback = callbacks[i][3];
14647 try {
14648 result.notify(isFunction(callback) ? callback(progress) : progress);
14649 } catch (e) {
14650 exceptionHandler(e);
14651 }
14652 }
14653 });
14654 }
14655 }
14656 };
14657
14658 /**
14659 * @ngdoc method
14660 * @name $q#reject
14661 * @kind function
14662 *
14663 * @description
14664 * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
14665 * used to forward rejection in a chain of promises. If you are dealing with the last promise in
14666 * a promise chain, you don't need to worry about it.
14667 *
14668 * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
14669 * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
14670 * a promise error callback and you want to forward the error to the promise derived from the
14671 * current promise, you have to "rethrow" the error by returning a rejection constructed via
14672 * `reject`.
14673 *
14674 * ```js
14675 * promiseB = promiseA.then(function(result) {
14676 * // success: do something and resolve promiseB
14677 * // with the old or a new result
14678 * return result;
14679 * }, function(reason) {
14680 * // error: handle the error if possible and
14681 * // resolve promiseB with newPromiseOrValue,
14682 * // otherwise forward the rejection to promiseB
14683 * if (canHandle(reason)) {
14684 * // handle the error and recover
14685 * return newPromiseOrValue;
14686 * }
14687 * return $q.reject(reason);
14688 * });
14689 * ```
14690 *
14691 * @param {*} reason Constant, message, exception or an object representing the rejection reason.
14692 * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
14693 */
14694 var reject = function(reason) {
14695 var result = new Deferred();
14696 result.reject(reason);
14697 return result.promise;
14698 };
14699
14700 var makePromise = function makePromise(value, resolved) {
14701 var result = new Deferred();
14702 if (resolved) {
14703 result.resolve(value);
14704 } else {
14705 result.reject(value);
14706 }
14707 return result.promise;
14708 };
14709
14710 var handleCallback = function handleCallback(value, isResolved, callback) {
14711 var callbackOutput = null;
14712 try {
14713 if (isFunction(callback)) callbackOutput = callback();
14714 } catch (e) {
14715 return makePromise(e, false);
14716 }
14717 if (isPromiseLike(callbackOutput)) {
14718 return callbackOutput.then(function() {
14719 return makePromise(value, isResolved);
14720 }, function(error) {
14721 return makePromise(error, false);
14722 });
14723 } else {
14724 return makePromise(value, isResolved);
14725 }
14726 };
14727
14728 /**
14729 * @ngdoc method
14730 * @name $q#when
14731 * @kind function
14732 *
14733 * @description
14734 * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
14735 * This is useful when you are dealing with an object that might or might not be a promise, or if
14736 * the promise comes from a source that can't be trusted.
14737 *
14738 * @param {*} value Value or a promise
14739 * @returns {Promise} Returns a promise of the passed value or promise
14740 */
14741
14742
14743 var when = function(value, callback, errback, progressBack) {
14744 var result = new Deferred();
14745 result.resolve(value);
14746 return result.promise.then(callback, errback, progressBack);
14747 };
14748
14749 /**
14750 * @ngdoc method
14751 * @name $q#resolve
14752 * @kind function
14753 *
14754 * @description
14755 * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6.
14756 *
14757 * @param {*} value Value or a promise
14758 * @returns {Promise} Returns a promise of the passed value or promise
14759 */
14760 var resolve = when;
14761
14762 /**
14763 * @ngdoc method
14764 * @name $q#all
14765 * @kind function
14766 *
14767 * @description
14768 * Combines multiple promises into a single promise that is resolved when all of the input
14769 * promises are resolved.
14770 *
14771 * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
14772 * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
14773 * each value corresponding to the promise at the same index/key in the `promises` array/hash.
14774 * If any of the promises is resolved with a rejection, this resulting promise will be rejected
14775 * with the same rejection value.
14776 */
14777
14778 function all(promises) {
14779 var deferred = new Deferred(),
14780 counter = 0,
14781 results = isArray(promises) ? [] : {};
14782
14783 forEach(promises, function(promise, key) {
14784 counter++;
14785 when(promise).then(function(value) {
14786 if (results.hasOwnProperty(key)) return;
14787 results[key] = value;
14788 if (!(--counter)) deferred.resolve(results);
14789 }, function(reason) {
14790 if (results.hasOwnProperty(key)) return;
14791 deferred.reject(reason);
14792 });
14793 });
14794
14795 if (counter === 0) {
14796 deferred.resolve(results);
14797 }
14798
14799 return deferred.promise;
14800 }
14801
14802 var $Q = function Q(resolver) {
14803 if (!isFunction(resolver)) {
14804 throw $qMinErr('norslvr', "Expected resolverFn, got '{0}'", resolver);
14805 }
14806
14807 if (!(this instanceof Q)) {
14808 // More useful when $Q is the Promise itself.
14809 return new Q(resolver);
14810 }
14811
14812 var deferred = new Deferred();
14813
14814 function resolveFn(value) {
14815 deferred.resolve(value);
14816 }
14817
14818 function rejectFn(reason) {
14819 deferred.reject(reason);
14820 }
14821
14822 resolver(resolveFn, rejectFn);
14823
14824 return deferred.promise;
14825 };
14826
14827 $Q.defer = defer;
14828 $Q.reject = reject;
14829 $Q.when = when;
14830 $Q.resolve = resolve;
14831 $Q.all = all;
14832
14833 return $Q;
14834 }
14835
14836 function $$RAFProvider() { //rAF
14837 this.$get = ['$window', '$timeout', function($window, $timeout) {
14838 var requestAnimationFrame = $window.requestAnimationFrame ||
14839 $window.webkitRequestAnimationFrame;
14840
14841 var cancelAnimationFrame = $window.cancelAnimationFrame ||
14842 $window.webkitCancelAnimationFrame ||
14843 $window.webkitCancelRequestAnimationFrame;
14844
14845 var rafSupported = !!requestAnimationFrame;
14846 var rafFn = rafSupported
14847 ? function(fn) {
14848 var id = requestAnimationFrame(fn);
14849 return function() {
14850 cancelAnimationFrame(id);
14851 };
14852 }
14853 : function(fn) {
14854 var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666
14855 return function() {
14856 $timeout.cancel(timer);
14857 };
14858 };
14859
14860 queueFn.supported = rafSupported;
14861
14862 var cancelLastRAF;
14863 var taskCount = 0;
14864 var taskQueue = [];
14865 return queueFn;
14866
14867 function flush() {
14868 for (var i = 0; i < taskQueue.length; i++) {
14869 var task = taskQueue[i];
14870 if (task) {
14871 taskQueue[i] = null;
14872 task();
14873 }
14874 }
14875 taskCount = taskQueue.length = 0;
14876 }
14877
14878 function queueFn(asyncFn) {
14879 var index = taskQueue.length;
14880
14881 taskCount++;
14882 taskQueue.push(asyncFn);
14883
14884 if (index === 0) {
14885 cancelLastRAF = rafFn(flush);
14886 }
14887
14888 return function cancelQueueFn() {
14889 if (index >= 0) {
14890 taskQueue[index] = null;
14891 index = null;
14892
14893 if (--taskCount === 0 && cancelLastRAF) {
14894 cancelLastRAF();
14895 cancelLastRAF = null;
14896 taskQueue.length = 0;
14897 }
14898 }
14899 };
14900 }
14901 }];
14902 }
14903
14904 /**
14905 * DESIGN NOTES
14906 *
14907 * The design decisions behind the scope are heavily favored for speed and memory consumption.
14908 *
14909 * The typical use of scope is to watch the expressions, which most of the time return the same
14910 * value as last time so we optimize the operation.
14911 *
14912 * Closures construction is expensive in terms of speed as well as memory:
14913 * - No closures, instead use prototypical inheritance for API
14914 * - Internal state needs to be stored on scope directly, which means that private state is
14915 * exposed as $$____ properties
14916 *
14917 * Loop operations are optimized by using while(count--) { ... }
14918 * - this means that in order to keep the same order of execution as addition we have to add
14919 * items to the array at the beginning (unshift) instead of at the end (push)
14920 *
14921 * Child scopes are created and removed often
14922 * - Using an array would be slow since inserts in middle are expensive so we use linked list
14923 *
14924 * There are few watches then a lot of observers. This is why you don't want the observer to be
14925 * implemented in the same way as watch. Watch requires return of initialization function which
14926 * are expensive to construct.
14927 */
14928
14929
14930 /**
14931 * @ngdoc provider
14932 * @name $rootScopeProvider
14933 * @description
14934 *
14935 * Provider for the $rootScope service.
14936 */
14937
14938 /**
14939 * @ngdoc method
14940 * @name $rootScopeProvider#digestTtl
14941 * @description
14942 *
14943 * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
14944 * assuming that the model is unstable.
14945 *
14946 * The current default is 10 iterations.
14947 *
14948 * In complex applications it's possible that the dependencies between `$watch`s will result in
14949 * several digest iterations. However if an application needs more than the default 10 digest
14950 * iterations for its model to stabilize then you should investigate what is causing the model to
14951 * continuously change during the digest.
14952 *
14953 * Increasing the TTL could have performance implications, so you should not change it without
14954 * proper justification.
14955 *
14956 * @param {number} limit The number of digest iterations.
14957 */
14958
14959
14960 /**
14961 * @ngdoc service
14962 * @name $rootScope
14963 * @description
14964 *
14965 * Every application has a single root {@link ng.$rootScope.Scope scope}.
14966 * All other scopes are descendant scopes of the root scope. Scopes provide separation
14967 * between the model and the view, via a mechanism for watching the model for changes.
14968 * They also provide an event emission/broadcast and subscription facility. See the
14969 * {@link guide/scope developer guide on scopes}.
14970 */
14971 function $RootScopeProvider() {
14972 var TTL = 10;
14973 var $rootScopeMinErr = minErr('$rootScope');
14974 var lastDirtyWatch = null;
14975 var applyAsyncId = null;
14976
14977 this.digestTtl = function(value) {
14978 if (arguments.length) {
14979 TTL = value;
14980 }
14981 return TTL;
14982 };
14983
14984 function createChildScopeClass(parent) {
14985 function ChildScope() {
14986 this.$$watchers = this.$$nextSibling =
14987 this.$$childHead = this.$$childTail = null;
14988 this.$$listeners = {};
14989 this.$$listenerCount = {};
14990 this.$$watchersCount = 0;
14991 this.$id = nextUid();
14992 this.$$ChildScope = null;
14993 }
14994 ChildScope.prototype = parent;
14995 return ChildScope;
14996 }
14997
14998 this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
14999 function($injector, $exceptionHandler, $parse, $browser) {
15000
15001 function destroyChildScope($event) {
15002 $event.currentScope.$$destroyed = true;
15003 }
15004
15005 /**
15006 * @ngdoc type
15007 * @name $rootScope.Scope
15008 *
15009 * @description
15010 * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
15011 * {@link auto.$injector $injector}. Child scopes are created using the
15012 * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when
15013 * compiled HTML template is executed.)
15014 *
15015 * Here is a simple scope snippet to show how you can interact with the scope.
15016 * ```html
15017 * <file src="./test/ng/rootScopeSpec.js" tag="docs1" />
15018 * ```
15019 *
15020 * # Inheritance
15021 * A scope can inherit from a parent scope, as in this example:
15022 * ```js
15023 var parent = $rootScope;
15024 var child = parent.$new();
15025
15026 parent.salutation = "Hello";
15027 expect(child.salutation).toEqual('Hello');
15028
15029 child.salutation = "Welcome";
15030 expect(child.salutation).toEqual('Welcome');
15031 expect(parent.salutation).toEqual('Hello');
15032 * ```
15033 *
15034 * When interacting with `Scope` in tests, additional helper methods are available on the
15035 * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional
15036 * details.
15037 *
15038 *
15039 * @param {Object.<string, function()>=} providers Map of service factory which need to be
15040 * provided for the current scope. Defaults to {@link ng}.
15041 * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
15042 * append/override services provided by `providers`. This is handy
15043 * when unit-testing and having the need to override a default
15044 * service.
15045 * @returns {Object} Newly created scope.
15046 *
15047 */
15048 function Scope() {
15049 this.$id = nextUid();
15050 this.$$phase = this.$parent = this.$$watchers =
15051 this.$$nextSibling = this.$$prevSibling =
15052 this.$$childHead = this.$$childTail = null;
15053 this.$root = this;
15054 this.$$destroyed = false;
15055 this.$$listeners = {};
15056 this.$$listenerCount = {};
15057 this.$$watchersCount = 0;
15058 this.$$isolateBindings = null;
15059 }
15060
15061 /**
15062 * @ngdoc property
15063 * @name $rootScope.Scope#$id
15064 *
15065 * @description
15066 * Unique scope ID (monotonically increasing) useful for debugging.
15067 */
15068
15069 /**
15070 * @ngdoc property
15071 * @name $rootScope.Scope#$parent
15072 *
15073 * @description
15074 * Reference to the parent scope.
15075 */
15076
15077 /**
15078 * @ngdoc property
15079 * @name $rootScope.Scope#$root
15080 *
15081 * @description
15082 * Reference to the root scope.
15083 */
15084
15085 Scope.prototype = {
15086 constructor: Scope,
15087 /**
15088 * @ngdoc method
15089 * @name $rootScope.Scope#$new
15090 * @kind function
15091 *
15092 * @description
15093 * Creates a new child {@link ng.$rootScope.Scope scope}.
15094 *
15095 * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event.
15096 * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}.
15097 *
15098 * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is
15099 * desired for the scope and its child scopes to be permanently detached from the parent and
15100 * thus stop participating in model change detection and listener notification by invoking.
15101 *
15102 * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
15103 * parent scope. The scope is isolated, as it can not see parent scope properties.
15104 * When creating widgets, it is useful for the widget to not accidentally read parent
15105 * state.
15106 *
15107 * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent`
15108 * of the newly created scope. Defaults to `this` scope if not provided.
15109 * This is used when creating a transclude scope to correctly place it
15110 * in the scope hierarchy while maintaining the correct prototypical
15111 * inheritance.
15112 *
15113 * @returns {Object} The newly created child scope.
15114 *
15115 */
15116 $new: function(isolate, parent) {
15117 var child;
15118
15119 parent = parent || this;
15120
15121 if (isolate) {
15122 child = new Scope();
15123 child.$root = this.$root;
15124 } else {
15125 // Only create a child scope class if somebody asks for one,
15126 // but cache it to allow the VM to optimize lookups.
15127 if (!this.$$ChildScope) {
15128 this.$$ChildScope = createChildScopeClass(this);
15129 }
15130 child = new this.$$ChildScope();
15131 }
15132 child.$parent = parent;
15133 child.$$prevSibling = parent.$$childTail;
15134 if (parent.$$childHead) {
15135 parent.$$childTail.$$nextSibling = child;
15136 parent.$$childTail = child;
15137 } else {
15138 parent.$$childHead = parent.$$childTail = child;
15139 }
15140
15141 // When the new scope is not isolated or we inherit from `this`, and
15142 // the parent scope is destroyed, the property `$$destroyed` is inherited
15143 // prototypically. In all other cases, this property needs to be set
15144 // when the parent scope is destroyed.
15145 // The listener needs to be added after the parent is set
15146 if (isolate || parent != this) child.$on('$destroy', destroyChildScope);
15147
15148 return child;
15149 },
15150
15151 /**
15152 * @ngdoc method
15153 * @name $rootScope.Scope#$watch
15154 * @kind function
15155 *
15156 * @description
15157 * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
15158 *
15159 * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest
15160 * $digest()} and should return the value that will be watched. (Since
15161 * {@link ng.$rootScope.Scope#$digest $digest()} reruns when it detects changes the
15162 * `watchExpression` can execute multiple times per
15163 * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.)
15164 * - The `listener` is called only when the value from the current `watchExpression` and the
15165 * previous call to `watchExpression` are not equal (with the exception of the initial run,
15166 * see below). Inequality is determined according to reference inequality,
15167 * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators)
15168 * via the `!==` Javascript operator, unless `objectEquality == true`
15169 * (see next point)
15170 * - When `objectEquality == true`, inequality of the `watchExpression` is determined
15171 * according to the {@link angular.equals} function. To save the value of the object for
15172 * later comparison, the {@link angular.copy} function is used. This therefore means that
15173 * watching complex objects will have adverse memory and performance implications.
15174 * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
15175 * This is achieved by rerunning the watchers until no changes are detected. The rerun
15176 * iteration limit is 10 to prevent an infinite loop deadlock.
15177 *
15178 *
15179 * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called,
15180 * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
15181 * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a
15182 * change is detected, be prepared for multiple calls to your listener.)
15183 *
15184 * After a watcher is registered with the scope, the `listener` fn is called asynchronously
15185 * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the
15186 * watcher. In rare cases, this is undesirable because the listener is called when the result
15187 * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
15188 * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
15189 * listener was called due to initialization.
15190 *
15191 *
15192 *
15193 * # Example
15194 * ```js
15195 // let's assume that scope was dependency injected as the $rootScope
15196 var scope = $rootScope;
15197 scope.name = 'misko';
15198 scope.counter = 0;
15199
15200 expect(scope.counter).toEqual(0);
15201 scope.$watch('name', function(newValue, oldValue) {
15202 scope.counter = scope.counter + 1;
15203 });
15204 expect(scope.counter).toEqual(0);
15205
15206 scope.$digest();
15207 // the listener is always called during the first $digest loop after it was registered
15208 expect(scope.counter).toEqual(1);
15209
15210 scope.$digest();
15211 // but now it will not be called unless the value changes
15212 expect(scope.counter).toEqual(1);
15213
15214 scope.name = 'adam';
15215 scope.$digest();
15216 expect(scope.counter).toEqual(2);
15217
15218
15219
15220 // Using a function as a watchExpression
15221 var food;
15222 scope.foodCounter = 0;
15223 expect(scope.foodCounter).toEqual(0);
15224 scope.$watch(
15225 // This function returns the value being watched. It is called for each turn of the $digest loop
15226 function() { return food; },
15227 // This is the change listener, called when the value returned from the above function changes
15228 function(newValue, oldValue) {
15229 if ( newValue !== oldValue ) {
15230 // Only increment the counter if the value changed
15231 scope.foodCounter = scope.foodCounter + 1;
15232 }
15233 }
15234 );
15235 // No digest has been run so the counter will be zero
15236 expect(scope.foodCounter).toEqual(0);
15237
15238 // Run the digest but since food has not changed count will still be zero
15239 scope.$digest();
15240 expect(scope.foodCounter).toEqual(0);
15241
15242 // Update food and run digest. Now the counter will increment
15243 food = 'cheeseburger';
15244 scope.$digest();
15245 expect(scope.foodCounter).toEqual(1);
15246
15247 * ```
15248 *
15249 *
15250 *
15251 * @param {(function()|string)} watchExpression Expression that is evaluated on each
15252 * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers
15253 * a call to the `listener`.
15254 *
15255 * - `string`: Evaluated as {@link guide/expression expression}
15256 * - `function(scope)`: called with current `scope` as a parameter.
15257 * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value
15258 * of `watchExpression` changes.
15259 *
15260 * - `newVal` contains the current value of the `watchExpression`
15261 * - `oldVal` contains the previous value of the `watchExpression`
15262 * - `scope` refers to the current scope
15263 * @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
15264 * comparing for reference equality.
15265 * @returns {function()} Returns a deregistration function for this listener.
15266 */
15267 $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) {
15268 var get = $parse(watchExp);
15269
15270 if (get.$$watchDelegate) {
15271 return get.$$watchDelegate(this, listener, objectEquality, get, watchExp);
15272 }
15273 var scope = this,
15274 array = scope.$$watchers,
15275 watcher = {
15276 fn: listener,
15277 last: initWatchVal,
15278 get: get,
15279 exp: prettyPrintExpression || watchExp,
15280 eq: !!objectEquality
15281 };
15282
15283 lastDirtyWatch = null;
15284
15285 if (!isFunction(listener)) {
15286 watcher.fn = noop;
15287 }
15288
15289 if (!array) {
15290 array = scope.$$watchers = [];
15291 }
15292 // we use unshift since we use a while loop in $digest for speed.
15293 // the while loop reads in reverse order.
15294 array.unshift(watcher);
15295 incrementWatchersCount(this, 1);
15296
15297 return function deregisterWatch() {
15298 if (arrayRemove(array, watcher) >= 0) {
15299 incrementWatchersCount(scope, -1);
15300 }
15301 lastDirtyWatch = null;
15302 };
15303 },
15304
15305 /**
15306 * @ngdoc method
15307 * @name $rootScope.Scope#$watchGroup
15308 * @kind function
15309 *
15310 * @description
15311 * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
15312 * If any one expression in the collection changes the `listener` is executed.
15313 *
15314 * - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
15315 * call to $digest() to see if any items changes.
15316 * - The `listener` is called whenever any expression in the `watchExpressions` array changes.
15317 *
15318 * @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
15319 * watched using {@link ng.$rootScope.Scope#$watch $watch()}
15320 *
15321 * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any
15322 * expression in `watchExpressions` changes
15323 * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
15324 * those of `watchExpression`
15325 * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
15326 * those of `watchExpression`
15327 * The `scope` refers to the current scope.
15328 * @returns {function()} Returns a de-registration function for all listeners.
15329 */
15330 $watchGroup: function(watchExpressions, listener) {
15331 var oldValues = new Array(watchExpressions.length);
15332 var newValues = new Array(watchExpressions.length);
15333 var deregisterFns = [];
15334 var self = this;
15335 var changeReactionScheduled = false;
15336 var firstRun = true;
15337
15338 if (!watchExpressions.length) {
15339 // No expressions means we call the listener ASAP
15340 var shouldCall = true;
15341 self.$evalAsync(function() {
15342 if (shouldCall) listener(newValues, newValues, self);
15343 });
15344 return function deregisterWatchGroup() {
15345 shouldCall = false;
15346 };
15347 }
15348
15349 if (watchExpressions.length === 1) {
15350 // Special case size of one
15351 return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
15352 newValues[0] = value;
15353 oldValues[0] = oldValue;
15354 listener(newValues, (value === oldValue) ? newValues : oldValues, scope);
15355 });
15356 }
15357
15358 forEach(watchExpressions, function(expr, i) {
15359 var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
15360 newValues[i] = value;
15361 oldValues[i] = oldValue;
15362 if (!changeReactionScheduled) {
15363 changeReactionScheduled = true;
15364 self.$evalAsync(watchGroupAction);
15365 }
15366 });
15367 deregisterFns.push(unwatchFn);
15368 });
15369
15370 function watchGroupAction() {
15371 changeReactionScheduled = false;
15372
15373 if (firstRun) {
15374 firstRun = false;
15375 listener(newValues, newValues, self);
15376 } else {
15377 listener(newValues, oldValues, self);
15378 }
15379 }
15380
15381 return function deregisterWatchGroup() {
15382 while (deregisterFns.length) {
15383 deregisterFns.shift()();
15384 }
15385 };
15386 },
15387
15388
15389 /**
15390 * @ngdoc method
15391 * @name $rootScope.Scope#$watchCollection
15392 * @kind function
15393 *
15394 * @description
15395 * Shallow watches the properties of an object and fires whenever any of the properties change
15396 * (for arrays, this implies watching the array items; for object maps, this implies watching
15397 * the properties). If a change is detected, the `listener` callback is fired.
15398 *
15399 * - The `obj` collection is observed via standard $watch operation and is examined on every
15400 * call to $digest() to see if any items have been added, removed, or moved.
15401 * - The `listener` is called whenever anything within the `obj` has changed. Examples include
15402 * adding, removing, and moving items belonging to an object or array.
15403 *
15404 *
15405 * # Example
15406 * ```js
15407 $scope.names = ['igor', 'matias', 'misko', 'james'];
15408 $scope.dataCount = 4;
15409
15410 $scope.$watchCollection('names', function(newNames, oldNames) {
15411 $scope.dataCount = newNames.length;
15412 });
15413
15414 expect($scope.dataCount).toEqual(4);
15415 $scope.$digest();
15416
15417 //still at 4 ... no changes
15418 expect($scope.dataCount).toEqual(4);
15419
15420 $scope.names.pop();
15421 $scope.$digest();
15422
15423 //now there's been a change
15424 expect($scope.dataCount).toEqual(3);
15425 * ```
15426 *
15427 *
15428 * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The
15429 * expression value should evaluate to an object or an array which is observed on each
15430 * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the
15431 * collection will trigger a call to the `listener`.
15432 *
15433 * @param {function(newCollection, oldCollection, scope)} listener a callback function called
15434 * when a change is detected.
15435 * - The `newCollection` object is the newly modified data obtained from the `obj` expression
15436 * - The `oldCollection` object is a copy of the former collection data.
15437 * Due to performance considerations, the`oldCollection` value is computed only if the
15438 * `listener` function declares two or more arguments.
15439 * - The `scope` argument refers to the current scope.
15440 *
15441 * @returns {function()} Returns a de-registration function for this listener. When the
15442 * de-registration function is executed, the internal watch operation is terminated.
15443 */
15444 $watchCollection: function(obj, listener) {
15445 $watchCollectionInterceptor.$stateful = true;
15446
15447 var self = this;
15448 // the current value, updated on each dirty-check run
15449 var newValue;
15450 // a shallow copy of the newValue from the last dirty-check run,
15451 // updated to match newValue during dirty-check run
15452 var oldValue;
15453 // a shallow copy of the newValue from when the last change happened
15454 var veryOldValue;
15455 // only track veryOldValue if the listener is asking for it
15456 var trackVeryOldValue = (listener.length > 1);
15457 var changeDetected = 0;
15458 var changeDetector = $parse(obj, $watchCollectionInterceptor);
15459 var internalArray = [];
15460 var internalObject = {};
15461 var initRun = true;
15462 var oldLength = 0;
15463
15464 function $watchCollectionInterceptor(_value) {
15465 newValue = _value;
15466 var newLength, key, bothNaN, newItem, oldItem;
15467
15468 // If the new value is undefined, then return undefined as the watch may be a one-time watch
15469 if (isUndefined(newValue)) return;
15470
15471 if (!isObject(newValue)) { // if primitive
15472 if (oldValue !== newValue) {
15473 oldValue = newValue;
15474 changeDetected++;
15475 }
15476 } else if (isArrayLike(newValue)) {
15477 if (oldValue !== internalArray) {
15478 // we are transitioning from something which was not an array into array.
15479 oldValue = internalArray;
15480 oldLength = oldValue.length = 0;
15481 changeDetected++;
15482 }
15483
15484 newLength = newValue.length;
15485
15486 if (oldLength !== newLength) {
15487 // if lengths do not match we need to trigger change notification
15488 changeDetected++;
15489 oldValue.length = oldLength = newLength;
15490 }
15491 // copy the items to oldValue and look for changes.
15492 for (var i = 0; i < newLength; i++) {
15493 oldItem = oldValue[i];
15494 newItem = newValue[i];
15495
15496 bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
15497 if (!bothNaN && (oldItem !== newItem)) {
15498 changeDetected++;
15499 oldValue[i] = newItem;
15500 }
15501 }
15502 } else {
15503 if (oldValue !== internalObject) {
15504 // we are transitioning from something which was not an object into object.
15505 oldValue = internalObject = {};
15506 oldLength = 0;
15507 changeDetected++;
15508 }
15509 // copy the items to oldValue and look for changes.
15510 newLength = 0;
15511 for (key in newValue) {
15512 if (newValue.hasOwnProperty(key)) {
15513 newLength++;
15514 newItem = newValue[key];
15515 oldItem = oldValue[key];
15516
15517 if (key in oldValue) {
15518 bothNaN = (oldItem !== oldItem) && (newItem !== newItem);
15519 if (!bothNaN && (oldItem !== newItem)) {
15520 changeDetected++;
15521 oldValue[key] = newItem;
15522 }
15523 } else {
15524 oldLength++;
15525 oldValue[key] = newItem;
15526 changeDetected++;
15527 }
15528 }
15529 }
15530 if (oldLength > newLength) {
15531 // we used to have more keys, need to find them and destroy them.
15532 changeDetected++;
15533 for (key in oldValue) {
15534 if (!newValue.hasOwnProperty(key)) {
15535 oldLength--;
15536 delete oldValue[key];
15537 }
15538 }
15539 }
15540 }
15541 return changeDetected;
15542 }
15543
15544 function $watchCollectionAction() {
15545 if (initRun) {
15546 initRun = false;
15547 listener(newValue, newValue, self);
15548 } else {
15549 listener(newValue, veryOldValue, self);
15550 }
15551
15552 // make a copy for the next time a collection is changed
15553 if (trackVeryOldValue) {
15554 if (!isObject(newValue)) {
15555 //primitive
15556 veryOldValue = newValue;
15557 } else if (isArrayLike(newValue)) {
15558 veryOldValue = new Array(newValue.length);
15559 for (var i = 0; i < newValue.length; i++) {
15560 veryOldValue[i] = newValue[i];
15561 }
15562 } else { // if object
15563 veryOldValue = {};
15564 for (var key in newValue) {
15565 if (hasOwnProperty.call(newValue, key)) {
15566 veryOldValue[key] = newValue[key];
15567 }
15568 }
15569 }
15570 }
15571 }
15572
15573 return this.$watch(changeDetector, $watchCollectionAction);
15574 },
15575
15576 /**
15577 * @ngdoc method
15578 * @name $rootScope.Scope#$digest
15579 * @kind function
15580 *
15581 * @description
15582 * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and
15583 * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change
15584 * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers}
15585 * until no more listeners are firing. This means that it is possible to get into an infinite
15586 * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
15587 * iterations exceeds 10.
15588 *
15589 * Usually, you don't call `$digest()` directly in
15590 * {@link ng.directive:ngController controllers} or in
15591 * {@link ng.$compileProvider#directive directives}.
15592 * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
15593 * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.
15594 *
15595 * If you want to be notified whenever `$digest()` is called,
15596 * you can register a `watchExpression` function with
15597 * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`.
15598 *
15599 * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
15600 *
15601 * # Example
15602 * ```js
15603 var scope = ...;
15604 scope.name = 'misko';
15605 scope.counter = 0;
15606
15607 expect(scope.counter).toEqual(0);
15608 scope.$watch('name', function(newValue, oldValue) {
15609 scope.counter = scope.counter + 1;
15610 });
15611 expect(scope.counter).toEqual(0);
15612
15613 scope.$digest();
15614 // the listener is always called during the first $digest loop after it was registered
15615 expect(scope.counter).toEqual(1);
15616
15617 scope.$digest();
15618 // but now it will not be called unless the value changes
15619 expect(scope.counter).toEqual(1);
15620
15621 scope.name = 'adam';
15622 scope.$digest();
15623 expect(scope.counter).toEqual(2);
15624 * ```
15625 *
15626 */
15627 $digest: function() {
15628 var watch, value, last,
15629 watchers,
15630 length,
15631 dirty, ttl = TTL,
15632 next, current, target = this,
15633 watchLog = [],
15634 logIdx, logMsg, asyncTask;
15635
15636 beginPhase('$digest');
15637 // Check for changes to browser url that happened in sync before the call to $digest
15638 $browser.$$checkUrlChange();
15639
15640 if (this === $rootScope && applyAsyncId !== null) {
15641 // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then
15642 // cancel the scheduled $apply and flush the queue of expressions to be evaluated.
15643 $browser.defer.cancel(applyAsyncId);
15644 flushApplyAsync();
15645 }
15646
15647 lastDirtyWatch = null;
15648
15649 do { // "while dirty" loop
15650 dirty = false;
15651 current = target;
15652
15653 while (asyncQueue.length) {
15654 try {
15655 asyncTask = asyncQueue.shift();
15656 asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals);
15657 } catch (e) {
15658 $exceptionHandler(e);
15659 }
15660 lastDirtyWatch = null;
15661 }
15662
15663 traverseScopesLoop:
15664 do { // "traverse the scopes" loop
15665 if ((watchers = current.$$watchers)) {
15666 // process our watches
15667 length = watchers.length;
15668 while (length--) {
15669 try {
15670 watch = watchers[length];
15671 // Most common watches are on primitives, in which case we can short
15672 // circuit it with === operator, only when === fails do we use .equals
15673 if (watch) {
15674 if ((value = watch.get(current)) !== (last = watch.last) &&
15675 !(watch.eq
15676 ? equals(value, last)
15677 : (typeof value === 'number' && typeof last === 'number'
15678 && isNaN(value) && isNaN(last)))) {
15679 dirty = true;
15680 lastDirtyWatch = watch;
15681 watch.last = watch.eq ? copy(value, null) : value;
15682 watch.fn(value, ((last === initWatchVal) ? value : last), current);
15683 if (ttl < 5) {
15684 logIdx = 4 - ttl;
15685 if (!watchLog[logIdx]) watchLog[logIdx] = [];
15686 watchLog[logIdx].push({
15687 msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp,
15688 newVal: value,
15689 oldVal: last
15690 });
15691 }
15692 } else if (watch === lastDirtyWatch) {
15693 // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
15694 // have already been tested.
15695 dirty = false;
15696 break traverseScopesLoop;
15697 }
15698 }
15699 } catch (e) {
15700 $exceptionHandler(e);
15701 }
15702 }
15703 }
15704
15705 // Insanity Warning: scope depth-first traversal
15706 // yes, this code is a bit crazy, but it works and we have tests to prove it!
15707 // this piece should be kept in sync with the traversal in $broadcast
15708 if (!(next = ((current.$$watchersCount && current.$$childHead) ||
15709 (current !== target && current.$$nextSibling)))) {
15710 while (current !== target && !(next = current.$$nextSibling)) {
15711 current = current.$parent;
15712 }
15713 }
15714 } while ((current = next));
15715
15716 // `break traverseScopesLoop;` takes us to here
15717
15718 if ((dirty || asyncQueue.length) && !(ttl--)) {
15719 clearPhase();
15720 throw $rootScopeMinErr('infdig',
15721 '{0} $digest() iterations reached. Aborting!\n' +
15722 'Watchers fired in the last 5 iterations: {1}',
15723 TTL, watchLog);
15724 }
15725
15726 } while (dirty || asyncQueue.length);
15727
15728 clearPhase();
15729
15730 while (postDigestQueue.length) {
15731 try {
15732 postDigestQueue.shift()();
15733 } catch (e) {
15734 $exceptionHandler(e);
15735 }
15736 }
15737 },
15738
15739
15740 /**
15741 * @ngdoc event
15742 * @name $rootScope.Scope#$destroy
15743 * @eventType broadcast on scope being destroyed
15744 *
15745 * @description
15746 * Broadcasted when a scope and its children are being destroyed.
15747 *
15748 * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
15749 * clean up DOM bindings before an element is removed from the DOM.
15750 */
15751
15752 /**
15753 * @ngdoc method
15754 * @name $rootScope.Scope#$destroy
15755 * @kind function
15756 *
15757 * @description
15758 * Removes the current scope (and all of its children) from the parent scope. Removal implies
15759 * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer
15760 * propagate to the current scope and its children. Removal also implies that the current
15761 * scope is eligible for garbage collection.
15762 *
15763 * The `$destroy()` is usually used by directives such as
15764 * {@link ng.directive:ngRepeat ngRepeat} for managing the
15765 * unrolling of the loop.
15766 *
15767 * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
15768 * Application code can register a `$destroy` event handler that will give it a chance to
15769 * perform any necessary cleanup.
15770 *
15771 * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
15772 * clean up DOM bindings before an element is removed from the DOM.
15773 */
15774 $destroy: function() {
15775 // We can't destroy a scope that has been already destroyed.
15776 if (this.$$destroyed) return;
15777 var parent = this.$parent;
15778
15779 this.$broadcast('$destroy');
15780 this.$$destroyed = true;
15781
15782 if (this === $rootScope) {
15783 //Remove handlers attached to window when $rootScope is removed
15784 $browser.$$applicationDestroyed();
15785 }
15786
15787 incrementWatchersCount(this, -this.$$watchersCount);
15788 for (var eventName in this.$$listenerCount) {
15789 decrementListenerCount(this, this.$$listenerCount[eventName], eventName);
15790 }
15791
15792 // sever all the references to parent scopes (after this cleanup, the current scope should
15793 // not be retained by any of our references and should be eligible for garbage collection)
15794 if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
15795 if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
15796 if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
15797 if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
15798
15799 // Disable listeners, watchers and apply/digest methods
15800 this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;
15801 this.$on = this.$watch = this.$watchGroup = function() { return noop; };
15802 this.$$listeners = {};
15803
15804 // All of the code below is bogus code that works around V8's memory leak via optimized code
15805 // and inline caches.
15806 //
15807 // see:
15808 // - https://code.google.com/p/v8/issues/detail?id=2073#c26
15809 // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909
15810 // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
15811
15812 this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
15813 this.$$childTail = this.$root = this.$$watchers = null;
15814 },
15815
15816 /**
15817 * @ngdoc method
15818 * @name $rootScope.Scope#$eval
15819 * @kind function
15820 *
15821 * @description
15822 * Executes the `expression` on the current scope and returns the result. Any exceptions in
15823 * the expression are propagated (uncaught). This is useful when evaluating Angular
15824 * expressions.
15825 *
15826 * # Example
15827 * ```js
15828 var scope = ng.$rootScope.Scope();
15829 scope.a = 1;
15830 scope.b = 2;
15831
15832 expect(scope.$eval('a+b')).toEqual(3);
15833 expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
15834 * ```
15835 *
15836 * @param {(string|function())=} expression An angular expression to be executed.
15837 *
15838 * - `string`: execute using the rules as defined in {@link guide/expression expression}.
15839 * - `function(scope)`: execute the function with the current `scope` parameter.
15840 *
15841 * @param {(object)=} locals Local variables object, useful for overriding values in scope.
15842 * @returns {*} The result of evaluating the expression.
15843 */
15844 $eval: function(expr, locals) {
15845 return $parse(expr)(this, locals);
15846 },
15847
15848 /**
15849 * @ngdoc method
15850 * @name $rootScope.Scope#$evalAsync
15851 * @kind function
15852 *
15853 * @description
15854 * Executes the expression on the current scope at a later point in time.
15855 *
15856 * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
15857 * that:
15858 *
15859 * - it will execute after the function that scheduled the evaluation (preferably before DOM
15860 * rendering).
15861 * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after
15862 * `expression` execution.
15863 *
15864 * Any exceptions from the execution of the expression are forwarded to the
15865 * {@link ng.$exceptionHandler $exceptionHandler} service.
15866 *
15867 * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
15868 * will be scheduled. However, it is encouraged to always call code that changes the model
15869 * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
15870 *
15871 * @param {(string|function())=} expression An angular expression to be executed.
15872 *
15873 * - `string`: execute using the rules as defined in {@link guide/expression expression}.
15874 * - `function(scope)`: execute the function with the current `scope` parameter.
15875 *
15876 * @param {(object)=} locals Local variables object, useful for overriding values in scope.
15877 */
15878 $evalAsync: function(expr, locals) {
15879 // if we are outside of an $digest loop and this is the first time we are scheduling async
15880 // task also schedule async auto-flush
15881 if (!$rootScope.$$phase && !asyncQueue.length) {
15882 $browser.defer(function() {
15883 if (asyncQueue.length) {
15884 $rootScope.$digest();
15885 }
15886 });
15887 }
15888
15889 asyncQueue.push({scope: this, expression: expr, locals: locals});
15890 },
15891
15892 $$postDigest: function(fn) {
15893 postDigestQueue.push(fn);
15894 },
15895
15896 /**
15897 * @ngdoc method
15898 * @name $rootScope.Scope#$apply
15899 * @kind function
15900 *
15901 * @description
15902 * `$apply()` is used to execute an expression in angular from outside of the angular
15903 * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
15904 * Because we are calling into the angular framework we need to perform proper scope life
15905 * cycle of {@link ng.$exceptionHandler exception handling},
15906 * {@link ng.$rootScope.Scope#$digest executing watches}.
15907 *
15908 * ## Life cycle
15909 *
15910 * # Pseudo-Code of `$apply()`
15911 * ```js
15912 function $apply(expr) {
15913 try {
15914 return $eval(expr);
15915 } catch (e) {
15916 $exceptionHandler(e);
15917 } finally {
15918 $root.$digest();
15919 }
15920 }
15921 * ```
15922 *
15923 *
15924 * Scope's `$apply()` method transitions through the following stages:
15925 *
15926 * 1. The {@link guide/expression expression} is executed using the
15927 * {@link ng.$rootScope.Scope#$eval $eval()} method.
15928 * 2. Any exceptions from the execution of the expression are forwarded to the
15929 * {@link ng.$exceptionHandler $exceptionHandler} service.
15930 * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the
15931 * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
15932 *
15933 *
15934 * @param {(string|function())=} exp An angular expression to be executed.
15935 *
15936 * - `string`: execute using the rules as defined in {@link guide/expression expression}.
15937 * - `function(scope)`: execute the function with current `scope` parameter.
15938 *
15939 * @returns {*} The result of evaluating the expression.
15940 */
15941 $apply: function(expr) {
15942 try {
15943 beginPhase('$apply');
15944 return this.$eval(expr);
15945 } catch (e) {
15946 $exceptionHandler(e);
15947 } finally {
15948 clearPhase();
15949 try {
15950 $rootScope.$digest();
15951 } catch (e) {
15952 $exceptionHandler(e);
15953 throw e;
15954 }
15955 }
15956 },
15957
15958 /**
15959 * @ngdoc method
15960 * @name $rootScope.Scope#$applyAsync
15961 * @kind function
15962 *
15963 * @description
15964 * Schedule the invocation of $apply to occur at a later time. The actual time difference
15965 * varies across browsers, but is typically around ~10 milliseconds.
15966 *
15967 * This can be used to queue up multiple expressions which need to be evaluated in the same
15968 * digest.
15969 *
15970 * @param {(string|function())=} exp An angular expression to be executed.
15971 *
15972 * - `string`: execute using the rules as defined in {@link guide/expression expression}.
15973 * - `function(scope)`: execute the function with current `scope` parameter.
15974 */
15975 $applyAsync: function(expr) {
15976 var scope = this;
15977 expr && applyAsyncQueue.push($applyAsyncExpression);
15978 scheduleApplyAsync();
15979
15980 function $applyAsyncExpression() {
15981 scope.$eval(expr);
15982 }
15983 },
15984
15985 /**
15986 * @ngdoc method
15987 * @name $rootScope.Scope#$on
15988 * @kind function
15989 *
15990 * @description
15991 * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for
15992 * discussion of event life cycle.
15993 *
15994 * The event listener function format is: `function(event, args...)`. The `event` object
15995 * passed into the listener has the following attributes:
15996 *
15997 * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
15998 * `$broadcast`-ed.
15999 * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the
16000 * event propagates through the scope hierarchy, this property is set to null.
16001 * - `name` - `{string}`: name of the event.
16002 * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
16003 * further event propagation (available only for events that were `$emit`-ed).
16004 * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
16005 * to true.
16006 * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
16007 *
16008 * @param {string} name Event name to listen on.
16009 * @param {function(event, ...args)} listener Function to call when the event is emitted.
16010 * @returns {function()} Returns a deregistration function for this listener.
16011 */
16012 $on: function(name, listener) {
16013 var namedListeners = this.$$listeners[name];
16014 if (!namedListeners) {
16015 this.$$listeners[name] = namedListeners = [];
16016 }
16017 namedListeners.push(listener);
16018
16019 var current = this;
16020 do {
16021 if (!current.$$listenerCount[name]) {
16022 current.$$listenerCount[name] = 0;
16023 }
16024 current.$$listenerCount[name]++;
16025 } while ((current = current.$parent));
16026
16027 var self = this;
16028 return function() {
16029 var indexOfListener = namedListeners.indexOf(listener);
16030 if (indexOfListener !== -1) {
16031 namedListeners[indexOfListener] = null;
16032 decrementListenerCount(self, 1, name);
16033 }
16034 };
16035 },
16036
16037
16038 /**
16039 * @ngdoc method
16040 * @name $rootScope.Scope#$emit
16041 * @kind function
16042 *
16043 * @description
16044 * Dispatches an event `name` upwards through the scope hierarchy notifying the
16045 * registered {@link ng.$rootScope.Scope#$on} listeners.
16046 *
16047 * The event life cycle starts at the scope on which `$emit` was called. All
16048 * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
16049 * notified. Afterwards, the event traverses upwards toward the root scope and calls all
16050 * registered listeners along the way. The event will stop propagating if one of the listeners
16051 * cancels it.
16052 *
16053 * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
16054 * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
16055 *
16056 * @param {string} name Event name to emit.
16057 * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
16058 * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}).
16059 */
16060 $emit: function(name, args) {
16061 var empty = [],
16062 namedListeners,
16063 scope = this,
16064 stopPropagation = false,
16065 event = {
16066 name: name,
16067 targetScope: scope,
16068 stopPropagation: function() {stopPropagation = true;},
16069 preventDefault: function() {
16070 event.defaultPrevented = true;
16071 },
16072 defaultPrevented: false
16073 },
16074 listenerArgs = concat([event], arguments, 1),
16075 i, length;
16076
16077 do {
16078 namedListeners = scope.$$listeners[name] || empty;
16079 event.currentScope = scope;
16080 for (i = 0, length = namedListeners.length; i < length; i++) {
16081
16082 // if listeners were deregistered, defragment the array
16083 if (!namedListeners[i]) {
16084 namedListeners.splice(i, 1);
16085 i--;
16086 length--;
16087 continue;
16088 }
16089 try {
16090 //allow all listeners attached to the current scope to run
16091 namedListeners[i].apply(null, listenerArgs);
16092 } catch (e) {
16093 $exceptionHandler(e);
16094 }
16095 }
16096 //if any listener on the current scope stops propagation, prevent bubbling
16097 if (stopPropagation) {
16098 event.currentScope = null;
16099 return event;
16100 }
16101 //traverse upwards
16102 scope = scope.$parent;
16103 } while (scope);
16104
16105 event.currentScope = null;
16106
16107 return event;
16108 },
16109
16110
16111 /**
16112 * @ngdoc method
16113 * @name $rootScope.Scope#$broadcast
16114 * @kind function
16115 *
16116 * @description
16117 * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
16118 * registered {@link ng.$rootScope.Scope#$on} listeners.
16119 *
16120 * The event life cycle starts at the scope on which `$broadcast` was called. All
16121 * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get
16122 * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
16123 * scope and calls all registered listeners along the way. The event cannot be canceled.
16124 *
16125 * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed
16126 * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
16127 *
16128 * @param {string} name Event name to broadcast.
16129 * @param {...*} args Optional one or more arguments which will be passed onto the event listeners.
16130 * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on}
16131 */
16132 $broadcast: function(name, args) {
16133 var target = this,
16134 current = target,
16135 next = target,
16136 event = {
16137 name: name,
16138 targetScope: target,
16139 preventDefault: function() {
16140 event.defaultPrevented = true;
16141 },
16142 defaultPrevented: false
16143 };
16144
16145 if (!target.$$listenerCount[name]) return event;
16146
16147 var listenerArgs = concat([event], arguments, 1),
16148 listeners, i, length;
16149
16150 //down while you can, then up and next sibling or up and next sibling until back at root
16151 while ((current = next)) {
16152 event.currentScope = current;
16153 listeners = current.$$listeners[name] || [];
16154 for (i = 0, length = listeners.length; i < length; i++) {
16155 // if listeners were deregistered, defragment the array
16156 if (!listeners[i]) {
16157 listeners.splice(i, 1);
16158 i--;
16159 length--;
16160 continue;
16161 }
16162
16163 try {
16164 listeners[i].apply(null, listenerArgs);
16165 } catch (e) {
16166 $exceptionHandler(e);
16167 }
16168 }
16169
16170 // Insanity Warning: scope depth-first traversal
16171 // yes, this code is a bit crazy, but it works and we have tests to prove it!
16172 // this piece should be kept in sync with the traversal in $digest
16173 // (though it differs due to having the extra check for $$listenerCount)
16174 if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
16175 (current !== target && current.$$nextSibling)))) {
16176 while (current !== target && !(next = current.$$nextSibling)) {
16177 current = current.$parent;
16178 }
16179 }
16180 }
16181
16182 event.currentScope = null;
16183 return event;
16184 }
16185 };
16186
16187 var $rootScope = new Scope();
16188
16189 //The internal queues. Expose them on the $rootScope for debugging/testing purposes.
16190 var asyncQueue = $rootScope.$$asyncQueue = [];
16191 var postDigestQueue = $rootScope.$$postDigestQueue = [];
16192 var applyAsyncQueue = $rootScope.$$applyAsyncQueue = [];
16193
16194 return $rootScope;
16195
16196
16197 function beginPhase(phase) {
16198 if ($rootScope.$$phase) {
16199 throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
16200 }
16201
16202 $rootScope.$$phase = phase;
16203 }
16204
16205 function clearPhase() {
16206 $rootScope.$$phase = null;
16207 }
16208
16209 function incrementWatchersCount(current, count) {
16210 do {
16211 current.$$watchersCount += count;
16212 } while ((current = current.$parent));
16213 }
16214
16215 function decrementListenerCount(current, count, name) {
16216 do {
16217 current.$$listenerCount[name] -= count;
16218
16219 if (current.$$listenerCount[name] === 0) {
16220 delete current.$$listenerCount[name];
16221 }
16222 } while ((current = current.$parent));
16223 }
16224
16225 /**
16226 * function used as an initial value for watchers.
16227 * because it's unique we can easily tell it apart from other values
16228 */
16229 function initWatchVal() {}
16230
16231 function flushApplyAsync() {
16232 while (applyAsyncQueue.length) {
16233 try {
16234 applyAsyncQueue.shift()();
16235 } catch (e) {
16236 $exceptionHandler(e);
16237 }
16238 }
16239 applyAsyncId = null;
16240 }
16241
16242 function scheduleApplyAsync() {
16243 if (applyAsyncId === null) {
16244 applyAsyncId = $browser.defer(function() {
16245 $rootScope.$apply(flushApplyAsync);
16246 });
16247 }
16248 }
16249 }];
16250 }
16251
16252 /**
16253 * @description
16254 * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
16255 */
16256 function $$SanitizeUriProvider() {
16257 var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
16258 imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/;
16259
16260 /**
16261 * @description
16262 * Retrieves or overrides the default regular expression that is used for whitelisting of safe
16263 * urls during a[href] sanitization.
16264 *
16265 * The sanitization is a security measure aimed at prevent XSS attacks via html links.
16266 *
16267 * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
16268 * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
16269 * regular expression. If a match is found, the original url is written into the dom. Otherwise,
16270 * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
16271 *
16272 * @param {RegExp=} regexp New regexp to whitelist urls with.
16273 * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
16274 * chaining otherwise.
16275 */
16276 this.aHrefSanitizationWhitelist = function(regexp) {
16277 if (isDefined(regexp)) {
16278 aHrefSanitizationWhitelist = regexp;
16279 return this;
16280 }
16281 return aHrefSanitizationWhitelist;
16282 };
16283
16284
16285 /**
16286 * @description
16287 * Retrieves or overrides the default regular expression that is used for whitelisting of safe
16288 * urls during img[src] sanitization.
16289 *
16290 * The sanitization is a security measure aimed at prevent XSS attacks via html links.
16291 *
16292 * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
16293 * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
16294 * regular expression. If a match is found, the original url is written into the dom. Otherwise,
16295 * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
16296 *
16297 * @param {RegExp=} regexp New regexp to whitelist urls with.
16298 * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
16299 * chaining otherwise.
16300 */
16301 this.imgSrcSanitizationWhitelist = function(regexp) {
16302 if (isDefined(regexp)) {
16303 imgSrcSanitizationWhitelist = regexp;
16304 return this;
16305 }
16306 return imgSrcSanitizationWhitelist;
16307 };
16308
16309 this.$get = function() {
16310 return function sanitizeUri(uri, isImage) {
16311 var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
16312 var normalizedVal;
16313 normalizedVal = urlResolve(uri).href;
16314 if (normalizedVal !== '' && !normalizedVal.match(regex)) {
16315 return 'unsafe:' + normalizedVal;
16316 }
16317 return uri;
16318 };
16319 };
16320 }
16321
16322 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
16323 * Any commits to this file should be reviewed with security in mind. *
16324 * Changes to this file can potentially create security vulnerabilities. *
16325 * An approval from 2 Core members with history of modifying *
16326 * this file is required. *
16327 * *
16328 * Does the change somehow allow for arbitrary javascript to be executed? *
16329 * Or allows for someone to change the prototype of built-in objects? *
16330 * Or gives undesired access to variables likes document or window? *
16331 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16332
16333 var $sceMinErr = minErr('$sce');
16334
16335 var SCE_CONTEXTS = {
16336 HTML: 'html',
16337 CSS: 'css',
16338 URL: 'url',
16339 // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
16340 // url. (e.g. ng-include, script src, templateUrl)
16341 RESOURCE_URL: 'resourceUrl',
16342 JS: 'js'
16343 };
16344
16345 // Helper functions follow.
16346
16347 function adjustMatcher(matcher) {
16348 if (matcher === 'self') {
16349 return matcher;
16350 } else if (isString(matcher)) {
16351 // Strings match exactly except for 2 wildcards - '*' and '**'.
16352 // '*' matches any character except those from the set ':/.?&'.
16353 // '**' matches any character (like .* in a RegExp).
16354 // More than 2 *'s raises an error as it's ill defined.
16355 if (matcher.indexOf('***') > -1) {
16356 throw $sceMinErr('iwcard',
16357 'Illegal sequence *** in string matcher. String: {0}', matcher);
16358 }
16359 matcher = escapeForRegexp(matcher).
16360 replace('\\*\\*', '.*').
16361 replace('\\*', '[^:/.?&;]*');
16362 return new RegExp('^' + matcher + '$');
16363 } else if (isRegExp(matcher)) {
16364 // The only other type of matcher allowed is a Regexp.
16365 // Match entire URL / disallow partial matches.
16366 // Flags are reset (i.e. no global, ignoreCase or multiline)
16367 return new RegExp('^' + matcher.source + '$');
16368 } else {
16369 throw $sceMinErr('imatcher',
16370 'Matchers may only be "self", string patterns or RegExp objects');
16371 }
16372 }
16373
16374
16375 function adjustMatchers(matchers) {
16376 var adjustedMatchers = [];
16377 if (isDefined(matchers)) {
16378 forEach(matchers, function(matcher) {
16379 adjustedMatchers.push(adjustMatcher(matcher));
16380 });
16381 }
16382 return adjustedMatchers;
16383 }
16384
16385
16386 /**
16387 * @ngdoc service
16388 * @name $sceDelegate
16389 * @kind function
16390 *
16391 * @description
16392 *
16393 * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
16394 * Contextual Escaping (SCE)} services to AngularJS.
16395 *
16396 * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
16397 * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is
16398 * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
16399 * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
16400 * work because `$sce` delegates to `$sceDelegate` for these operations.
16401 *
16402 * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
16403 *
16404 * The default instance of `$sceDelegate` should work out of the box with little pain. While you
16405 * can override it completely to change the behavior of `$sce`, the common case would
16406 * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
16407 * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
16408 * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist
16409 * $sceDelegateProvider.resourceUrlWhitelist} and {@link
16410 * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
16411 */
16412
16413 /**
16414 * @ngdoc provider
16415 * @name $sceDelegateProvider
16416 * @description
16417 *
16418 * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
16419 * $sceDelegate} service. This allows one to get/set the whitelists and blacklists used to ensure
16420 * that the URLs used for sourcing Angular templates are safe. Refer {@link
16421 * ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
16422 * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
16423 *
16424 * For the general details about this service in Angular, read the main page for {@link ng.$sce
16425 * Strict Contextual Escaping (SCE)}.
16426 *
16427 * **Example**: Consider the following case. <a name="example"></a>
16428 *
16429 * - your app is hosted at url `http://myapp.example.com/`
16430 * - but some of your templates are hosted on other domains you control such as
16431 * `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
16432 * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
16433 *
16434 * Here is what a secure configuration for this scenario might look like:
16435 *
16436 * ```
16437 * angular.module('myApp', []).config(function($sceDelegateProvider) {
16438 * $sceDelegateProvider.resourceUrlWhitelist([
16439 * // Allow same origin resource loads.
16440 * 'self',
16441 * // Allow loading from our assets domain. Notice the difference between * and **.
16442 * 'http://srv*.assets.example.com/**'
16443 * ]);
16444 *
16445 * // The blacklist overrides the whitelist so the open redirect here is blocked.
16446 * $sceDelegateProvider.resourceUrlBlacklist([
16447 * 'http://myapp.example.com/clickThru**'
16448 * ]);
16449 * });
16450 * ```
16451 */
16452
16453 function $SceDelegateProvider() {
16454 this.SCE_CONTEXTS = SCE_CONTEXTS;
16455
16456 // Resource URLs can also be trusted by policy.
16457 var resourceUrlWhitelist = ['self'],
16458 resourceUrlBlacklist = [];
16459
16460 /**
16461 * @ngdoc method
16462 * @name $sceDelegateProvider#resourceUrlWhitelist
16463 * @kind function
16464 *
16465 * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
16466 * provided. This must be an array or null. A snapshot of this array is used so further
16467 * changes to the array are ignored.
16468 *
16469 * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
16470 * allowed in this array.
16471 *
16472 * Note: **an empty whitelist array will block all URLs**!
16473 *
16474 * @return {Array} the currently set whitelist array.
16475 *
16476 * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
16477 * same origin resource requests.
16478 *
16479 * @description
16480 * Sets/Gets the whitelist of trusted resource URLs.
16481 */
16482 this.resourceUrlWhitelist = function(value) {
16483 if (arguments.length) {
16484 resourceUrlWhitelist = adjustMatchers(value);
16485 }
16486 return resourceUrlWhitelist;
16487 };
16488
16489 /**
16490 * @ngdoc method
16491 * @name $sceDelegateProvider#resourceUrlBlacklist
16492 * @kind function
16493 *
16494 * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
16495 * provided. This must be an array or null. A snapshot of this array is used so further
16496 * changes to the array are ignored.
16497 *
16498 * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
16499 * allowed in this array.
16500 *
16501 * The typical usage for the blacklist is to **block
16502 * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
16503 * these would otherwise be trusted but actually return content from the redirected domain.
16504 *
16505 * Finally, **the blacklist overrides the whitelist** and has the final say.
16506 *
16507 * @return {Array} the currently set blacklist array.
16508 *
16509 * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
16510 * is no blacklist.)
16511 *
16512 * @description
16513 * Sets/Gets the blacklist of trusted resource URLs.
16514 */
16515
16516 this.resourceUrlBlacklist = function(value) {
16517 if (arguments.length) {
16518 resourceUrlBlacklist = adjustMatchers(value);
16519 }
16520 return resourceUrlBlacklist;
16521 };
16522
16523 this.$get = ['$injector', function($injector) {
16524
16525 var htmlSanitizer = function htmlSanitizer(html) {
16526 throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
16527 };
16528
16529 if ($injector.has('$sanitize')) {
16530 htmlSanitizer = $injector.get('$sanitize');
16531 }
16532
16533
16534 function matchUrl(matcher, parsedUrl) {
16535 if (matcher === 'self') {
16536 return urlIsSameOrigin(parsedUrl);
16537 } else {
16538 // definitely a regex. See adjustMatchers()
16539 return !!matcher.exec(parsedUrl.href);
16540 }
16541 }
16542
16543 function isResourceUrlAllowedByPolicy(url) {
16544 var parsedUrl = urlResolve(url.toString());
16545 var i, n, allowed = false;
16546 // Ensure that at least one item from the whitelist allows this url.
16547 for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
16548 if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
16549 allowed = true;
16550 break;
16551 }
16552 }
16553 if (allowed) {
16554 // Ensure that no item from the blacklist blocked this url.
16555 for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
16556 if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
16557 allowed = false;
16558 break;
16559 }
16560 }
16561 }
16562 return allowed;
16563 }
16564
16565 function generateHolderType(Base) {
16566 var holderType = function TrustedValueHolderType(trustedValue) {
16567 this.$$unwrapTrustedValue = function() {
16568 return trustedValue;
16569 };
16570 };
16571 if (Base) {
16572 holderType.prototype = new Base();
16573 }
16574 holderType.prototype.valueOf = function sceValueOf() {
16575 return this.$$unwrapTrustedValue();
16576 };
16577 holderType.prototype.toString = function sceToString() {
16578 return this.$$unwrapTrustedValue().toString();
16579 };
16580 return holderType;
16581 }
16582
16583 var trustedValueHolderBase = generateHolderType(),
16584 byType = {};
16585
16586 byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
16587 byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
16588 byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
16589 byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
16590 byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
16591
16592 /**
16593 * @ngdoc method
16594 * @name $sceDelegate#trustAs
16595 *
16596 * @description
16597 * Returns an object that is trusted by angular for use in specified strict
16598 * contextual escaping contexts (such as ng-bind-html, ng-include, any src
16599 * attribute interpolation, any dom event binding attribute interpolation
16600 * such as for onclick, etc.) that uses the provided value.
16601 * See {@link ng.$sce $sce} for enabling strict contextual escaping.
16602 *
16603 * @param {string} type The kind of context in which this value is safe for use. e.g. url,
16604 * resourceUrl, html, js and css.
16605 * @param {*} value The value that that should be considered trusted/safe.
16606 * @returns {*} A value that can be used to stand in for the provided `value` in places
16607 * where Angular expects a $sce.trustAs() return value.
16608 */
16609 function trustAs(type, trustedValue) {
16610 var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
16611 if (!Constructor) {
16612 throw $sceMinErr('icontext',
16613 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
16614 type, trustedValue);
16615 }
16616 if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
16617 return trustedValue;
16618 }
16619 // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting
16620 // mutable objects, we ensure here that the value passed in is actually a string.
16621 if (typeof trustedValue !== 'string') {
16622 throw $sceMinErr('itype',
16623 'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
16624 type);
16625 }
16626 return new Constructor(trustedValue);
16627 }
16628
16629 /**
16630 * @ngdoc method
16631 * @name $sceDelegate#valueOf
16632 *
16633 * @description
16634 * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs
16635 * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
16636 * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}.
16637 *
16638 * If the passed parameter is not a value that had been returned by {@link
16639 * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, returns it as-is.
16640 *
16641 * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}
16642 * call or anything else.
16643 * @returns {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs
16644 * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns
16645 * `value` unchanged.
16646 */
16647 function valueOf(maybeTrusted) {
16648 if (maybeTrusted instanceof trustedValueHolderBase) {
16649 return maybeTrusted.$$unwrapTrustedValue();
16650 } else {
16651 return maybeTrusted;
16652 }
16653 }
16654
16655 /**
16656 * @ngdoc method
16657 * @name $sceDelegate#getTrusted
16658 *
16659 * @description
16660 * Takes the result of a {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} call and
16661 * returns the originally supplied value if the queried context type is a supertype of the
16662 * created type. If this condition isn't satisfied, throws an exception.
16663 *
16664 * @param {string} type The kind of context in which this value is to be used.
16665 * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs
16666 * `$sceDelegate.trustAs`} call.
16667 * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#trustAs
16668 * `$sceDelegate.trustAs`} if valid in this context. Otherwise, throws an exception.
16669 */
16670 function getTrusted(type, maybeTrusted) {
16671 if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
16672 return maybeTrusted;
16673 }
16674 var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
16675 if (constructor && maybeTrusted instanceof constructor) {
16676 return maybeTrusted.$$unwrapTrustedValue();
16677 }
16678 // If we get here, then we may only take one of two actions.
16679 // 1. sanitize the value for the requested type, or
16680 // 2. throw an exception.
16681 if (type === SCE_CONTEXTS.RESOURCE_URL) {
16682 if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
16683 return maybeTrusted;
16684 } else {
16685 throw $sceMinErr('insecurl',
16686 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}',
16687 maybeTrusted.toString());
16688 }
16689 } else if (type === SCE_CONTEXTS.HTML) {
16690 return htmlSanitizer(maybeTrusted);
16691 }
16692 throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
16693 }
16694
16695 return { trustAs: trustAs,
16696 getTrusted: getTrusted,
16697 valueOf: valueOf };
16698 }];
16699 }
16700
16701
16702 /**
16703 * @ngdoc provider
16704 * @name $sceProvider
16705 * @description
16706 *
16707 * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
16708 * - enable/disable Strict Contextual Escaping (SCE) in a module
16709 * - override the default implementation with a custom delegate
16710 *
16711 * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
16712 */
16713
16714 /* jshint maxlen: false*/
16715
16716 /**
16717 * @ngdoc service
16718 * @name $sce
16719 * @kind function
16720 *
16721 * @description
16722 *
16723 * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
16724 *
16725 * # Strict Contextual Escaping
16726 *
16727 * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
16728 * contexts to result in a value that is marked as safe to use for that context. One example of
16729 * such a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer
16730 * to these contexts as privileged or SCE contexts.
16731 *
16732 * As of version 1.2, Angular ships with SCE enabled by default.
16733 *
16734 * Note: When enabled (the default), IE<11 in quirks mode is not supported. In this mode, IE<11 allow
16735 * one to execute arbitrary javascript by the use of the expression() syntax. Refer
16736 * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
16737 * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
16738 * to the top of your HTML document.
16739 *
16740 * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
16741 * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
16742 *
16743 * Here's an example of a binding in a privileged context:
16744 *
16745 * ```
16746 * <input ng-model="userHtml" aria-label="User input">
16747 * <div ng-bind-html="userHtml"></div>
16748 * ```
16749 *
16750 * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
16751 * disabled, this application allows the user to render arbitrary HTML into the DIV.
16752 * In a more realistic example, one may be rendering user comments, blog articles, etc. via
16753 * bindings. (HTML is just one example of a context where rendering user controlled input creates
16754 * security vulnerabilities.)
16755 *
16756 * For the case of HTML, you might use a library, either on the client side, or on the server side,
16757 * to sanitize unsafe HTML before binding to the value and rendering it in the document.
16758 *
16759 * How would you ensure that every place that used these types of bindings was bound to a value that
16760 * was sanitized by your library (or returned as safe for rendering by your server?) How can you
16761 * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
16762 * properties/fields and forgot to update the binding to the sanitized value?
16763 *
16764 * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
16765 * determine that something explicitly says it's safe to use a value for binding in that
16766 * context. You can then audit your code (a simple grep would do) to ensure that this is only done
16767 * for those values that you can easily tell are safe - because they were received from your server,
16768 * sanitized by your library, etc. You can organize your codebase to help with this - perhaps
16769 * allowing only the files in a specific directory to do this. Ensuring that the internal API
16770 * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
16771 *
16772 * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs}
16773 * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to
16774 * obtain values that will be accepted by SCE / privileged contexts.
16775 *
16776 *
16777 * ## How does it work?
16778 *
16779 * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted
16780 * $sce.getTrusted(context, value)} rather than to the value directly. Directives use {@link
16781 * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
16782 * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
16783 *
16784 * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
16785 * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly
16786 * simplified):
16787 *
16788 * ```
16789 * var ngBindHtmlDirective = ['$sce', function($sce) {
16790 * return function(scope, element, attr) {
16791 * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
16792 * element.html(value || '');
16793 * });
16794 * };
16795 * }];
16796 * ```
16797 *
16798 * ## Impact on loading templates
16799 *
16800 * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
16801 * `templateUrl`'s specified by {@link guide/directive directives}.
16802 *
16803 * By default, Angular only loads templates from the same domain and protocol as the application
16804 * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl
16805 * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or
16806 * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist
16807 * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value.
16808 *
16809 * *Please note*:
16810 * The browser's
16811 * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
16812 * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
16813 * policy apply in addition to this and may further restrict whether the template is successfully
16814 * loaded. This means that without the right CORS policy, loading templates from a different domain
16815 * won't work on all browsers. Also, loading templates from `file://` URL does not work on some
16816 * browsers.
16817 *
16818 * ## This feels like too much overhead
16819 *
16820 * It's important to remember that SCE only applies to interpolation expressions.
16821 *
16822 * If your expressions are constant literals, they're automatically trusted and you don't need to
16823 * call `$sce.trustAs` on them (remember to include the `ngSanitize` module) (e.g.
16824 * `<div ng-bind-html="'<b>implicitly trusted</b>'"></div>`) just works.
16825 *
16826 * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
16827 * through {@link ng.$sce#getTrusted $sce.getTrusted}. SCE doesn't play a role here.
16828 *
16829 * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
16830 * templates in `ng-include` from your application's domain without having to even know about SCE.
16831 * It blocks loading templates from other domains or loading templates over http from an https
16832 * served document. You can change these by setting your own custom {@link
16833 * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link
16834 * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs.
16835 *
16836 * This significantly reduces the overhead. It is far easier to pay the small overhead and have an
16837 * application that's secure and can be audited to verify that with much more ease than bolting
16838 * security onto an application later.
16839 *
16840 * <a name="contexts"></a>
16841 * ## What trusted context types are supported?
16842 *
16843 * | Context | Notes |
16844 * |---------------------|----------------|
16845 * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. |
16846 * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. |
16847 * | `$sce.URL` | For URLs that are safe to follow as links. Currently unused (`<a href=` and `<img src=` sanitize their urls and don't constitute an SCE context. |
16848 * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.) <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
16849 * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. |
16850 *
16851 * ## Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
16852 *
16853 * Each element in these arrays must be one of the following:
16854 *
16855 * - **'self'**
16856 * - The special **string**, `'self'`, can be used to match against all URLs of the **same
16857 * domain** as the application document using the **same protocol**.
16858 * - **String** (except the special value `'self'`)
16859 * - The string is matched against the full *normalized / absolute URL* of the resource
16860 * being tested (substring matches are not good enough.)
16861 * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters
16862 * match themselves.
16863 * - `*`: matches zero or more occurrences of any character other than one of the following 6
16864 * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'. It's a useful wildcard for use
16865 * in a whitelist.
16866 * - `**`: matches zero or more occurrences of *any* character. As such, it's not
16867 * not appropriate to use in for a scheme, domain, etc. as it would match too much. (e.g.
16868 * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
16869 * not have been the intention.) Its usage at the very end of the path is ok. (e.g.
16870 * http://foo.example.com/templates/**).
16871 * - **RegExp** (*see caveat below*)
16872 * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax
16873 * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to
16874 * accidentally introduce a bug when one updates a complex expression (imho, all regexes should
16875 * have good test coverage.). For instance, the use of `.` in the regex is correct only in a
16876 * small number of cases. A `.` character in the regex used when matching the scheme or a
16877 * subdomain could be matched against a `:` or literal `.` that was likely not intended. It
16878 * is highly recommended to use the string patterns and only fall back to regular expressions
16879 * if they as a last resort.
16880 * - The regular expression must be an instance of RegExp (i.e. not a string.) It is
16881 * matched against the **entire** *normalized / absolute URL* of the resource being tested
16882 * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags
16883 * present on the RegExp (such as multiline, global, ignoreCase) are ignored.
16884 * - If you are generating your JavaScript from some other templating engine (not
16885 * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
16886 * remember to escape your regular expression (and be aware that you might need more than
16887 * one level of escaping depending on your templating engine and the way you interpolated
16888 * the value.) Do make use of your platform's escaping mechanism as it might be good
16889 * enough before coding your own. e.g. Ruby has
16890 * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
16891 * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
16892 * Javascript lacks a similar built in function for escaping. Take a look at Google
16893 * Closure library's [goog.string.regExpEscape(s)](
16894 * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
16895 *
16896 * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
16897 *
16898 * ## Show me an example using SCE.
16899 *
16900 * <example module="mySceApp" deps="angular-sanitize.js">
16901 * <file name="index.html">
16902 * <div ng-controller="AppController as myCtrl">
16903 * <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
16904 * <b>User comments</b><br>
16905 * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
16906 * $sanitize is available. If $sanitize isn't available, this results in an error instead of an
16907 * exploit.
16908 * <div class="well">
16909 * <div ng-repeat="userComment in myCtrl.userComments">
16910 * <b>{{userComment.name}}</b>:
16911 * <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
16912 * <br>
16913 * </div>
16914 * </div>
16915 * </div>
16916 * </file>
16917 *
16918 * <file name="script.js">
16919 * angular.module('mySceApp', ['ngSanitize'])
16920 * .controller('AppController', ['$http', '$templateCache', '$sce',
16921 * function($http, $templateCache, $sce) {
16922 * var self = this;
16923 * $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
16924 * self.userComments = userComments;
16925 * });
16926 * self.explicitlyTrustedHtml = $sce.trustAsHtml(
16927 * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
16928 * 'sanitization.&quot;">Hover over this text.</span>');
16929 * }]);
16930 * </file>
16931 *
16932 * <file name="test_data.json">
16933 * [
16934 * { "name": "Alice",
16935 * "htmlComment":
16936 * "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
16937 * },
16938 * { "name": "Bob",
16939 * "htmlComment": "<i>Yes!</i> Am I the only other one?"
16940 * }
16941 * ]
16942 * </file>
16943 *
16944 * <file name="protractor.js" type="protractor">
16945 * describe('SCE doc demo', function() {
16946 * it('should sanitize untrusted values', function() {
16947 * expect(element.all(by.css('.htmlComment')).first().getInnerHtml())
16948 * .toBe('<span>Is <i>anyone</i> reading this?</span>');
16949 * });
16950 *
16951 * it('should NOT sanitize explicitly trusted values', function() {
16952 * expect(element(by.id('explicitlyTrustedHtml')).getInnerHtml()).toBe(
16953 * '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
16954 * 'sanitization.&quot;">Hover over this text.</span>');
16955 * });
16956 * });
16957 * </file>
16958 * </example>
16959 *
16960 *
16961 *
16962 * ## Can I disable SCE completely?
16963 *
16964 * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits
16965 * for little coding overhead. It will be much harder to take an SCE disabled application and
16966 * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE
16967 * for cases where you have a lot of existing code that was written before SCE was introduced and
16968 * you're migrating them a module at a time.
16969 *
16970 * That said, here's how you can completely disable SCE:
16971 *
16972 * ```
16973 * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
16974 * // Completely disable SCE. For demonstration purposes only!
16975 * // Do not use in new projects.
16976 * $sceProvider.enabled(false);
16977 * });
16978 * ```
16979 *
16980 */
16981 /* jshint maxlen: 100 */
16982
16983 function $SceProvider() {
16984 var enabled = true;
16985
16986 /**
16987 * @ngdoc method
16988 * @name $sceProvider#enabled
16989 * @kind function
16990 *
16991 * @param {boolean=} value If provided, then enables/disables SCE.
16992 * @return {boolean} true if SCE is enabled, false otherwise.
16993 *
16994 * @description
16995 * Enables/disables SCE and returns the current value.
16996 */
16997 this.enabled = function(value) {
16998 if (arguments.length) {
16999 enabled = !!value;
17000 }
17001 return enabled;
17002 };
17003
17004
17005 /* Design notes on the default implementation for SCE.
17006 *
17007 * The API contract for the SCE delegate
17008 * -------------------------------------
17009 * The SCE delegate object must provide the following 3 methods:
17010 *
17011 * - trustAs(contextEnum, value)
17012 * This method is used to tell the SCE service that the provided value is OK to use in the
17013 * contexts specified by contextEnum. It must return an object that will be accepted by
17014 * getTrusted() for a compatible contextEnum and return this value.
17015 *
17016 * - valueOf(value)
17017 * For values that were not produced by trustAs(), return them as is. For values that were
17018 * produced by trustAs(), return the corresponding input value to trustAs. Basically, if
17019 * trustAs is wrapping the given values into some type, this operation unwraps it when given
17020 * such a value.
17021 *
17022 * - getTrusted(contextEnum, value)
17023 * This function should return the a value that is safe to use in the context specified by
17024 * contextEnum or throw and exception otherwise.
17025 *
17026 * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
17027 * opaque or wrapped in some holder object. That happens to be an implementation detail. For
17028 * instance, an implementation could maintain a registry of all trusted objects by context. In
17029 * such a case, trustAs() would return the same object that was passed in. getTrusted() would
17030 * return the same object passed in if it was found in the registry under a compatible context or
17031 * throw an exception otherwise. An implementation might only wrap values some of the time based
17032 * on some criteria. getTrusted() might return a value and not throw an exception for special
17033 * constants or objects even if not wrapped. All such implementations fulfill this contract.
17034 *
17035 *
17036 * A note on the inheritance model for SCE contexts
17037 * ------------------------------------------------
17038 * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This
17039 * is purely an implementation details.
17040 *
17041 * The contract is simply this:
17042 *
17043 * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
17044 * will also succeed.
17045 *
17046 * Inheritance happens to capture this in a natural way. In some future, we
17047 * may not use inheritance anymore. That is OK because no code outside of
17048 * sce.js and sceSpecs.js would need to be aware of this detail.
17049 */
17050
17051 this.$get = ['$parse', '$sceDelegate', function(
17052 $parse, $sceDelegate) {
17053 // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow
17054 // the "expression(javascript expression)" syntax which is insecure.
17055 if (enabled && msie < 8) {
17056 throw $sceMinErr('iequirks',
17057 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' +
17058 'mode. You can fix this by adding the text <!doctype html> to the top of your HTML ' +
17059 'document. See http://docs.angularjs.org/api/ng.$sce for more information.');
17060 }
17061
17062 var sce = shallowCopy(SCE_CONTEXTS);
17063
17064 /**
17065 * @ngdoc method
17066 * @name $sce#isEnabled
17067 * @kind function
17068 *
17069 * @return {Boolean} true if SCE is enabled, false otherwise. If you want to set the value, you
17070 * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
17071 *
17072 * @description
17073 * Returns a boolean indicating if SCE is enabled.
17074 */
17075 sce.isEnabled = function() {
17076 return enabled;
17077 };
17078 sce.trustAs = $sceDelegate.trustAs;
17079 sce.getTrusted = $sceDelegate.getTrusted;
17080 sce.valueOf = $sceDelegate.valueOf;
17081
17082 if (!enabled) {
17083 sce.trustAs = sce.getTrusted = function(type, value) { return value; };
17084 sce.valueOf = identity;
17085 }
17086
17087 /**
17088 * @ngdoc method
17089 * @name $sce#parseAs
17090 *
17091 * @description
17092 * Converts Angular {@link guide/expression expression} into a function. This is like {@link
17093 * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it
17094 * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*,
17095 * *result*)}
17096 *
17097 * @param {string} type The kind of SCE context in which this result will be used.
17098 * @param {string} expression String expression to compile.
17099 * @returns {function(context, locals)} a function which represents the compiled expression:
17100 *
17101 * * `context` – `{object}` – an object against which any expressions embedded in the strings
17102 * are evaluated against (typically a scope object).
17103 * * `locals` – `{object=}` – local variables context object, useful for overriding values in
17104 * `context`.
17105 */
17106 sce.parseAs = function sceParseAs(type, expr) {
17107 var parsed = $parse(expr);
17108 if (parsed.literal && parsed.constant) {
17109 return parsed;
17110 } else {
17111 return $parse(expr, function(value) {
17112 return sce.getTrusted(type, value);
17113 });
17114 }
17115 };
17116
17117 /**
17118 * @ngdoc method
17119 * @name $sce#trustAs
17120 *
17121 * @description
17122 * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such,
17123 * returns an object that is trusted by angular for use in specified strict contextual
17124 * escaping contexts (such as ng-bind-html, ng-include, any src attribute
17125 * interpolation, any dom event binding attribute interpolation such as for onclick, etc.)
17126 * that uses the provided value. See * {@link ng.$sce $sce} for enabling strict contextual
17127 * escaping.
17128 *
17129 * @param {string} type The kind of context in which this value is safe for use. e.g. url,
17130 * resourceUrl, html, js and css.
17131 * @param {*} value The value that that should be considered trusted/safe.
17132 * @returns {*} A value that can be used to stand in for the provided `value` in places
17133 * where Angular expects a $sce.trustAs() return value.
17134 */
17135
17136 /**
17137 * @ngdoc method
17138 * @name $sce#trustAsHtml
17139 *
17140 * @description
17141 * Shorthand method. `$sce.trustAsHtml(value)` →
17142 * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
17143 *
17144 * @param {*} value The value to trustAs.
17145 * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedHtml
17146 * $sce.getTrustedHtml(value)} to obtain the original value. (privileged directives
17147 * only accept expressions that are either literal constants or are the
17148 * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
17149 */
17150
17151 /**
17152 * @ngdoc method
17153 * @name $sce#trustAsUrl
17154 *
17155 * @description
17156 * Shorthand method. `$sce.trustAsUrl(value)` →
17157 * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`}
17158 *
17159 * @param {*} value The value to trustAs.
17160 * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedUrl
17161 * $sce.getTrustedUrl(value)} to obtain the original value. (privileged directives
17162 * only accept expressions that are either literal constants or are the
17163 * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
17164 */
17165
17166 /**
17167 * @ngdoc method
17168 * @name $sce#trustAsResourceUrl
17169 *
17170 * @description
17171 * Shorthand method. `$sce.trustAsResourceUrl(value)` →
17172 * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
17173 *
17174 * @param {*} value The value to trustAs.
17175 * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedResourceUrl
17176 * $sce.getTrustedResourceUrl(value)} to obtain the original value. (privileged directives
17177 * only accept expressions that are either literal constants or are the return
17178 * value of {@link ng.$sce#trustAs $sce.trustAs}.)
17179 */
17180
17181 /**
17182 * @ngdoc method
17183 * @name $sce#trustAsJs
17184 *
17185 * @description
17186 * Shorthand method. `$sce.trustAsJs(value)` →
17187 * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`}
17188 *
17189 * @param {*} value The value to trustAs.
17190 * @returns {*} An object that can be passed to {@link ng.$sce#getTrustedJs
17191 * $sce.getTrustedJs(value)} to obtain the original value. (privileged directives
17192 * only accept expressions that are either literal constants or are the
17193 * return value of {@link ng.$sce#trustAs $sce.trustAs}.)
17194 */
17195
17196 /**
17197 * @ngdoc method
17198 * @name $sce#getTrusted
17199 *
17200 * @description
17201 * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such,
17202 * takes the result of a {@link ng.$sce#trustAs `$sce.trustAs`}() call and returns the
17203 * originally supplied value if the queried context type is a supertype of the created type.
17204 * If this condition isn't satisfied, throws an exception.
17205 *
17206 * @param {string} type The kind of context in which this value is to be used.
17207 * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs `$sce.trustAs`}
17208 * call.
17209 * @returns {*} The value the was originally provided to
17210 * {@link ng.$sce#trustAs `$sce.trustAs`} if valid in this context.
17211 * Otherwise, throws an exception.
17212 */
17213
17214 /**
17215 * @ngdoc method
17216 * @name $sce#getTrustedHtml
17217 *
17218 * @description
17219 * Shorthand method. `$sce.getTrustedHtml(value)` →
17220 * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
17221 *
17222 * @param {*} value The value to pass to `$sce.getTrusted`.
17223 * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
17224 */
17225
17226 /**
17227 * @ngdoc method
17228 * @name $sce#getTrustedCss
17229 *
17230 * @description
17231 * Shorthand method. `$sce.getTrustedCss(value)` →
17232 * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
17233 *
17234 * @param {*} value The value to pass to `$sce.getTrusted`.
17235 * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
17236 */
17237
17238 /**
17239 * @ngdoc method
17240 * @name $sce#getTrustedUrl
17241 *
17242 * @description
17243 * Shorthand method. `$sce.getTrustedUrl(value)` →
17244 * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
17245 *
17246 * @param {*} value The value to pass to `$sce.getTrusted`.
17247 * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
17248 */
17249
17250 /**
17251 * @ngdoc method
17252 * @name $sce#getTrustedResourceUrl
17253 *
17254 * @description
17255 * Shorthand method. `$sce.getTrustedResourceUrl(value)` →
17256 * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
17257 *
17258 * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
17259 * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
17260 */
17261
17262 /**
17263 * @ngdoc method
17264 * @name $sce#getTrustedJs
17265 *
17266 * @description
17267 * Shorthand method. `$sce.getTrustedJs(value)` →
17268 * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
17269 *
17270 * @param {*} value The value to pass to `$sce.getTrusted`.
17271 * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
17272 */
17273
17274 /**
17275 * @ngdoc method
17276 * @name $sce#parseAsHtml
17277 *
17278 * @description
17279 * Shorthand method. `$sce.parseAsHtml(expression string)` →
17280 * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`}
17281 *
17282 * @param {string} expression String expression to compile.
17283 * @returns {function(context, locals)} a function which represents the compiled expression:
17284 *
17285 * * `context` – `{object}` – an object against which any expressions embedded in the strings
17286 * are evaluated against (typically a scope object).
17287 * * `locals` – `{object=}` – local variables context object, useful for overriding values in
17288 * `context`.
17289 */
17290
17291 /**
17292 * @ngdoc method
17293 * @name $sce#parseAsCss
17294 *
17295 * @description
17296 * Shorthand method. `$sce.parseAsCss(value)` →
17297 * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`}
17298 *
17299 * @param {string} expression String expression to compile.
17300 * @returns {function(context, locals)} a function which represents the compiled expression:
17301 *
17302 * * `context` – `{object}` – an object against which any expressions embedded in the strings
17303 * are evaluated against (typically a scope object).
17304 * * `locals` – `{object=}` – local variables context object, useful for overriding values in
17305 * `context`.
17306 */
17307
17308 /**
17309 * @ngdoc method
17310 * @name $sce#parseAsUrl
17311 *
17312 * @description
17313 * Shorthand method. `$sce.parseAsUrl(value)` →
17314 * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`}
17315 *
17316 * @param {string} expression String expression to compile.
17317 * @returns {function(context, locals)} a function which represents the compiled expression:
17318 *
17319 * * `context` – `{object}` – an object against which any expressions embedded in the strings
17320 * are evaluated against (typically a scope object).
17321 * * `locals` – `{object=}` – local variables context object, useful for overriding values in
17322 * `context`.
17323 */
17324
17325 /**
17326 * @ngdoc method
17327 * @name $sce#parseAsResourceUrl
17328 *
17329 * @description
17330 * Shorthand method. `$sce.parseAsResourceUrl(value)` →
17331 * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`}
17332 *
17333 * @param {string} expression String expression to compile.
17334 * @returns {function(context, locals)} a function which represents the compiled expression:
17335 *
17336 * * `context` – `{object}` – an object against which any expressions embedded in the strings
17337 * are evaluated against (typically a scope object).
17338 * * `locals` – `{object=}` – local variables context object, useful for overriding values in
17339 * `context`.
17340 */
17341
17342 /**
17343 * @ngdoc method
17344 * @name $sce#parseAsJs
17345 *
17346 * @description
17347 * Shorthand method. `$sce.parseAsJs(value)` →
17348 * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`}
17349 *
17350 * @param {string} expression String expression to compile.
17351 * @returns {function(context, locals)} a function which represents the compiled expression:
17352 *
17353 * * `context` – `{object}` – an object against which any expressions embedded in the strings
17354 * are evaluated against (typically a scope object).
17355 * * `locals` – `{object=}` – local variables context object, useful for overriding values in
17356 * `context`.
17357 */
17358
17359 // Shorthand delegations.
17360 var parse = sce.parseAs,
17361 getTrusted = sce.getTrusted,
17362 trustAs = sce.trustAs;
17363
17364 forEach(SCE_CONTEXTS, function(enumValue, name) {
17365 var lName = lowercase(name);
17366 sce[camelCase("parse_as_" + lName)] = function(expr) {
17367 return parse(enumValue, expr);
17368 };
17369 sce[camelCase("get_trusted_" + lName)] = function(value) {
17370 return getTrusted(enumValue, value);
17371 };
17372 sce[camelCase("trust_as_" + lName)] = function(value) {
17373 return trustAs(enumValue, value);
17374 };
17375 });
17376
17377 return sce;
17378 }];
17379 }
17380
17381 /**
17382 * !!! This is an undocumented "private" service !!!
17383 *
17384 * @name $sniffer
17385 * @requires $window
17386 * @requires $document
17387 *
17388 * @property {boolean} history Does the browser support html5 history api ?
17389 * @property {boolean} transitions Does the browser support CSS transition events ?
17390 * @property {boolean} animations Does the browser support CSS animation events ?
17391 *
17392 * @description
17393 * This is very simple implementation of testing browser's features.
17394 */
17395 function $SnifferProvider() {
17396 this.$get = ['$window', '$document', function($window, $document) {
17397 var eventSupport = {},
17398 android =
17399 toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
17400 boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
17401 document = $document[0] || {},
17402 vendorPrefix,
17403 vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/,
17404 bodyStyle = document.body && document.body.style,
17405 transitions = false,
17406 animations = false,
17407 match;
17408
17409 if (bodyStyle) {
17410 for (var prop in bodyStyle) {
17411 if (match = vendorRegex.exec(prop)) {
17412 vendorPrefix = match[0];
17413 vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
17414 break;
17415 }
17416 }
17417
17418 if (!vendorPrefix) {
17419 vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
17420 }
17421
17422 transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
17423 animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
17424
17425 if (android && (!transitions || !animations)) {
17426 transitions = isString(bodyStyle.webkitTransition);
17427 animations = isString(bodyStyle.webkitAnimation);
17428 }
17429 }
17430
17431
17432 return {
17433 // Android has history.pushState, but it does not update location correctly
17434 // so let's not use the history API at all.
17435 // http://code.google.com/p/android/issues/detail?id=17471
17436 // https://github.com/angular/angular.js/issues/904
17437
17438 // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has
17439 // so let's not use the history API also
17440 // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
17441 // jshint -W018
17442 history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
17443 // jshint +W018
17444 hasEvent: function(event) {
17445 // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
17446 // it. In particular the event is not fired when backspace or delete key are pressed or
17447 // when cut operation is performed.
17448 // IE10+ implements 'input' event but it erroneously fires under various situations,
17449 // e.g. when placeholder changes, or a form is focused.
17450 if (event === 'input' && msie <= 11) return false;
17451
17452 if (isUndefined(eventSupport[event])) {
17453 var divElm = document.createElement('div');
17454 eventSupport[event] = 'on' + event in divElm;
17455 }
17456
17457 return eventSupport[event];
17458 },
17459 csp: csp(),
17460 vendorPrefix: vendorPrefix,
17461 transitions: transitions,
17462 animations: animations,
17463 android: android
17464 };
17465 }];
17466 }
17467
17468 var $compileMinErr = minErr('$compile');
17469
17470 /**
17471 * @ngdoc service
17472 * @name $templateRequest
17473 *
17474 * @description
17475 * The `$templateRequest` service runs security checks then downloads the provided template using
17476 * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
17477 * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
17478 * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
17479 * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
17480 * when `tpl` is of type string and `$templateCache` has the matching entry.
17481 *
17482 * @param {string|TrustedResourceUrl} tpl The HTTP request template URL
17483 * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
17484 *
17485 * @return {Promise} a promise for the HTTP response data of the given URL.
17486 *
17487 * @property {number} totalPendingRequests total amount of pending template requests being downloaded.
17488 */
17489 function $TemplateRequestProvider() {
17490 this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
17491 function handleRequestFn(tpl, ignoreRequestError) {
17492 handleRequestFn.totalPendingRequests++;
17493
17494 // We consider the template cache holds only trusted templates, so
17495 // there's no need to go through whitelisting again for keys that already
17496 // are included in there. This also makes Angular accept any script
17497 // directive, no matter its name. However, we still need to unwrap trusted
17498 // types.
17499 if (!isString(tpl) || !$templateCache.get(tpl)) {
17500 tpl = $sce.getTrustedResourceUrl(tpl);
17501 }
17502
17503 var transformResponse = $http.defaults && $http.defaults.transformResponse;
17504
17505 if (isArray(transformResponse)) {
17506 transformResponse = transformResponse.filter(function(transformer) {
17507 return transformer !== defaultHttpResponseTransform;
17508 });
17509 } else if (transformResponse === defaultHttpResponseTransform) {
17510 transformResponse = null;
17511 }
17512
17513 var httpOptions = {
17514 cache: $templateCache,
17515 transformResponse: transformResponse
17516 };
17517
17518 return $http.get(tpl, httpOptions)
17519 ['finally'](function() {
17520 handleRequestFn.totalPendingRequests--;
17521 })
17522 .then(function(response) {
17523 $templateCache.put(tpl, response.data);
17524 return response.data;
17525 }, handleError);
17526
17527 function handleError(resp) {
17528 if (!ignoreRequestError) {
17529 throw $compileMinErr('tpload', 'Failed to load template: {0} (HTTP status: {1} {2})',
17530 tpl, resp.status, resp.statusText);
17531 }
17532 return $q.reject(resp);
17533 }
17534 }
17535
17536 handleRequestFn.totalPendingRequests = 0;
17537
17538 return handleRequestFn;
17539 }];
17540 }
17541
17542 function $$TestabilityProvider() {
17543 this.$get = ['$rootScope', '$browser', '$location',
17544 function($rootScope, $browser, $location) {
17545
17546 /**
17547 * @name $testability
17548 *
17549 * @description
17550 * The private $$testability service provides a collection of methods for use when debugging
17551 * or by automated test and debugging tools.
17552 */
17553 var testability = {};
17554
17555 /**
17556 * @name $$testability#findBindings
17557 *
17558 * @description
17559 * Returns an array of elements that are bound (via ng-bind or {{}})
17560 * to expressions matching the input.
17561 *
17562 * @param {Element} element The element root to search from.
17563 * @param {string} expression The binding expression to match.
17564 * @param {boolean} opt_exactMatch If true, only returns exact matches
17565 * for the expression. Filters and whitespace are ignored.
17566 */
17567 testability.findBindings = function(element, expression, opt_exactMatch) {
17568 var bindings = element.getElementsByClassName('ng-binding');
17569 var matches = [];
17570 forEach(bindings, function(binding) {
17571 var dataBinding = angular.element(binding).data('$binding');
17572 if (dataBinding) {
17573 forEach(dataBinding, function(bindingName) {
17574 if (opt_exactMatch) {
17575 var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)');
17576 if (matcher.test(bindingName)) {
17577 matches.push(binding);
17578 }
17579 } else {
17580 if (bindingName.indexOf(expression) != -1) {
17581 matches.push(binding);
17582 }
17583 }
17584 });
17585 }
17586 });
17587 return matches;
17588 };
17589
17590 /**
17591 * @name $$testability#findModels
17592 *
17593 * @description
17594 * Returns an array of elements that are two-way found via ng-model to
17595 * expressions matching the input.
17596 *
17597 * @param {Element} element The element root to search from.
17598 * @param {string} expression The model expression to match.
17599 * @param {boolean} opt_exactMatch If true, only returns exact matches
17600 * for the expression.
17601 */
17602 testability.findModels = function(element, expression, opt_exactMatch) {
17603 var prefixes = ['ng-', 'data-ng-', 'ng\\:'];
17604 for (var p = 0; p < prefixes.length; ++p) {
17605 var attributeEquals = opt_exactMatch ? '=' : '*=';
17606 var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]';
17607 var elements = element.querySelectorAll(selector);
17608 if (elements.length) {
17609 return elements;
17610 }
17611 }
17612 };
17613
17614 /**
17615 * @name $$testability#getLocation
17616 *
17617 * @description
17618 * Shortcut for getting the location in a browser agnostic way. Returns
17619 * the path, search, and hash. (e.g. /path?a=b#hash)
17620 */
17621 testability.getLocation = function() {
17622 return $location.url();
17623 };
17624
17625 /**
17626 * @name $$testability#setLocation
17627 *
17628 * @description
17629 * Shortcut for navigating to a location without doing a full page reload.
17630 *
17631 * @param {string} url The location url (path, search and hash,
17632 * e.g. /path?a=b#hash) to go to.
17633 */
17634 testability.setLocation = function(url) {
17635 if (url !== $location.url()) {
17636 $location.url(url);
17637 $rootScope.$digest();
17638 }
17639 };
17640
17641 /**
17642 * @name $$testability#whenStable
17643 *
17644 * @description
17645 * Calls the callback when $timeout and $http requests are completed.
17646 *
17647 * @param {function} callback
17648 */
17649 testability.whenStable = function(callback) {
17650 $browser.notifyWhenNoOutstandingRequests(callback);
17651 };
17652
17653 return testability;
17654 }];
17655 }
17656
17657 function $TimeoutProvider() {
17658 this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
17659 function($rootScope, $browser, $q, $$q, $exceptionHandler) {
17660
17661 var deferreds = {};
17662
17663
17664 /**
17665 * @ngdoc service
17666 * @name $timeout
17667 *
17668 * @description
17669 * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
17670 * block and delegates any exceptions to
17671 * {@link ng.$exceptionHandler $exceptionHandler} service.
17672 *
17673 * The return value of calling `$timeout` is a promise, which will be resolved when
17674 * the delay has passed and the timeout function, if provided, is executed.
17675 *
17676 * To cancel a timeout request, call `$timeout.cancel(promise)`.
17677 *
17678 * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
17679 * synchronously flush the queue of deferred functions.
17680 *
17681 * If you only want a promise that will be resolved after some specified delay
17682 * then you can call `$timeout` without the `fn` function.
17683 *
17684 * @param {function()=} fn A function, whose execution should be delayed.
17685 * @param {number=} [delay=0] Delay in milliseconds.
17686 * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
17687 * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block.
17688 * @param {...*=} Pass additional parameters to the executed function.
17689 * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
17690 * promise will be resolved with is the return value of the `fn` function.
17691 *
17692 */
17693 function timeout(fn, delay, invokeApply) {
17694 if (!isFunction(fn)) {
17695 invokeApply = delay;
17696 delay = fn;
17697 fn = noop;
17698 }
17699
17700 var args = sliceArgs(arguments, 3),
17701 skipApply = (isDefined(invokeApply) && !invokeApply),
17702 deferred = (skipApply ? $$q : $q).defer(),
17703 promise = deferred.promise,
17704 timeoutId;
17705
17706 timeoutId = $browser.defer(function() {
17707 try {
17708 deferred.resolve(fn.apply(null, args));
17709 } catch (e) {
17710 deferred.reject(e);
17711 $exceptionHandler(e);
17712 }
17713 finally {
17714 delete deferreds[promise.$$timeoutId];
17715 }
17716
17717 if (!skipApply) $rootScope.$apply();
17718 }, delay);
17719
17720 promise.$$timeoutId = timeoutId;
17721 deferreds[timeoutId] = deferred;
17722
17723 return promise;
17724 }
17725
17726
17727 /**
17728 * @ngdoc method
17729 * @name $timeout#cancel
17730 *
17731 * @description
17732 * Cancels a task associated with the `promise`. As a result of this, the promise will be
17733 * resolved with a rejection.
17734 *
17735 * @param {Promise=} promise Promise returned by the `$timeout` function.
17736 * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
17737 * canceled.
17738 */
17739 timeout.cancel = function(promise) {
17740 if (promise && promise.$$timeoutId in deferreds) {
17741 deferreds[promise.$$timeoutId].reject('canceled');
17742 delete deferreds[promise.$$timeoutId];
17743 return $browser.defer.cancel(promise.$$timeoutId);
17744 }
17745 return false;
17746 };
17747
17748 return timeout;
17749 }];
17750 }
17751
17752 // NOTE: The usage of window and document instead of $window and $document here is
17753 // deliberate. This service depends on the specific behavior of anchor nodes created by the
17754 // browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
17755 // cause us to break tests. In addition, when the browser resolves a URL for XHR, it
17756 // doesn't know about mocked locations and resolves URLs to the real document - which is
17757 // exactly the behavior needed here. There is little value is mocking these out for this
17758 // service.
17759 var urlParsingNode = document.createElement("a");
17760 var originUrl = urlResolve(window.location.href);
17761
17762
17763 /**
17764 *
17765 * Implementation Notes for non-IE browsers
17766 * ----------------------------------------
17767 * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
17768 * results both in the normalizing and parsing of the URL. Normalizing means that a relative
17769 * URL will be resolved into an absolute URL in the context of the application document.
17770 * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
17771 * properties are all populated to reflect the normalized URL. This approach has wide
17772 * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc. See
17773 * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
17774 *
17775 * Implementation Notes for IE
17776 * ---------------------------
17777 * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other
17778 * browsers. However, the parsed components will not be set if the URL assigned did not specify
17779 * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
17780 * work around that by performing the parsing in a 2nd step by taking a previously normalized
17781 * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
17782 * properties such as protocol, hostname, port, etc.
17783 *
17784 * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one
17785 * uses the inner HTML approach to assign the URL as part of an HTML snippet -
17786 * http://stackoverflow.com/a/472729) However, setting img[src] does normalize the URL.
17787 * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception.
17788 * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that
17789 * method and IE < 8 is unsupported.
17790 *
17791 * References:
17792 * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
17793 * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
17794 * http://url.spec.whatwg.org/#urlutils
17795 * https://github.com/angular/angular.js/pull/2902
17796 * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
17797 *
17798 * @kind function
17799 * @param {string} url The URL to be parsed.
17800 * @description Normalizes and parses a URL.
17801 * @returns {object} Returns the normalized URL as a dictionary.
17802 *
17803 * | member name | Description |
17804 * |---------------|----------------|
17805 * | href | A normalized version of the provided URL if it was not an absolute URL |
17806 * | protocol | The protocol including the trailing colon |
17807 * | host | The host and port (if the port is non-default) of the normalizedUrl |
17808 * | search | The search params, minus the question mark |
17809 * | hash | The hash string, minus the hash symbol
17810 * | hostname | The hostname
17811 * | port | The port, without ":"
17812 * | pathname | The pathname, beginning with "/"
17813 *
17814 */
17815 function urlResolve(url) {
17816 var href = url;
17817
17818 if (msie) {
17819 // Normalize before parse. Refer Implementation Notes on why this is
17820 // done in two steps on IE.
17821 urlParsingNode.setAttribute("href", href);
17822 href = urlParsingNode.href;
17823 }
17824
17825 urlParsingNode.setAttribute('href', href);
17826
17827 // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
17828 return {
17829 href: urlParsingNode.href,
17830 protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
17831 host: urlParsingNode.host,
17832 search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
17833 hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
17834 hostname: urlParsingNode.hostname,
17835 port: urlParsingNode.port,
17836 pathname: (urlParsingNode.pathname.charAt(0) === '/')
17837 ? urlParsingNode.pathname
17838 : '/' + urlParsingNode.pathname
17839 };
17840 }
17841
17842 /**
17843 * Parse a request URL and determine whether this is a same-origin request as the application document.
17844 *
17845 * @param {string|object} requestUrl The url of the request as a string that will be resolved
17846 * or a parsed URL object.
17847 * @returns {boolean} Whether the request is for the same origin as the application document.
17848 */
17849 function urlIsSameOrigin(requestUrl) {
17850 var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
17851 return (parsed.protocol === originUrl.protocol &&
17852 parsed.host === originUrl.host);
17853 }
17854
17855 /**
17856 * @ngdoc service
17857 * @name $window
17858 *
17859 * @description
17860 * A reference to the browser's `window` object. While `window`
17861 * is globally available in JavaScript, it causes testability problems, because
17862 * it is a global variable. In angular we always refer to it through the
17863 * `$window` service, so it may be overridden, removed or mocked for testing.
17864 *
17865 * Expressions, like the one defined for the `ngClick` directive in the example
17866 * below, are evaluated with respect to the current scope. Therefore, there is
17867 * no risk of inadvertently coding in a dependency on a global value in such an
17868 * expression.
17869 *
17870 * @example
17871 <example module="windowExample">
17872 <file name="index.html">
17873 <script>
17874 angular.module('windowExample', [])
17875 .controller('ExampleController', ['$scope', '$window', function($scope, $window) {
17876 $scope.greeting = 'Hello, World!';
17877 $scope.doGreeting = function(greeting) {
17878 $window.alert(greeting);
17879 };
17880 }]);
17881 </script>
17882 <div ng-controller="ExampleController">
17883 <input type="text" ng-model="greeting" aria-label="greeting" />
17884 <button ng-click="doGreeting(greeting)">ALERT</button>
17885 </div>
17886 </file>
17887 <file name="protractor.js" type="protractor">
17888 it('should display the greeting in the input box', function() {
17889 element(by.model('greeting')).sendKeys('Hello, E2E Tests');
17890 // If we click the button it will block the test runner
17891 // element(':button').click();
17892 });
17893 </file>
17894 </example>
17895 */
17896 function $WindowProvider() {
17897 this.$get = valueFn(window);
17898 }
17899
17900 /**
17901 * @name $$cookieReader
17902 * @requires $document
17903 *
17904 * @description
17905 * This is a private service for reading cookies used by $http and ngCookies
17906 *
17907 * @return {Object} a key/value map of the current cookies
17908 */
17909 function $$CookieReader($document) {
17910 var rawDocument = $document[0] || {};
17911 var lastCookies = {};
17912 var lastCookieString = '';
17913
17914 function safeDecodeURIComponent(str) {
17915 try {
17916 return decodeURIComponent(str);
17917 } catch (e) {
17918 return str;
17919 }
17920 }
17921
17922 return function() {
17923 var cookieArray, cookie, i, index, name;
17924 var currentCookieString = rawDocument.cookie || '';
17925
17926 if (currentCookieString !== lastCookieString) {
17927 lastCookieString = currentCookieString;
17928 cookieArray = lastCookieString.split('; ');
17929 lastCookies = {};
17930
17931 for (i = 0; i < cookieArray.length; i++) {
17932 cookie = cookieArray[i];
17933 index = cookie.indexOf('=');
17934 if (index > 0) { //ignore nameless cookies
17935 name = safeDecodeURIComponent(cookie.substring(0, index));
17936 // the first value that is seen for a cookie is the most
17937 // specific one. values for the same cookie name that
17938 // follow are for less specific paths.
17939 if (lastCookies[name] === undefined) {
17940 lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1));
17941 }
17942 }
17943 }
17944 }
17945 return lastCookies;
17946 };
17947 }
17948
17949 $$CookieReader.$inject = ['$document'];
17950
17951 function $$CookieReaderProvider() {
17952 this.$get = $$CookieReader;
17953 }
17954
17955 /* global currencyFilter: true,
17956 dateFilter: true,
17957 filterFilter: true,
17958 jsonFilter: true,
17959 limitToFilter: true,
17960 lowercaseFilter: true,
17961 numberFilter: true,
17962 orderByFilter: true,
17963 uppercaseFilter: true,
17964 */
17965
17966 /**
17967 * @ngdoc provider
17968 * @name $filterProvider
17969 * @description
17970 *
17971 * Filters are just functions which transform input to an output. However filters need to be
17972 * Dependency Injected. To achieve this a filter definition consists of a factory function which is
17973 * annotated with dependencies and is responsible for creating a filter function.
17974 *
17975 * <div class="alert alert-warning">
17976 * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
17977 * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
17978 * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
17979 * (`myapp_subsection_filterx`).
17980 * </div>
17981 *
17982 * ```js
17983 * // Filter registration
17984 * function MyModule($provide, $filterProvider) {
17985 * // create a service to demonstrate injection (not always needed)
17986 * $provide.value('greet', function(name){
17987 * return 'Hello ' + name + '!';
17988 * });
17989 *
17990 * // register a filter factory which uses the
17991 * // greet service to demonstrate DI.
17992 * $filterProvider.register('greet', function(greet){
17993 * // return the filter function which uses the greet service
17994 * // to generate salutation
17995 * return function(text) {
17996 * // filters need to be forgiving so check input validity
17997 * return text && greet(text) || text;
17998 * };
17999 * });
18000 * }
18001 * ```
18002 *
18003 * The filter function is registered with the `$injector` under the filter name suffix with
18004 * `Filter`.
18005 *
18006 * ```js
18007 * it('should be the same instance', inject(
18008 * function($filterProvider) {
18009 * $filterProvider.register('reverse', function(){
18010 * return ...;
18011 * });
18012 * },
18013 * function($filter, reverseFilter) {
18014 * expect($filter('reverse')).toBe(reverseFilter);
18015 * });
18016 * ```
18017 *
18018 *
18019 * For more information about how angular filters work, and how to create your own filters, see
18020 * {@link guide/filter Filters} in the Angular Developer Guide.
18021 */
18022
18023 /**
18024 * @ngdoc service
18025 * @name $filter
18026 * @kind function
18027 * @description
18028 * Filters are used for formatting data displayed to the user.
18029 *
18030 * The general syntax in templates is as follows:
18031 *
18032 * {{ expression [| filter_name[:parameter_value] ... ] }}
18033 *
18034 * @param {String} name Name of the filter function to retrieve
18035 * @return {Function} the filter function
18036 * @example
18037 <example name="$filter" module="filterExample">
18038 <file name="index.html">
18039 <div ng-controller="MainCtrl">
18040 <h3>{{ originalText }}</h3>
18041 <h3>{{ filteredText }}</h3>
18042 </div>
18043 </file>
18044
18045 <file name="script.js">
18046 angular.module('filterExample', [])
18047 .controller('MainCtrl', function($scope, $filter) {
18048 $scope.originalText = 'hello';
18049 $scope.filteredText = $filter('uppercase')($scope.originalText);
18050 });
18051 </file>
18052 </example>
18053 */
18054 $FilterProvider.$inject = ['$provide'];
18055 function $FilterProvider($provide) {
18056 var suffix = 'Filter';
18057
18058 /**
18059 * @ngdoc method
18060 * @name $filterProvider#register
18061 * @param {string|Object} name Name of the filter function, or an object map of filters where
18062 * the keys are the filter names and the values are the filter factories.
18063 *
18064 * <div class="alert alert-warning">
18065 * **Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
18066 * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace
18067 * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores
18068 * (`myapp_subsection_filterx`).
18069 * </div>
18070 * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
18071 * of the registered filter instances.
18072 */
18073 function register(name, factory) {
18074 if (isObject(name)) {
18075 var filters = {};
18076 forEach(name, function(filter, key) {
18077 filters[key] = register(key, filter);
18078 });
18079 return filters;
18080 } else {
18081 return $provide.factory(name + suffix, factory);
18082 }
18083 }
18084 this.register = register;
18085
18086 this.$get = ['$injector', function($injector) {
18087 return function(name) {
18088 return $injector.get(name + suffix);
18089 };
18090 }];
18091
18092 ////////////////////////////////////////
18093
18094 /* global
18095 currencyFilter: false,
18096 dateFilter: false,
18097 filterFilter: false,
18098 jsonFilter: false,
18099 limitToFilter: false,
18100 lowercaseFilter: false,
18101 numberFilter: false,
18102 orderByFilter: false,
18103 uppercaseFilter: false,
18104 */
18105
18106 register('currency', currencyFilter);
18107 register('date', dateFilter);
18108 register('filter', filterFilter);
18109 register('json', jsonFilter);
18110 register('limitTo', limitToFilter);
18111 register('lowercase', lowercaseFilter);
18112 register('number', numberFilter);
18113 register('orderBy', orderByFilter);
18114 register('uppercase', uppercaseFilter);
18115 }
18116
18117 /**
18118 * @ngdoc filter
18119 * @name filter
18120 * @kind function
18121 *
18122 * @description
18123 * Selects a subset of items from `array` and returns it as a new array.
18124 *
18125 * @param {Array} array The source array.
18126 * @param {string|Object|function()} expression The predicate to be used for selecting items from
18127 * `array`.
18128 *
18129 * Can be one of:
18130 *
18131 * - `string`: The string is used for matching against the contents of the `array`. All strings or
18132 * objects with string properties in `array` that match this string will be returned. This also
18133 * applies to nested object properties.
18134 * The predicate can be negated by prefixing the string with `!`.
18135 *
18136 * - `Object`: A pattern object can be used to filter specific properties on objects contained
18137 * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
18138 * which have property `name` containing "M" and property `phone` containing "1". A special
18139 * property name `$` can be used (as in `{$:"text"}`) to accept a match against any
18140 * property of the object or its nested object properties. That's equivalent to the simple
18141 * substring match with a `string` as described above. The predicate can be negated by prefixing
18142 * the string with `!`.
18143 * For example `{name: "!M"}` predicate will return an array of items which have property `name`
18144 * not containing "M".
18145 *
18146 * Note that a named property will match properties on the same level only, while the special
18147 * `$` property will match properties on the same level or deeper. E.g. an array item like
18148 * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but
18149 * **will** be matched by `{$: 'John'}`.
18150 *
18151 * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters.
18152 * The function is called for each element of the array, with the element, its index, and
18153 * the entire array itself as arguments.
18154 *
18155 * The final result is an array of those elements that the predicate returned true for.
18156 *
18157 * @param {function(actual, expected)|true|undefined} comparator Comparator which is used in
18158 * determining if the expected value (from the filter expression) and actual value (from
18159 * the object in the array) should be considered a match.
18160 *
18161 * Can be one of:
18162 *
18163 * - `function(actual, expected)`:
18164 * The function will be given the object value and the predicate value to compare and
18165 * should return true if both values should be considered equal.
18166 *
18167 * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`.
18168 * This is essentially strict comparison of expected and actual.
18169 *
18170 * - `false|undefined`: A short hand for a function which will look for a substring match in case
18171 * insensitive way.
18172 *
18173 * Primitive values are converted to strings. Objects are not compared against primitives,
18174 * unless they have a custom `toString` method (e.g. `Date` objects).
18175 *
18176 * @example
18177 <example>
18178 <file name="index.html">
18179 <div ng-init="friends = [{name:'John', phone:'555-1276'},
18180 {name:'Mary', phone:'800-BIG-MARY'},
18181 {name:'Mike', phone:'555-4321'},
18182 {name:'Adam', phone:'555-5678'},
18183 {name:'Julie', phone:'555-8765'},
18184 {name:'Juliette', phone:'555-5678'}]"></div>
18185
18186 <label>Search: <input ng-model="searchText"></label>
18187 <table id="searchTextResults">
18188 <tr><th>Name</th><th>Phone</th></tr>
18189 <tr ng-repeat="friend in friends | filter:searchText">
18190 <td>{{friend.name}}</td>
18191 <td>{{friend.phone}}</td>
18192 </tr>
18193 </table>
18194 <hr>
18195 <label>Any: <input ng-model="search.$"></label> <br>
18196 <label>Name only <input ng-model="search.name"></label><br>
18197 <label>Phone only <input ng-model="search.phone"></label><br>
18198 <label>Equality <input type="checkbox" ng-model="strict"></label><br>
18199 <table id="searchObjResults">
18200 <tr><th>Name</th><th>Phone</th></tr>
18201 <tr ng-repeat="friendObj in friends | filter:search:strict">
18202 <td>{{friendObj.name}}</td>
18203 <td>{{friendObj.phone}}</td>
18204 </tr>
18205 </table>
18206 </file>
18207 <file name="protractor.js" type="protractor">
18208 var expectFriendNames = function(expectedNames, key) {
18209 element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) {
18210 arr.forEach(function(wd, i) {
18211 expect(wd.getText()).toMatch(expectedNames[i]);
18212 });
18213 });
18214 };
18215
18216 it('should search across all fields when filtering with a string', function() {
18217 var searchText = element(by.model('searchText'));
18218 searchText.clear();
18219 searchText.sendKeys('m');
18220 expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend');
18221
18222 searchText.clear();
18223 searchText.sendKeys('76');
18224 expectFriendNames(['John', 'Julie'], 'friend');
18225 });
18226
18227 it('should search in specific fields when filtering with a predicate object', function() {
18228 var searchAny = element(by.model('search.$'));
18229 searchAny.clear();
18230 searchAny.sendKeys('i');
18231 expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj');
18232 });
18233 it('should use a equal comparison when comparator is true', function() {
18234 var searchName = element(by.model('search.name'));
18235 var strict = element(by.model('strict'));
18236 searchName.clear();
18237 searchName.sendKeys('Julie');
18238 strict.click();
18239 expectFriendNames(['Julie'], 'friendObj');
18240 });
18241 </file>
18242 </example>
18243 */
18244 function filterFilter() {
18245 return function(array, expression, comparator) {
18246 if (!isArrayLike(array)) {
18247 if (array == null) {
18248 return array;
18249 } else {
18250 throw minErr('filter')('notarray', 'Expected array but received: {0}', array);
18251 }
18252 }
18253
18254 var expressionType = getTypeForFilter(expression);
18255 var predicateFn;
18256 var matchAgainstAnyProp;
18257
18258 switch (expressionType) {
18259 case 'function':
18260 predicateFn = expression;
18261 break;
18262 case 'boolean':
18263 case 'null':
18264 case 'number':
18265 case 'string':
18266 matchAgainstAnyProp = true;
18267 //jshint -W086
18268 case 'object':
18269 //jshint +W086
18270 predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
18271 break;
18272 default:
18273 return array;
18274 }
18275
18276 return Array.prototype.filter.call(array, predicateFn);
18277 };
18278 }
18279
18280 // Helper functions for `filterFilter`
18281 function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
18282 var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
18283 var predicateFn;
18284
18285 if (comparator === true) {
18286 comparator = equals;
18287 } else if (!isFunction(comparator)) {
18288 comparator = function(actual, expected) {
18289 if (isUndefined(actual)) {
18290 // No substring matching against `undefined`
18291 return false;
18292 }
18293 if ((actual === null) || (expected === null)) {
18294 // No substring matching against `null`; only match against `null`
18295 return actual === expected;
18296 }
18297 if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) {
18298 // Should not compare primitives against objects, unless they have custom `toString` method
18299 return false;
18300 }
18301
18302 actual = lowercase('' + actual);
18303 expected = lowercase('' + expected);
18304 return actual.indexOf(expected) !== -1;
18305 };
18306 }
18307
18308 predicateFn = function(item) {
18309 if (shouldMatchPrimitives && !isObject(item)) {
18310 return deepCompare(item, expression.$, comparator, false);
18311 }
18312 return deepCompare(item, expression, comparator, matchAgainstAnyProp);
18313 };
18314
18315 return predicateFn;
18316 }
18317
18318 function deepCompare(actual, expected, comparator, matchAgainstAnyProp, dontMatchWholeObject) {
18319 var actualType = getTypeForFilter(actual);
18320 var expectedType = getTypeForFilter(expected);
18321
18322 if ((expectedType === 'string') && (expected.charAt(0) === '!')) {
18323 return !deepCompare(actual, expected.substring(1), comparator, matchAgainstAnyProp);
18324 } else if (isArray(actual)) {
18325 // In case `actual` is an array, consider it a match
18326 // if ANY of it's items matches `expected`
18327 return actual.some(function(item) {
18328 return deepCompare(item, expected, comparator, matchAgainstAnyProp);
18329 });
18330 }
18331
18332 switch (actualType) {
18333 case 'object':
18334 var key;
18335 if (matchAgainstAnyProp) {
18336 for (key in actual) {
18337 if ((key.charAt(0) !== '$') && deepCompare(actual[key], expected, comparator, true)) {
18338 return true;
18339 }
18340 }
18341 return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, false);
18342 } else if (expectedType === 'object') {
18343 for (key in expected) {
18344 var expectedVal = expected[key];
18345 if (isFunction(expectedVal) || isUndefined(expectedVal)) {
18346 continue;
18347 }
18348
18349 var matchAnyProperty = key === '$';
18350 var actualVal = matchAnyProperty ? actual : actual[key];
18351 if (!deepCompare(actualVal, expectedVal, comparator, matchAnyProperty, matchAnyProperty)) {
18352 return false;
18353 }
18354 }
18355 return true;
18356 } else {
18357 return comparator(actual, expected);
18358 }
18359 break;
18360 case 'function':
18361 return false;
18362 default:
18363 return comparator(actual, expected);
18364 }
18365 }
18366
18367 // Used for easily differentiating between `null` and actual `object`
18368 function getTypeForFilter(val) {
18369 return (val === null) ? 'null' : typeof val;
18370 }
18371
18372 /**
18373 * @ngdoc filter
18374 * @name currency
18375 * @kind function
18376 *
18377 * @description
18378 * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
18379 * symbol for current locale is used.
18380 *
18381 * @param {number} amount Input to filter.
18382 * @param {string=} symbol Currency symbol or identifier to be displayed.
18383 * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale
18384 * @returns {string} Formatted number.
18385 *
18386 *
18387 * @example
18388 <example module="currencyExample">
18389 <file name="index.html">
18390 <script>
18391 angular.module('currencyExample', [])
18392 .controller('ExampleController', ['$scope', function($scope) {
18393 $scope.amount = 1234.56;
18394 }]);
18395 </script>
18396 <div ng-controller="ExampleController">
18397 <input type="number" ng-model="amount" aria-label="amount"> <br>
18398 default currency symbol ($): <span id="currency-default">{{amount | currency}}</span><br>
18399 custom currency identifier (USD$): <span id="currency-custom">{{amount | currency:"USD$"}}</span>
18400 no fractions (0): <span id="currency-no-fractions">{{amount | currency:"USD$":0}}</span>
18401 </div>
18402 </file>
18403 <file name="protractor.js" type="protractor">
18404 it('should init with 1234.56', function() {
18405 expect(element(by.id('currency-default')).getText()).toBe('$1,234.56');
18406 expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56');
18407 expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235');
18408 });
18409 it('should update', function() {
18410 if (browser.params.browser == 'safari') {
18411 // Safari does not understand the minus key. See
18412 // https://github.com/angular/protractor/issues/481
18413 return;
18414 }
18415 element(by.model('amount')).clear();
18416 element(by.model('amount')).sendKeys('-1234');
18417 expect(element(by.id('currency-default')).getText()).toBe('($1,234.00)');
18418 expect(element(by.id('currency-custom')).getText()).toBe('(USD$1,234.00)');
18419 expect(element(by.id('currency-no-fractions')).getText()).toBe('(USD$1,234)');
18420 });
18421 </file>
18422 </example>
18423 */
18424 currencyFilter.$inject = ['$locale'];
18425 function currencyFilter($locale) {
18426 var formats = $locale.NUMBER_FORMATS;
18427 return function(amount, currencySymbol, fractionSize) {
18428 if (isUndefined(currencySymbol)) {
18429 currencySymbol = formats.CURRENCY_SYM;
18430 }
18431
18432 if (isUndefined(fractionSize)) {
18433 fractionSize = formats.PATTERNS[1].maxFrac;
18434 }
18435
18436 // if null or undefined pass it through
18437 return (amount == null)
18438 ? amount
18439 : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize).
18440 replace(/\u00A4/g, currencySymbol);
18441 };
18442 }
18443
18444 /**
18445 * @ngdoc filter
18446 * @name number
18447 * @kind function
18448 *
18449 * @description
18450 * Formats a number as text.
18451 *
18452 * If the input is null or undefined, it will just be returned.
18453 * If the input is infinite (Infinity/-Infinity) the Infinity symbol '∞' is returned.
18454 * If the input is not a number an empty string is returned.
18455 *
18456 *
18457 * @param {number|string} number Number to format.
18458 * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
18459 * If this is not provided then the fraction size is computed from the current locale's number
18460 * formatting pattern. In the case of the default locale, it will be 3.
18461 * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
18462 *
18463 * @example
18464 <example module="numberFilterExample">
18465 <file name="index.html">
18466 <script>
18467 angular.module('numberFilterExample', [])
18468 .controller('ExampleController', ['$scope', function($scope) {
18469 $scope.val = 1234.56789;
18470 }]);
18471 </script>
18472 <div ng-controller="ExampleController">
18473 <label>Enter number: <input ng-model='val'></label><br>
18474 Default formatting: <span id='number-default'>{{val | number}}</span><br>
18475 No fractions: <span>{{val | number:0}}</span><br>
18476 Negative number: <span>{{-val | number:4}}</span>
18477 </div>
18478 </file>
18479 <file name="protractor.js" type="protractor">
18480 it('should format numbers', function() {
18481 expect(element(by.id('number-default')).getText()).toBe('1,234.568');
18482 expect(element(by.binding('val | number:0')).getText()).toBe('1,235');
18483 expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679');
18484 });
18485
18486 it('should update', function() {
18487 element(by.model('val')).clear();
18488 element(by.model('val')).sendKeys('3374.333');
18489 expect(element(by.id('number-default')).getText()).toBe('3,374.333');
18490 expect(element(by.binding('val | number:0')).getText()).toBe('3,374');
18491 expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330');
18492 });
18493 </file>
18494 </example>
18495 */
18496
18497
18498 numberFilter.$inject = ['$locale'];
18499 function numberFilter($locale) {
18500 var formats = $locale.NUMBER_FORMATS;
18501 return function(number, fractionSize) {
18502
18503 // if null or undefined pass it through
18504 return (number == null)
18505 ? number
18506 : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
18507 fractionSize);
18508 };
18509 }
18510
18511 var DECIMAL_SEP = '.';
18512 function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
18513 if (isObject(number)) return '';
18514
18515 var isNegative = number < 0;
18516 number = Math.abs(number);
18517
18518 var isInfinity = number === Infinity;
18519 if (!isInfinity && !isFinite(number)) return '';
18520
18521 var numStr = number + '',
18522 formatedText = '',
18523 hasExponent = false,
18524 parts = [];
18525
18526 if (isInfinity) formatedText = '\u221e';
18527
18528 if (!isInfinity && numStr.indexOf('e') !== -1) {
18529 var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
18530 if (match && match[2] == '-' && match[3] > fractionSize + 1) {
18531 number = 0;
18532 } else {
18533 formatedText = numStr;
18534 hasExponent = true;
18535 }
18536 }
18537
18538 if (!isInfinity && !hasExponent) {
18539 var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
18540
18541 // determine fractionSize if it is not specified
18542 if (isUndefined(fractionSize)) {
18543 fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
18544 }
18545
18546 // safely round numbers in JS without hitting imprecisions of floating-point arithmetics
18547 // inspired by:
18548 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
18549 number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
18550
18551 var fraction = ('' + number).split(DECIMAL_SEP);
18552 var whole = fraction[0];
18553 fraction = fraction[1] || '';
18554
18555 var i, pos = 0,
18556 lgroup = pattern.lgSize,
18557 group = pattern.gSize;
18558
18559 if (whole.length >= (lgroup + group)) {
18560 pos = whole.length - lgroup;
18561 for (i = 0; i < pos; i++) {
18562 if ((pos - i) % group === 0 && i !== 0) {
18563 formatedText += groupSep;
18564 }
18565 formatedText += whole.charAt(i);
18566 }
18567 }
18568
18569 for (i = pos; i < whole.length; i++) {
18570 if ((whole.length - i) % lgroup === 0 && i !== 0) {
18571 formatedText += groupSep;
18572 }
18573 formatedText += whole.charAt(i);
18574 }
18575
18576 // format fraction part.
18577 while (fraction.length < fractionSize) {
18578 fraction += '0';
18579 }
18580
18581 if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
18582 } else {
18583 if (fractionSize > 0 && number < 1) {
18584 formatedText = number.toFixed(fractionSize);
18585 number = parseFloat(formatedText);
18586 }
18587 }
18588
18589 if (number === 0) {
18590 isNegative = false;
18591 }
18592
18593 parts.push(isNegative ? pattern.negPre : pattern.posPre,
18594 formatedText,
18595 isNegative ? pattern.negSuf : pattern.posSuf);
18596 return parts.join('');
18597 }
18598
18599 function padNumber(num, digits, trim) {
18600 var neg = '';
18601 if (num < 0) {
18602 neg = '-';
18603 num = -num;
18604 }
18605 num = '' + num;
18606 while (num.length < digits) num = '0' + num;
18607 if (trim) {
18608 num = num.substr(num.length - digits);
18609 }
18610 return neg + num;
18611 }
18612
18613
18614 function dateGetter(name, size, offset, trim) {
18615 offset = offset || 0;
18616 return function(date) {
18617 var value = date['get' + name]();
18618 if (offset > 0 || value > -offset) {
18619 value += offset;
18620 }
18621 if (value === 0 && offset == -12) value = 12;
18622 return padNumber(value, size, trim);
18623 };
18624 }
18625
18626 function dateStrGetter(name, shortForm) {
18627 return function(date, formats) {
18628 var value = date['get' + name]();
18629 var get = uppercase(shortForm ? ('SHORT' + name) : name);
18630
18631 return formats[get][value];
18632 };
18633 }
18634
18635 function timeZoneGetter(date, formats, offset) {
18636 var zone = -1 * offset;
18637 var paddedZone = (zone >= 0) ? "+" : "";
18638
18639 paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
18640 padNumber(Math.abs(zone % 60), 2);
18641
18642 return paddedZone;
18643 }
18644
18645 function getFirstThursdayOfYear(year) {
18646 // 0 = index of January
18647 var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();
18648 // 4 = index of Thursday (+1 to account for 1st = 5)
18649 // 11 = index of *next* Thursday (+1 account for 1st = 12)
18650 return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);
18651 }
18652
18653 function getThursdayThisWeek(datetime) {
18654 return new Date(datetime.getFullYear(), datetime.getMonth(),
18655 // 4 = index of Thursday
18656 datetime.getDate() + (4 - datetime.getDay()));
18657 }
18658
18659 function weekGetter(size) {
18660 return function(date) {
18661 var firstThurs = getFirstThursdayOfYear(date.getFullYear()),
18662 thisThurs = getThursdayThisWeek(date);
18663
18664 var diff = +thisThurs - +firstThurs,
18665 result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
18666
18667 return padNumber(result, size);
18668 };
18669 }
18670
18671 function ampmGetter(date, formats) {
18672 return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
18673 }
18674
18675 function eraGetter(date, formats) {
18676 return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1];
18677 }
18678
18679 function longEraGetter(date, formats) {
18680 return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1];
18681 }
18682
18683 var DATE_FORMATS = {
18684 yyyy: dateGetter('FullYear', 4),
18685 yy: dateGetter('FullYear', 2, 0, true),
18686 y: dateGetter('FullYear', 1),
18687 MMMM: dateStrGetter('Month'),
18688 MMM: dateStrGetter('Month', true),
18689 MM: dateGetter('Month', 2, 1),
18690 M: dateGetter('Month', 1, 1),
18691 dd: dateGetter('Date', 2),
18692 d: dateGetter('Date', 1),
18693 HH: dateGetter('Hours', 2),
18694 H: dateGetter('Hours', 1),
18695 hh: dateGetter('Hours', 2, -12),
18696 h: dateGetter('Hours', 1, -12),
18697 mm: dateGetter('Minutes', 2),
18698 m: dateGetter('Minutes', 1),
18699 ss: dateGetter('Seconds', 2),
18700 s: dateGetter('Seconds', 1),
18701 // while ISO 8601 requires fractions to be prefixed with `.` or `,`
18702 // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
18703 sss: dateGetter('Milliseconds', 3),
18704 EEEE: dateStrGetter('Day'),
18705 EEE: dateStrGetter('Day', true),
18706 a: ampmGetter,
18707 Z: timeZoneGetter,
18708 ww: weekGetter(2),
18709 w: weekGetter(1),
18710 G: eraGetter,
18711 GG: eraGetter,
18712 GGG: eraGetter,
18713 GGGG: longEraGetter
18714 };
18715
18716 var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,
18717 NUMBER_STRING = /^\-?\d+$/;
18718
18719 /**
18720 * @ngdoc filter
18721 * @name date
18722 * @kind function
18723 *
18724 * @description
18725 * Formats `date` to a string based on the requested `format`.
18726 *
18727 * `format` string can be composed of the following elements:
18728 *
18729 * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
18730 * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
18731 * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
18732 * * `'MMMM'`: Month in year (January-December)
18733 * * `'MMM'`: Month in year (Jan-Dec)
18734 * * `'MM'`: Month in year, padded (01-12)
18735 * * `'M'`: Month in year (1-12)
18736 * * `'dd'`: Day in month, padded (01-31)
18737 * * `'d'`: Day in month (1-31)
18738 * * `'EEEE'`: Day in Week,(Sunday-Saturday)
18739 * * `'EEE'`: Day in Week, (Sun-Sat)
18740 * * `'HH'`: Hour in day, padded (00-23)
18741 * * `'H'`: Hour in day (0-23)
18742 * * `'hh'`: Hour in AM/PM, padded (01-12)
18743 * * `'h'`: Hour in AM/PM, (1-12)
18744 * * `'mm'`: Minute in hour, padded (00-59)
18745 * * `'m'`: Minute in hour (0-59)
18746 * * `'ss'`: Second in minute, padded (00-59)
18747 * * `'s'`: Second in minute (0-59)
18748 * * `'sss'`: Millisecond in second, padded (000-999)
18749 * * `'a'`: AM/PM marker
18750 * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
18751 * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year
18752 * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year
18753 * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD')
18754 * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini')
18755 *
18756 * `format` string can also be one of the following predefined
18757 * {@link guide/i18n localizable formats}:
18758 *
18759 * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
18760 * (e.g. Sep 3, 2010 12:05:08 PM)
18761 * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM)
18762 * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale
18763 * (e.g. Friday, September 3, 2010)
18764 * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)
18765 * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
18766 * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
18767 * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM)
18768 * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM)
18769 *
18770 * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g.
18771 * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence
18772 * (e.g. `"h 'o''clock'"`).
18773 *
18774 * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
18775 * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its
18776 * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
18777 * specified in the string input, the time is considered to be in the local timezone.
18778 * @param {string=} format Formatting rules (see Description). If not specified,
18779 * `mediumDate` is used.
18780 * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the
18781 * continental US time zone abbreviations, but for general use, use a time zone offset, for
18782 * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
18783 * If not specified, the timezone of the browser will be used.
18784 * @returns {string} Formatted string or the input if input is not recognized as date/millis.
18785 *
18786 * @example
18787 <example>
18788 <file name="index.html">
18789 <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
18790 <span>{{1288323623006 | date:'medium'}}</span><br>
18791 <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
18792 <span>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span><br>
18793 <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
18794 <span>{{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}</span><br>
18795 <span ng-non-bindable>{{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}</span>:
18796 <span>{{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}</span><br>
18797 </file>
18798 <file name="protractor.js" type="protractor">
18799 it('should format date', function() {
18800 expect(element(by.binding("1288323623006 | date:'medium'")).getText()).
18801 toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
18802 expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()).
18803 toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
18804 expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()).
18805 toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
18806 expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()).
18807 toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/);
18808 });
18809 </file>
18810 </example>
18811 */
18812 dateFilter.$inject = ['$locale'];
18813 function dateFilter($locale) {
18814
18815
18816 var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
18817 // 1 2 3 4 5 6 7 8 9 10 11
18818 function jsonStringToDate(string) {
18819 var match;
18820 if (match = string.match(R_ISO8601_STR)) {
18821 var date = new Date(0),
18822 tzHour = 0,
18823 tzMin = 0,
18824 dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
18825 timeSetter = match[8] ? date.setUTCHours : date.setHours;
18826
18827 if (match[9]) {
18828 tzHour = toInt(match[9] + match[10]);
18829 tzMin = toInt(match[9] + match[11]);
18830 }
18831 dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3]));
18832 var h = toInt(match[4] || 0) - tzHour;
18833 var m = toInt(match[5] || 0) - tzMin;
18834 var s = toInt(match[6] || 0);
18835 var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
18836 timeSetter.call(date, h, m, s, ms);
18837 return date;
18838 }
18839 return string;
18840 }
18841
18842
18843 return function(date, format, timezone) {
18844 var text = '',
18845 parts = [],
18846 fn, match;
18847
18848 format = format || 'mediumDate';
18849 format = $locale.DATETIME_FORMATS[format] || format;
18850 if (isString(date)) {
18851 date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date);
18852 }
18853
18854 if (isNumber(date)) {
18855 date = new Date(date);
18856 }
18857
18858 if (!isDate(date) || !isFinite(date.getTime())) {
18859 return date;
18860 }
18861
18862 while (format) {
18863 match = DATE_FORMATS_SPLIT.exec(format);
18864 if (match) {
18865 parts = concat(parts, match, 1);
18866 format = parts.pop();
18867 } else {
18868 parts.push(format);
18869 format = null;
18870 }
18871 }
18872
18873 var dateTimezoneOffset = date.getTimezoneOffset();
18874 if (timezone) {
18875 dateTimezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
18876 date = convertTimezoneToLocal(date, timezone, true);
18877 }
18878 forEach(parts, function(value) {
18879 fn = DATE_FORMATS[value];
18880 text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset)
18881 : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
18882 });
18883
18884 return text;
18885 };
18886 }
18887
18888
18889 /**
18890 * @ngdoc filter
18891 * @name json
18892 * @kind function
18893 *
18894 * @description
18895 * Allows you to convert a JavaScript object into JSON string.
18896 *
18897 * This filter is mostly useful for debugging. When using the double curly {{value}} notation
18898 * the binding is automatically converted to JSON.
18899 *
18900 * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
18901 * @param {number=} spacing The number of spaces to use per indentation, defaults to 2.
18902 * @returns {string} JSON string.
18903 *
18904 *
18905 * @example
18906 <example>
18907 <file name="index.html">
18908 <pre id="default-spacing">{{ {'name':'value'} | json }}</pre>
18909 <pre id="custom-spacing">{{ {'name':'value'} | json:4 }}</pre>
18910 </file>
18911 <file name="protractor.js" type="protractor">
18912 it('should jsonify filtered objects', function() {
18913 expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
18914 expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n "name": ?"value"\n}/);
18915 });
18916 </file>
18917 </example>
18918 *
18919 */
18920 function jsonFilter() {
18921 return function(object, spacing) {
18922 if (isUndefined(spacing)) {
18923 spacing = 2;
18924 }
18925 return toJson(object, spacing);
18926 };
18927 }
18928
18929
18930 /**
18931 * @ngdoc filter
18932 * @name lowercase
18933 * @kind function
18934 * @description
18935 * Converts string to lowercase.
18936 * @see angular.lowercase
18937 */
18938 var lowercaseFilter = valueFn(lowercase);
18939
18940
18941 /**
18942 * @ngdoc filter
18943 * @name uppercase
18944 * @kind function
18945 * @description
18946 * Converts string to uppercase.
18947 * @see angular.uppercase
18948 */
18949 var uppercaseFilter = valueFn(uppercase);
18950
18951 /**
18952 * @ngdoc filter
18953 * @name limitTo
18954 * @kind function
18955 *
18956 * @description
18957 * Creates a new array or string containing only a specified number of elements. The elements
18958 * are taken from either the beginning or the end of the source array, string or number, as specified by
18959 * the value and sign (positive or negative) of `limit`. If a number is used as input, it is
18960 * converted to a string.
18961 *
18962 * @param {Array|string|number} input Source array, string or number to be limited.
18963 * @param {string|number} limit The length of the returned array or string. If the `limit` number
18964 * is positive, `limit` number of items from the beginning of the source array/string are copied.
18965 * If the number is negative, `limit` number of items from the end of the source array/string
18966 * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined,
18967 * the input will be returned unchanged.
18968 * @param {(string|number)=} begin Index at which to begin limitation. As a negative index, `begin`
18969 * indicates an offset from the end of `input`. Defaults to `0`.
18970 * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
18971 * had less than `limit` elements.
18972 *
18973 * @example
18974 <example module="limitToExample">
18975 <file name="index.html">
18976 <script>
18977 angular.module('limitToExample', [])
18978 .controller('ExampleController', ['$scope', function($scope) {
18979 $scope.numbers = [1,2,3,4,5,6,7,8,9];
18980 $scope.letters = "abcdefghi";
18981 $scope.longNumber = 2345432342;
18982 $scope.numLimit = 3;
18983 $scope.letterLimit = 3;
18984 $scope.longNumberLimit = 3;
18985 }]);
18986 </script>
18987 <div ng-controller="ExampleController">
18988 <label>
18989 Limit {{numbers}} to:
18990 <input type="number" step="1" ng-model="numLimit">
18991 </label>
18992 <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
18993 <label>
18994 Limit {{letters}} to:
18995 <input type="number" step="1" ng-model="letterLimit">
18996 </label>
18997 <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
18998 <label>
18999 Limit {{longNumber}} to:
19000 <input type="number" step="1" ng-model="longNumberLimit">
19001 </label>
19002 <p>Output long number: {{ longNumber | limitTo:longNumberLimit }}</p>
19003 </div>
19004 </file>
19005 <file name="protractor.js" type="protractor">
19006 var numLimitInput = element(by.model('numLimit'));
19007 var letterLimitInput = element(by.model('letterLimit'));
19008 var longNumberLimitInput = element(by.model('longNumberLimit'));
19009 var limitedNumbers = element(by.binding('numbers | limitTo:numLimit'));
19010 var limitedLetters = element(by.binding('letters | limitTo:letterLimit'));
19011 var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit'));
19012
19013 it('should limit the number array to first three items', function() {
19014 expect(numLimitInput.getAttribute('value')).toBe('3');
19015 expect(letterLimitInput.getAttribute('value')).toBe('3');
19016 expect(longNumberLimitInput.getAttribute('value')).toBe('3');
19017 expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]');
19018 expect(limitedLetters.getText()).toEqual('Output letters: abc');
19019 expect(limitedLongNumber.getText()).toEqual('Output long number: 234');
19020 });
19021
19022 // There is a bug in safari and protractor that doesn't like the minus key
19023 // it('should update the output when -3 is entered', function() {
19024 // numLimitInput.clear();
19025 // numLimitInput.sendKeys('-3');
19026 // letterLimitInput.clear();
19027 // letterLimitInput.sendKeys('-3');
19028 // longNumberLimitInput.clear();
19029 // longNumberLimitInput.sendKeys('-3');
19030 // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]');
19031 // expect(limitedLetters.getText()).toEqual('Output letters: ghi');
19032 // expect(limitedLongNumber.getText()).toEqual('Output long number: 342');
19033 // });
19034
19035 it('should not exceed the maximum size of input array', function() {
19036 numLimitInput.clear();
19037 numLimitInput.sendKeys('100');
19038 letterLimitInput.clear();
19039 letterLimitInput.sendKeys('100');
19040 longNumberLimitInput.clear();
19041 longNumberLimitInput.sendKeys('100');
19042 expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]');
19043 expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi');
19044 expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342');
19045 });
19046 </file>
19047 </example>
19048 */
19049 function limitToFilter() {
19050 return function(input, limit, begin) {
19051 if (Math.abs(Number(limit)) === Infinity) {
19052 limit = Number(limit);
19053 } else {
19054 limit = toInt(limit);
19055 }
19056 if (isNaN(limit)) return input;
19057
19058 if (isNumber(input)) input = input.toString();
19059 if (!isArray(input) && !isString(input)) return input;
19060
19061 begin = (!begin || isNaN(begin)) ? 0 : toInt(begin);
19062 begin = (begin < 0 && begin >= -input.length) ? input.length + begin : begin;
19063
19064 if (limit >= 0) {
19065 return input.slice(begin, begin + limit);
19066 } else {
19067 if (begin === 0) {
19068 return input.slice(limit, input.length);
19069 } else {
19070 return input.slice(Math.max(0, begin + limit), begin);
19071 }
19072 }
19073 };
19074 }
19075
19076 /**
19077 * @ngdoc filter
19078 * @name orderBy
19079 * @kind function
19080 *
19081 * @description
19082 * Orders a specified `array` by the `expression` predicate. It is ordered alphabetically
19083 * for strings and numerically for numbers. Note: if you notice numbers are not being sorted
19084 * as expected, make sure they are actually being saved as numbers and not strings.
19085 *
19086 * @param {Array} array The array to sort.
19087 * @param {function(*)|string|Array.<(function(*)|string)>=} expression A predicate to be
19088 * used by the comparator to determine the order of elements.
19089 *
19090 * Can be one of:
19091 *
19092 * - `function`: Getter function. The result of this function will be sorted using the
19093 * `<`, `===`, `>` operator.
19094 * - `string`: An Angular expression. The result of this expression is used to compare elements
19095 * (for example `name` to sort by a property called `name` or `name.substr(0, 3)` to sort by
19096 * 3 first characters of a property called `name`). The result of a constant expression
19097 * is interpreted as a property name to be used in comparisons (for example `"special name"`
19098 * to sort object by the value of their `special name` property). An expression can be
19099 * optionally prefixed with `+` or `-` to control ascending or descending sort order
19100 * (for example, `+name` or `-name`). If no property is provided, (e.g. `'+'`) then the array
19101 * element itself is used to compare where sorting.
19102 * - `Array`: An array of function or string predicates. The first predicate in the array
19103 * is used for sorting, but when two items are equivalent, the next predicate is used.
19104 *
19105 * If the predicate is missing or empty then it defaults to `'+'`.
19106 *
19107 * @param {boolean=} reverse Reverse the order of the array.
19108 * @returns {Array} Sorted copy of the source array.
19109 *
19110 *
19111 * @example
19112 * The example below demonstrates a simple ngRepeat, where the data is sorted
19113 * by age in descending order (predicate is set to `'-age'`).
19114 * `reverse` is not set, which means it defaults to `false`.
19115 <example module="orderByExample">
19116 <file name="index.html">
19117 <script>
19118 angular.module('orderByExample', [])
19119 .controller('ExampleController', ['$scope', function($scope) {
19120 $scope.friends =
19121 [{name:'John', phone:'555-1212', age:10},
19122 {name:'Mary', phone:'555-9876', age:19},
19123 {name:'Mike', phone:'555-4321', age:21},
19124 {name:'Adam', phone:'555-5678', age:35},
19125 {name:'Julie', phone:'555-8765', age:29}];
19126 }]);
19127 </script>
19128 <div ng-controller="ExampleController">
19129 <table class="friend">
19130 <tr>
19131 <th>Name</th>
19132 <th>Phone Number</th>
19133 <th>Age</th>
19134 </tr>
19135 <tr ng-repeat="friend in friends | orderBy:'-age'">
19136 <td>{{friend.name}}</td>
19137 <td>{{friend.phone}}</td>
19138 <td>{{friend.age}}</td>
19139 </tr>
19140 </table>
19141 </div>
19142 </file>
19143 </example>
19144 *
19145 * The predicate and reverse parameters can be controlled dynamically through scope properties,
19146 * as shown in the next example.
19147 * @example
19148 <example module="orderByExample">
19149 <file name="index.html">
19150 <script>
19151 angular.module('orderByExample', [])
19152 .controller('ExampleController', ['$scope', function($scope) {
19153 $scope.friends =
19154 [{name:'John', phone:'555-1212', age:10},
19155 {name:'Mary', phone:'555-9876', age:19},
19156 {name:'Mike', phone:'555-4321', age:21},
19157 {name:'Adam', phone:'555-5678', age:35},
19158 {name:'Julie', phone:'555-8765', age:29}];
19159 $scope.predicate = 'age';
19160 $scope.reverse = true;
19161 $scope.order = function(predicate) {
19162 $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
19163 $scope.predicate = predicate;
19164 };
19165 }]);
19166 </script>
19167 <style type="text/css">
19168 .sortorder:after {
19169 content: '\25b2';
19170 }
19171 .sortorder.reverse:after {
19172 content: '\25bc';
19173 }
19174 </style>
19175 <div ng-controller="ExampleController">
19176 <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
19177 <hr/>
19178 [ <a href="" ng-click="predicate=''">unsorted</a> ]
19179 <table class="friend">
19180 <tr>
19181 <th>
19182 <a href="" ng-click="order('name')">Name</a>
19183 <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
19184 </th>
19185 <th>
19186 <a href="" ng-click="order('phone')">Phone Number</a>
19187 <span class="sortorder" ng-show="predicate === 'phone'" ng-class="{reverse:reverse}"></span>
19188 </th>
19189 <th>
19190 <a href="" ng-click="order('age')">Age</a>
19191 <span class="sortorder" ng-show="predicate === 'age'" ng-class="{reverse:reverse}"></span>
19192 </th>
19193 </tr>
19194 <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
19195 <td>{{friend.name}}</td>
19196 <td>{{friend.phone}}</td>
19197 <td>{{friend.age}}</td>
19198 </tr>
19199 </table>
19200 </div>
19201 </file>
19202 </example>
19203 *
19204 * It's also possible to call the orderBy filter manually, by injecting `$filter`, retrieving the
19205 * filter routine with `$filter('orderBy')`, and calling the returned filter routine with the
19206 * desired parameters.
19207 *
19208 * Example:
19209 *
19210 * @example
19211 <example module="orderByExample">
19212 <file name="index.html">
19213 <div ng-controller="ExampleController">
19214 <table class="friend">
19215 <tr>
19216 <th><a href="" ng-click="reverse=false;order('name', false)">Name</a>
19217 (<a href="" ng-click="order('-name',false)">^</a>)</th>
19218 <th><a href="" ng-click="reverse=!reverse;order('phone', reverse)">Phone Number</a></th>
19219 <th><a href="" ng-click="reverse=!reverse;order('age',reverse)">Age</a></th>
19220 </tr>
19221 <tr ng-repeat="friend in friends">
19222 <td>{{friend.name}}</td>
19223 <td>{{friend.phone}}</td>
19224 <td>{{friend.age}}</td>
19225 </tr>
19226 </table>
19227 </div>
19228 </file>
19229
19230 <file name="script.js">
19231 angular.module('orderByExample', [])
19232 .controller('ExampleController', ['$scope', '$filter', function($scope, $filter) {
19233 var orderBy = $filter('orderBy');
19234 $scope.friends = [
19235 { name: 'John', phone: '555-1212', age: 10 },
19236 { name: 'Mary', phone: '555-9876', age: 19 },
19237 { name: 'Mike', phone: '555-4321', age: 21 },
19238 { name: 'Adam', phone: '555-5678', age: 35 },
19239 { name: 'Julie', phone: '555-8765', age: 29 }
19240 ];
19241 $scope.order = function(predicate, reverse) {
19242 $scope.friends = orderBy($scope.friends, predicate, reverse);
19243 };
19244 $scope.order('-age',false);
19245 }]);
19246 </file>
19247 </example>
19248 */
19249 orderByFilter.$inject = ['$parse'];
19250 function orderByFilter($parse) {
19251 return function(array, sortPredicate, reverseOrder) {
19252
19253 if (!(isArrayLike(array))) return array;
19254
19255 if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; }
19256 if (sortPredicate.length === 0) { sortPredicate = ['+']; }
19257
19258 var predicates = processPredicates(sortPredicate, reverseOrder);
19259
19260 // The next three lines are a version of a Swartzian Transform idiom from Perl
19261 // (sometimes called the Decorate-Sort-Undecorate idiom)
19262 // See https://en.wikipedia.org/wiki/Schwartzian_transform
19263 var compareValues = Array.prototype.map.call(array, getComparisonObject);
19264 compareValues.sort(doComparison);
19265 array = compareValues.map(function(item) { return item.value; });
19266
19267 return array;
19268
19269 function getComparisonObject(value, index) {
19270 return {
19271 value: value,
19272 predicateValues: predicates.map(function(predicate) {
19273 return getPredicateValue(predicate.get(value), index);
19274 })
19275 };
19276 }
19277
19278 function doComparison(v1, v2) {
19279 var result = 0;
19280 for (var index=0, length = predicates.length; index < length; ++index) {
19281 result = compare(v1.predicateValues[index], v2.predicateValues[index]) * predicates[index].descending;
19282 if (result) break;
19283 }
19284 return result;
19285 }
19286 };
19287
19288 function processPredicates(sortPredicate, reverseOrder) {
19289 reverseOrder = reverseOrder ? -1 : 1;
19290 return sortPredicate.map(function(predicate) {
19291 var descending = 1, get = identity;
19292
19293 if (isFunction(predicate)) {
19294 get = predicate;
19295 } else if (isString(predicate)) {
19296 if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
19297 descending = predicate.charAt(0) == '-' ? -1 : 1;
19298 predicate = predicate.substring(1);
19299 }
19300 if (predicate !== '') {
19301 get = $parse(predicate);
19302 if (get.constant) {
19303 var key = get();
19304 get = function(value) { return value[key]; };
19305 }
19306 }
19307 }
19308 return { get: get, descending: descending * reverseOrder };
19309 });
19310 }
19311
19312 function isPrimitive(value) {
19313 switch (typeof value) {
19314 case 'number': /* falls through */
19315 case 'boolean': /* falls through */
19316 case 'string':
19317 return true;
19318 default:
19319 return false;
19320 }
19321 }
19322
19323 function objectValue(value, index) {
19324 // If `valueOf` is a valid function use that
19325 if (typeof value.valueOf === 'function') {
19326 value = value.valueOf();
19327 if (isPrimitive(value)) return value;
19328 }
19329 // If `toString` is a valid function and not the one from `Object.prototype` use that
19330 if (hasCustomToString(value)) {
19331 value = value.toString();
19332 if (isPrimitive(value)) return value;
19333 }
19334 // We have a basic object so we use the position of the object in the collection
19335 return index;
19336 }
19337
19338 function getPredicateValue(value, index) {
19339 var type = typeof value;
19340 if (value === null) {
19341 type = 'string';
19342 value = 'null';
19343 } else if (type === 'string') {
19344 value = value.toLowerCase();
19345 } else if (type === 'object') {
19346 value = objectValue(value, index);
19347 }
19348 return { value: value, type: type };
19349 }
19350
19351 function compare(v1, v2) {
19352 var result = 0;
19353 if (v1.type === v2.type) {
19354 if (v1.value !== v2.value) {
19355 result = v1.value < v2.value ? -1 : 1;
19356 }
19357 } else {
19358 result = v1.type < v2.type ? -1 : 1;
19359 }
19360 return result;
19361 }
19362 }
19363
19364 function ngDirective(directive) {
19365 if (isFunction(directive)) {
19366 directive = {
19367 link: directive
19368 };
19369 }
19370 directive.restrict = directive.restrict || 'AC';
19371 return valueFn(directive);
19372 }
19373
19374 /**
19375 * @ngdoc directive
19376 * @name a
19377 * @restrict E
19378 *
19379 * @description
19380 * Modifies the default behavior of the html A tag so that the default action is prevented when
19381 * the href attribute is empty.
19382 *
19383 * This change permits the easy creation of action links with the `ngClick` directive
19384 * without changing the location or causing page reloads, e.g.:
19385 * `<a href="" ng-click="list.addItem()">Add Item</a>`
19386 */
19387 var htmlAnchorDirective = valueFn({
19388 restrict: 'E',
19389 compile: function(element, attr) {
19390 if (!attr.href && !attr.xlinkHref) {
19391 return function(scope, element) {
19392 // If the linked element is not an anchor tag anymore, do nothing
19393 if (element[0].nodeName.toLowerCase() !== 'a') return;
19394
19395 // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
19396 var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
19397 'xlink:href' : 'href';
19398 element.on('click', function(event) {
19399 // if we have no href url, then don't navigate anywhere.
19400 if (!element.attr(href)) {
19401 event.preventDefault();
19402 }
19403 });
19404 };
19405 }
19406 }
19407 });
19408
19409 /**
19410 * @ngdoc directive
19411 * @name ngHref
19412 * @restrict A
19413 * @priority 99
19414 *
19415 * @description
19416 * Using Angular markup like `{{hash}}` in an href attribute will
19417 * make the link go to the wrong URL if the user clicks it before
19418 * Angular has a chance to replace the `{{hash}}` markup with its
19419 * value. Until Angular replaces the markup the link will be broken
19420 * and will most likely return a 404 error. The `ngHref` directive
19421 * solves this problem.
19422 *
19423 * The wrong way to write it:
19424 * ```html
19425 * <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
19426 * ```
19427 *
19428 * The correct way to write it:
19429 * ```html
19430 * <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
19431 * ```
19432 *
19433 * @element A
19434 * @param {template} ngHref any string which can contain `{{}}` markup.
19435 *
19436 * @example
19437 * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
19438 * in links and their different behaviors:
19439 <example>
19440 <file name="index.html">
19441 <input ng-model="value" /><br />
19442 <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
19443 <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
19444 <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
19445 <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
19446 <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
19447 <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
19448 </file>
19449 <file name="protractor.js" type="protractor">
19450 it('should execute ng-click but not reload when href without value', function() {
19451 element(by.id('link-1')).click();
19452 expect(element(by.model('value')).getAttribute('value')).toEqual('1');
19453 expect(element(by.id('link-1')).getAttribute('href')).toBe('');
19454 });
19455
19456 it('should execute ng-click but not reload when href empty string', function() {
19457 element(by.id('link-2')).click();
19458 expect(element(by.model('value')).getAttribute('value')).toEqual('2');
19459 expect(element(by.id('link-2')).getAttribute('href')).toBe('');
19460 });
19461
19462 it('should execute ng-click and change url when ng-href specified', function() {
19463 expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/);
19464
19465 element(by.id('link-3')).click();
19466
19467 // At this point, we navigate away from an Angular page, so we need
19468 // to use browser.driver to get the base webdriver.
19469
19470 browser.wait(function() {
19471 return browser.driver.getCurrentUrl().then(function(url) {
19472 return url.match(/\/123$/);
19473 });
19474 }, 5000, 'page should navigate to /123');
19475 });
19476
19477 it('should execute ng-click but not reload when href empty string and name specified', function() {
19478 element(by.id('link-4')).click();
19479 expect(element(by.model('value')).getAttribute('value')).toEqual('4');
19480 expect(element(by.id('link-4')).getAttribute('href')).toBe('');
19481 });
19482
19483 it('should execute ng-click but not reload when no href but name specified', function() {
19484 element(by.id('link-5')).click();
19485 expect(element(by.model('value')).getAttribute('value')).toEqual('5');
19486 expect(element(by.id('link-5')).getAttribute('href')).toBe(null);
19487 });
19488
19489 it('should only change url when only ng-href', function() {
19490 element(by.model('value')).clear();
19491 element(by.model('value')).sendKeys('6');
19492 expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/);
19493
19494 element(by.id('link-6')).click();
19495
19496 // At this point, we navigate away from an Angular page, so we need
19497 // to use browser.driver to get the base webdriver.
19498 browser.wait(function() {
19499 return browser.driver.getCurrentUrl().then(function(url) {
19500 return url.match(/\/6$/);
19501 });
19502 }, 5000, 'page should navigate to /6');
19503 });
19504 </file>
19505 </example>
19506 */
19507
19508 /**
19509 * @ngdoc directive
19510 * @name ngSrc
19511 * @restrict A
19512 * @priority 99
19513 *
19514 * @description
19515 * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
19516 * work right: The browser will fetch from the URL with the literal
19517 * text `{{hash}}` until Angular replaces the expression inside
19518 * `{{hash}}`. The `ngSrc` directive solves this problem.
19519 *
19520 * The buggy way to write it:
19521 * ```html
19522 * <img src="http://www.gravatar.com/avatar/{{hash}}" alt="Description"/>
19523 * ```
19524 *
19525 * The correct way to write it:
19526 * ```html
19527 * <img ng-src="http://www.gravatar.com/avatar/{{hash}}" alt="Description" />
19528 * ```
19529 *
19530 * @element IMG
19531 * @param {template} ngSrc any string which can contain `{{}}` markup.
19532 */
19533
19534 /**
19535 * @ngdoc directive
19536 * @name ngSrcset
19537 * @restrict A
19538 * @priority 99
19539 *
19540 * @description
19541 * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
19542 * work right: The browser will fetch from the URL with the literal
19543 * text `{{hash}}` until Angular replaces the expression inside
19544 * `{{hash}}`. The `ngSrcset` directive solves this problem.
19545 *
19546 * The buggy way to write it:
19547 * ```html
19548 * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description"/>
19549 * ```
19550 *
19551 * The correct way to write it:
19552 * ```html
19553 * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x" alt="Description" />
19554 * ```
19555 *
19556 * @element IMG
19557 * @param {template} ngSrcset any string which can contain `{{}}` markup.
19558 */
19559
19560 /**
19561 * @ngdoc directive
19562 * @name ngDisabled
19563 * @restrict A
19564 * @priority 100
19565 *
19566 * @description
19567 *
19568 * This directive sets the `disabled` attribute on the element if the
19569 * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy.
19570 *
19571 * A special directive is necessary because we cannot use interpolation inside the `disabled`
19572 * attribute. The following example would make the button enabled on Chrome/Firefox
19573 * but not on older IEs:
19574 *
19575 * ```html
19576 * <!-- See below for an example of ng-disabled being used correctly -->
19577 * <div ng-init="isDisabled = false">
19578 * <button disabled="{{isDisabled}}">Disabled</button>
19579 * </div>
19580 * ```
19581 *
19582 * This is because the HTML specification does not require browsers to preserve the values of
19583 * boolean attributes such as `disabled` (Their presence means true and their absence means false.)
19584 * If we put an Angular interpolation expression into such an attribute then the
19585 * binding information would be lost when the browser removes the attribute.
19586 *
19587 * @example
19588 <example>
19589 <file name="index.html">
19590 <label>Click me to toggle: <input type="checkbox" ng-model="checked"></label><br/>
19591 <button ng-model="button" ng-disabled="checked">Button</button>
19592 </file>
19593 <file name="protractor.js" type="protractor">
19594 it('should toggle button', function() {
19595 expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy();
19596 element(by.model('checked')).click();
19597 expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy();
19598 });
19599 </file>
19600 </example>
19601 *
19602 * @element INPUT
19603 * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy,
19604 * then the `disabled` attribute will be set on the element
19605 */
19606
19607
19608 /**
19609 * @ngdoc directive
19610 * @name ngChecked
19611 * @restrict A
19612 * @priority 100
19613 *
19614 * @description
19615 * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy.
19616 *
19617 * Note that this directive should not be used together with {@link ngModel `ngModel`},
19618 * as this can lead to unexpected behavior.
19619 *
19620 * ### Why do we need `ngChecked`?
19621 *
19622 * The HTML specification does not require browsers to preserve the values of boolean attributes
19623 * such as checked. (Their presence means true and their absence means false.)
19624 * If we put an Angular interpolation expression into such an attribute then the
19625 * binding information would be lost when the browser removes the attribute.
19626 * The `ngChecked` directive solves this problem for the `checked` attribute.
19627 * This complementary directive is not removed by the browser and so provides
19628 * a permanent reliable place to store the binding information.
19629 * @example
19630 <example>
19631 <file name="index.html">
19632 <label>Check me to check both: <input type="checkbox" ng-model="master"></label><br/>
19633 <input id="checkSlave" type="checkbox" ng-checked="master" aria-label="Slave input">
19634 </file>
19635 <file name="protractor.js" type="protractor">
19636 it('should check both checkBoxes', function() {
19637 expect(element(by.id('checkSlave')).getAttribute('checked')).toBeFalsy();
19638 element(by.model('master')).click();
19639 expect(element(by.id('checkSlave')).getAttribute('checked')).toBeTruthy();
19640 });
19641 </file>
19642 </example>
19643 *
19644 * @element INPUT
19645 * @param {expression} ngChecked If the {@link guide/expression expression} is truthy,
19646 * then the `checked` attribute will be set on the element
19647 */
19648
19649
19650 /**
19651 * @ngdoc directive
19652 * @name ngReadonly
19653 * @restrict A
19654 * @priority 100
19655 *
19656 * @description
19657 * The HTML specification does not require browsers to preserve the values of boolean attributes
19658 * such as readonly. (Their presence means true and their absence means false.)
19659 * If we put an Angular interpolation expression into such an attribute then the
19660 * binding information would be lost when the browser removes the attribute.
19661 * The `ngReadonly` directive solves this problem for the `readonly` attribute.
19662 * This complementary directive is not removed by the browser and so provides
19663 * a permanent reliable place to store the binding information.
19664 * @example
19665 <example>
19666 <file name="index.html">
19667 <label>Check me to make text readonly: <input type="checkbox" ng-model="checked"></label><br/>
19668 <input type="text" ng-readonly="checked" value="I'm Angular" aria-label="Readonly field" />
19669 </file>
19670 <file name="protractor.js" type="protractor">
19671 it('should toggle readonly attr', function() {
19672 expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy();
19673 element(by.model('checked')).click();
19674 expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy();
19675 });
19676 </file>
19677 </example>
19678 *
19679 * @element INPUT
19680 * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy,
19681 * then special attribute "readonly" will be set on the element
19682 */
19683
19684
19685 /**
19686 * @ngdoc directive
19687 * @name ngSelected
19688 * @restrict A
19689 * @priority 100
19690 *
19691 * @description
19692 * The HTML specification does not require browsers to preserve the values of boolean attributes
19693 * such as selected. (Their presence means true and their absence means false.)
19694 * If we put an Angular interpolation expression into such an attribute then the
19695 * binding information would be lost when the browser removes the attribute.
19696 * The `ngSelected` directive solves this problem for the `selected` attribute.
19697 * This complementary directive is not removed by the browser and so provides
19698 * a permanent reliable place to store the binding information.
19699 *
19700 * @example
19701 <example>
19702 <file name="index.html">
19703 <label>Check me to select: <input type="checkbox" ng-model="selected"></label><br/>
19704 <select aria-label="ngSelected demo">
19705 <option>Hello!</option>
19706 <option id="greet" ng-selected="selected">Greetings!</option>
19707 </select>
19708 </file>
19709 <file name="protractor.js" type="protractor">
19710 it('should select Greetings!', function() {
19711 expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy();
19712 element(by.model('selected')).click();
19713 expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy();
19714 });
19715 </file>
19716 </example>
19717 *
19718 * @element OPTION
19719 * @param {expression} ngSelected If the {@link guide/expression expression} is truthy,
19720 * then special attribute "selected" will be set on the element
19721 */
19722
19723 /**
19724 * @ngdoc directive
19725 * @name ngOpen
19726 * @restrict A
19727 * @priority 100
19728 *
19729 * @description
19730 * The HTML specification does not require browsers to preserve the values of boolean attributes
19731 * such as open. (Their presence means true and their absence means false.)
19732 * If we put an Angular interpolation expression into such an attribute then the
19733 * binding information would be lost when the browser removes the attribute.
19734 * The `ngOpen` directive solves this problem for the `open` attribute.
19735 * This complementary directive is not removed by the browser and so provides
19736 * a permanent reliable place to store the binding information.
19737 * @example
19738 <example>
19739 <file name="index.html">
19740 <label>Check me check multiple: <input type="checkbox" ng-model="open"></label><br/>
19741 <details id="details" ng-open="open">
19742 <summary>Show/Hide me</summary>
19743 </details>
19744 </file>
19745 <file name="protractor.js" type="protractor">
19746 it('should toggle open', function() {
19747 expect(element(by.id('details')).getAttribute('open')).toBeFalsy();
19748 element(by.model('open')).click();
19749 expect(element(by.id('details')).getAttribute('open')).toBeTruthy();
19750 });
19751 </file>
19752 </example>
19753 *
19754 * @element DETAILS
19755 * @param {expression} ngOpen If the {@link guide/expression expression} is truthy,
19756 * then special attribute "open" will be set on the element
19757 */
19758
19759 var ngAttributeAliasDirectives = {};
19760
19761 // boolean attrs are evaluated
19762 forEach(BOOLEAN_ATTR, function(propName, attrName) {
19763 // binding to multiple is not supported
19764 if (propName == "multiple") return;
19765
19766 function defaultLinkFn(scope, element, attr) {
19767 scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
19768 attr.$set(attrName, !!value);
19769 });
19770 }
19771
19772 var normalized = directiveNormalize('ng-' + attrName);
19773 var linkFn = defaultLinkFn;
19774
19775 if (propName === 'checked') {
19776 linkFn = function(scope, element, attr) {
19777 // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
19778 if (attr.ngModel !== attr[normalized]) {
19779 defaultLinkFn(scope, element, attr);
19780 }
19781 };
19782 }
19783
19784 ngAttributeAliasDirectives[normalized] = function() {
19785 return {
19786 restrict: 'A',
19787 priority: 100,
19788 link: linkFn
19789 };
19790 };
19791 });
19792
19793 // aliased input attrs are evaluated
19794 forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
19795 ngAttributeAliasDirectives[ngAttr] = function() {
19796 return {
19797 priority: 100,
19798 link: function(scope, element, attr) {
19799 //special case ngPattern when a literal regular expression value
19800 //is used as the expression (this way we don't have to watch anything).
19801 if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") {
19802 var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
19803 if (match) {
19804 attr.$set("ngPattern", new RegExp(match[1], match[2]));
19805 return;
19806 }
19807 }
19808
19809 scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
19810 attr.$set(ngAttr, value);
19811 });
19812 }
19813 };
19814 };
19815 });
19816
19817 // ng-src, ng-srcset, ng-href are interpolated
19818 forEach(['src', 'srcset', 'href'], function(attrName) {
19819 var normalized = directiveNormalize('ng-' + attrName);
19820 ngAttributeAliasDirectives[normalized] = function() {
19821 return {
19822 priority: 99, // it needs to run after the attributes are interpolated
19823 link: function(scope, element, attr) {
19824 var propName = attrName,
19825 name = attrName;
19826
19827 if (attrName === 'href' &&
19828 toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
19829 name = 'xlinkHref';
19830 attr.$attr[name] = 'xlink:href';
19831 propName = null;
19832 }
19833
19834 attr.$observe(normalized, function(value) {
19835 if (!value) {
19836 if (attrName === 'href') {
19837 attr.$set(name, null);
19838 }
19839 return;
19840 }
19841
19842 attr.$set(name, value);
19843
19844 // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
19845 // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
19846 // to set the property as well to achieve the desired effect.
19847 // we use attr[attrName] value since $set can sanitize the url.
19848 if (msie && propName) element.prop(propName, attr[name]);
19849 });
19850 }
19851 };
19852 };
19853 });
19854
19855 /* global -nullFormCtrl, -SUBMITTED_CLASS, addSetValidityMethod: true
19856 */
19857 var nullFormCtrl = {
19858 $addControl: noop,
19859 $$renameControl: nullFormRenameControl,
19860 $removeControl: noop,
19861 $setValidity: noop,
19862 $setDirty: noop,
19863 $setPristine: noop,
19864 $setSubmitted: noop
19865 },
19866 SUBMITTED_CLASS = 'ng-submitted';
19867
19868 function nullFormRenameControl(control, name) {
19869 control.$name = name;
19870 }
19871
19872 /**
19873 * @ngdoc type
19874 * @name form.FormController
19875 *
19876 * @property {boolean} $pristine True if user has not interacted with the form yet.
19877 * @property {boolean} $dirty True if user has already interacted with the form.
19878 * @property {boolean} $valid True if all of the containing forms and controls are valid.
19879 * @property {boolean} $invalid True if at least one containing control or form is invalid.
19880 * @property {boolean} $submitted True if user has submitted the form even if its invalid.
19881 *
19882 * @property {Object} $error Is an object hash, containing references to controls or
19883 * forms with failing validators, where:
19884 *
19885 * - keys are validation tokens (error names),
19886 * - values are arrays of controls or forms that have a failing validator for given error name.
19887 *
19888 * Built-in validation tokens:
19889 *
19890 * - `email`
19891 * - `max`
19892 * - `maxlength`
19893 * - `min`
19894 * - `minlength`
19895 * - `number`
19896 * - `pattern`
19897 * - `required`
19898 * - `url`
19899 * - `date`
19900 * - `datetimelocal`
19901 * - `time`
19902 * - `week`
19903 * - `month`
19904 *
19905 * @description
19906 * `FormController` keeps track of all its controls and nested forms as well as the state of them,
19907 * such as being valid/invalid or dirty/pristine.
19908 *
19909 * Each {@link ng.directive:form form} directive creates an instance
19910 * of `FormController`.
19911 *
19912 */
19913 //asks for $scope to fool the BC controller module
19914 FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate'];
19915 function FormController(element, attrs, $scope, $animate, $interpolate) {
19916 var form = this,
19917 controls = [];
19918
19919 var parentForm = form.$$parentForm = element.parent().controller('form') || nullFormCtrl;
19920
19921 // init state
19922 form.$error = {};
19923 form.$$success = {};
19924 form.$pending = undefined;
19925 form.$name = $interpolate(attrs.name || attrs.ngForm || '')($scope);
19926 form.$dirty = false;
19927 form.$pristine = true;
19928 form.$valid = true;
19929 form.$invalid = false;
19930 form.$submitted = false;
19931
19932 parentForm.$addControl(form);
19933
19934 /**
19935 * @ngdoc method
19936 * @name form.FormController#$rollbackViewValue
19937 *
19938 * @description
19939 * Rollback all form controls pending updates to the `$modelValue`.
19940 *
19941 * Updates may be pending by a debounced event or because the input is waiting for a some future
19942 * event defined in `ng-model-options`. This method is typically needed by the reset button of
19943 * a form that uses `ng-model-options` to pend updates.
19944 */
19945 form.$rollbackViewValue = function() {
19946 forEach(controls, function(control) {
19947 control.$rollbackViewValue();
19948 });
19949 };
19950
19951 /**
19952 * @ngdoc method
19953 * @name form.FormController#$commitViewValue
19954 *
19955 * @description
19956 * Commit all form controls pending updates to the `$modelValue`.
19957 *
19958 * Updates may be pending by a debounced event or because the input is waiting for a some future
19959 * event defined in `ng-model-options`. This method is rarely needed as `NgModelController`
19960 * usually handles calling this in response to input events.
19961 */
19962 form.$commitViewValue = function() {
19963 forEach(controls, function(control) {
19964 control.$commitViewValue();
19965 });
19966 };
19967
19968 /**
19969 * @ngdoc method
19970 * @name form.FormController#$addControl
19971 *
19972 * @description
19973 * Register a control with the form.
19974 *
19975 * Input elements using ngModelController do this automatically when they are linked.
19976 */
19977 form.$addControl = function(control) {
19978 // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
19979 // and not added to the scope. Now we throw an error.
19980 assertNotHasOwnProperty(control.$name, 'input');
19981 controls.push(control);
19982
19983 if (control.$name) {
19984 form[control.$name] = control;
19985 }
19986 };
19987
19988 // Private API: rename a form control
19989 form.$$renameControl = function(control, newName) {
19990 var oldName = control.$name;
19991
19992 if (form[oldName] === control) {
19993 delete form[oldName];
19994 }
19995 form[newName] = control;
19996 control.$name = newName;
19997 };
19998
19999 /**
20000 * @ngdoc method
20001 * @name form.FormController#$removeControl
20002 *
20003 * @description
20004 * Deregister a control from the form.
20005 *
20006 * Input elements using ngModelController do this automatically when they are destroyed.
20007 */
20008 form.$removeControl = function(control) {
20009 if (control.$name && form[control.$name] === control) {
20010 delete form[control.$name];
20011 }
20012 forEach(form.$pending, function(value, name) {
20013 form.$setValidity(name, null, control);
20014 });
20015 forEach(form.$error, function(value, name) {
20016 form.$setValidity(name, null, control);
20017 });
20018 forEach(form.$$success, function(value, name) {
20019 form.$setValidity(name, null, control);
20020 });
20021
20022 arrayRemove(controls, control);
20023 };
20024
20025
20026 /**
20027 * @ngdoc method
20028 * @name form.FormController#$setValidity
20029 *
20030 * @description
20031 * Sets the validity of a form control.
20032 *
20033 * This method will also propagate to parent forms.
20034 */
20035 addSetValidityMethod({
20036 ctrl: this,
20037 $element: element,
20038 set: function(object, property, controller) {
20039 var list = object[property];
20040 if (!list) {
20041 object[property] = [controller];
20042 } else {
20043 var index = list.indexOf(controller);
20044 if (index === -1) {
20045 list.push(controller);
20046 }
20047 }
20048 },
20049 unset: function(object, property, controller) {
20050 var list = object[property];
20051 if (!list) {
20052 return;
20053 }
20054 arrayRemove(list, controller);
20055 if (list.length === 0) {
20056 delete object[property];
20057 }
20058 },
20059 parentForm: parentForm,
20060 $animate: $animate
20061 });
20062
20063 /**
20064 * @ngdoc method
20065 * @name form.FormController#$setDirty
20066 *
20067 * @description
20068 * Sets the form to a dirty state.
20069 *
20070 * This method can be called to add the 'ng-dirty' class and set the form to a dirty
20071 * state (ng-dirty class). This method will also propagate to parent forms.
20072 */
20073 form.$setDirty = function() {
20074 $animate.removeClass(element, PRISTINE_CLASS);
20075 $animate.addClass(element, DIRTY_CLASS);
20076 form.$dirty = true;
20077 form.$pristine = false;
20078 parentForm.$setDirty();
20079 };
20080
20081 /**
20082 * @ngdoc method
20083 * @name form.FormController#$setPristine
20084 *
20085 * @description
20086 * Sets the form to its pristine state.
20087 *
20088 * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
20089 * state (ng-pristine class). This method will also propagate to all the controls contained
20090 * in this form.
20091 *
20092 * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
20093 * saving or resetting it.
20094 */
20095 form.$setPristine = function() {
20096 $animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
20097 form.$dirty = false;
20098 form.$pristine = true;
20099 form.$submitted = false;
20100 forEach(controls, function(control) {
20101 control.$setPristine();
20102 });
20103 };
20104
20105 /**
20106 * @ngdoc method
20107 * @name form.FormController#$setUntouched
20108 *
20109 * @description
20110 * Sets the form to its untouched state.
20111 *
20112 * This method can be called to remove the 'ng-touched' class and set the form controls to their
20113 * untouched state (ng-untouched class).
20114 *
20115 * Setting a form controls back to their untouched state is often useful when setting the form
20116 * back to its pristine state.
20117 */
20118 form.$setUntouched = function() {
20119 forEach(controls, function(control) {
20120 control.$setUntouched();
20121 });
20122 };
20123
20124 /**
20125 * @ngdoc method
20126 * @name form.FormController#$setSubmitted
20127 *
20128 * @description
20129 * Sets the form to its submitted state.
20130 */
20131 form.$setSubmitted = function() {
20132 $animate.addClass(element, SUBMITTED_CLASS);
20133 form.$submitted = true;
20134 parentForm.$setSubmitted();
20135 };
20136 }
20137
20138 /**
20139 * @ngdoc directive
20140 * @name ngForm
20141 * @restrict EAC
20142 *
20143 * @description
20144 * Nestable alias of {@link ng.directive:form `form`} directive. HTML
20145 * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
20146 * sub-group of controls needs to be determined.
20147 *
20148 * Note: the purpose of `ngForm` is to group controls,
20149 * but not to be a replacement for the `<form>` tag with all of its capabilities
20150 * (e.g. posting to the server, ...).
20151 *
20152 * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
20153 * related scope, under this name.
20154 *
20155 */
20156
20157 /**
20158 * @ngdoc directive
20159 * @name form
20160 * @restrict E
20161 *
20162 * @description
20163 * Directive that instantiates
20164 * {@link form.FormController FormController}.
20165 *
20166 * If the `name` attribute is specified, the form controller is published onto the current scope under
20167 * this name.
20168 *
20169 * # Alias: {@link ng.directive:ngForm `ngForm`}
20170 *
20171 * In Angular, forms can be nested. This means that the outer form is valid when all of the child
20172 * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
20173 * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
20174 * `<form>` but can be nested. This allows you to have nested forms, which is very useful when
20175 * using Angular validation directives in forms that are dynamically generated using the
20176 * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
20177 * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
20178 * `ngForm` directive and nest these in an outer `form` element.
20179 *
20180 *
20181 * # CSS classes
20182 * - `ng-valid` is set if the form is valid.
20183 * - `ng-invalid` is set if the form is invalid.
20184 * - `ng-pristine` is set if the form is pristine.
20185 * - `ng-dirty` is set if the form is dirty.
20186 * - `ng-submitted` is set if the form was submitted.
20187 *
20188 * Keep in mind that ngAnimate can detect each of these classes when added and removed.
20189 *
20190 *
20191 * # Submitting a form and preventing the default action
20192 *
20193 * Since the role of forms in client-side Angular applications is different than in classical
20194 * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
20195 * page reload that sends the data to the server. Instead some javascript logic should be triggered
20196 * to handle the form submission in an application-specific way.
20197 *
20198 * For this reason, Angular prevents the default action (form submission to the server) unless the
20199 * `<form>` element has an `action` attribute specified.
20200 *
20201 * You can use one of the following two ways to specify what javascript method should be called when
20202 * a form is submitted:
20203 *
20204 * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
20205 * - {@link ng.directive:ngClick ngClick} directive on the first
20206 * button or input field of type submit (input[type=submit])
20207 *
20208 * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
20209 * or {@link ng.directive:ngClick ngClick} directives.
20210 * This is because of the following form submission rules in the HTML specification:
20211 *
20212 * - If a form has only one input field then hitting enter in this field triggers form submit
20213 * (`ngSubmit`)
20214 * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
20215 * doesn't trigger submit
20216 * - if a form has one or more input fields and one or more buttons or input[type=submit] then
20217 * hitting enter in any of the input fields will trigger the click handler on the *first* button or
20218 * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
20219 *
20220 * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is
20221 * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
20222 * to have access to the updated model.
20223 *
20224 * ## Animation Hooks
20225 *
20226 * Animations in ngForm are triggered when any of the associated CSS classes are added and removed.
20227 * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any
20228 * other validations that are performed within the form. Animations in ngForm are similar to how
20229 * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well
20230 * as JS animations.
20231 *
20232 * The following example shows a simple way to utilize CSS transitions to style a form element
20233 * that has been rendered as invalid after it has been validated:
20234 *
20235 * <pre>
20236 * //be sure to include ngAnimate as a module to hook into more
20237 * //advanced animations
20238 * .my-form {
20239 * transition:0.5s linear all;
20240 * background: white;
20241 * }
20242 * .my-form.ng-invalid {
20243 * background: red;
20244 * color:white;
20245 * }
20246 * </pre>
20247 *
20248 * @example
20249 <example deps="angular-animate.js" animations="true" fixBase="true" module="formExample">
20250 <file name="index.html">
20251 <script>
20252 angular.module('formExample', [])
20253 .controller('FormController', ['$scope', function($scope) {
20254 $scope.userType = 'guest';
20255 }]);
20256 </script>
20257 <style>
20258 .my-form {
20259 -webkit-transition:all linear 0.5s;
20260 transition:all linear 0.5s;
20261 background: transparent;
20262 }
20263 .my-form.ng-invalid {
20264 background: red;
20265 }
20266 </style>
20267 <form name="myForm" ng-controller="FormController" class="my-form">
20268 userType: <input name="input" ng-model="userType" required>
20269 <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
20270 <code>userType = {{userType}}</code><br>
20271 <code>myForm.input.$valid = {{myForm.input.$valid}}</code><br>
20272 <code>myForm.input.$error = {{myForm.input.$error}}</code><br>
20273 <code>myForm.$valid = {{myForm.$valid}}</code><br>
20274 <code>myForm.$error.required = {{!!myForm.$error.required}}</code><br>
20275 </form>
20276 </file>
20277 <file name="protractor.js" type="protractor">
20278 it('should initialize to model', function() {
20279 var userType = element(by.binding('userType'));
20280 var valid = element(by.binding('myForm.input.$valid'));
20281
20282 expect(userType.getText()).toContain('guest');
20283 expect(valid.getText()).toContain('true');
20284 });
20285
20286 it('should be invalid if empty', function() {
20287 var userType = element(by.binding('userType'));
20288 var valid = element(by.binding('myForm.input.$valid'));
20289 var userInput = element(by.model('userType'));
20290
20291 userInput.clear();
20292 userInput.sendKeys('');
20293
20294 expect(userType.getText()).toEqual('userType =');
20295 expect(valid.getText()).toContain('false');
20296 });
20297 </file>
20298 </example>
20299 *
20300 * @param {string=} name Name of the form. If specified, the form controller will be published into
20301 * related scope, under this name.
20302 */
20303 var formDirectiveFactory = function(isNgForm) {
20304 return ['$timeout', function($timeout) {
20305 var formDirective = {
20306 name: 'form',
20307 restrict: isNgForm ? 'EAC' : 'E',
20308 controller: FormController,
20309 compile: function ngFormCompile(formElement, attr) {
20310 // Setup initial state of the control
20311 formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS);
20312
20313 var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false);
20314
20315 return {
20316 pre: function ngFormPreLink(scope, formElement, attr, controller) {
20317 // if `action` attr is not present on the form, prevent the default action (submission)
20318 if (!('action' in attr)) {
20319 // we can't use jq events because if a form is destroyed during submission the default
20320 // action is not prevented. see #1238
20321 //
20322 // IE 9 is not affected because it doesn't fire a submit event and try to do a full
20323 // page reload if the form was destroyed by submission of the form via a click handler
20324 // on a button in the form. Looks like an IE9 specific bug.
20325 var handleFormSubmission = function(event) {
20326 scope.$apply(function() {
20327 controller.$commitViewValue();
20328 controller.$setSubmitted();
20329 });
20330
20331 event.preventDefault();
20332 };
20333
20334 addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
20335
20336 // unregister the preventDefault listener so that we don't not leak memory but in a
20337 // way that will achieve the prevention of the default action.
20338 formElement.on('$destroy', function() {
20339 $timeout(function() {
20340 removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);
20341 }, 0, false);
20342 });
20343 }
20344
20345 var parentFormCtrl = controller.$$parentForm;
20346
20347 if (nameAttr) {
20348 setter(scope, controller.$name, controller, controller.$name);
20349 attr.$observe(nameAttr, function(newValue) {
20350 if (controller.$name === newValue) return;
20351 setter(scope, controller.$name, undefined, controller.$name);
20352 parentFormCtrl.$$renameControl(controller, newValue);
20353 setter(scope, controller.$name, controller, controller.$name);
20354 });
20355 }
20356 formElement.on('$destroy', function() {
20357 parentFormCtrl.$removeControl(controller);
20358 if (nameAttr) {
20359 setter(scope, attr[nameAttr], undefined, controller.$name);
20360 }
20361 extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
20362 });
20363 }
20364 };
20365 }
20366 };
20367
20368 return formDirective;
20369 }];
20370 };
20371
20372 var formDirective = formDirectiveFactory();
20373 var ngFormDirective = formDirectiveFactory(true);
20374
20375 /* global VALID_CLASS: false,
20376 INVALID_CLASS: false,
20377 PRISTINE_CLASS: false,
20378 DIRTY_CLASS: false,
20379 UNTOUCHED_CLASS: false,
20380 TOUCHED_CLASS: false,
20381 $ngModelMinErr: false,
20382 */
20383
20384 // Regex code is obtained from SO: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231
20385 var ISO_DATE_REGEXP = /\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/;
20386 var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
20387 var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
20388 var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/;
20389 var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
20390 var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
20391 var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
20392 var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
20393 var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/;
20394
20395 var inputType = {
20396
20397 /**
20398 * @ngdoc input
20399 * @name input[text]
20400 *
20401 * @description
20402 * Standard HTML text input with angular data binding, inherited by most of the `input` elements.
20403 *
20404 *
20405 * @param {string} ngModel Assignable angular expression to data-bind to.
20406 * @param {string=} name Property name of the form under which the control is published.
20407 * @param {string=} required Adds `required` validation error key if the value is not entered.
20408 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20409 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20410 * `required` when you want to data-bind to the `required` attribute.
20411 * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
20412 * minlength.
20413 * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
20414 * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
20415 * any length.
20416 * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
20417 * that contains the regular expression body that will be converted to a regular expression
20418 * as in the ngPattern directive.
20419 * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
20420 * a RegExp found by evaluating the Angular expression given in the attribute value.
20421 * If the expression evaluates to a RegExp object, then this is used directly.
20422 * If the expression evaluates to a string, then it will be converted to a RegExp
20423 * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
20424 * `new RegExp('^abc$')`.<br />
20425 * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
20426 * start at the index of the last search's match, thus not taking the whole input value into
20427 * account.
20428 * @param {string=} ngChange Angular expression to be executed when input changes due to user
20429 * interaction with the input element.
20430 * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
20431 * This parameter is ignored for input[type=password] controls, which will never trim the
20432 * input.
20433 *
20434 * @example
20435 <example name="text-input-directive" module="textInputExample">
20436 <file name="index.html">
20437 <script>
20438 angular.module('textInputExample', [])
20439 .controller('ExampleController', ['$scope', function($scope) {
20440 $scope.example = {
20441 text: 'guest',
20442 word: /^\s*\w*\s*$/
20443 };
20444 }]);
20445 </script>
20446 <form name="myForm" ng-controller="ExampleController">
20447 <label>Single word:
20448 <input type="text" name="input" ng-model="example.text"
20449 ng-pattern="example.word" required ng-trim="false">
20450 </label>
20451 <div role="alert">
20452 <span class="error" ng-show="myForm.input.$error.required">
20453 Required!</span>
20454 <span class="error" ng-show="myForm.input.$error.pattern">
20455 Single word only!</span>
20456 </div>
20457 <tt>text = {{example.text}}</tt><br/>
20458 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20459 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20460 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20461 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20462 </form>
20463 </file>
20464 <file name="protractor.js" type="protractor">
20465 var text = element(by.binding('example.text'));
20466 var valid = element(by.binding('myForm.input.$valid'));
20467 var input = element(by.model('example.text'));
20468
20469 it('should initialize to model', function() {
20470 expect(text.getText()).toContain('guest');
20471 expect(valid.getText()).toContain('true');
20472 });
20473
20474 it('should be invalid if empty', function() {
20475 input.clear();
20476 input.sendKeys('');
20477
20478 expect(text.getText()).toEqual('text =');
20479 expect(valid.getText()).toContain('false');
20480 });
20481
20482 it('should be invalid if multi word', function() {
20483 input.clear();
20484 input.sendKeys('hello world');
20485
20486 expect(valid.getText()).toContain('false');
20487 });
20488 </file>
20489 </example>
20490 */
20491 'text': textInputType,
20492
20493 /**
20494 * @ngdoc input
20495 * @name input[date]
20496 *
20497 * @description
20498 * Input with date validation and transformation. In browsers that do not yet support
20499 * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
20500 * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many
20501 * modern browsers do not yet support this input type, it is important to provide cues to users on the
20502 * expected input format via a placeholder or label.
20503 *
20504 * The model must always be a Date object, otherwise Angular will throw an error.
20505 * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
20506 *
20507 * The timezone to be used to read/write the `Date` instance in the model can be defined using
20508 * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
20509 *
20510 * @param {string} ngModel Assignable angular expression to data-bind to.
20511 * @param {string=} name Property name of the form under which the control is published.
20512 * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
20513 * valid ISO date string (yyyy-MM-dd).
20514 * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
20515 * a valid ISO date string (yyyy-MM-dd).
20516 * @param {string=} required Sets `required` validation error key if the value is not entered.
20517 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20518 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20519 * `required` when you want to data-bind to the `required` attribute.
20520 * @param {string=} ngChange Angular expression to be executed when input changes due to user
20521 * interaction with the input element.
20522 *
20523 * @example
20524 <example name="date-input-directive" module="dateInputExample">
20525 <file name="index.html">
20526 <script>
20527 angular.module('dateInputExample', [])
20528 .controller('DateController', ['$scope', function($scope) {
20529 $scope.example = {
20530 value: new Date(2013, 9, 22)
20531 };
20532 }]);
20533 </script>
20534 <form name="myForm" ng-controller="DateController as dateCtrl">
20535 <label for="exampleInput">Pick a date in 2013:</label>
20536 <input type="date" id="exampleInput" name="input" ng-model="example.value"
20537 placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
20538 <div role="alert">
20539 <span class="error" ng-show="myForm.input.$error.required">
20540 Required!</span>
20541 <span class="error" ng-show="myForm.input.$error.date">
20542 Not a valid date!</span>
20543 </div>
20544 <tt>value = {{example.value | date: "yyyy-MM-dd"}}</tt><br/>
20545 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20546 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20547 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20548 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20549 </form>
20550 </file>
20551 <file name="protractor.js" type="protractor">
20552 var value = element(by.binding('example.value | date: "yyyy-MM-dd"'));
20553 var valid = element(by.binding('myForm.input.$valid'));
20554 var input = element(by.model('example.value'));
20555
20556 // currently protractor/webdriver does not support
20557 // sending keys to all known HTML5 input controls
20558 // for various browsers (see https://github.com/angular/protractor/issues/562).
20559 function setInput(val) {
20560 // set the value of the element and force validation.
20561 var scr = "var ipt = document.getElementById('exampleInput'); " +
20562 "ipt.value = '" + val + "';" +
20563 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
20564 browser.executeScript(scr);
20565 }
20566
20567 it('should initialize to model', function() {
20568 expect(value.getText()).toContain('2013-10-22');
20569 expect(valid.getText()).toContain('myForm.input.$valid = true');
20570 });
20571
20572 it('should be invalid if empty', function() {
20573 setInput('');
20574 expect(value.getText()).toEqual('value =');
20575 expect(valid.getText()).toContain('myForm.input.$valid = false');
20576 });
20577
20578 it('should be invalid if over max', function() {
20579 setInput('2015-01-01');
20580 expect(value.getText()).toContain('');
20581 expect(valid.getText()).toContain('myForm.input.$valid = false');
20582 });
20583 </file>
20584 </example>
20585 */
20586 'date': createDateInputType('date', DATE_REGEXP,
20587 createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
20588 'yyyy-MM-dd'),
20589
20590 /**
20591 * @ngdoc input
20592 * @name input[datetime-local]
20593 *
20594 * @description
20595 * Input with datetime validation and transformation. In browsers that do not yet support
20596 * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
20597 * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`.
20598 *
20599 * The model must always be a Date object, otherwise Angular will throw an error.
20600 * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
20601 *
20602 * The timezone to be used to read/write the `Date` instance in the model can be defined using
20603 * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
20604 *
20605 * @param {string} ngModel Assignable angular expression to data-bind to.
20606 * @param {string=} name Property name of the form under which the control is published.
20607 * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
20608 * valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
20609 * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
20610 * a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss).
20611 * @param {string=} required Sets `required` validation error key if the value is not entered.
20612 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20613 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20614 * `required` when you want to data-bind to the `required` attribute.
20615 * @param {string=} ngChange Angular expression to be executed when input changes due to user
20616 * interaction with the input element.
20617 *
20618 * @example
20619 <example name="datetimelocal-input-directive" module="dateExample">
20620 <file name="index.html">
20621 <script>
20622 angular.module('dateExample', [])
20623 .controller('DateController', ['$scope', function($scope) {
20624 $scope.example = {
20625 value: new Date(2010, 11, 28, 14, 57)
20626 };
20627 }]);
20628 </script>
20629 <form name="myForm" ng-controller="DateController as dateCtrl">
20630 <label for="exampleInput">Pick a date between in 2013:</label>
20631 <input type="datetime-local" id="exampleInput" name="input" ng-model="example.value"
20632 placeholder="yyyy-MM-ddTHH:mm:ss" min="2001-01-01T00:00:00" max="2013-12-31T00:00:00" required />
20633 <div role="alert">
20634 <span class="error" ng-show="myForm.input.$error.required">
20635 Required!</span>
20636 <span class="error" ng-show="myForm.input.$error.datetimelocal">
20637 Not a valid date!</span>
20638 </div>
20639 <tt>value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}</tt><br/>
20640 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20641 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20642 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20643 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20644 </form>
20645 </file>
20646 <file name="protractor.js" type="protractor">
20647 var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"'));
20648 var valid = element(by.binding('myForm.input.$valid'));
20649 var input = element(by.model('example.value'));
20650
20651 // currently protractor/webdriver does not support
20652 // sending keys to all known HTML5 input controls
20653 // for various browsers (https://github.com/angular/protractor/issues/562).
20654 function setInput(val) {
20655 // set the value of the element and force validation.
20656 var scr = "var ipt = document.getElementById('exampleInput'); " +
20657 "ipt.value = '" + val + "';" +
20658 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
20659 browser.executeScript(scr);
20660 }
20661
20662 it('should initialize to model', function() {
20663 expect(value.getText()).toContain('2010-12-28T14:57:00');
20664 expect(valid.getText()).toContain('myForm.input.$valid = true');
20665 });
20666
20667 it('should be invalid if empty', function() {
20668 setInput('');
20669 expect(value.getText()).toEqual('value =');
20670 expect(valid.getText()).toContain('myForm.input.$valid = false');
20671 });
20672
20673 it('should be invalid if over max', function() {
20674 setInput('2015-01-01T23:59:00');
20675 expect(value.getText()).toContain('');
20676 expect(valid.getText()).toContain('myForm.input.$valid = false');
20677 });
20678 </file>
20679 </example>
20680 */
20681 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,
20682 createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']),
20683 'yyyy-MM-ddTHH:mm:ss.sss'),
20684
20685 /**
20686 * @ngdoc input
20687 * @name input[time]
20688 *
20689 * @description
20690 * Input with time validation and transformation. In browsers that do not yet support
20691 * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
20692 * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a
20693 * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`.
20694 *
20695 * The model must always be a Date object, otherwise Angular will throw an error.
20696 * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
20697 *
20698 * The timezone to be used to read/write the `Date` instance in the model can be defined using
20699 * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
20700 *
20701 * @param {string} ngModel Assignable angular expression to data-bind to.
20702 * @param {string=} name Property name of the form under which the control is published.
20703 * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
20704 * valid ISO time format (HH:mm:ss).
20705 * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a
20706 * valid ISO time format (HH:mm:ss).
20707 * @param {string=} required Sets `required` validation error key if the value is not entered.
20708 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20709 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20710 * `required` when you want to data-bind to the `required` attribute.
20711 * @param {string=} ngChange Angular expression to be executed when input changes due to user
20712 * interaction with the input element.
20713 *
20714 * @example
20715 <example name="time-input-directive" module="timeExample">
20716 <file name="index.html">
20717 <script>
20718 angular.module('timeExample', [])
20719 .controller('DateController', ['$scope', function($scope) {
20720 $scope.example = {
20721 value: new Date(1970, 0, 1, 14, 57, 0)
20722 };
20723 }]);
20724 </script>
20725 <form name="myForm" ng-controller="DateController as dateCtrl">
20726 <label for="exampleInput">Pick a between 8am and 5pm:</label>
20727 <input type="time" id="exampleInput" name="input" ng-model="example.value"
20728 placeholder="HH:mm:ss" min="08:00:00" max="17:00:00" required />
20729 <div role="alert">
20730 <span class="error" ng-show="myForm.input.$error.required">
20731 Required!</span>
20732 <span class="error" ng-show="myForm.input.$error.time">
20733 Not a valid date!</span>
20734 </div>
20735 <tt>value = {{example.value | date: "HH:mm:ss"}}</tt><br/>
20736 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20737 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20738 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20739 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20740 </form>
20741 </file>
20742 <file name="protractor.js" type="protractor">
20743 var value = element(by.binding('example.value | date: "HH:mm:ss"'));
20744 var valid = element(by.binding('myForm.input.$valid'));
20745 var input = element(by.model('example.value'));
20746
20747 // currently protractor/webdriver does not support
20748 // sending keys to all known HTML5 input controls
20749 // for various browsers (https://github.com/angular/protractor/issues/562).
20750 function setInput(val) {
20751 // set the value of the element and force validation.
20752 var scr = "var ipt = document.getElementById('exampleInput'); " +
20753 "ipt.value = '" + val + "';" +
20754 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
20755 browser.executeScript(scr);
20756 }
20757
20758 it('should initialize to model', function() {
20759 expect(value.getText()).toContain('14:57:00');
20760 expect(valid.getText()).toContain('myForm.input.$valid = true');
20761 });
20762
20763 it('should be invalid if empty', function() {
20764 setInput('');
20765 expect(value.getText()).toEqual('value =');
20766 expect(valid.getText()).toContain('myForm.input.$valid = false');
20767 });
20768
20769 it('should be invalid if over max', function() {
20770 setInput('23:59:00');
20771 expect(value.getText()).toContain('');
20772 expect(valid.getText()).toContain('myForm.input.$valid = false');
20773 });
20774 </file>
20775 </example>
20776 */
20777 'time': createDateInputType('time', TIME_REGEXP,
20778 createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']),
20779 'HH:mm:ss.sss'),
20780
20781 /**
20782 * @ngdoc input
20783 * @name input[week]
20784 *
20785 * @description
20786 * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
20787 * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
20788 * week format (yyyy-W##), for example: `2013-W02`.
20789 *
20790 * The model must always be a Date object, otherwise Angular will throw an error.
20791 * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
20792 *
20793 * The timezone to be used to read/write the `Date` instance in the model can be defined using
20794 * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
20795 *
20796 * @param {string} ngModel Assignable angular expression to data-bind to.
20797 * @param {string=} name Property name of the form under which the control is published.
20798 * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
20799 * valid ISO week format (yyyy-W##).
20800 * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
20801 * a valid ISO week format (yyyy-W##).
20802 * @param {string=} required Sets `required` validation error key if the value is not entered.
20803 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20804 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20805 * `required` when you want to data-bind to the `required` attribute.
20806 * @param {string=} ngChange Angular expression to be executed when input changes due to user
20807 * interaction with the input element.
20808 *
20809 * @example
20810 <example name="week-input-directive" module="weekExample">
20811 <file name="index.html">
20812 <script>
20813 angular.module('weekExample', [])
20814 .controller('DateController', ['$scope', function($scope) {
20815 $scope.example = {
20816 value: new Date(2013, 0, 3)
20817 };
20818 }]);
20819 </script>
20820 <form name="myForm" ng-controller="DateController as dateCtrl">
20821 <label>Pick a date between in 2013:
20822 <input id="exampleInput" type="week" name="input" ng-model="example.value"
20823 placeholder="YYYY-W##" min="2012-W32"
20824 max="2013-W52" required />
20825 </label>
20826 <div role="alert">
20827 <span class="error" ng-show="myForm.input.$error.required">
20828 Required!</span>
20829 <span class="error" ng-show="myForm.input.$error.week">
20830 Not a valid date!</span>
20831 </div>
20832 <tt>value = {{example.value | date: "yyyy-Www"}}</tt><br/>
20833 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20834 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20835 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20836 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20837 </form>
20838 </file>
20839 <file name="protractor.js" type="protractor">
20840 var value = element(by.binding('example.value | date: "yyyy-Www"'));
20841 var valid = element(by.binding('myForm.input.$valid'));
20842 var input = element(by.model('example.value'));
20843
20844 // currently protractor/webdriver does not support
20845 // sending keys to all known HTML5 input controls
20846 // for various browsers (https://github.com/angular/protractor/issues/562).
20847 function setInput(val) {
20848 // set the value of the element and force validation.
20849 var scr = "var ipt = document.getElementById('exampleInput'); " +
20850 "ipt.value = '" + val + "';" +
20851 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
20852 browser.executeScript(scr);
20853 }
20854
20855 it('should initialize to model', function() {
20856 expect(value.getText()).toContain('2013-W01');
20857 expect(valid.getText()).toContain('myForm.input.$valid = true');
20858 });
20859
20860 it('should be invalid if empty', function() {
20861 setInput('');
20862 expect(value.getText()).toEqual('value =');
20863 expect(valid.getText()).toContain('myForm.input.$valid = false');
20864 });
20865
20866 it('should be invalid if over max', function() {
20867 setInput('2015-W01');
20868 expect(value.getText()).toContain('');
20869 expect(valid.getText()).toContain('myForm.input.$valid = false');
20870 });
20871 </file>
20872 </example>
20873 */
20874 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),
20875
20876 /**
20877 * @ngdoc input
20878 * @name input[month]
20879 *
20880 * @description
20881 * Input with month validation and transformation. In browsers that do not yet support
20882 * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
20883 * month format (yyyy-MM), for example: `2009-01`.
20884 *
20885 * The model must always be a Date object, otherwise Angular will throw an error.
20886 * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string.
20887 * If the model is not set to the first of the month, the next view to model update will set it
20888 * to the first of the month.
20889 *
20890 * The timezone to be used to read/write the `Date` instance in the model can be defined using
20891 * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser.
20892 *
20893 * @param {string} ngModel Assignable angular expression to data-bind to.
20894 * @param {string=} name Property name of the form under which the control is published.
20895 * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be
20896 * a valid ISO month format (yyyy-MM).
20897 * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must
20898 * be a valid ISO month format (yyyy-MM).
20899 * @param {string=} required Sets `required` validation error key if the value is not entered.
20900 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
20901 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
20902 * `required` when you want to data-bind to the `required` attribute.
20903 * @param {string=} ngChange Angular expression to be executed when input changes due to user
20904 * interaction with the input element.
20905 *
20906 * @example
20907 <example name="month-input-directive" module="monthExample">
20908 <file name="index.html">
20909 <script>
20910 angular.module('monthExample', [])
20911 .controller('DateController', ['$scope', function($scope) {
20912 $scope.example = {
20913 value: new Date(2013, 9, 1)
20914 };
20915 }]);
20916 </script>
20917 <form name="myForm" ng-controller="DateController as dateCtrl">
20918 <label for="exampleInput">Pick a month in 2013:</label>
20919 <input id="exampleInput" type="month" name="input" ng-model="example.value"
20920 placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
20921 <div role="alert">
20922 <span class="error" ng-show="myForm.input.$error.required">
20923 Required!</span>
20924 <span class="error" ng-show="myForm.input.$error.month">
20925 Not a valid month!</span>
20926 </div>
20927 <tt>value = {{example.value | date: "yyyy-MM"}}</tt><br/>
20928 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
20929 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
20930 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
20931 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
20932 </form>
20933 </file>
20934 <file name="protractor.js" type="protractor">
20935 var value = element(by.binding('example.value | date: "yyyy-MM"'));
20936 var valid = element(by.binding('myForm.input.$valid'));
20937 var input = element(by.model('example.value'));
20938
20939 // currently protractor/webdriver does not support
20940 // sending keys to all known HTML5 input controls
20941 // for various browsers (https://github.com/angular/protractor/issues/562).
20942 function setInput(val) {
20943 // set the value of the element and force validation.
20944 var scr = "var ipt = document.getElementById('exampleInput'); " +
20945 "ipt.value = '" + val + "';" +
20946 "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
20947 browser.executeScript(scr);
20948 }
20949
20950 it('should initialize to model', function() {
20951 expect(value.getText()).toContain('2013-10');
20952 expect(valid.getText()).toContain('myForm.input.$valid = true');
20953 });
20954
20955 it('should be invalid if empty', function() {
20956 setInput('');
20957 expect(value.getText()).toEqual('value =');
20958 expect(valid.getText()).toContain('myForm.input.$valid = false');
20959 });
20960
20961 it('should be invalid if over max', function() {
20962 setInput('2015-01');
20963 expect(value.getText()).toContain('');
20964 expect(valid.getText()).toContain('myForm.input.$valid = false');
20965 });
20966 </file>
20967 </example>
20968 */
20969 'month': createDateInputType('month', MONTH_REGEXP,
20970 createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),
20971 'yyyy-MM'),
20972
20973 /**
20974 * @ngdoc input
20975 * @name input[number]
20976 *
20977 * @description
20978 * Text input with number validation and transformation. Sets the `number` validation
20979 * error if not a valid number.
20980 *
20981 * <div class="alert alert-warning">
20982 * The model must always be of type `number` otherwise Angular will throw an error.
20983 * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt}
20984 * error docs for more information and an example of how to convert your model if necessary.
20985 * </div>
20986 *
20987 * ## Issues with HTML5 constraint validation
20988 *
20989 * In browsers that follow the
20990 * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29),
20991 * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}.
20992 * If a non-number is entered in the input, the browser will report the value as an empty string,
20993 * which means the view / model values in `ngModel` and subsequently the scope value
20994 * will also be an empty string.
20995 *
20996 *
20997 * @param {string} ngModel Assignable angular expression to data-bind to.
20998 * @param {string=} name Property name of the form under which the control is published.
20999 * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
21000 * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
21001 * @param {string=} required Sets `required` validation error key if the value is not entered.
21002 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21003 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21004 * `required` when you want to data-bind to the `required` attribute.
21005 * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
21006 * minlength.
21007 * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
21008 * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
21009 * any length.
21010 * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
21011 * that contains the regular expression body that will be converted to a regular expression
21012 * as in the ngPattern directive.
21013 * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
21014 * a RegExp found by evaluating the Angular expression given in the attribute value.
21015 * If the expression evaluates to a RegExp object, then this is used directly.
21016 * If the expression evaluates to a string, then it will be converted to a RegExp
21017 * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
21018 * `new RegExp('^abc$')`.<br />
21019 * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
21020 * start at the index of the last search's match, thus not taking the whole input value into
21021 * account.
21022 * @param {string=} ngChange Angular expression to be executed when input changes due to user
21023 * interaction with the input element.
21024 *
21025 * @example
21026 <example name="number-input-directive" module="numberExample">
21027 <file name="index.html">
21028 <script>
21029 angular.module('numberExample', [])
21030 .controller('ExampleController', ['$scope', function($scope) {
21031 $scope.example = {
21032 value: 12
21033 };
21034 }]);
21035 </script>
21036 <form name="myForm" ng-controller="ExampleController">
21037 <label>Number:
21038 <input type="number" name="input" ng-model="example.value"
21039 min="0" max="99" required>
21040 </label>
21041 <div role="alert">
21042 <span class="error" ng-show="myForm.input.$error.required">
21043 Required!</span>
21044 <span class="error" ng-show="myForm.input.$error.number">
21045 Not valid number!</span>
21046 </div>
21047 <tt>value = {{example.value}}</tt><br/>
21048 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21049 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21050 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21051 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21052 </form>
21053 </file>
21054 <file name="protractor.js" type="protractor">
21055 var value = element(by.binding('example.value'));
21056 var valid = element(by.binding('myForm.input.$valid'));
21057 var input = element(by.model('example.value'));
21058
21059 it('should initialize to model', function() {
21060 expect(value.getText()).toContain('12');
21061 expect(valid.getText()).toContain('true');
21062 });
21063
21064 it('should be invalid if empty', function() {
21065 input.clear();
21066 input.sendKeys('');
21067 expect(value.getText()).toEqual('value =');
21068 expect(valid.getText()).toContain('false');
21069 });
21070
21071 it('should be invalid if over max', function() {
21072 input.clear();
21073 input.sendKeys('123');
21074 expect(value.getText()).toEqual('value =');
21075 expect(valid.getText()).toContain('false');
21076 });
21077 </file>
21078 </example>
21079 */
21080 'number': numberInputType,
21081
21082
21083 /**
21084 * @ngdoc input
21085 * @name input[url]
21086 *
21087 * @description
21088 * Text input with URL validation. Sets the `url` validation error key if the content is not a
21089 * valid URL.
21090 *
21091 * <div class="alert alert-warning">
21092 * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex
21093 * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify
21094 * the built-in validators (see the {@link guide/forms Forms guide})
21095 * </div>
21096 *
21097 * @param {string} ngModel Assignable angular expression to data-bind to.
21098 * @param {string=} name Property name of the form under which the control is published.
21099 * @param {string=} required Sets `required` validation error key if the value is not entered.
21100 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21101 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21102 * `required` when you want to data-bind to the `required` attribute.
21103 * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
21104 * minlength.
21105 * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
21106 * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
21107 * any length.
21108 * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
21109 * that contains the regular expression body that will be converted to a regular expression
21110 * as in the ngPattern directive.
21111 * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
21112 * a RegExp found by evaluating the Angular expression given in the attribute value.
21113 * If the expression evaluates to a RegExp object, then this is used directly.
21114 * If the expression evaluates to a string, then it will be converted to a RegExp
21115 * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
21116 * `new RegExp('^abc$')`.<br />
21117 * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
21118 * start at the index of the last search's match, thus not taking the whole input value into
21119 * account.
21120 * @param {string=} ngChange Angular expression to be executed when input changes due to user
21121 * interaction with the input element.
21122 *
21123 * @example
21124 <example name="url-input-directive" module="urlExample">
21125 <file name="index.html">
21126 <script>
21127 angular.module('urlExample', [])
21128 .controller('ExampleController', ['$scope', function($scope) {
21129 $scope.url = {
21130 text: 'http://google.com'
21131 };
21132 }]);
21133 </script>
21134 <form name="myForm" ng-controller="ExampleController">
21135 <label>URL:
21136 <input type="url" name="input" ng-model="url.text" required>
21137 <label>
21138 <div role="alert">
21139 <span class="error" ng-show="myForm.input.$error.required">
21140 Required!</span>
21141 <span class="error" ng-show="myForm.input.$error.url">
21142 Not valid url!</span>
21143 </div>
21144 <tt>text = {{url.text}}</tt><br/>
21145 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21146 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21147 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21148 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21149 <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
21150 </form>
21151 </file>
21152 <file name="protractor.js" type="protractor">
21153 var text = element(by.binding('url.text'));
21154 var valid = element(by.binding('myForm.input.$valid'));
21155 var input = element(by.model('url.text'));
21156
21157 it('should initialize to model', function() {
21158 expect(text.getText()).toContain('http://google.com');
21159 expect(valid.getText()).toContain('true');
21160 });
21161
21162 it('should be invalid if empty', function() {
21163 input.clear();
21164 input.sendKeys('');
21165
21166 expect(text.getText()).toEqual('text =');
21167 expect(valid.getText()).toContain('false');
21168 });
21169
21170 it('should be invalid if not url', function() {
21171 input.clear();
21172 input.sendKeys('box');
21173
21174 expect(valid.getText()).toContain('false');
21175 });
21176 </file>
21177 </example>
21178 */
21179 'url': urlInputType,
21180
21181
21182 /**
21183 * @ngdoc input
21184 * @name input[email]
21185 *
21186 * @description
21187 * Text input with email validation. Sets the `email` validation error key if not a valid email
21188 * address.
21189 *
21190 * <div class="alert alert-warning">
21191 * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex
21192 * used in Chromium. If you need stricter validation (e.g. requiring a top-level domain), you can
21193 * use `ng-pattern` or modify the built-in validators (see the {@link guide/forms Forms guide})
21194 * </div>
21195 *
21196 * @param {string} ngModel Assignable angular expression to data-bind to.
21197 * @param {string=} name Property name of the form under which the control is published.
21198 * @param {string=} required Sets `required` validation error key if the value is not entered.
21199 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21200 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21201 * `required` when you want to data-bind to the `required` attribute.
21202 * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
21203 * minlength.
21204 * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
21205 * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of
21206 * any length.
21207 * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string
21208 * that contains the regular expression body that will be converted to a regular expression
21209 * as in the ngPattern directive.
21210 * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
21211 * a RegExp found by evaluating the Angular expression given in the attribute value.
21212 * If the expression evaluates to a RegExp object, then this is used directly.
21213 * If the expression evaluates to a string, then it will be converted to a RegExp
21214 * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
21215 * `new RegExp('^abc$')`.<br />
21216 * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
21217 * start at the index of the last search's match, thus not taking the whole input value into
21218 * account.
21219 * @param {string=} ngChange Angular expression to be executed when input changes due to user
21220 * interaction with the input element.
21221 *
21222 * @example
21223 <example name="email-input-directive" module="emailExample">
21224 <file name="index.html">
21225 <script>
21226 angular.module('emailExample', [])
21227 .controller('ExampleController', ['$scope', function($scope) {
21228 $scope.email = {
21229 text: '[email protected]'
21230 };
21231 }]);
21232 </script>
21233 <form name="myForm" ng-controller="ExampleController">
21234 <label>Email:
21235 <input type="email" name="input" ng-model="email.text" required>
21236 </label>
21237 <div role="alert">
21238 <span class="error" ng-show="myForm.input.$error.required">
21239 Required!</span>
21240 <span class="error" ng-show="myForm.input.$error.email">
21241 Not valid email!</span>
21242 </div>
21243 <tt>text = {{email.text}}</tt><br/>
21244 <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
21245 <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
21246 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21247 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21248 <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
21249 </form>
21250 </file>
21251 <file name="protractor.js" type="protractor">
21252 var text = element(by.binding('email.text'));
21253 var valid = element(by.binding('myForm.input.$valid'));
21254 var input = element(by.model('email.text'));
21255
21256 it('should initialize to model', function() {
21257 expect(text.getText()).toContain('[email protected]');
21258 expect(valid.getText()).toContain('true');
21259 });
21260
21261 it('should be invalid if empty', function() {
21262 input.clear();
21263 input.sendKeys('');
21264 expect(text.getText()).toEqual('text =');
21265 expect(valid.getText()).toContain('false');
21266 });
21267
21268 it('should be invalid if not email', function() {
21269 input.clear();
21270 input.sendKeys('xxx');
21271
21272 expect(valid.getText()).toContain('false');
21273 });
21274 </file>
21275 </example>
21276 */
21277 'email': emailInputType,
21278
21279
21280 /**
21281 * @ngdoc input
21282 * @name input[radio]
21283 *
21284 * @description
21285 * HTML radio button.
21286 *
21287 * @param {string} ngModel Assignable angular expression to data-bind to.
21288 * @param {string} value The value to which the `ngModel` expression should be set when selected.
21289 * Note that `value` only supports `string` values, i.e. the scope model needs to be a string,
21290 * too. Use `ngValue` if you need complex models (`number`, `object`, ...).
21291 * @param {string=} name Property name of the form under which the control is published.
21292 * @param {string=} ngChange Angular expression to be executed when input changes due to user
21293 * interaction with the input element.
21294 * @param {string} ngValue Angular expression to which `ngModel` will be be set when the radio
21295 * is selected. Should be used instead of the `value` attribute if you need
21296 * a non-string `ngModel` (`boolean`, `array`, ...).
21297 *
21298 * @example
21299 <example name="radio-input-directive" module="radioExample">
21300 <file name="index.html">
21301 <script>
21302 angular.module('radioExample', [])
21303 .controller('ExampleController', ['$scope', function($scope) {
21304 $scope.color = {
21305 name: 'blue'
21306 };
21307 $scope.specialValue = {
21308 "id": "12345",
21309 "value": "green"
21310 };
21311 }]);
21312 </script>
21313 <form name="myForm" ng-controller="ExampleController">
21314 <label>
21315 <input type="radio" ng-model="color.name" value="red">
21316 Red
21317 </label><br/>
21318 <label>
21319 <input type="radio" ng-model="color.name" ng-value="specialValue">
21320 Green
21321 </label><br/>
21322 <label>
21323 <input type="radio" ng-model="color.name" value="blue">
21324 Blue
21325 </label><br/>
21326 <tt>color = {{color.name | json}}</tt><br/>
21327 </form>
21328 Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.
21329 </file>
21330 <file name="protractor.js" type="protractor">
21331 it('should change state', function() {
21332 var color = element(by.binding('color.name'));
21333
21334 expect(color.getText()).toContain('blue');
21335
21336 element.all(by.model('color.name')).get(0).click();
21337
21338 expect(color.getText()).toContain('red');
21339 });
21340 </file>
21341 </example>
21342 */
21343 'radio': radioInputType,
21344
21345
21346 /**
21347 * @ngdoc input
21348 * @name input[checkbox]
21349 *
21350 * @description
21351 * HTML checkbox.
21352 *
21353 * @param {string} ngModel Assignable angular expression to data-bind to.
21354 * @param {string=} name Property name of the form under which the control is published.
21355 * @param {expression=} ngTrueValue The value to which the expression should be set when selected.
21356 * @param {expression=} ngFalseValue The value to which the expression should be set when not selected.
21357 * @param {string=} ngChange Angular expression to be executed when input changes due to user
21358 * interaction with the input element.
21359 *
21360 * @example
21361 <example name="checkbox-input-directive" module="checkboxExample">
21362 <file name="index.html">
21363 <script>
21364 angular.module('checkboxExample', [])
21365 .controller('ExampleController', ['$scope', function($scope) {
21366 $scope.checkboxModel = {
21367 value1 : true,
21368 value2 : 'YES'
21369 };
21370 }]);
21371 </script>
21372 <form name="myForm" ng-controller="ExampleController">
21373 <label>Value1:
21374 <input type="checkbox" ng-model="checkboxModel.value1">
21375 </label><br/>
21376 <label>Value2:
21377 <input type="checkbox" ng-model="checkboxModel.value2"
21378 ng-true-value="'YES'" ng-false-value="'NO'">
21379 </label><br/>
21380 <tt>value1 = {{checkboxModel.value1}}</tt><br/>
21381 <tt>value2 = {{checkboxModel.value2}}</tt><br/>
21382 </form>
21383 </file>
21384 <file name="protractor.js" type="protractor">
21385 it('should change state', function() {
21386 var value1 = element(by.binding('checkboxModel.value1'));
21387 var value2 = element(by.binding('checkboxModel.value2'));
21388
21389 expect(value1.getText()).toContain('true');
21390 expect(value2.getText()).toContain('YES');
21391
21392 element(by.model('checkboxModel.value1')).click();
21393 element(by.model('checkboxModel.value2')).click();
21394
21395 expect(value1.getText()).toContain('false');
21396 expect(value2.getText()).toContain('NO');
21397 });
21398 </file>
21399 </example>
21400 */
21401 'checkbox': checkboxInputType,
21402
21403 'hidden': noop,
21404 'button': noop,
21405 'submit': noop,
21406 'reset': noop,
21407 'file': noop
21408 };
21409
21410 function stringBasedInputType(ctrl) {
21411 ctrl.$formatters.push(function(value) {
21412 return ctrl.$isEmpty(value) ? value : value.toString();
21413 });
21414 }
21415
21416 function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
21417 baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
21418 stringBasedInputType(ctrl);
21419 }
21420
21421 function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
21422 var type = lowercase(element[0].type);
21423
21424 // In composition mode, users are still inputing intermediate text buffer,
21425 // hold the listener until composition is done.
21426 // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
21427 if (!$sniffer.android) {
21428 var composing = false;
21429
21430 element.on('compositionstart', function(data) {
21431 composing = true;
21432 });
21433
21434 element.on('compositionend', function() {
21435 composing = false;
21436 listener();
21437 });
21438 }
21439
21440 var listener = function(ev) {
21441 if (timeout) {
21442 $browser.defer.cancel(timeout);
21443 timeout = null;
21444 }
21445 if (composing) return;
21446 var value = element.val(),
21447 event = ev && ev.type;
21448
21449 // By default we will trim the value
21450 // If the attribute ng-trim exists we will avoid trimming
21451 // If input type is 'password', the value is never trimmed
21452 if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) {
21453 value = trim(value);
21454 }
21455
21456 // If a control is suffering from bad input (due to native validators), browsers discard its
21457 // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the
21458 // control's value is the same empty value twice in a row.
21459 if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {
21460 ctrl.$setViewValue(value, event);
21461 }
21462 };
21463
21464 // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
21465 // input event on backspace, delete or cut
21466 if ($sniffer.hasEvent('input')) {
21467 element.on('input', listener);
21468 } else {
21469 var timeout;
21470
21471 var deferListener = function(ev, input, origValue) {
21472 if (!timeout) {
21473 timeout = $browser.defer(function() {
21474 timeout = null;
21475 if (!input || input.value !== origValue) {
21476 listener(ev);
21477 }
21478 });
21479 }
21480 };
21481
21482 element.on('keydown', function(event) {
21483 var key = event.keyCode;
21484
21485 // ignore
21486 // command modifiers arrows
21487 if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
21488
21489 deferListener(event, this, this.value);
21490 });
21491
21492 // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
21493 if ($sniffer.hasEvent('paste')) {
21494 element.on('paste cut', deferListener);
21495 }
21496 }
21497
21498 // if user paste into input using mouse on older browser
21499 // or form autocomplete on newer browser, we need "change" event to catch it
21500 element.on('change', listener);
21501
21502 ctrl.$render = function() {
21503 element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
21504 };
21505 }
21506
21507 function weekParser(isoWeek, existingDate) {
21508 if (isDate(isoWeek)) {
21509 return isoWeek;
21510 }
21511
21512 if (isString(isoWeek)) {
21513 WEEK_REGEXP.lastIndex = 0;
21514 var parts = WEEK_REGEXP.exec(isoWeek);
21515 if (parts) {
21516 var year = +parts[1],
21517 week = +parts[2],
21518 hours = 0,
21519 minutes = 0,
21520 seconds = 0,
21521 milliseconds = 0,
21522 firstThurs = getFirstThursdayOfYear(year),
21523 addDays = (week - 1) * 7;
21524
21525 if (existingDate) {
21526 hours = existingDate.getHours();
21527 minutes = existingDate.getMinutes();
21528 seconds = existingDate.getSeconds();
21529 milliseconds = existingDate.getMilliseconds();
21530 }
21531
21532 return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds);
21533 }
21534 }
21535
21536 return NaN;
21537 }
21538
21539 function createDateParser(regexp, mapping) {
21540 return function(iso, date) {
21541 var parts, map;
21542
21543 if (isDate(iso)) {
21544 return iso;
21545 }
21546
21547 if (isString(iso)) {
21548 // When a date is JSON'ified to wraps itself inside of an extra
21549 // set of double quotes. This makes the date parsing code unable
21550 // to match the date string and parse it as a date.
21551 if (iso.charAt(0) == '"' && iso.charAt(iso.length - 1) == '"') {
21552 iso = iso.substring(1, iso.length - 1);
21553 }
21554 if (ISO_DATE_REGEXP.test(iso)) {
21555 return new Date(iso);
21556 }
21557 regexp.lastIndex = 0;
21558 parts = regexp.exec(iso);
21559
21560 if (parts) {
21561 parts.shift();
21562 if (date) {
21563 map = {
21564 yyyy: date.getFullYear(),
21565 MM: date.getMonth() + 1,
21566 dd: date.getDate(),
21567 HH: date.getHours(),
21568 mm: date.getMinutes(),
21569 ss: date.getSeconds(),
21570 sss: date.getMilliseconds() / 1000
21571 };
21572 } else {
21573 map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 };
21574 }
21575
21576 forEach(parts, function(part, index) {
21577 if (index < mapping.length) {
21578 map[mapping[index]] = +part;
21579 }
21580 });
21581 return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
21582 }
21583 }
21584
21585 return NaN;
21586 };
21587 }
21588
21589 function createDateInputType(type, regexp, parseDate, format) {
21590 return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {
21591 badInputChecker(scope, element, attr, ctrl);
21592 baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
21593 var timezone = ctrl && ctrl.$options && ctrl.$options.timezone;
21594 var previousDate;
21595
21596 ctrl.$$parserName = type;
21597 ctrl.$parsers.push(function(value) {
21598 if (ctrl.$isEmpty(value)) return null;
21599 if (regexp.test(value)) {
21600 // Note: We cannot read ctrl.$modelValue, as there might be a different
21601 // parser/formatter in the processing chain so that the model
21602 // contains some different data format!
21603 var parsedDate = parseDate(value, previousDate);
21604 if (timezone) {
21605 parsedDate = convertTimezoneToLocal(parsedDate, timezone);
21606 }
21607 return parsedDate;
21608 }
21609 return undefined;
21610 });
21611
21612 ctrl.$formatters.push(function(value) {
21613 if (value && !isDate(value)) {
21614 throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);
21615 }
21616 if (isValidDate(value)) {
21617 previousDate = value;
21618 if (previousDate && timezone) {
21619 previousDate = convertTimezoneToLocal(previousDate, timezone, true);
21620 }
21621 return $filter('date')(value, format, timezone);
21622 } else {
21623 previousDate = null;
21624 return '';
21625 }
21626 });
21627
21628 if (isDefined(attr.min) || attr.ngMin) {
21629 var minVal;
21630 ctrl.$validators.min = function(value) {
21631 return !isValidDate(value) || isUndefined(minVal) || parseDate(value) >= minVal;
21632 };
21633 attr.$observe('min', function(val) {
21634 minVal = parseObservedDateValue(val);
21635 ctrl.$validate();
21636 });
21637 }
21638
21639 if (isDefined(attr.max) || attr.ngMax) {
21640 var maxVal;
21641 ctrl.$validators.max = function(value) {
21642 return !isValidDate(value) || isUndefined(maxVal) || parseDate(value) <= maxVal;
21643 };
21644 attr.$observe('max', function(val) {
21645 maxVal = parseObservedDateValue(val);
21646 ctrl.$validate();
21647 });
21648 }
21649
21650 function isValidDate(value) {
21651 // Invalid Date: getTime() returns NaN
21652 return value && !(value.getTime && value.getTime() !== value.getTime());
21653 }
21654
21655 function parseObservedDateValue(val) {
21656 return isDefined(val) ? (isDate(val) ? val : parseDate(val)) : undefined;
21657 }
21658 };
21659 }
21660
21661 function badInputChecker(scope, element, attr, ctrl) {
21662 var node = element[0];
21663 var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);
21664 if (nativeValidation) {
21665 ctrl.$parsers.push(function(value) {
21666 var validity = element.prop(VALIDITY_STATE_PROPERTY) || {};
21667 // Detect bug in FF35 for input[email] (https://bugzilla.mozilla.org/show_bug.cgi?id=1064430):
21668 // - also sets validity.badInput (should only be validity.typeMismatch).
21669 // - see http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-(type=email)
21670 // - can ignore this case as we can still read out the erroneous email...
21671 return validity.badInput && !validity.typeMismatch ? undefined : value;
21672 });
21673 }
21674 }
21675
21676 function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
21677 badInputChecker(scope, element, attr, ctrl);
21678 baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
21679
21680 ctrl.$$parserName = 'number';
21681 ctrl.$parsers.push(function(value) {
21682 if (ctrl.$isEmpty(value)) return null;
21683 if (NUMBER_REGEXP.test(value)) return parseFloat(value);
21684 return undefined;
21685 });
21686
21687 ctrl.$formatters.push(function(value) {
21688 if (!ctrl.$isEmpty(value)) {
21689 if (!isNumber(value)) {
21690 throw $ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value);
21691 }
21692 value = value.toString();
21693 }
21694 return value;
21695 });
21696
21697 if (isDefined(attr.min) || attr.ngMin) {
21698 var minVal;
21699 ctrl.$validators.min = function(value) {
21700 return ctrl.$isEmpty(value) || isUndefined(minVal) || value >= minVal;
21701 };
21702
21703 attr.$observe('min', function(val) {
21704 if (isDefined(val) && !isNumber(val)) {
21705 val = parseFloat(val, 10);
21706 }
21707 minVal = isNumber(val) && !isNaN(val) ? val : undefined;
21708 // TODO(matsko): implement validateLater to reduce number of validations
21709 ctrl.$validate();
21710 });
21711 }
21712
21713 if (isDefined(attr.max) || attr.ngMax) {
21714 var maxVal;
21715 ctrl.$validators.max = function(value) {
21716 return ctrl.$isEmpty(value) || isUndefined(maxVal) || value <= maxVal;
21717 };
21718
21719 attr.$observe('max', function(val) {
21720 if (isDefined(val) && !isNumber(val)) {
21721 val = parseFloat(val, 10);
21722 }
21723 maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
21724 // TODO(matsko): implement validateLater to reduce number of validations
21725 ctrl.$validate();
21726 });
21727 }
21728 }
21729
21730 function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
21731 // Note: no badInputChecker here by purpose as `url` is only a validation
21732 // in browsers, i.e. we can always read out input.value even if it is not valid!
21733 baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
21734 stringBasedInputType(ctrl);
21735
21736 ctrl.$$parserName = 'url';
21737 ctrl.$validators.url = function(modelValue, viewValue) {
21738 var value = modelValue || viewValue;
21739 return ctrl.$isEmpty(value) || URL_REGEXP.test(value);
21740 };
21741 }
21742
21743 function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
21744 // Note: no badInputChecker here by purpose as `url` is only a validation
21745 // in browsers, i.e. we can always read out input.value even if it is not valid!
21746 baseInputType(scope, element, attr, ctrl, $sniffer, $browser);
21747 stringBasedInputType(ctrl);
21748
21749 ctrl.$$parserName = 'email';
21750 ctrl.$validators.email = function(modelValue, viewValue) {
21751 var value = modelValue || viewValue;
21752 return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value);
21753 };
21754 }
21755
21756 function radioInputType(scope, element, attr, ctrl) {
21757 // make the name unique, if not defined
21758 if (isUndefined(attr.name)) {
21759 element.attr('name', nextUid());
21760 }
21761
21762 var listener = function(ev) {
21763 if (element[0].checked) {
21764 ctrl.$setViewValue(attr.value, ev && ev.type);
21765 }
21766 };
21767
21768 element.on('click', listener);
21769
21770 ctrl.$render = function() {
21771 var value = attr.value;
21772 element[0].checked = (value == ctrl.$viewValue);
21773 };
21774
21775 attr.$observe('value', ctrl.$render);
21776 }
21777
21778 function parseConstantExpr($parse, context, name, expression, fallback) {
21779 var parseFn;
21780 if (isDefined(expression)) {
21781 parseFn = $parse(expression);
21782 if (!parseFn.constant) {
21783 throw minErr('ngModel')('constexpr', 'Expected constant expression for `{0}`, but saw ' +
21784 '`{1}`.', name, expression);
21785 }
21786 return parseFn(context);
21787 }
21788 return fallback;
21789 }
21790
21791 function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) {
21792 var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true);
21793 var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);
21794
21795 var listener = function(ev) {
21796 ctrl.$setViewValue(element[0].checked, ev && ev.type);
21797 };
21798
21799 element.on('click', listener);
21800
21801 ctrl.$render = function() {
21802 element[0].checked = ctrl.$viewValue;
21803 };
21804
21805 // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false`
21806 // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert
21807 // it to a boolean.
21808 ctrl.$isEmpty = function(value) {
21809 return value === false;
21810 };
21811
21812 ctrl.$formatters.push(function(value) {
21813 return equals(value, trueValue);
21814 });
21815
21816 ctrl.$parsers.push(function(value) {
21817 return value ? trueValue : falseValue;
21818 });
21819 }
21820
21821
21822 /**
21823 * @ngdoc directive
21824 * @name textarea
21825 * @restrict E
21826 *
21827 * @description
21828 * HTML textarea element control with angular data-binding. The data-binding and validation
21829 * properties of this element are exactly the same as those of the
21830 * {@link ng.directive:input input element}.
21831 *
21832 * @param {string} ngModel Assignable angular expression to data-bind to.
21833 * @param {string=} name Property name of the form under which the control is published.
21834 * @param {string=} required Sets `required` validation error key if the value is not entered.
21835 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
21836 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
21837 * `required` when you want to data-bind to the `required` attribute.
21838 * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
21839 * minlength.
21840 * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
21841 * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
21842 * length.
21843 * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
21844 * a RegExp found by evaluating the Angular expression given in the attribute value.
21845 * If the expression evaluates to a RegExp object, then this is used directly.
21846 * If the expression evaluates to a string, then it will be converted to a RegExp
21847 * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
21848 * `new RegExp('^abc$')`.<br />
21849 * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
21850 * start at the index of the last search's match, thus not taking the whole input value into
21851 * account.
21852 * @param {string=} ngChange Angular expression to be executed when input changes due to user
21853 * interaction with the input element.
21854 * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
21855 */
21856
21857
21858 /**
21859 * @ngdoc directive
21860 * @name input
21861 * @restrict E
21862 *
21863 * @description
21864 * HTML input element control. When used together with {@link ngModel `ngModel`}, it provides data-binding,
21865 * input state control, and validation.
21866 * Input control follows HTML5 input types and polyfills the HTML5 validation behavior for older browsers.
21867 *
21868 * <div class="alert alert-warning">
21869 * **Note:** Not every feature offered is available for all input types.
21870 * Specifically, data binding and event handling via `ng-model` is unsupported for `input[file]`.
21871 * </div>
21872 *
21873 * @param {string} ngModel Assignable angular expression to data-bind to.
21874 * @param {string=} name Property name of the form under which the control is published.
21875 * @param {string=} required Sets `required` validation error key if the value is not entered.
21876 * @param {boolean=} ngRequired Sets `required` attribute if set to true
21877 * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
21878 * minlength.
21879 * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
21880 * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any
21881 * length.
21882 * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel value does not match
21883 * a RegExp found by evaluating the Angular expression given in the attribute value.
21884 * If the expression evaluates to a RegExp object, then this is used directly.
21885 * If the expression evaluates to a string, then it will be converted to a RegExp
21886 * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to
21887 * `new RegExp('^abc$')`.<br />
21888 * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
21889 * start at the index of the last search's match, thus not taking the whole input value into
21890 * account.
21891 * @param {string=} ngChange Angular expression to be executed when input changes due to user
21892 * interaction with the input element.
21893 * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
21894 * This parameter is ignored for input[type=password] controls, which will never trim the
21895 * input.
21896 *
21897 * @example
21898 <example name="input-directive" module="inputExample">
21899 <file name="index.html">
21900 <script>
21901 angular.module('inputExample', [])
21902 .controller('ExampleController', ['$scope', function($scope) {
21903 $scope.user = {name: 'guest', last: 'visitor'};
21904 }]);
21905 </script>
21906 <div ng-controller="ExampleController">
21907 <form name="myForm">
21908 <label>
21909 User name:
21910 <input type="text" name="userName" ng-model="user.name" required>
21911 </label>
21912 <div role="alert">
21913 <span class="error" ng-show="myForm.userName.$error.required">
21914 Required!</span>
21915 </div>
21916 <label>
21917 Last name:
21918 <input type="text" name="lastName" ng-model="user.last"
21919 ng-minlength="3" ng-maxlength="10">
21920 </label>
21921 <div role="alert">
21922 <span class="error" ng-show="myForm.lastName.$error.minlength">
21923 Too short!</span>
21924 <span class="error" ng-show="myForm.lastName.$error.maxlength">
21925 Too long!</span>
21926 </div>
21927 </form>
21928 <hr>
21929 <tt>user = {{user}}</tt><br/>
21930 <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br/>
21931 <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br/>
21932 <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br/>
21933 <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br/>
21934 <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
21935 <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
21936 <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br/>
21937 <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br/>
21938 </div>
21939 </file>
21940 <file name="protractor.js" type="protractor">
21941 var user = element(by.exactBinding('user'));
21942 var userNameValid = element(by.binding('myForm.userName.$valid'));
21943 var lastNameValid = element(by.binding('myForm.lastName.$valid'));
21944 var lastNameError = element(by.binding('myForm.lastName.$error'));
21945 var formValid = element(by.binding('myForm.$valid'));
21946 var userNameInput = element(by.model('user.name'));
21947 var userLastInput = element(by.model('user.last'));
21948
21949 it('should initialize to model', function() {
21950 expect(user.getText()).toContain('{"name":"guest","last":"visitor"}');
21951 expect(userNameValid.getText()).toContain('true');
21952 expect(formValid.getText()).toContain('true');
21953 });
21954
21955 it('should be invalid if empty when required', function() {
21956 userNameInput.clear();
21957 userNameInput.sendKeys('');
21958
21959 expect(user.getText()).toContain('{"last":"visitor"}');
21960 expect(userNameValid.getText()).toContain('false');
21961 expect(formValid.getText()).toContain('false');
21962 });
21963
21964 it('should be valid if empty when min length is set', function() {
21965 userLastInput.clear();
21966 userLastInput.sendKeys('');
21967
21968 expect(user.getText()).toContain('{"name":"guest","last":""}');
21969 expect(lastNameValid.getText()).toContain('true');
21970 expect(formValid.getText()).toContain('true');
21971 });
21972
21973 it('should be invalid if less than required min length', function() {
21974 userLastInput.clear();
21975 userLastInput.sendKeys('xx');
21976
21977 expect(user.getText()).toContain('{"name":"guest"}');
21978 expect(lastNameValid.getText()).toContain('false');
21979 expect(lastNameError.getText()).toContain('minlength');
21980 expect(formValid.getText()).toContain('false');
21981 });
21982
21983 it('should be invalid if longer than max length', function() {
21984 userLastInput.clear();
21985 userLastInput.sendKeys('some ridiculously long name');
21986
21987 expect(user.getText()).toContain('{"name":"guest"}');
21988 expect(lastNameValid.getText()).toContain('false');
21989 expect(lastNameError.getText()).toContain('maxlength');
21990 expect(formValid.getText()).toContain('false');
21991 });
21992 </file>
21993 </example>
21994 */
21995 var inputDirective = ['$browser', '$sniffer', '$filter', '$parse',
21996 function($browser, $sniffer, $filter, $parse) {
21997 return {
21998 restrict: 'E',
21999 require: ['?ngModel'],
22000 link: {
22001 pre: function(scope, element, attr, ctrls) {
22002 if (ctrls[0]) {
22003 (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrls[0], $sniffer,
22004 $browser, $filter, $parse);
22005 }
22006 }
22007 }
22008 };
22009 }];
22010
22011
22012
22013 var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
22014 /**
22015 * @ngdoc directive
22016 * @name ngValue
22017 *
22018 * @description
22019 * Binds the given expression to the value of `<option>` or {@link input[radio] `input[radio]`},
22020 * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to
22021 * the bound value.
22022 *
22023 * `ngValue` is useful when dynamically generating lists of radio buttons using
22024 * {@link ngRepeat `ngRepeat`}, as shown below.
22025 *
22026 * Likewise, `ngValue` can be used to generate `<option>` elements for
22027 * the {@link select `select`} element. In that case however, only strings are supported
22028 * for the `value `attribute, so the resulting `ngModel` will always be a string.
22029 * Support for `select` models with non-string values is available via `ngOptions`.
22030 *
22031 * @element input
22032 * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
22033 * of the `input` element
22034 *
22035 * @example
22036 <example name="ngValue-directive" module="valueExample">
22037 <file name="index.html">
22038 <script>
22039 angular.module('valueExample', [])
22040 .controller('ExampleController', ['$scope', function($scope) {
22041 $scope.names = ['pizza', 'unicorns', 'robots'];
22042 $scope.my = { favorite: 'unicorns' };
22043 }]);
22044 </script>
22045 <form ng-controller="ExampleController">
22046 <h2>Which is your favorite?</h2>
22047 <label ng-repeat="name in names" for="{{name}}">
22048 {{name}}
22049 <input type="radio"
22050 ng-model="my.favorite"
22051 ng-value="name"
22052 id="{{name}}"
22053 name="favorite">
22054 </label>
22055 <div>You chose {{my.favorite}}</div>
22056 </form>
22057 </file>
22058 <file name="protractor.js" type="protractor">
22059 var favorite = element(by.binding('my.favorite'));
22060
22061 it('should initialize to model', function() {
22062 expect(favorite.getText()).toContain('unicorns');
22063 });
22064 it('should bind the values to the inputs', function() {
22065 element.all(by.model('my.favorite')).get(0).click();
22066 expect(favorite.getText()).toContain('pizza');
22067 });
22068 </file>
22069 </example>
22070 */
22071 var ngValueDirective = function() {
22072 return {
22073 restrict: 'A',
22074 priority: 100,
22075 compile: function(tpl, tplAttr) {
22076 if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
22077 return function ngValueConstantLink(scope, elm, attr) {
22078 attr.$set('value', scope.$eval(attr.ngValue));
22079 };
22080 } else {
22081 return function ngValueLink(scope, elm, attr) {
22082 scope.$watch(attr.ngValue, function valueWatchAction(value) {
22083 attr.$set('value', value);
22084 });
22085 };
22086 }
22087 }
22088 };
22089 };
22090
22091 /**
22092 * @ngdoc directive
22093 * @name ngBind
22094 * @restrict AC
22095 *
22096 * @description
22097 * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
22098 * with the value of a given expression, and to update the text content when the value of that
22099 * expression changes.
22100 *
22101 * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
22102 * `{{ expression }}` which is similar but less verbose.
22103 *
22104 * It is preferable to use `ngBind` instead of `{{ expression }}` if a template is momentarily
22105 * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
22106 * element attribute, it makes the bindings invisible to the user while the page is loading.
22107 *
22108 * An alternative solution to this problem would be using the
22109 * {@link ng.directive:ngCloak ngCloak} directive.
22110 *
22111 *
22112 * @element ANY
22113 * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
22114 *
22115 * @example
22116 * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
22117 <example module="bindExample">
22118 <file name="index.html">
22119 <script>
22120 angular.module('bindExample', [])
22121 .controller('ExampleController', ['$scope', function($scope) {
22122 $scope.name = 'Whirled';
22123 }]);
22124 </script>
22125 <div ng-controller="ExampleController">
22126 <label>Enter name: <input type="text" ng-model="name"></label><br>
22127 Hello <span ng-bind="name"></span>!
22128 </div>
22129 </file>
22130 <file name="protractor.js" type="protractor">
22131 it('should check ng-bind', function() {
22132 var nameInput = element(by.model('name'));
22133
22134 expect(element(by.binding('name')).getText()).toBe('Whirled');
22135 nameInput.clear();
22136 nameInput.sendKeys('world');
22137 expect(element(by.binding('name')).getText()).toBe('world');
22138 });
22139 </file>
22140 </example>
22141 */
22142 var ngBindDirective = ['$compile', function($compile) {
22143 return {
22144 restrict: 'AC',
22145 compile: function ngBindCompile(templateElement) {
22146 $compile.$$addBindingClass(templateElement);
22147 return function ngBindLink(scope, element, attr) {
22148 $compile.$$addBindingInfo(element, attr.ngBind);
22149 element = element[0];
22150 scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
22151 element.textContent = value === undefined ? '' : value;
22152 });
22153 };
22154 }
22155 };
22156 }];
22157
22158
22159 /**
22160 * @ngdoc directive
22161 * @name ngBindTemplate
22162 *
22163 * @description
22164 * The `ngBindTemplate` directive specifies that the element
22165 * text content should be replaced with the interpolation of the template
22166 * in the `ngBindTemplate` attribute.
22167 * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
22168 * expressions. This directive is needed since some HTML elements
22169 * (such as TITLE and OPTION) cannot contain SPAN elements.
22170 *
22171 * @element ANY
22172 * @param {string} ngBindTemplate template of form
22173 * <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
22174 *
22175 * @example
22176 * Try it here: enter text in text box and watch the greeting change.
22177 <example module="bindExample">
22178 <file name="index.html">
22179 <script>
22180 angular.module('bindExample', [])
22181 .controller('ExampleController', ['$scope', function($scope) {
22182 $scope.salutation = 'Hello';
22183 $scope.name = 'World';
22184 }]);
22185 </script>
22186 <div ng-controller="ExampleController">
22187 <label>Salutation: <input type="text" ng-model="salutation"></label><br>
22188 <label>Name: <input type="text" ng-model="name"></label><br>
22189 <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
22190 </div>
22191 </file>
22192 <file name="protractor.js" type="protractor">
22193 it('should check ng-bind', function() {
22194 var salutationElem = element(by.binding('salutation'));
22195 var salutationInput = element(by.model('salutation'));
22196 var nameInput = element(by.model('name'));
22197
22198 expect(salutationElem.getText()).toBe('Hello World!');
22199
22200 salutationInput.clear();
22201 salutationInput.sendKeys('Greetings');
22202 nameInput.clear();
22203 nameInput.sendKeys('user');
22204
22205 expect(salutationElem.getText()).toBe('Greetings user!');
22206 });
22207 </file>
22208 </example>
22209 */
22210 var ngBindTemplateDirective = ['$interpolate', '$compile', function($interpolate, $compile) {
22211 return {
22212 compile: function ngBindTemplateCompile(templateElement) {
22213 $compile.$$addBindingClass(templateElement);
22214 return function ngBindTemplateLink(scope, element, attr) {
22215 var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
22216 $compile.$$addBindingInfo(element, interpolateFn.expressions);
22217 element = element[0];
22218 attr.$observe('ngBindTemplate', function(value) {
22219 element.textContent = value === undefined ? '' : value;
22220 });
22221 };
22222 }
22223 };
22224 }];
22225
22226
22227 /**
22228 * @ngdoc directive
22229 * @name ngBindHtml
22230 *
22231 * @description
22232 * Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default,
22233 * the resulting HTML content will be sanitized using the {@link ngSanitize.$sanitize $sanitize} service.
22234 * To utilize this functionality, ensure that `$sanitize` is available, for example, by including {@link
22235 * ngSanitize} in your module's dependencies (not in core Angular). In order to use {@link ngSanitize}
22236 * in your module's dependencies, you need to include "angular-sanitize.js" in your application.
22237 *
22238 * You may also bypass sanitization for values you know are safe. To do so, bind to
22239 * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}. See the example
22240 * under {@link ng.$sce#show-me-an-example-using-sce- Strict Contextual Escaping (SCE)}.
22241 *
22242 * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
22243 * will have an exception (instead of an exploit.)
22244 *
22245 * @element ANY
22246 * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
22247 *
22248 * @example
22249
22250 <example module="bindHtmlExample" deps="angular-sanitize.js">
22251 <file name="index.html">
22252 <div ng-controller="ExampleController">
22253 <p ng-bind-html="myHTML"></p>
22254 </div>
22255 </file>
22256
22257 <file name="script.js">
22258 angular.module('bindHtmlExample', ['ngSanitize'])
22259 .controller('ExampleController', ['$scope', function($scope) {
22260 $scope.myHTML =
22261 'I am an <code>HTML</code>string with ' +
22262 '<a href="#">links!</a> and other <em>stuff</em>';
22263 }]);
22264 </file>
22265
22266 <file name="protractor.js" type="protractor">
22267 it('should check ng-bind-html', function() {
22268 expect(element(by.binding('myHTML')).getText()).toBe(
22269 'I am an HTMLstring with links! and other stuff');
22270 });
22271 </file>
22272 </example>
22273 */
22274 var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) {
22275 return {
22276 restrict: 'A',
22277 compile: function ngBindHtmlCompile(tElement, tAttrs) {
22278 var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml);
22279 var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) {
22280 return (value || '').toString();
22281 });
22282 $compile.$$addBindingClass(tElement);
22283
22284 return function ngBindHtmlLink(scope, element, attr) {
22285 $compile.$$addBindingInfo(element, attr.ngBindHtml);
22286
22287 scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() {
22288 // we re-evaluate the expr because we want a TrustedValueHolderType
22289 // for $sce, not a string
22290 element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || '');
22291 });
22292 };
22293 }
22294 };
22295 }];
22296
22297 /**
22298 * @ngdoc directive
22299 * @name ngChange
22300 *
22301 * @description
22302 * Evaluate the given expression when the user changes the input.
22303 * The expression is evaluated immediately, unlike the JavaScript onchange event
22304 * which only triggers at the end of a change (usually, when the user leaves the
22305 * form element or presses the return key).
22306 *
22307 * The `ngChange` expression is only evaluated when a change in the input value causes
22308 * a new value to be committed to the model.
22309 *
22310 * It will not be evaluated:
22311 * * if the value returned from the `$parsers` transformation pipeline has not changed
22312 * * if the input has continued to be invalid since the model will stay `null`
22313 * * if the model is changed programmatically and not by a change to the input value
22314 *
22315 *
22316 * Note, this directive requires `ngModel` to be present.
22317 *
22318 * @element input
22319 * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
22320 * in input value.
22321 *
22322 * @example
22323 * <example name="ngChange-directive" module="changeExample">
22324 * <file name="index.html">
22325 * <script>
22326 * angular.module('changeExample', [])
22327 * .controller('ExampleController', ['$scope', function($scope) {
22328 * $scope.counter = 0;
22329 * $scope.change = function() {
22330 * $scope.counter++;
22331 * };
22332 * }]);
22333 * </script>
22334 * <div ng-controller="ExampleController">
22335 * <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
22336 * <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
22337 * <label for="ng-change-example2">Confirmed</label><br />
22338 * <tt>debug = {{confirmed}}</tt><br/>
22339 * <tt>counter = {{counter}}</tt><br/>
22340 * </div>
22341 * </file>
22342 * <file name="protractor.js" type="protractor">
22343 * var counter = element(by.binding('counter'));
22344 * var debug = element(by.binding('confirmed'));
22345 *
22346 * it('should evaluate the expression if changing from view', function() {
22347 * expect(counter.getText()).toContain('0');
22348 *
22349 * element(by.id('ng-change-example1')).click();
22350 *
22351 * expect(counter.getText()).toContain('1');
22352 * expect(debug.getText()).toContain('true');
22353 * });
22354 *
22355 * it('should not evaluate the expression if changing from model', function() {
22356 * element(by.id('ng-change-example2')).click();
22357
22358 * expect(counter.getText()).toContain('0');
22359 * expect(debug.getText()).toContain('true');
22360 * });
22361 * </file>
22362 * </example>
22363 */
22364 var ngChangeDirective = valueFn({
22365 restrict: 'A',
22366 require: 'ngModel',
22367 link: function(scope, element, attr, ctrl) {
22368 ctrl.$viewChangeListeners.push(function() {
22369 scope.$eval(attr.ngChange);
22370 });
22371 }
22372 });
22373
22374 function classDirective(name, selector) {
22375 name = 'ngClass' + name;
22376 return ['$animate', function($animate) {
22377 return {
22378 restrict: 'AC',
22379 link: function(scope, element, attr) {
22380 var oldVal;
22381
22382 scope.$watch(attr[name], ngClassWatchAction, true);
22383
22384 attr.$observe('class', function(value) {
22385 ngClassWatchAction(scope.$eval(attr[name]));
22386 });
22387
22388
22389 if (name !== 'ngClass') {
22390 scope.$watch('$index', function($index, old$index) {
22391 // jshint bitwise: false
22392 var mod = $index & 1;
22393 if (mod !== (old$index & 1)) {
22394 var classes = arrayClasses(scope.$eval(attr[name]));
22395 mod === selector ?
22396 addClasses(classes) :
22397 removeClasses(classes);
22398 }
22399 });
22400 }
22401
22402 function addClasses(classes) {
22403 var newClasses = digestClassCounts(classes, 1);
22404 attr.$addClass(newClasses);
22405 }
22406
22407 function removeClasses(classes) {
22408 var newClasses = digestClassCounts(classes, -1);
22409 attr.$removeClass(newClasses);
22410 }
22411
22412 function digestClassCounts(classes, count) {
22413 // Use createMap() to prevent class assumptions involving property
22414 // names in Object.prototype
22415 var classCounts = element.data('$classCounts') || createMap();
22416 var classesToUpdate = [];
22417 forEach(classes, function(className) {
22418 if (count > 0 || classCounts[className]) {
22419 classCounts[className] = (classCounts[className] || 0) + count;
22420 if (classCounts[className] === +(count > 0)) {
22421 classesToUpdate.push(className);
22422 }
22423 }
22424 });
22425 element.data('$classCounts', classCounts);
22426 return classesToUpdate.join(' ');
22427 }
22428
22429 function updateClasses(oldClasses, newClasses) {
22430 var toAdd = arrayDifference(newClasses, oldClasses);
22431 var toRemove = arrayDifference(oldClasses, newClasses);
22432 toAdd = digestClassCounts(toAdd, 1);
22433 toRemove = digestClassCounts(toRemove, -1);
22434 if (toAdd && toAdd.length) {
22435 $animate.addClass(element, toAdd);
22436 }
22437 if (toRemove && toRemove.length) {
22438 $animate.removeClass(element, toRemove);
22439 }
22440 }
22441
22442 function ngClassWatchAction(newVal) {
22443 if (selector === true || scope.$index % 2 === selector) {
22444 var newClasses = arrayClasses(newVal || []);
22445 if (!oldVal) {
22446 addClasses(newClasses);
22447 } else if (!equals(newVal,oldVal)) {
22448 var oldClasses = arrayClasses(oldVal);
22449 updateClasses(oldClasses, newClasses);
22450 }
22451 }
22452 oldVal = shallowCopy(newVal);
22453 }
22454 }
22455 };
22456
22457 function arrayDifference(tokens1, tokens2) {
22458 var values = [];
22459
22460 outer:
22461 for (var i = 0; i < tokens1.length; i++) {
22462 var token = tokens1[i];
22463 for (var j = 0; j < tokens2.length; j++) {
22464 if (token == tokens2[j]) continue outer;
22465 }
22466 values.push(token);
22467 }
22468 return values;
22469 }
22470
22471 function arrayClasses(classVal) {
22472 var classes = [];
22473 if (isArray(classVal)) {
22474 forEach(classVal, function(v) {
22475 classes = classes.concat(arrayClasses(v));
22476 });
22477 return classes;
22478 } else if (isString(classVal)) {
22479 return classVal.split(' ');
22480 } else if (isObject(classVal)) {
22481 forEach(classVal, function(v, k) {
22482 if (v) {
22483 classes = classes.concat(k.split(' '));
22484 }
22485 });
22486 return classes;
22487 }
22488 return classVal;
22489 }
22490 }];
22491 }
22492
22493 /**
22494 * @ngdoc directive
22495 * @name ngClass
22496 * @restrict AC
22497 *
22498 * @description
22499 * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
22500 * an expression that represents all classes to be added.
22501 *
22502 * The directive operates in three different ways, depending on which of three types the expression
22503 * evaluates to:
22504 *
22505 * 1. If the expression evaluates to a string, the string should be one or more space-delimited class
22506 * names.
22507 *
22508 * 2. If the expression evaluates to an object, then for each key-value pair of the
22509 * object with a truthy value the corresponding key is used as a class name.
22510 *
22511 * 3. If the expression evaluates to an array, each element of the array should either be a string as in
22512 * type 1 or an object as in type 2. This means that you can mix strings and objects together in an array
22513 * to give you more control over what CSS classes appear. See the code below for an example of this.
22514 *
22515 *
22516 * The directive won't add duplicate classes if a particular class was already set.
22517 *
22518 * When the expression changes, the previously added classes are removed and only then are the
22519 * new classes added.
22520 *
22521 * @animations
22522 * **add** - happens just before the class is applied to the elements
22523 *
22524 * **remove** - happens just before the class is removed from the element
22525 *
22526 * @element ANY
22527 * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
22528 * of the evaluation can be a string representing space delimited class
22529 * names, an array, or a map of class names to boolean values. In the case of a map, the
22530 * names of the properties whose values are truthy will be added as css classes to the
22531 * element.
22532 *
22533 * @example Example that demonstrates basic bindings via ngClass directive.
22534 <example>
22535 <file name="index.html">
22536 <p ng-class="{strike: deleted, bold: important, 'has-error': error}">Map Syntax Example</p>
22537 <label>
22538 <input type="checkbox" ng-model="deleted">
22539 deleted (apply "strike" class)
22540 </label><br>
22541 <label>
22542 <input type="checkbox" ng-model="important">
22543 important (apply "bold" class)
22544 </label><br>
22545 <label>
22546 <input type="checkbox" ng-model="error">
22547 error (apply "has-error" class)
22548 </label>
22549 <hr>
22550 <p ng-class="style">Using String Syntax</p>
22551 <input type="text" ng-model="style"
22552 placeholder="Type: bold strike red" aria-label="Type: bold strike red">
22553 <hr>
22554 <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
22555 <input ng-model="style1"
22556 placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red"><br>
22557 <input ng-model="style2"
22558 placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 2"><br>
22559 <input ng-model="style3"
22560 placeholder="Type: bold, strike or red" aria-label="Type: bold, strike or red 3"><br>
22561 <hr>
22562 <p ng-class="[style4, {orange: warning}]">Using Array and Map Syntax</p>
22563 <input ng-model="style4" placeholder="Type: bold, strike" aria-label="Type: bold, strike"><br>
22564 <label><input type="checkbox" ng-model="warning"> warning (apply "orange" class)</label>
22565 </file>
22566 <file name="style.css">
22567 .strike {
22568 text-decoration: line-through;
22569 }
22570 .bold {
22571 font-weight: bold;
22572 }
22573 .red {
22574 color: red;
22575 }
22576 .has-error {
22577 color: red;
22578 background-color: yellow;
22579 }
22580 .orange {
22581 color: orange;
22582 }
22583 </file>
22584 <file name="protractor.js" type="protractor">
22585 var ps = element.all(by.css('p'));
22586
22587 it('should let you toggle the class', function() {
22588
22589 expect(ps.first().getAttribute('class')).not.toMatch(/bold/);
22590 expect(ps.first().getAttribute('class')).not.toMatch(/has-error/);
22591
22592 element(by.model('important')).click();
22593 expect(ps.first().getAttribute('class')).toMatch(/bold/);
22594
22595 element(by.model('error')).click();
22596 expect(ps.first().getAttribute('class')).toMatch(/has-error/);
22597 });
22598
22599 it('should let you toggle string example', function() {
22600 expect(ps.get(1).getAttribute('class')).toBe('');
22601 element(by.model('style')).clear();
22602 element(by.model('style')).sendKeys('red');
22603 expect(ps.get(1).getAttribute('class')).toBe('red');
22604 });
22605
22606 it('array example should have 3 classes', function() {
22607 expect(ps.get(2).getAttribute('class')).toBe('');
22608 element(by.model('style1')).sendKeys('bold');
22609 element(by.model('style2')).sendKeys('strike');
22610 element(by.model('style3')).sendKeys('red');
22611 expect(ps.get(2).getAttribute('class')).toBe('bold strike red');
22612 });
22613
22614 it('array with map example should have 2 classes', function() {
22615 expect(ps.last().getAttribute('class')).toBe('');
22616 element(by.model('style4')).sendKeys('bold');
22617 element(by.model('warning')).click();
22618 expect(ps.last().getAttribute('class')).toBe('bold orange');
22619 });
22620 </file>
22621 </example>
22622
22623 ## Animations
22624
22625 The example below demonstrates how to perform animations using ngClass.
22626
22627 <example module="ngAnimate" deps="angular-animate.js" animations="true">
22628 <file name="index.html">
22629 <input id="setbtn" type="button" value="set" ng-click="myVar='my-class'">
22630 <input id="clearbtn" type="button" value="clear" ng-click="myVar=''">
22631 <br>
22632 <span class="base-class" ng-class="myVar">Sample Text</span>
22633 </file>
22634 <file name="style.css">
22635 .base-class {
22636 -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
22637 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
22638 }
22639
22640 .base-class.my-class {
22641 color: red;
22642 font-size:3em;
22643 }
22644 </file>
22645 <file name="protractor.js" type="protractor">
22646 it('should check ng-class', function() {
22647 expect(element(by.css('.base-class')).getAttribute('class')).not.
22648 toMatch(/my-class/);
22649
22650 element(by.id('setbtn')).click();
22651
22652 expect(element(by.css('.base-class')).getAttribute('class')).
22653 toMatch(/my-class/);
22654
22655 element(by.id('clearbtn')).click();
22656
22657 expect(element(by.css('.base-class')).getAttribute('class')).not.
22658 toMatch(/my-class/);
22659 });
22660 </file>
22661 </example>
22662
22663
22664 ## ngClass and pre-existing CSS3 Transitions/Animations
22665 The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
22666 Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
22667 any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
22668 to view the step by step details of {@link $animate#addClass $animate.addClass} and
22669 {@link $animate#removeClass $animate.removeClass}.
22670 */
22671 var ngClassDirective = classDirective('', true);
22672
22673 /**
22674 * @ngdoc directive
22675 * @name ngClassOdd
22676 * @restrict AC
22677 *
22678 * @description
22679 * The `ngClassOdd` and `ngClassEven` directives work exactly as
22680 * {@link ng.directive:ngClass ngClass}, except they work in
22681 * conjunction with `ngRepeat` and take effect only on odd (even) rows.
22682 *
22683 * This directive can be applied only within the scope of an
22684 * {@link ng.directive:ngRepeat ngRepeat}.
22685 *
22686 * @element ANY
22687 * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
22688 * of the evaluation can be a string representing space delimited class names or an array.
22689 *
22690 * @example
22691 <example>
22692 <file name="index.html">
22693 <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
22694 <li ng-repeat="name in names">
22695 <span ng-class-odd="'odd'" ng-class-even="'even'">
22696 {{name}}
22697 </span>
22698 </li>
22699 </ol>
22700 </file>
22701 <file name="style.css">
22702 .odd {
22703 color: red;
22704 }
22705 .even {
22706 color: blue;
22707 }
22708 </file>
22709 <file name="protractor.js" type="protractor">
22710 it('should check ng-class-odd and ng-class-even', function() {
22711 expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
22712 toMatch(/odd/);
22713 expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
22714 toMatch(/even/);
22715 });
22716 </file>
22717 </example>
22718 */
22719 var ngClassOddDirective = classDirective('Odd', 0);
22720
22721 /**
22722 * @ngdoc directive
22723 * @name ngClassEven
22724 * @restrict AC
22725 *
22726 * @description
22727 * The `ngClassOdd` and `ngClassEven` directives work exactly as
22728 * {@link ng.directive:ngClass ngClass}, except they work in
22729 * conjunction with `ngRepeat` and take effect only on odd (even) rows.
22730 *
22731 * This directive can be applied only within the scope of an
22732 * {@link ng.directive:ngRepeat ngRepeat}.
22733 *
22734 * @element ANY
22735 * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
22736 * result of the evaluation can be a string representing space delimited class names or an array.
22737 *
22738 * @example
22739 <example>
22740 <file name="index.html">
22741 <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
22742 <li ng-repeat="name in names">
22743 <span ng-class-odd="'odd'" ng-class-even="'even'">
22744 {{name}} &nbsp; &nbsp; &nbsp;
22745 </span>
22746 </li>
22747 </ol>
22748 </file>
22749 <file name="style.css">
22750 .odd {
22751 color: red;
22752 }
22753 .even {
22754 color: blue;
22755 }
22756 </file>
22757 <file name="protractor.js" type="protractor">
22758 it('should check ng-class-odd and ng-class-even', function() {
22759 expect(element(by.repeater('name in names').row(0).column('name')).getAttribute('class')).
22760 toMatch(/odd/);
22761 expect(element(by.repeater('name in names').row(1).column('name')).getAttribute('class')).
22762 toMatch(/even/);
22763 });
22764 </file>
22765 </example>
22766 */
22767 var ngClassEvenDirective = classDirective('Even', 1);
22768
22769 /**
22770 * @ngdoc directive
22771 * @name ngCloak
22772 * @restrict AC
22773 *
22774 * @description
22775 * The `ngCloak` directive is used to prevent the Angular html template from being briefly
22776 * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
22777 * directive to avoid the undesirable flicker effect caused by the html template display.
22778 *
22779 * The directive can be applied to the `<body>` element, but the preferred usage is to apply
22780 * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
22781 * of the browser view.
22782 *
22783 * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
22784 * `angular.min.js`.
22785 * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
22786 *
22787 * ```css
22788 * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
22789 * display: none !important;
22790 * }
22791 * ```
22792 *
22793 * When this css rule is loaded by the browser, all html elements (including their children) that
22794 * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
22795 * during the compilation of the template it deletes the `ngCloak` element attribute, making
22796 * the compiled element visible.
22797 *
22798 * For the best result, the `angular.js` script must be loaded in the head section of the html
22799 * document; alternatively, the css rule above must be included in the external stylesheet of the
22800 * application.
22801 *
22802 * @element ANY
22803 *
22804 * @example
22805 <example>
22806 <file name="index.html">
22807 <div id="template1" ng-cloak>{{ 'hello' }}</div>
22808 <div id="template2" class="ng-cloak">{{ 'world' }}</div>
22809 </file>
22810 <file name="protractor.js" type="protractor">
22811 it('should remove the template directive and css class', function() {
22812 expect($('#template1').getAttribute('ng-cloak')).
22813 toBeNull();
22814 expect($('#template2').getAttribute('ng-cloak')).
22815 toBeNull();
22816 });
22817 </file>
22818 </example>
22819 *
22820 */
22821 var ngCloakDirective = ngDirective({
22822 compile: function(element, attr) {
22823 attr.$set('ngCloak', undefined);
22824 element.removeClass('ng-cloak');
22825 }
22826 });
22827
22828 /**
22829 * @ngdoc directive
22830 * @name ngController
22831 *
22832 * @description
22833 * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
22834 * supports the principles behind the Model-View-Controller design pattern.
22835 *
22836 * MVC components in angular:
22837 *
22838 * * Model — Models are the properties of a scope; scopes are attached to the DOM where scope properties
22839 * are accessed through bindings.
22840 * * View — The template (HTML with data bindings) that is rendered into the View.
22841 * * Controller — The `ngController` directive specifies a Controller class; the class contains business
22842 * logic behind the application to decorate the scope with functions and values
22843 *
22844 * Note that you can also attach controllers to the DOM by declaring it in a route definition
22845 * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
22846 * again using `ng-controller` in the template itself. This will cause the controller to be attached
22847 * and executed twice.
22848 *
22849 * @element ANY
22850 * @scope
22851 * @priority 500
22852 * @param {expression} ngController Name of a constructor function registered with the current
22853 * {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}
22854 * that on the current scope evaluates to a constructor function.
22855 *
22856 * The controller instance can be published into a scope property by specifying
22857 * `ng-controller="as propertyName"`.
22858 *
22859 * If the current `$controllerProvider` is configured to use globals (via
22860 * {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
22861 * also be the name of a globally accessible constructor function (not recommended).
22862 *
22863 * @example
22864 * Here is a simple form for editing user contact information. Adding, removing, clearing, and
22865 * greeting are methods declared on the controller (see source tab). These methods can
22866 * easily be called from the angular markup. Any changes to the data are automatically reflected
22867 * in the View without the need for a manual update.
22868 *
22869 * Two different declaration styles are included below:
22870 *
22871 * * one binds methods and properties directly onto the controller using `this`:
22872 * `ng-controller="SettingsController1 as settings"`
22873 * * one injects `$scope` into the controller:
22874 * `ng-controller="SettingsController2"`
22875 *
22876 * The second option is more common in the Angular community, and is generally used in boilerplates
22877 * and in this guide. However, there are advantages to binding properties directly to the controller
22878 * and avoiding scope.
22879 *
22880 * * Using `controller as` makes it obvious which controller you are accessing in the template when
22881 * multiple controllers apply to an element.
22882 * * If you are writing your controllers as classes you have easier access to the properties and
22883 * methods, which will appear on the scope, from inside the controller code.
22884 * * Since there is always a `.` in the bindings, you don't have to worry about prototypal
22885 * inheritance masking primitives.
22886 *
22887 * This example demonstrates the `controller as` syntax.
22888 *
22889 * <example name="ngControllerAs" module="controllerAsExample">
22890 * <file name="index.html">
22891 * <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
22892 * <label>Name: <input type="text" ng-model="settings.name"/></label>
22893 * <button ng-click="settings.greet()">greet</button><br/>
22894 * Contact:
22895 * <ul>
22896 * <li ng-repeat="contact in settings.contacts">
22897 * <select ng-model="contact.type" aria-label="Contact method" id="select_{{$index}}">
22898 * <option>phone</option>
22899 * <option>email</option>
22900 * </select>
22901 * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
22902 * <button ng-click="settings.clearContact(contact)">clear</button>
22903 * <button ng-click="settings.removeContact(contact)" aria-label="Remove">X</button>
22904 * </li>
22905 * <li><button ng-click="settings.addContact()">add</button></li>
22906 * </ul>
22907 * </div>
22908 * </file>
22909 * <file name="app.js">
22910 * angular.module('controllerAsExample', [])
22911 * .controller('SettingsController1', SettingsController1);
22912 *
22913 * function SettingsController1() {
22914 * this.name = "John Smith";
22915 * this.contacts = [
22916 * {type: 'phone', value: '408 555 1212'},
22917 * {type: 'email', value: '[email protected]'} ];
22918 * }
22919 *
22920 * SettingsController1.prototype.greet = function() {
22921 * alert(this.name);
22922 * };
22923 *
22924 * SettingsController1.prototype.addContact = function() {
22925 * this.contacts.push({type: 'email', value: '[email protected]'});
22926 * };
22927 *
22928 * SettingsController1.prototype.removeContact = function(contactToRemove) {
22929 * var index = this.contacts.indexOf(contactToRemove);
22930 * this.contacts.splice(index, 1);
22931 * };
22932 *
22933 * SettingsController1.prototype.clearContact = function(contact) {
22934 * contact.type = 'phone';
22935 * contact.value = '';
22936 * };
22937 * </file>
22938 * <file name="protractor.js" type="protractor">
22939 * it('should check controller as', function() {
22940 * var container = element(by.id('ctrl-as-exmpl'));
22941 * expect(container.element(by.model('settings.name'))
22942 * .getAttribute('value')).toBe('John Smith');
22943 *
22944 * var firstRepeat =
22945 * container.element(by.repeater('contact in settings.contacts').row(0));
22946 * var secondRepeat =
22947 * container.element(by.repeater('contact in settings.contacts').row(1));
22948 *
22949 * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
22950 * .toBe('408 555 1212');
22951 *
22952 * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
22953 * .toBe('[email protected]');
22954 *
22955 * firstRepeat.element(by.buttonText('clear')).click();
22956 *
22957 * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
22958 * .toBe('');
22959 *
22960 * container.element(by.buttonText('add')).click();
22961 *
22962 * expect(container.element(by.repeater('contact in settings.contacts').row(2))
22963 * .element(by.model('contact.value'))
22964 * .getAttribute('value'))
22965 * .toBe('[email protected]');
22966 * });
22967 * </file>
22968 * </example>
22969 *
22970 * This example demonstrates the "attach to `$scope`" style of controller.
22971 *
22972 * <example name="ngController" module="controllerExample">
22973 * <file name="index.html">
22974 * <div id="ctrl-exmpl" ng-controller="SettingsController2">
22975 * <label>Name: <input type="text" ng-model="name"/></label>
22976 * <button ng-click="greet()">greet</button><br/>
22977 * Contact:
22978 * <ul>
22979 * <li ng-repeat="contact in contacts">
22980 * <select ng-model="contact.type" id="select_{{$index}}">
22981 * <option>phone</option>
22982 * <option>email</option>
22983 * </select>
22984 * <input type="text" ng-model="contact.value" aria-labelledby="select_{{$index}}" />
22985 * <button ng-click="clearContact(contact)">clear</button>
22986 * <button ng-click="removeContact(contact)">X</button>
22987 * </li>
22988 * <li>[ <button ng-click="addContact()">add</button> ]</li>
22989 * </ul>
22990 * </div>
22991 * </file>
22992 * <file name="app.js">
22993 * angular.module('controllerExample', [])
22994 * .controller('SettingsController2', ['$scope', SettingsController2]);
22995 *
22996 * function SettingsController2($scope) {
22997 * $scope.name = "John Smith";
22998 * $scope.contacts = [
22999 * {type:'phone', value:'408 555 1212'},
23000 * {type:'email', value:'[email protected]'} ];
23001 *
23002 * $scope.greet = function() {
23003 * alert($scope.name);
23004 * };
23005 *
23006 * $scope.addContact = function() {
23007 * $scope.contacts.push({type:'email', value:'[email protected]'});
23008 * };
23009 *
23010 * $scope.removeContact = function(contactToRemove) {
23011 * var index = $scope.contacts.indexOf(contactToRemove);
23012 * $scope.contacts.splice(index, 1);
23013 * };
23014 *
23015 * $scope.clearContact = function(contact) {
23016 * contact.type = 'phone';
23017 * contact.value = '';
23018 * };
23019 * }
23020 * </file>
23021 * <file name="protractor.js" type="protractor">
23022 * it('should check controller', function() {
23023 * var container = element(by.id('ctrl-exmpl'));
23024 *
23025 * expect(container.element(by.model('name'))
23026 * .getAttribute('value')).toBe('John Smith');
23027 *
23028 * var firstRepeat =
23029 * container.element(by.repeater('contact in contacts').row(0));
23030 * var secondRepeat =
23031 * container.element(by.repeater('contact in contacts').row(1));
23032 *
23033 * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
23034 * .toBe('408 555 1212');
23035 * expect(secondRepeat.element(by.model('contact.value')).getAttribute('value'))
23036 * .toBe('[email protected]');
23037 *
23038 * firstRepeat.element(by.buttonText('clear')).click();
23039 *
23040 * expect(firstRepeat.element(by.model('contact.value')).getAttribute('value'))
23041 * .toBe('');
23042 *
23043 * container.element(by.buttonText('add')).click();
23044 *
23045 * expect(container.element(by.repeater('contact in contacts').row(2))
23046 * .element(by.model('contact.value'))
23047 * .getAttribute('value'))
23048 * .toBe('[email protected]');
23049 * });
23050 * </file>
23051 *</example>
23052
23053 */
23054 var ngControllerDirective = [function() {
23055 return {
23056 restrict: 'A',
23057 scope: true,
23058 controller: '@',
23059 priority: 500
23060 };
23061 }];
23062
23063 /**
23064 * @ngdoc directive
23065 * @name ngCsp
23066 *
23067 * @element html
23068 * @description
23069 * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
23070 *
23071 * This is necessary when developing things like Google Chrome Extensions or Universal Windows Apps.
23072 *
23073 * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
23074 * For Angular to be CSP compatible there are only two things that we need to do differently:
23075 *
23076 * - don't use `Function` constructor to generate optimized value getters
23077 * - don't inject custom stylesheet into the document
23078 *
23079 * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
23080 * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
23081 * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
23082 * be raised.
23083 *
23084 * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
23085 * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
23086 * To make those directives work in CSP mode, include the `angular-csp.css` manually.
23087 *
23088 * Angular tries to autodetect if CSP is active and automatically turn on the CSP-safe mode. This
23089 * autodetection however triggers a CSP error to be logged in the console:
23090 *
23091 * ```
23092 * Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of
23093 * script in the following Content Security Policy directive: "default-src 'self'". Note that
23094 * 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
23095 * ```
23096 *
23097 * This error is harmless but annoying. To prevent the error from showing up, put the `ngCsp`
23098 * directive on the root element of the application or on the `angular.js` script tag, whichever
23099 * appears first in the html document.
23100 *
23101 * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
23102 *
23103 * @example
23104 * This example shows how to apply the `ngCsp` directive to the `html` tag.
23105 ```html
23106 <!doctype html>
23107 <html ng-app ng-csp>
23108 ...
23109 ...
23110 </html>
23111 ```
23112 * @example
23113 // Note: the suffix `.csp` in the example name triggers
23114 // csp mode in our http server!
23115 <example name="example.csp" module="cspExample" ng-csp="true">
23116 <file name="index.html">
23117 <div ng-controller="MainController as ctrl">
23118 <div>
23119 <button ng-click="ctrl.inc()" id="inc">Increment</button>
23120 <span id="counter">
23121 {{ctrl.counter}}
23122 </span>
23123 </div>
23124
23125 <div>
23126 <button ng-click="ctrl.evil()" id="evil">Evil</button>
23127 <span id="evilError">
23128 {{ctrl.evilError}}
23129 </span>
23130 </div>
23131 </div>
23132 </file>
23133 <file name="script.js">
23134 angular.module('cspExample', [])
23135 .controller('MainController', function() {
23136 this.counter = 0;
23137 this.inc = function() {
23138 this.counter++;
23139 };
23140 this.evil = function() {
23141 // jshint evil:true
23142 try {
23143 eval('1+2');
23144 } catch (e) {
23145 this.evilError = e.message;
23146 }
23147 };
23148 });
23149 </file>
23150 <file name="protractor.js" type="protractor">
23151 var util, webdriver;
23152
23153 var incBtn = element(by.id('inc'));
23154 var counter = element(by.id('counter'));
23155 var evilBtn = element(by.id('evil'));
23156 var evilError = element(by.id('evilError'));
23157
23158 function getAndClearSevereErrors() {
23159 return browser.manage().logs().get('browser').then(function(browserLog) {
23160 return browserLog.filter(function(logEntry) {
23161 return logEntry.level.value > webdriver.logging.Level.WARNING.value;
23162 });
23163 });
23164 }
23165
23166 function clearErrors() {
23167 getAndClearSevereErrors();
23168 }
23169
23170 function expectNoErrors() {
23171 getAndClearSevereErrors().then(function(filteredLog) {
23172 expect(filteredLog.length).toEqual(0);
23173 if (filteredLog.length) {
23174 console.log('browser console errors: ' + util.inspect(filteredLog));
23175 }
23176 });
23177 }
23178
23179 function expectError(regex) {
23180 getAndClearSevereErrors().then(function(filteredLog) {
23181 var found = false;
23182 filteredLog.forEach(function(log) {
23183 if (log.message.match(regex)) {
23184 found = true;
23185 }
23186 });
23187 if (!found) {
23188 throw new Error('expected an error that matches ' + regex);
23189 }
23190 });
23191 }
23192
23193 beforeEach(function() {
23194 util = require('util');
23195 webdriver = require('protractor/node_modules/selenium-webdriver');
23196 });
23197
23198 // For now, we only test on Chrome,
23199 // as Safari does not load the page with Protractor's injected scripts,
23200 // and Firefox webdriver always disables content security policy (#6358)
23201 if (browser.params.browser !== 'chrome') {
23202 return;
23203 }
23204
23205 it('should not report errors when the page is loaded', function() {
23206 // clear errors so we are not dependent on previous tests
23207 clearErrors();
23208 // Need to reload the page as the page is already loaded when
23209 // we come here
23210 browser.driver.getCurrentUrl().then(function(url) {
23211 browser.get(url);
23212 });
23213 expectNoErrors();
23214 });
23215
23216 it('should evaluate expressions', function() {
23217 expect(counter.getText()).toEqual('0');
23218 incBtn.click();
23219 expect(counter.getText()).toEqual('1');
23220 expectNoErrors();
23221 });
23222
23223 it('should throw and report an error when using "eval"', function() {
23224 evilBtn.click();
23225 expect(evilError.getText()).toMatch(/Content Security Policy/);
23226 expectError(/Content Security Policy/);
23227 });
23228 </file>
23229 </example>
23230 */
23231
23232 // ngCsp is not implemented as a proper directive any more, because we need it be processed while we
23233 // bootstrap the system (before $parse is instantiated), for this reason we just have
23234 // the csp.isActive() fn that looks for ng-csp attribute anywhere in the current doc
23235
23236 /**
23237 * @ngdoc directive
23238 * @name ngClick
23239 *
23240 * @description
23241 * The ngClick directive allows you to specify custom behavior when
23242 * an element is clicked.
23243 *
23244 * @element ANY
23245 * @priority 0
23246 * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
23247 * click. ({@link guide/expression#-event- Event object is available as `$event`})
23248 *
23249 * @example
23250 <example>
23251 <file name="index.html">
23252 <button ng-click="count = count + 1" ng-init="count=0">
23253 Increment
23254 </button>
23255 <span>
23256 count: {{count}}
23257 </span>
23258 </file>
23259 <file name="protractor.js" type="protractor">
23260 it('should check ng-click', function() {
23261 expect(element(by.binding('count')).getText()).toMatch('0');
23262 element(by.css('button')).click();
23263 expect(element(by.binding('count')).getText()).toMatch('1');
23264 });
23265 </file>
23266 </example>
23267 */
23268 /*
23269 * A collection of directives that allows creation of custom event handlers that are defined as
23270 * angular expressions and are compiled and executed within the current scope.
23271 */
23272 var ngEventDirectives = {};
23273
23274 // For events that might fire synchronously during DOM manipulation
23275 // we need to execute their event handlers asynchronously using $evalAsync,
23276 // so that they are not executed in an inconsistent state.
23277 var forceAsyncEvents = {
23278 'blur': true,
23279 'focus': true
23280 };
23281 forEach(
23282 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
23283 function(eventName) {
23284 var directiveName = directiveNormalize('ng-' + eventName);
23285 ngEventDirectives[directiveName] = ['$parse', '$rootScope', function($parse, $rootScope) {
23286 return {
23287 restrict: 'A',
23288 compile: function($element, attr) {
23289 // We expose the powerful $event object on the scope that provides access to the Window,
23290 // etc. that isn't protected by the fast paths in $parse. We explicitly request better
23291 // checks at the cost of speed since event handler expressions are not executed as
23292 // frequently as regular change detection.
23293 var fn = $parse(attr[directiveName], /* interceptorFn */ null, /* expensiveChecks */ true);
23294 return function ngEventHandler(scope, element) {
23295 element.on(eventName, function(event) {
23296 var callback = function() {
23297 fn(scope, {$event:event});
23298 };
23299 if (forceAsyncEvents[eventName] && $rootScope.$$phase) {
23300 scope.$evalAsync(callback);
23301 } else {
23302 scope.$apply(callback);
23303 }
23304 });
23305 };
23306 }
23307 };
23308 }];
23309 }
23310 );
23311
23312 /**
23313 * @ngdoc directive
23314 * @name ngDblclick
23315 *
23316 * @description
23317 * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
23318 *
23319 * @element ANY
23320 * @priority 0
23321 * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
23322 * a dblclick. (The Event object is available as `$event`)
23323 *
23324 * @example
23325 <example>
23326 <file name="index.html">
23327 <button ng-dblclick="count = count + 1" ng-init="count=0">
23328 Increment (on double click)
23329 </button>
23330 count: {{count}}
23331 </file>
23332 </example>
23333 */
23334
23335
23336 /**
23337 * @ngdoc directive
23338 * @name ngMousedown
23339 *
23340 * @description
23341 * The ngMousedown directive allows you to specify custom behavior on mousedown event.
23342 *
23343 * @element ANY
23344 * @priority 0
23345 * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
23346 * mousedown. ({@link guide/expression#-event- Event object is available as `$event`})
23347 *
23348 * @example
23349 <example>
23350 <file name="index.html">
23351 <button ng-mousedown="count = count + 1" ng-init="count=0">
23352 Increment (on mouse down)
23353 </button>
23354 count: {{count}}
23355 </file>
23356 </example>
23357 */
23358
23359
23360 /**
23361 * @ngdoc directive
23362 * @name ngMouseup
23363 *
23364 * @description
23365 * Specify custom behavior on mouseup event.
23366 *
23367 * @element ANY
23368 * @priority 0
23369 * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
23370 * mouseup. ({@link guide/expression#-event- Event object is available as `$event`})
23371 *
23372 * @example
23373 <example>
23374 <file name="index.html">
23375 <button ng-mouseup="count = count + 1" ng-init="count=0">
23376 Increment (on mouse up)
23377 </button>
23378 count: {{count}}
23379 </file>
23380 </example>
23381 */
23382
23383 /**
23384 * @ngdoc directive
23385 * @name ngMouseover
23386 *
23387 * @description
23388 * Specify custom behavior on mouseover event.
23389 *
23390 * @element ANY
23391 * @priority 0
23392 * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
23393 * mouseover. ({@link guide/expression#-event- Event object is available as `$event`})
23394 *
23395 * @example
23396 <example>
23397 <file name="index.html">
23398 <button ng-mouseover="count = count + 1" ng-init="count=0">
23399 Increment (when mouse is over)
23400 </button>
23401 count: {{count}}
23402 </file>
23403 </example>
23404 */
23405
23406
23407 /**
23408 * @ngdoc directive
23409 * @name ngMouseenter
23410 *
23411 * @description
23412 * Specify custom behavior on mouseenter event.
23413 *
23414 * @element ANY
23415 * @priority 0
23416 * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
23417 * mouseenter. ({@link guide/expression#-event- Event object is available as `$event`})
23418 *
23419 * @example
23420 <example>
23421 <file name="index.html">
23422 <button ng-mouseenter="count = count + 1" ng-init="count=0">
23423 Increment (when mouse enters)
23424 </button>
23425 count: {{count}}
23426 </file>
23427 </example>
23428 */
23429
23430
23431 /**
23432 * @ngdoc directive
23433 * @name ngMouseleave
23434 *
23435 * @description
23436 * Specify custom behavior on mouseleave event.
23437 *
23438 * @element ANY
23439 * @priority 0
23440 * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
23441 * mouseleave. ({@link guide/expression#-event- Event object is available as `$event`})
23442 *
23443 * @example
23444 <example>
23445 <file name="index.html">
23446 <button ng-mouseleave="count = count + 1" ng-init="count=0">
23447 Increment (when mouse leaves)
23448 </button>
23449 count: {{count}}
23450 </file>
23451 </example>
23452 */
23453
23454
23455 /**
23456 * @ngdoc directive
23457 * @name ngMousemove
23458 *
23459 * @description
23460 * Specify custom behavior on mousemove event.
23461 *
23462 * @element ANY
23463 * @priority 0
23464 * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
23465 * mousemove. ({@link guide/expression#-event- Event object is available as `$event`})
23466 *
23467 * @example
23468 <example>
23469 <file name="index.html">
23470 <button ng-mousemove="count = count + 1" ng-init="count=0">
23471 Increment (when mouse moves)
23472 </button>
23473 count: {{count}}
23474 </file>
23475 </example>
23476 */
23477
23478
23479 /**
23480 * @ngdoc directive
23481 * @name ngKeydown
23482 *
23483 * @description
23484 * Specify custom behavior on keydown event.
23485 *
23486 * @element ANY
23487 * @priority 0
23488 * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
23489 * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
23490 *
23491 * @example
23492 <example>
23493 <file name="index.html">
23494 <input ng-keydown="count = count + 1" ng-init="count=0">
23495 key down count: {{count}}
23496 </file>
23497 </example>
23498 */
23499
23500
23501 /**
23502 * @ngdoc directive
23503 * @name ngKeyup
23504 *
23505 * @description
23506 * Specify custom behavior on keyup event.
23507 *
23508 * @element ANY
23509 * @priority 0
23510 * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
23511 * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
23512 *
23513 * @example
23514 <example>
23515 <file name="index.html">
23516 <p>Typing in the input box below updates the key count</p>
23517 <input ng-keyup="count = count + 1" ng-init="count=0"> key up count: {{count}}
23518
23519 <p>Typing in the input box below updates the keycode</p>
23520 <input ng-keyup="event=$event">
23521 <p>event keyCode: {{ event.keyCode }}</p>
23522 <p>event altKey: {{ event.altKey }}</p>
23523 </file>
23524 </example>
23525 */
23526
23527
23528 /**
23529 * @ngdoc directive
23530 * @name ngKeypress
23531 *
23532 * @description
23533 * Specify custom behavior on keypress event.
23534 *
23535 * @element ANY
23536 * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
23537 * keypress. ({@link guide/expression#-event- Event object is available as `$event`}
23538 * and can be interrogated for keyCode, altKey, etc.)
23539 *
23540 * @example
23541 <example>
23542 <file name="index.html">
23543 <input ng-keypress="count = count + 1" ng-init="count=0">
23544 key press count: {{count}}
23545 </file>
23546 </example>
23547 */
23548
23549
23550 /**
23551 * @ngdoc directive
23552 * @name ngSubmit
23553 *
23554 * @description
23555 * Enables binding angular expressions to onsubmit events.
23556 *
23557 * Additionally it prevents the default action (which for form means sending the request to the
23558 * server and reloading the current page), but only if the form does not contain `action`,
23559 * `data-action`, or `x-action` attributes.
23560 *
23561 * <div class="alert alert-warning">
23562 * **Warning:** Be careful not to cause "double-submission" by using both the `ngClick` and
23563 * `ngSubmit` handlers together. See the
23564 * {@link form#submitting-a-form-and-preventing-the-default-action `form` directive documentation}
23565 * for a detailed discussion of when `ngSubmit` may be triggered.
23566 * </div>
23567 *
23568 * @element form
23569 * @priority 0
23570 * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
23571 * ({@link guide/expression#-event- Event object is available as `$event`})
23572 *
23573 * @example
23574 <example module="submitExample">
23575 <file name="index.html">
23576 <script>
23577 angular.module('submitExample', [])
23578 .controller('ExampleController', ['$scope', function($scope) {
23579 $scope.list = [];
23580 $scope.text = 'hello';
23581 $scope.submit = function() {
23582 if ($scope.text) {
23583 $scope.list.push(this.text);
23584 $scope.text = '';
23585 }
23586 };
23587 }]);
23588 </script>
23589 <form ng-submit="submit()" ng-controller="ExampleController">
23590 Enter text and hit enter:
23591 <input type="text" ng-model="text" name="text" />
23592 <input type="submit" id="submit" value="Submit" />
23593 <pre>list={{list}}</pre>
23594 </form>
23595 </file>
23596 <file name="protractor.js" type="protractor">
23597 it('should check ng-submit', function() {
23598 expect(element(by.binding('list')).getText()).toBe('list=[]');
23599 element(by.css('#submit')).click();
23600 expect(element(by.binding('list')).getText()).toContain('hello');
23601 expect(element(by.model('text')).getAttribute('value')).toBe('');
23602 });
23603 it('should ignore empty strings', function() {
23604 expect(element(by.binding('list')).getText()).toBe('list=[]');
23605 element(by.css('#submit')).click();
23606 element(by.css('#submit')).click();
23607 expect(element(by.binding('list')).getText()).toContain('hello');
23608 });
23609 </file>
23610 </example>
23611 */
23612
23613 /**
23614 * @ngdoc directive
23615 * @name ngFocus
23616 *
23617 * @description
23618 * Specify custom behavior on focus event.
23619 *
23620 * Note: As the `focus` event is executed synchronously when calling `input.focus()`
23621 * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
23622 * during an `$apply` to ensure a consistent state.
23623 *
23624 * @element window, input, select, textarea, a
23625 * @priority 0
23626 * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
23627 * focus. ({@link guide/expression#-event- Event object is available as `$event`})
23628 *
23629 * @example
23630 * See {@link ng.directive:ngClick ngClick}
23631 */
23632
23633 /**
23634 * @ngdoc directive
23635 * @name ngBlur
23636 *
23637 * @description
23638 * Specify custom behavior on blur event.
23639 *
23640 * A [blur event](https://developer.mozilla.org/en-US/docs/Web/Events/blur) fires when
23641 * an element has lost focus.
23642 *
23643 * Note: As the `blur` event is executed synchronously also during DOM manipulations
23644 * (e.g. removing a focussed input),
23645 * AngularJS executes the expression using `scope.$evalAsync` if the event is fired
23646 * during an `$apply` to ensure a consistent state.
23647 *
23648 * @element window, input, select, textarea, a
23649 * @priority 0
23650 * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
23651 * blur. ({@link guide/expression#-event- Event object is available as `$event`})
23652 *
23653 * @example
23654 * See {@link ng.directive:ngClick ngClick}
23655 */
23656
23657 /**
23658 * @ngdoc directive
23659 * @name ngCopy
23660 *
23661 * @description
23662 * Specify custom behavior on copy event.
23663 *
23664 * @element window, input, select, textarea, a
23665 * @priority 0
23666 * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
23667 * copy. ({@link guide/expression#-event- Event object is available as `$event`})
23668 *
23669 * @example
23670 <example>
23671 <file name="index.html">
23672 <input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
23673 copied: {{copied}}
23674 </file>
23675 </example>
23676 */
23677
23678 /**
23679 * @ngdoc directive
23680 * @name ngCut
23681 *
23682 * @description
23683 * Specify custom behavior on cut event.
23684 *
23685 * @element window, input, select, textarea, a
23686 * @priority 0
23687 * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
23688 * cut. ({@link guide/expression#-event- Event object is available as `$event`})
23689 *
23690 * @example
23691 <example>
23692 <file name="index.html">
23693 <input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
23694 cut: {{cut}}
23695 </file>
23696 </example>
23697 */
23698
23699 /**
23700 * @ngdoc directive
23701 * @name ngPaste
23702 *
23703 * @description
23704 * Specify custom behavior on paste event.
23705 *
23706 * @element window, input, select, textarea, a
23707 * @priority 0
23708 * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
23709 * paste. ({@link guide/expression#-event- Event object is available as `$event`})
23710 *
23711 * @example
23712 <example>
23713 <file name="index.html">
23714 <input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
23715 pasted: {{paste}}
23716 </file>
23717 </example>
23718 */
23719
23720 /**
23721 * @ngdoc directive
23722 * @name ngIf
23723 * @restrict A
23724 * @multiElement
23725 *
23726 * @description
23727 * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
23728 * {expression}. If the expression assigned to `ngIf` evaluates to a false
23729 * value then the element is removed from the DOM, otherwise a clone of the
23730 * element is reinserted into the DOM.
23731 *
23732 * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
23733 * element in the DOM rather than changing its visibility via the `display` css property. A common
23734 * case when this difference is significant is when using css selectors that rely on an element's
23735 * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
23736 *
23737 * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
23738 * is created when the element is restored. The scope created within `ngIf` inherits from
23739 * its parent scope using
23740 * [prototypal inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes#javascript-prototypal-inheritance).
23741 * An important implication of this is if `ngModel` is used within `ngIf` to bind to
23742 * a javascript primitive defined in the parent scope. In this case any modifications made to the
23743 * variable within the child scope will override (hide) the value in the parent scope.
23744 *
23745 * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
23746 * is if an element's class attribute is directly modified after it's compiled, using something like
23747 * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
23748 * the added class will be lost because the original compiled state is used to regenerate the element.
23749 *
23750 * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
23751 * and `leave` effects.
23752 *
23753 * @animations
23754 * enter - happens just after the `ngIf` contents change and a new DOM element is created and injected into the `ngIf` container
23755 * leave - happens just before the `ngIf` contents are removed from the DOM
23756 *
23757 * @element ANY
23758 * @scope
23759 * @priority 600
23760 * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
23761 * the element is removed from the DOM tree. If it is truthy a copy of the compiled
23762 * element is added to the DOM tree.
23763 *
23764 * @example
23765 <example module="ngAnimate" deps="angular-animate.js" animations="true">
23766 <file name="index.html">
23767 <label>Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /></label><br/>
23768 Show when checked:
23769 <span ng-if="checked" class="animate-if">
23770 This is removed when the checkbox is unchecked.
23771 </span>
23772 </file>
23773 <file name="animations.css">
23774 .animate-if {
23775 background:white;
23776 border:1px solid black;
23777 padding:10px;
23778 }
23779
23780 .animate-if.ng-enter, .animate-if.ng-leave {
23781 -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
23782 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
23783 }
23784
23785 .animate-if.ng-enter,
23786 .animate-if.ng-leave.ng-leave-active {
23787 opacity:0;
23788 }
23789
23790 .animate-if.ng-leave,
23791 .animate-if.ng-enter.ng-enter-active {
23792 opacity:1;
23793 }
23794 </file>
23795 </example>
23796 */
23797 var ngIfDirective = ['$animate', function($animate) {
23798 return {
23799 multiElement: true,
23800 transclude: 'element',
23801 priority: 600,
23802 terminal: true,
23803 restrict: 'A',
23804 $$tlb: true,
23805 link: function($scope, $element, $attr, ctrl, $transclude) {
23806 var block, childScope, previousElements;
23807 $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
23808
23809 if (value) {
23810 if (!childScope) {
23811 $transclude(function(clone, newScope) {
23812 childScope = newScope;
23813 clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
23814 // Note: We only need the first/last node of the cloned nodes.
23815 // However, we need to keep the reference to the jqlite wrapper as it might be changed later
23816 // by a directive with templateUrl when its template arrives.
23817 block = {
23818 clone: clone
23819 };
23820 $animate.enter(clone, $element.parent(), $element);
23821 });
23822 }
23823 } else {
23824 if (previousElements) {
23825 previousElements.remove();
23826 previousElements = null;
23827 }
23828 if (childScope) {
23829 childScope.$destroy();
23830 childScope = null;
23831 }
23832 if (block) {
23833 previousElements = getBlockNodes(block.clone);
23834 $animate.leave(previousElements).then(function() {
23835 previousElements = null;
23836 });
23837 block = null;
23838 }
23839 }
23840 });
23841 }
23842 };
23843 }];
23844
23845 /**
23846 * @ngdoc directive
23847 * @name ngInclude
23848 * @restrict ECA
23849 *
23850 * @description
23851 * Fetches, compiles and includes an external HTML fragment.
23852 *
23853 * By default, the template URL is restricted to the same domain and protocol as the
23854 * application document. This is done by calling {@link $sce#getTrustedResourceUrl
23855 * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
23856 * you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist them} or
23857 * {@link $sce#trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link
23858 * ng.$sce Strict Contextual Escaping}.
23859 *
23860 * In addition, the browser's
23861 * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest)
23862 * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
23863 * policy may further restrict whether the template is successfully loaded.
23864 * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
23865 * access on some browsers.
23866 *
23867 * @animations
23868 * enter - animation is used to bring new content into the browser.
23869 * leave - animation is used to animate existing content away.
23870 *
23871 * The enter and leave animation occur concurrently.
23872 *
23873 * @scope
23874 * @priority 400
23875 *
23876 * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
23877 * make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
23878 * @param {string=} onload Expression to evaluate when a new partial is loaded.
23879 *
23880 * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
23881 * $anchorScroll} to scroll the viewport after the content is loaded.
23882 *
23883 * - If the attribute is not set, disable scrolling.
23884 * - If the attribute is set without value, enable scrolling.
23885 * - Otherwise enable scrolling only if the expression evaluates to truthy value.
23886 *
23887 * @example
23888 <example module="includeExample" deps="angular-animate.js" animations="true">
23889 <file name="index.html">
23890 <div ng-controller="ExampleController">
23891 <select ng-model="template" ng-options="t.name for t in templates">
23892 <option value="">(blank)</option>
23893 </select>
23894 url of the template: <code>{{template.url}}</code>
23895 <hr/>
23896 <div class="slide-animate-container">
23897 <div class="slide-animate" ng-include="template.url"></div>
23898 </div>
23899 </div>
23900 </file>
23901 <file name="script.js">
23902 angular.module('includeExample', ['ngAnimate'])
23903 .controller('ExampleController', ['$scope', function($scope) {
23904 $scope.templates =
23905 [ { name: 'template1.html', url: 'template1.html'},
23906 { name: 'template2.html', url: 'template2.html'} ];
23907 $scope.template = $scope.templates[0];
23908 }]);
23909 </file>
23910 <file name="template1.html">
23911 Content of template1.html
23912 </file>
23913 <file name="template2.html">
23914 Content of template2.html
23915 </file>
23916 <file name="animations.css">
23917 .slide-animate-container {
23918 position:relative;
23919 background:white;
23920 border:1px solid black;
23921 height:40px;
23922 overflow:hidden;
23923 }
23924
23925 .slide-animate {
23926 padding:10px;
23927 }
23928
23929 .slide-animate.ng-enter, .slide-animate.ng-leave {
23930 -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
23931 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
23932
23933 position:absolute;
23934 top:0;
23935 left:0;
23936 right:0;
23937 bottom:0;
23938 display:block;
23939 padding:10px;
23940 }
23941
23942 .slide-animate.ng-enter {
23943 top:-50px;
23944 }
23945 .slide-animate.ng-enter.ng-enter-active {
23946 top:0;
23947 }
23948
23949 .slide-animate.ng-leave {
23950 top:0;
23951 }
23952 .slide-animate.ng-leave.ng-leave-active {
23953 top:50px;
23954 }
23955 </file>
23956 <file name="protractor.js" type="protractor">
23957 var templateSelect = element(by.model('template'));
23958 var includeElem = element(by.css('[ng-include]'));
23959
23960 it('should load template1.html', function() {
23961 expect(includeElem.getText()).toMatch(/Content of template1.html/);
23962 });
23963
23964 it('should load template2.html', function() {
23965 if (browser.params.browser == 'firefox') {
23966 // Firefox can't handle using selects
23967 // See https://github.com/angular/protractor/issues/480
23968 return;
23969 }
23970 templateSelect.click();
23971 templateSelect.all(by.css('option')).get(2).click();
23972 expect(includeElem.getText()).toMatch(/Content of template2.html/);
23973 });
23974
23975 it('should change to blank', function() {
23976 if (browser.params.browser == 'firefox') {
23977 // Firefox can't handle using selects
23978 return;
23979 }
23980 templateSelect.click();
23981 templateSelect.all(by.css('option')).get(0).click();
23982 expect(includeElem.isPresent()).toBe(false);
23983 });
23984 </file>
23985 </example>
23986 */
23987
23988
23989 /**
23990 * @ngdoc event
23991 * @name ngInclude#$includeContentRequested
23992 * @eventType emit on the scope ngInclude was declared in
23993 * @description
23994 * Emitted every time the ngInclude content is requested.
23995 *
23996 * @param {Object} angularEvent Synthetic event object.
23997 * @param {String} src URL of content to load.
23998 */
23999
24000
24001 /**
24002 * @ngdoc event
24003 * @name ngInclude#$includeContentLoaded
24004 * @eventType emit on the current ngInclude scope
24005 * @description
24006 * Emitted every time the ngInclude content is reloaded.
24007 *
24008 * @param {Object} angularEvent Synthetic event object.
24009 * @param {String} src URL of content to load.
24010 */
24011
24012
24013 /**
24014 * @ngdoc event
24015 * @name ngInclude#$includeContentError
24016 * @eventType emit on the scope ngInclude was declared in
24017 * @description
24018 * Emitted when a template HTTP request yields an erroneous response (status < 200 || status > 299)
24019 *
24020 * @param {Object} angularEvent Synthetic event object.
24021 * @param {String} src URL of content to load.
24022 */
24023 var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
24024 function($templateRequest, $anchorScroll, $animate) {
24025 return {
24026 restrict: 'ECA',
24027 priority: 400,
24028 terminal: true,
24029 transclude: 'element',
24030 controller: angular.noop,
24031 compile: function(element, attr) {
24032 var srcExp = attr.ngInclude || attr.src,
24033 onloadExp = attr.onload || '',
24034 autoScrollExp = attr.autoscroll;
24035
24036 return function(scope, $element, $attr, ctrl, $transclude) {
24037 var changeCounter = 0,
24038 currentScope,
24039 previousElement,
24040 currentElement;
24041
24042 var cleanupLastIncludeContent = function() {
24043 if (previousElement) {
24044 previousElement.remove();
24045 previousElement = null;
24046 }
24047 if (currentScope) {
24048 currentScope.$destroy();
24049 currentScope = null;
24050 }
24051 if (currentElement) {
24052 $animate.leave(currentElement).then(function() {
24053 previousElement = null;
24054 });
24055 previousElement = currentElement;
24056 currentElement = null;
24057 }
24058 };
24059
24060 scope.$watch(srcExp, function ngIncludeWatchAction(src) {
24061 var afterAnimation = function() {
24062 if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
24063 $anchorScroll();
24064 }
24065 };
24066 var thisChangeId = ++changeCounter;
24067
24068 if (src) {
24069 //set the 2nd param to true to ignore the template request error so that the inner
24070 //contents and scope can be cleaned up.
24071 $templateRequest(src, true).then(function(response) {
24072 if (thisChangeId !== changeCounter) return;
24073 var newScope = scope.$new();
24074 ctrl.template = response;
24075
24076 // Note: This will also link all children of ng-include that were contained in the original
24077 // html. If that content contains controllers, ... they could pollute/change the scope.
24078 // However, using ng-include on an element with additional content does not make sense...
24079 // Note: We can't remove them in the cloneAttchFn of $transclude as that
24080 // function is called before linking the content, which would apply child
24081 // directives to non existing elements.
24082 var clone = $transclude(newScope, function(clone) {
24083 cleanupLastIncludeContent();
24084 $animate.enter(clone, null, $element).then(afterAnimation);
24085 });
24086
24087 currentScope = newScope;
24088 currentElement = clone;
24089
24090 currentScope.$emit('$includeContentLoaded', src);
24091 scope.$eval(onloadExp);
24092 }, function() {
24093 if (thisChangeId === changeCounter) {
24094 cleanupLastIncludeContent();
24095 scope.$emit('$includeContentError', src);
24096 }
24097 });
24098 scope.$emit('$includeContentRequested', src);
24099 } else {
24100 cleanupLastIncludeContent();
24101 ctrl.template = null;
24102 }
24103 });
24104 };
24105 }
24106 };
24107 }];
24108
24109 // This directive is called during the $transclude call of the first `ngInclude` directive.
24110 // It will replace and compile the content of the element with the loaded template.
24111 // We need this directive so that the element content is already filled when
24112 // the link function of another directive on the same element as ngInclude
24113 // is called.
24114 var ngIncludeFillContentDirective = ['$compile',
24115 function($compile) {
24116 return {
24117 restrict: 'ECA',
24118 priority: -400,
24119 require: 'ngInclude',
24120 link: function(scope, $element, $attr, ctrl) {
24121 if (/SVG/.test($element[0].toString())) {
24122 // WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
24123 // support innerHTML, so detect this here and try to generate the contents
24124 // specially.
24125 $element.empty();
24126 $compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
24127 function namespaceAdaptedClone(clone) {
24128 $element.append(clone);
24129 }, {futureParentElement: $element});
24130 return;
24131 }
24132
24133 $element.html(ctrl.template);
24134 $compile($element.contents())(scope);
24135 }
24136 };
24137 }];
24138
24139 /**
24140 * @ngdoc directive
24141 * @name ngInit
24142 * @restrict AC
24143 *
24144 * @description
24145 * The `ngInit` directive allows you to evaluate an expression in the
24146 * current scope.
24147 *
24148 * <div class="alert alert-danger">
24149 * The only appropriate use of `ngInit` is for aliasing special properties of
24150 * {@link ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
24151 * should use {@link guide/controller controllers} rather than `ngInit`
24152 * to initialize values on a scope.
24153 * </div>
24154 * <div class="alert alert-warning">
24155 * **Note**: If you have assignment in `ngInit` along with {@link ng.$filter `$filter`}, make
24156 * sure you have parenthesis for correct precedence:
24157 * <pre class="prettyprint">
24158 * `<div ng-init="test1 = (data | orderBy:'name')"></div>`
24159 * </pre>
24160 * </div>
24161 *
24162 * @priority 450
24163 *
24164 * @element ANY
24165 * @param {expression} ngInit {@link guide/expression Expression} to eval.
24166 *
24167 * @example
24168 <example module="initExample">
24169 <file name="index.html">
24170 <script>
24171 angular.module('initExample', [])
24172 .controller('ExampleController', ['$scope', function($scope) {
24173 $scope.list = [['a', 'b'], ['c', 'd']];
24174 }]);
24175 </script>
24176 <div ng-controller="ExampleController">
24177 <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
24178 <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
24179 <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
24180 </div>
24181 </div>
24182 </div>
24183 </file>
24184 <file name="protractor.js" type="protractor">
24185 it('should alias index positions', function() {
24186 var elements = element.all(by.css('.example-init'));
24187 expect(elements.get(0).getText()).toBe('list[ 0 ][ 0 ] = a;');
24188 expect(elements.get(1).getText()).toBe('list[ 0 ][ 1 ] = b;');
24189 expect(elements.get(2).getText()).toBe('list[ 1 ][ 0 ] = c;');
24190 expect(elements.get(3).getText()).toBe('list[ 1 ][ 1 ] = d;');
24191 });
24192 </file>
24193 </example>
24194 */
24195 var ngInitDirective = ngDirective({
24196 priority: 450,
24197 compile: function() {
24198 return {
24199 pre: function(scope, element, attrs) {
24200 scope.$eval(attrs.ngInit);
24201 }
24202 };
24203 }
24204 });
24205
24206 /**
24207 * @ngdoc directive
24208 * @name ngList
24209 *
24210 * @description
24211 * Text input that converts between a delimited string and an array of strings. The default
24212 * delimiter is a comma followed by a space - equivalent to `ng-list=", "`. You can specify a custom
24213 * delimiter as the value of the `ngList` attribute - for example, `ng-list=" | "`.
24214 *
24215 * The behaviour of the directive is affected by the use of the `ngTrim` attribute.
24216 * * If `ngTrim` is set to `"false"` then whitespace around both the separator and each
24217 * list item is respected. This implies that the user of the directive is responsible for
24218 * dealing with whitespace but also allows you to use whitespace as a delimiter, such as a
24219 * tab or newline character.
24220 * * Otherwise whitespace around the delimiter is ignored when splitting (although it is respected
24221 * when joining the list items back together) and whitespace around each list item is stripped
24222 * before it is added to the model.
24223 *
24224 * ### Example with Validation
24225 *
24226 * <example name="ngList-directive" module="listExample">
24227 * <file name="app.js">
24228 * angular.module('listExample', [])
24229 * .controller('ExampleController', ['$scope', function($scope) {
24230 * $scope.names = ['morpheus', 'neo', 'trinity'];
24231 * }]);
24232 * </file>
24233 * <file name="index.html">
24234 * <form name="myForm" ng-controller="ExampleController">
24235 * <label>List: <input name="namesInput" ng-model="names" ng-list required></label>
24236 * <span role="alert">
24237 * <span class="error" ng-show="myForm.namesInput.$error.required">
24238 * Required!</span>
24239 * </span>
24240 * <br>
24241 * <tt>names = {{names}}</tt><br/>
24242 * <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
24243 * <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
24244 * <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
24245 * <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
24246 * </form>
24247 * </file>
24248 * <file name="protractor.js" type="protractor">
24249 * var listInput = element(by.model('names'));
24250 * var names = element(by.exactBinding('names'));
24251 * var valid = element(by.binding('myForm.namesInput.$valid'));
24252 * var error = element(by.css('span.error'));
24253 *
24254 * it('should initialize to model', function() {
24255 * expect(names.getText()).toContain('["morpheus","neo","trinity"]');
24256 * expect(valid.getText()).toContain('true');
24257 * expect(error.getCssValue('display')).toBe('none');
24258 * });
24259 *
24260 * it('should be invalid if empty', function() {
24261 * listInput.clear();
24262 * listInput.sendKeys('');
24263 *
24264 * expect(names.getText()).toContain('');
24265 * expect(valid.getText()).toContain('false');
24266 * expect(error.getCssValue('display')).not.toBe('none');
24267 * });
24268 * </file>
24269 * </example>
24270 *
24271 * ### Example - splitting on whitespace
24272 * <example name="ngList-directive-newlines">
24273 * <file name="index.html">
24274 * <textarea ng-model="list" ng-list="&#10;" ng-trim="false"></textarea>
24275 * <pre>{{ list | json }}</pre>
24276 * </file>
24277 * <file name="protractor.js" type="protractor">
24278 * it("should split the text by newlines", function() {
24279 * var listInput = element(by.model('list'));
24280 * var output = element(by.binding('list | json'));
24281 * listInput.sendKeys('abc\ndef\nghi');
24282 * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]');
24283 * });
24284 * </file>
24285 * </example>
24286 *
24287 * @element input
24288 * @param {string=} ngList optional delimiter that should be used to split the value.
24289 */
24290 var ngListDirective = function() {
24291 return {
24292 restrict: 'A',
24293 priority: 100,
24294 require: 'ngModel',
24295 link: function(scope, element, attr, ctrl) {
24296 // We want to control whitespace trimming so we use this convoluted approach
24297 // to access the ngList attribute, which doesn't pre-trim the attribute
24298 var ngList = element.attr(attr.$attr.ngList) || ', ';
24299 var trimValues = attr.ngTrim !== 'false';
24300 var separator = trimValues ? trim(ngList) : ngList;
24301
24302 var parse = function(viewValue) {
24303 // If the viewValue is invalid (say required but empty) it will be `undefined`
24304 if (isUndefined(viewValue)) return;
24305
24306 var list = [];
24307
24308 if (viewValue) {
24309 forEach(viewValue.split(separator), function(value) {
24310 if (value) list.push(trimValues ? trim(value) : value);
24311 });
24312 }
24313
24314 return list;
24315 };
24316
24317 ctrl.$parsers.push(parse);
24318 ctrl.$formatters.push(function(value) {
24319 if (isArray(value)) {
24320 return value.join(ngList);
24321 }
24322
24323 return undefined;
24324 });
24325
24326 // Override the standard $isEmpty because an empty array means the input is empty.
24327 ctrl.$isEmpty = function(value) {
24328 return !value || !value.length;
24329 };
24330 }
24331 };
24332 };
24333
24334 /* global VALID_CLASS: true,
24335 INVALID_CLASS: true,
24336 PRISTINE_CLASS: true,
24337 DIRTY_CLASS: true,
24338 UNTOUCHED_CLASS: true,
24339 TOUCHED_CLASS: true,
24340 */
24341
24342 var VALID_CLASS = 'ng-valid',
24343 INVALID_CLASS = 'ng-invalid',
24344 PRISTINE_CLASS = 'ng-pristine',
24345 DIRTY_CLASS = 'ng-dirty',
24346 UNTOUCHED_CLASS = 'ng-untouched',
24347 TOUCHED_CLASS = 'ng-touched',
24348 PENDING_CLASS = 'ng-pending';
24349
24350
24351 var $ngModelMinErr = new minErr('ngModel');
24352
24353 /**
24354 * @ngdoc type
24355 * @name ngModel.NgModelController
24356 *
24357 * @property {string} $viewValue Actual string value in the view.
24358 * @property {*} $modelValue The value in the model that the control is bound to.
24359 * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
24360 the control reads value from the DOM. The functions are called in array order, each passing
24361 its return value through to the next. The last return value is forwarded to the
24362 {@link ngModel.NgModelController#$validators `$validators`} collection.
24363
24364 Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue
24365 `$viewValue`}.
24366
24367 Returning `undefined` from a parser means a parse error occurred. In that case,
24368 no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel`
24369 will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`}
24370 is set to `true`. The parse error is stored in `ngModel.$error.parse`.
24371
24372 *
24373 * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
24374 the model value changes. The functions are called in reverse array order, each passing the value through to the
24375 next. The last return value is used as the actual DOM value.
24376 Used to format / convert values for display in the control.
24377 * ```js
24378 * function formatter(value) {
24379 * if (value) {
24380 * return value.toUpperCase();
24381 * }
24382 * }
24383 * ngModel.$formatters.push(formatter);
24384 * ```
24385 *
24386 * @property {Object.<string, function>} $validators A collection of validators that are applied
24387 * whenever the model value changes. The key value within the object refers to the name of the
24388 * validator while the function refers to the validation operation. The validation operation is
24389 * provided with the model value as an argument and must return a true or false value depending
24390 * on the response of that validation.
24391 *
24392 * ```js
24393 * ngModel.$validators.validCharacters = function(modelValue, viewValue) {
24394 * var value = modelValue || viewValue;
24395 * return /[0-9]+/.test(value) &&
24396 * /[a-z]+/.test(value) &&
24397 * /[A-Z]+/.test(value) &&
24398 * /\W+/.test(value);
24399 * };
24400 * ```
24401 *
24402 * @property {Object.<string, function>} $asyncValidators A collection of validations that are expected to
24403 * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided
24404 * is expected to return a promise when it is run during the model validation process. Once the promise
24405 * is delivered then the validation status will be set to true when fulfilled and false when rejected.
24406 * When the asynchronous validators are triggered, each of the validators will run in parallel and the model
24407 * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator
24408 * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators
24409 * will only run once all synchronous validators have passed.
24410 *
24411 * Please note that if $http is used then it is important that the server returns a success HTTP response code
24412 * in order to fulfill the validation and a status level of `4xx` in order to reject the validation.
24413 *
24414 * ```js
24415 * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
24416 * var value = modelValue || viewValue;
24417 *
24418 * // Lookup user by username
24419 * return $http.get('/api/users/' + value).
24420 * then(function resolved() {
24421 * //username exists, this means validation fails
24422 * return $q.reject('exists');
24423 * }, function rejected() {
24424 * //username does not exist, therefore this validation passes
24425 * return true;
24426 * });
24427 * };
24428 * ```
24429 *
24430 * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
24431 * view value has changed. It is called with no arguments, and its return value is ignored.
24432 * This can be used in place of additional $watches against the model value.
24433 *
24434 * @property {Object} $error An object hash with all failing validator ids as keys.
24435 * @property {Object} $pending An object hash with all pending validator ids as keys.
24436 *
24437 * @property {boolean} $untouched True if control has not lost focus yet.
24438 * @property {boolean} $touched True if control has lost focus.
24439 * @property {boolean} $pristine True if user has not interacted with the control yet.
24440 * @property {boolean} $dirty True if user has already interacted with the control.
24441 * @property {boolean} $valid True if there is no error.
24442 * @property {boolean} $invalid True if at least one error on the control.
24443 * @property {string} $name The name attribute of the control.
24444 *
24445 * @description
24446 *
24447 * `NgModelController` provides API for the {@link ngModel `ngModel`} directive.
24448 * The controller contains services for data-binding, validation, CSS updates, and value formatting
24449 * and parsing. It purposefully does not contain any logic which deals with DOM rendering or
24450 * listening to DOM events.
24451 * Such DOM related logic should be provided by other directives which make use of
24452 * `NgModelController` for data-binding to control elements.
24453 * Angular provides this DOM logic for most {@link input `input`} elements.
24454 * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example
24455 * custom control example} that uses `ngModelController` to bind to `contenteditable` elements.
24456 *
24457 * @example
24458 * ### Custom Control Example
24459 * This example shows how to use `NgModelController` with a custom control to achieve
24460 * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
24461 * collaborate together to achieve the desired result.
24462 *
24463 * `contenteditable` is an HTML5 attribute, which tells the browser to let the element
24464 * contents be edited in place by the user.
24465 *
24466 * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize}
24467 * module to automatically remove "bad" content like inline event listener (e.g. `<span onclick="...">`).
24468 * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks
24469 * that content using the `$sce` service.
24470 *
24471 * <example name="NgModelController" module="customControl" deps="angular-sanitize.js">
24472 <file name="style.css">
24473 [contenteditable] {
24474 border: 1px solid black;
24475 background-color: white;
24476 min-height: 20px;
24477 }
24478
24479 .ng-invalid {
24480 border: 1px solid red;
24481 }
24482
24483 </file>
24484 <file name="script.js">
24485 angular.module('customControl', ['ngSanitize']).
24486 directive('contenteditable', ['$sce', function($sce) {
24487 return {
24488 restrict: 'A', // only activate on element attribute
24489 require: '?ngModel', // get a hold of NgModelController
24490 link: function(scope, element, attrs, ngModel) {
24491 if (!ngModel) return; // do nothing if no ng-model
24492
24493 // Specify how UI should be updated
24494 ngModel.$render = function() {
24495 element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
24496 };
24497
24498 // Listen for change events to enable binding
24499 element.on('blur keyup change', function() {
24500 scope.$evalAsync(read);
24501 });
24502 read(); // initialize
24503
24504 // Write data to the model
24505 function read() {
24506 var html = element.html();
24507 // When we clear the content editable the browser leaves a <br> behind
24508 // If strip-br attribute is provided then we strip this out
24509 if ( attrs.stripBr && html == '<br>' ) {
24510 html = '';
24511 }
24512 ngModel.$setViewValue(html);
24513 }
24514 }
24515 };
24516 }]);
24517 </file>
24518 <file name="index.html">
24519 <form name="myForm">
24520 <div contenteditable
24521 name="myWidget" ng-model="userContent"
24522 strip-br="true"
24523 required>Change me!</div>
24524 <span ng-show="myForm.myWidget.$error.required">Required!</span>
24525 <hr>
24526 <textarea ng-model="userContent" aria-label="Dynamic textarea"></textarea>
24527 </form>
24528 </file>
24529 <file name="protractor.js" type="protractor">
24530 it('should data-bind and become invalid', function() {
24531 if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
24532 // SafariDriver can't handle contenteditable
24533 // and Firefox driver can't clear contenteditables very well
24534 return;
24535 }
24536 var contentEditable = element(by.css('[contenteditable]'));
24537 var content = 'Change me!';
24538
24539 expect(contentEditable.getText()).toEqual(content);
24540
24541 contentEditable.clear();
24542 contentEditable.sendKeys(protractor.Key.BACK_SPACE);
24543 expect(contentEditable.getText()).toEqual('');
24544 expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
24545 });
24546 </file>
24547 * </example>
24548 *
24549 *
24550 */
24551 var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope', '$q', '$interpolate',
24552 function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope, $q, $interpolate) {
24553 this.$viewValue = Number.NaN;
24554 this.$modelValue = Number.NaN;
24555 this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity.
24556 this.$validators = {};
24557 this.$asyncValidators = {};
24558 this.$parsers = [];
24559 this.$formatters = [];
24560 this.$viewChangeListeners = [];
24561 this.$untouched = true;
24562 this.$touched = false;
24563 this.$pristine = true;
24564 this.$dirty = false;
24565 this.$valid = true;
24566 this.$invalid = false;
24567 this.$error = {}; // keep invalid keys here
24568 this.$$success = {}; // keep valid keys here
24569 this.$pending = undefined; // keep pending keys here
24570 this.$name = $interpolate($attr.name || '', false)($scope);
24571
24572
24573 var parsedNgModel = $parse($attr.ngModel),
24574 parsedNgModelAssign = parsedNgModel.assign,
24575 ngModelGet = parsedNgModel,
24576 ngModelSet = parsedNgModelAssign,
24577 pendingDebounce = null,
24578 parserValid,
24579 ctrl = this;
24580
24581 this.$$setOptions = function(options) {
24582 ctrl.$options = options;
24583 if (options && options.getterSetter) {
24584 var invokeModelGetter = $parse($attr.ngModel + '()'),
24585 invokeModelSetter = $parse($attr.ngModel + '($$$p)');
24586
24587 ngModelGet = function($scope) {
24588 var modelValue = parsedNgModel($scope);
24589 if (isFunction(modelValue)) {
24590 modelValue = invokeModelGetter($scope);
24591 }
24592 return modelValue;
24593 };
24594 ngModelSet = function($scope, newValue) {
24595 if (isFunction(parsedNgModel($scope))) {
24596 invokeModelSetter($scope, {$$$p: ctrl.$modelValue});
24597 } else {
24598 parsedNgModelAssign($scope, ctrl.$modelValue);
24599 }
24600 };
24601 } else if (!parsedNgModel.assign) {
24602 throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
24603 $attr.ngModel, startingTag($element));
24604 }
24605 };
24606
24607 /**
24608 * @ngdoc method
24609 * @name ngModel.NgModelController#$render
24610 *
24611 * @description
24612 * Called when the view needs to be updated. It is expected that the user of the ng-model
24613 * directive will implement this method.
24614 *
24615 * The `$render()` method is invoked in the following situations:
24616 *
24617 * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last
24618 * committed value then `$render()` is called to update the input control.
24619 * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and
24620 * the `$viewValue` are different from last time.
24621 *
24622 * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of
24623 * `$modelValue` and `$viewValue` are actually different from their previous value. If `$modelValue`
24624 * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be
24625 * invoked if you only change a property on the objects.
24626 */
24627 this.$render = noop;
24628
24629 /**
24630 * @ngdoc method
24631 * @name ngModel.NgModelController#$isEmpty
24632 *
24633 * @description
24634 * This is called when we need to determine if the value of an input is empty.
24635 *
24636 * For instance, the required directive does this to work out if the input has data or not.
24637 *
24638 * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
24639 *
24640 * You can override this for input directives whose concept of being empty is different from the
24641 * default. The `checkboxInputType` directive does this because in its case a value of `false`
24642 * implies empty.
24643 *
24644 * @param {*} value The value of the input to check for emptiness.
24645 * @returns {boolean} True if `value` is "empty".
24646 */
24647 this.$isEmpty = function(value) {
24648 return isUndefined(value) || value === '' || value === null || value !== value;
24649 };
24650
24651 var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
24652 currentValidationRunId = 0;
24653
24654 /**
24655 * @ngdoc method
24656 * @name ngModel.NgModelController#$setValidity
24657 *
24658 * @description
24659 * Change the validity state, and notify the form.
24660 *
24661 * This method can be called within $parsers/$formatters or a custom validation implementation.
24662 * However, in most cases it should be sufficient to use the `ngModel.$validators` and
24663 * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically.
24664 *
24665 * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned
24666 * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]`
24667 * (for unfulfilled `$asyncValidators`), so that it is available for data-binding.
24668 * The `validationErrorKey` should be in camelCase and will get converted into dash-case
24669 * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
24670 * class and can be bound to as `{{someForm.someControl.$error.myError}}` .
24671 * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined),
24672 * or skipped (null). Pending is used for unfulfilled `$asyncValidators`.
24673 * Skipped is used by Angular when validators do not run because of parse errors and
24674 * when `$asyncValidators` do not run because any of the `$validators` failed.
24675 */
24676 addSetValidityMethod({
24677 ctrl: this,
24678 $element: $element,
24679 set: function(object, property) {
24680 object[property] = true;
24681 },
24682 unset: function(object, property) {
24683 delete object[property];
24684 },
24685 parentForm: parentForm,
24686 $animate: $animate
24687 });
24688
24689 /**
24690 * @ngdoc method
24691 * @name ngModel.NgModelController#$setPristine
24692 *
24693 * @description
24694 * Sets the control to its pristine state.
24695 *
24696 * This method can be called to remove the `ng-dirty` class and set the control to its pristine
24697 * state (`ng-pristine` class). A model is considered to be pristine when the control
24698 * has not been changed from when first compiled.
24699 */
24700 this.$setPristine = function() {
24701 ctrl.$dirty = false;
24702 ctrl.$pristine = true;
24703 $animate.removeClass($element, DIRTY_CLASS);
24704 $animate.addClass($element, PRISTINE_CLASS);
24705 };
24706
24707 /**
24708 * @ngdoc method
24709 * @name ngModel.NgModelController#$setDirty
24710 *
24711 * @description
24712 * Sets the control to its dirty state.
24713 *
24714 * This method can be called to remove the `ng-pristine` class and set the control to its dirty
24715 * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed
24716 * from when first compiled.
24717 */
24718 this.$setDirty = function() {
24719 ctrl.$dirty = true;
24720 ctrl.$pristine = false;
24721 $animate.removeClass($element, PRISTINE_CLASS);
24722 $animate.addClass($element, DIRTY_CLASS);
24723 parentForm.$setDirty();
24724 };
24725
24726 /**
24727 * @ngdoc method
24728 * @name ngModel.NgModelController#$setUntouched
24729 *
24730 * @description
24731 * Sets the control to its untouched state.
24732 *
24733 * This method can be called to remove the `ng-touched` class and set the control to its
24734 * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched
24735 * by default, however this function can be used to restore that state if the model has
24736 * already been touched by the user.
24737 */
24738 this.$setUntouched = function() {
24739 ctrl.$touched = false;
24740 ctrl.$untouched = true;
24741 $animate.setClass($element, UNTOUCHED_CLASS, TOUCHED_CLASS);
24742 };
24743
24744 /**
24745 * @ngdoc method
24746 * @name ngModel.NgModelController#$setTouched
24747 *
24748 * @description
24749 * Sets the control to its touched state.
24750 *
24751 * This method can be called to remove the `ng-untouched` class and set the control to its
24752 * touched state (`ng-touched` class). A model is considered to be touched when the user has
24753 * first focused the control element and then shifted focus away from the control (blur event).
24754 */
24755 this.$setTouched = function() {
24756 ctrl.$touched = true;
24757 ctrl.$untouched = false;
24758 $animate.setClass($element, TOUCHED_CLASS, UNTOUCHED_CLASS);
24759 };
24760
24761 /**
24762 * @ngdoc method
24763 * @name ngModel.NgModelController#$rollbackViewValue
24764 *
24765 * @description
24766 * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`,
24767 * which may be caused by a pending debounced event or because the input is waiting for a some
24768 * future event.
24769 *
24770 * If you have an input that uses `ng-model-options` to set up debounced events or events such
24771 * as blur you can have a situation where there is a period when the `$viewValue`
24772 * is out of synch with the ngModel's `$modelValue`.
24773 *
24774 * In this case, you can run into difficulties if you try to update the ngModel's `$modelValue`
24775 * programmatically before these debounced/future events have resolved/occurred, because Angular's
24776 * dirty checking mechanism is not able to tell whether the model has actually changed or not.
24777 *
24778 * The `$rollbackViewValue()` method should be called before programmatically changing the model of an
24779 * input which may have such events pending. This is important in order to make sure that the
24780 * input field will be updated with the new model value and any pending operations are cancelled.
24781 *
24782 * <example name="ng-model-cancel-update" module="cancel-update-example">
24783 * <file name="app.js">
24784 * angular.module('cancel-update-example', [])
24785 *
24786 * .controller('CancelUpdateController', ['$scope', function($scope) {
24787 * $scope.resetWithCancel = function(e) {
24788 * if (e.keyCode == 27) {
24789 * $scope.myForm.myInput1.$rollbackViewValue();
24790 * $scope.myValue = '';
24791 * }
24792 * };
24793 * $scope.resetWithoutCancel = function(e) {
24794 * if (e.keyCode == 27) {
24795 * $scope.myValue = '';
24796 * }
24797 * };
24798 * }]);
24799 * </file>
24800 * <file name="index.html">
24801 * <div ng-controller="CancelUpdateController">
24802 * <p>Try typing something in each input. See that the model only updates when you
24803 * blur off the input.
24804 * </p>
24805 * <p>Now see what happens if you start typing then press the Escape key</p>
24806 *
24807 * <form name="myForm" ng-model-options="{ updateOn: 'blur' }">
24808 * <p id="inputDescription1">With $rollbackViewValue()</p>
24809 * <input name="myInput1" aria-describedby="inputDescription1" ng-model="myValue"
24810 * ng-keydown="resetWithCancel($event)"><br/>
24811 * myValue: "{{ myValue }}"
24812 *
24813 * <p id="inputDescription2">Without $rollbackViewValue()</p>
24814 * <input name="myInput2" aria-describedby="inputDescription2" ng-model="myValue"
24815 * ng-keydown="resetWithoutCancel($event)"><br/>
24816 * myValue: "{{ myValue }}"
24817 * </form>
24818 * </div>
24819 * </file>
24820 * </example>
24821 */
24822 this.$rollbackViewValue = function() {
24823 $timeout.cancel(pendingDebounce);
24824 ctrl.$viewValue = ctrl.$$lastCommittedViewValue;
24825 ctrl.$render();
24826 };
24827
24828 /**
24829 * @ngdoc method
24830 * @name ngModel.NgModelController#$validate
24831 *
24832 * @description
24833 * Runs each of the registered validators (first synchronous validators and then
24834 * asynchronous validators).
24835 * If the validity changes to invalid, the model will be set to `undefined`,
24836 * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`.
24837 * If the validity changes to valid, it will set the model to the last available valid
24838 * `$modelValue`, i.e. either the last parsed value or the last value set from the scope.
24839 */
24840 this.$validate = function() {
24841 // ignore $validate before model is initialized
24842 if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
24843 return;
24844 }
24845
24846 var viewValue = ctrl.$$lastCommittedViewValue;
24847 // Note: we use the $$rawModelValue as $modelValue might have been
24848 // set to undefined during a view -> model update that found validation
24849 // errors. We can't parse the view here, since that could change
24850 // the model although neither viewValue nor the model on the scope changed
24851 var modelValue = ctrl.$$rawModelValue;
24852
24853 var prevValid = ctrl.$valid;
24854 var prevModelValue = ctrl.$modelValue;
24855
24856 var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
24857
24858 ctrl.$$runValidators(modelValue, viewValue, function(allValid) {
24859 // If there was no change in validity, don't update the model
24860 // This prevents changing an invalid modelValue to undefined
24861 if (!allowInvalid && prevValid !== allValid) {
24862 // Note: Don't check ctrl.$valid here, as we could have
24863 // external validators (e.g. calculated on the server),
24864 // that just call $setValidity and need the model value
24865 // to calculate their validity.
24866 ctrl.$modelValue = allValid ? modelValue : undefined;
24867
24868 if (ctrl.$modelValue !== prevModelValue) {
24869 ctrl.$$writeModelToScope();
24870 }
24871 }
24872 });
24873
24874 };
24875
24876 this.$$runValidators = function(modelValue, viewValue, doneCallback) {
24877 currentValidationRunId++;
24878 var localValidationRunId = currentValidationRunId;
24879
24880 // check parser error
24881 if (!processParseErrors()) {
24882 validationDone(false);
24883 return;
24884 }
24885 if (!processSyncValidators()) {
24886 validationDone(false);
24887 return;
24888 }
24889 processAsyncValidators();
24890
24891 function processParseErrors() {
24892 var errorKey = ctrl.$$parserName || 'parse';
24893 if (parserValid === undefined) {
24894 setValidity(errorKey, null);
24895 } else {
24896 if (!parserValid) {
24897 forEach(ctrl.$validators, function(v, name) {
24898 setValidity(name, null);
24899 });
24900 forEach(ctrl.$asyncValidators, function(v, name) {
24901 setValidity(name, null);
24902 });
24903 }
24904 // Set the parse error last, to prevent unsetting it, should a $validators key == parserName
24905 setValidity(errorKey, parserValid);
24906 return parserValid;
24907 }
24908 return true;
24909 }
24910
24911 function processSyncValidators() {
24912 var syncValidatorsValid = true;
24913 forEach(ctrl.$validators, function(validator, name) {
24914 var result = validator(modelValue, viewValue);
24915 syncValidatorsValid = syncValidatorsValid && result;
24916 setValidity(name, result);
24917 });
24918 if (!syncValidatorsValid) {
24919 forEach(ctrl.$asyncValidators, function(v, name) {
24920 setValidity(name, null);
24921 });
24922 return false;
24923 }
24924 return true;
24925 }
24926
24927 function processAsyncValidators() {
24928 var validatorPromises = [];
24929 var allValid = true;
24930 forEach(ctrl.$asyncValidators, function(validator, name) {
24931 var promise = validator(modelValue, viewValue);
24932 if (!isPromiseLike(promise)) {
24933 throw $ngModelMinErr("$asyncValidators",
24934 "Expected asynchronous validator to return a promise but got '{0}' instead.", promise);
24935 }
24936 setValidity(name, undefined);
24937 validatorPromises.push(promise.then(function() {
24938 setValidity(name, true);
24939 }, function(error) {
24940 allValid = false;
24941 setValidity(name, false);
24942 }));
24943 });
24944 if (!validatorPromises.length) {
24945 validationDone(true);
24946 } else {
24947 $q.all(validatorPromises).then(function() {
24948 validationDone(allValid);
24949 }, noop);
24950 }
24951 }
24952
24953 function setValidity(name, isValid) {
24954 if (localValidationRunId === currentValidationRunId) {
24955 ctrl.$setValidity(name, isValid);
24956 }
24957 }
24958
24959 function validationDone(allValid) {
24960 if (localValidationRunId === currentValidationRunId) {
24961
24962 doneCallback(allValid);
24963 }
24964 }
24965 };
24966
24967 /**
24968 * @ngdoc method
24969 * @name ngModel.NgModelController#$commitViewValue
24970 *
24971 * @description
24972 * Commit a pending update to the `$modelValue`.
24973 *
24974 * Updates may be pending by a debounced event or because the input is waiting for a some future
24975 * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
24976 * usually handles calling this in response to input events.
24977 */
24978 this.$commitViewValue = function() {
24979 var viewValue = ctrl.$viewValue;
24980
24981 $timeout.cancel(pendingDebounce);
24982
24983 // If the view value has not changed then we should just exit, except in the case where there is
24984 // a native validator on the element. In this case the validation state may have changed even though
24985 // the viewValue has stayed empty.
24986 if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
24987 return;
24988 }
24989 ctrl.$$lastCommittedViewValue = viewValue;
24990
24991 // change to dirty
24992 if (ctrl.$pristine) {
24993 this.$setDirty();
24994 }
24995 this.$$parseAndValidate();
24996 };
24997
24998 this.$$parseAndValidate = function() {
24999 var viewValue = ctrl.$$lastCommittedViewValue;
25000 var modelValue = viewValue;
25001 parserValid = isUndefined(modelValue) ? undefined : true;
25002
25003 if (parserValid) {
25004 for (var i = 0; i < ctrl.$parsers.length; i++) {
25005 modelValue = ctrl.$parsers[i](modelValue);
25006 if (isUndefined(modelValue)) {
25007 parserValid = false;
25008 break;
25009 }
25010 }
25011 }
25012 if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
25013 // ctrl.$modelValue has not been touched yet...
25014 ctrl.$modelValue = ngModelGet($scope);
25015 }
25016 var prevModelValue = ctrl.$modelValue;
25017 var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
25018 ctrl.$$rawModelValue = modelValue;
25019
25020 if (allowInvalid) {
25021 ctrl.$modelValue = modelValue;
25022 writeToModelIfNeeded();
25023 }
25024
25025 // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date.
25026 // This can happen if e.g. $setViewValue is called from inside a parser
25027 ctrl.$$runValidators(modelValue, ctrl.$$lastCommittedViewValue, function(allValid) {
25028 if (!allowInvalid) {
25029 // Note: Don't check ctrl.$valid here, as we could have
25030 // external validators (e.g. calculated on the server),
25031 // that just call $setValidity and need the model value
25032 // to calculate their validity.
25033 ctrl.$modelValue = allValid ? modelValue : undefined;
25034 writeToModelIfNeeded();
25035 }
25036 });
25037
25038 function writeToModelIfNeeded() {
25039 if (ctrl.$modelValue !== prevModelValue) {
25040 ctrl.$$writeModelToScope();
25041 }
25042 }
25043 };
25044
25045 this.$$writeModelToScope = function() {
25046 ngModelSet($scope, ctrl.$modelValue);
25047 forEach(ctrl.$viewChangeListeners, function(listener) {
25048 try {
25049 listener();
25050 } catch (e) {
25051 $exceptionHandler(e);
25052 }
25053 });
25054 };
25055
25056 /**
25057 * @ngdoc method
25058 * @name ngModel.NgModelController#$setViewValue
25059 *
25060 * @description
25061 * Update the view value.
25062 *
25063 * This method should be called when an input directive want to change the view value; typically,
25064 * this is done from within a DOM event handler.
25065 *
25066 * For example {@link ng.directive:input input} calls it when the value of the input changes and
25067 * {@link ng.directive:select select} calls it when an option is selected.
25068 *
25069 * If the new `value` is an object (rather than a string or a number), we should make a copy of the
25070 * object before passing it to `$setViewValue`. This is because `ngModel` does not perform a deep
25071 * watch of objects, it only looks for a change of identity. If you only change the property of
25072 * the object then ngModel will not realise that the object has changed and will not invoke the
25073 * `$parsers` and `$validators` pipelines.
25074 *
25075 * For this reason, you should not change properties of the copy once it has been passed to
25076 * `$setViewValue`. Otherwise you may cause the model value on the scope to change incorrectly.
25077 *
25078 * When this method is called, the new `value` will be staged for committing through the `$parsers`
25079 * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged
25080 * value sent directly for processing, finally to be applied to `$modelValue` and then the
25081 * **expression** specified in the `ng-model` attribute.
25082 *
25083 * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
25084 *
25085 * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn`
25086 * and the `default` trigger is not listed, all those actions will remain pending until one of the
25087 * `updateOn` events is triggered on the DOM element.
25088 * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions}
25089 * directive is used with a custom debounce for this particular event.
25090 *
25091 * Note that calling this function does not trigger a `$digest`.
25092 *
25093 * @param {string} value Value from the view.
25094 * @param {string} trigger Event that triggered the update.
25095 */
25096 this.$setViewValue = function(value, trigger) {
25097 ctrl.$viewValue = value;
25098 if (!ctrl.$options || ctrl.$options.updateOnDefault) {
25099 ctrl.$$debounceViewValueCommit(trigger);
25100 }
25101 };
25102
25103 this.$$debounceViewValueCommit = function(trigger) {
25104 var debounceDelay = 0,
25105 options = ctrl.$options,
25106 debounce;
25107
25108 if (options && isDefined(options.debounce)) {
25109 debounce = options.debounce;
25110 if (isNumber(debounce)) {
25111 debounceDelay = debounce;
25112 } else if (isNumber(debounce[trigger])) {
25113 debounceDelay = debounce[trigger];
25114 } else if (isNumber(debounce['default'])) {
25115 debounceDelay = debounce['default'];
25116 }
25117 }
25118
25119 $timeout.cancel(pendingDebounce);
25120 if (debounceDelay) {
25121 pendingDebounce = $timeout(function() {
25122 ctrl.$commitViewValue();
25123 }, debounceDelay);
25124 } else if ($rootScope.$$phase) {
25125 ctrl.$commitViewValue();
25126 } else {
25127 $scope.$apply(function() {
25128 ctrl.$commitViewValue();
25129 });
25130 }
25131 };
25132
25133 // model -> value
25134 // Note: we cannot use a normal scope.$watch as we want to detect the following:
25135 // 1. scope value is 'a'
25136 // 2. user enters 'b'
25137 // 3. ng-change kicks in and reverts scope value to 'a'
25138 // -> scope value did not change since the last digest as
25139 // ng-change executes in apply phase
25140 // 4. view should be changed back to 'a'
25141 $scope.$watch(function ngModelWatch() {
25142 var modelValue = ngModelGet($scope);
25143
25144 // if scope model value and ngModel value are out of sync
25145 // TODO(perf): why not move this to the action fn?
25146 if (modelValue !== ctrl.$modelValue &&
25147 // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
25148 (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
25149 ) {
25150 ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
25151 parserValid = undefined;
25152
25153 var formatters = ctrl.$formatters,
25154 idx = formatters.length;
25155
25156 var viewValue = modelValue;
25157 while (idx--) {
25158 viewValue = formatters[idx](viewValue);
25159 }
25160 if (ctrl.$viewValue !== viewValue) {
25161 ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
25162 ctrl.$render();
25163
25164 ctrl.$$runValidators(modelValue, viewValue, noop);
25165 }
25166 }
25167
25168 return modelValue;
25169 });
25170 }];
25171
25172
25173 /**
25174 * @ngdoc directive
25175 * @name ngModel
25176 *
25177 * @element input
25178 * @priority 1
25179 *
25180 * @description
25181 * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
25182 * property on the scope using {@link ngModel.NgModelController NgModelController},
25183 * which is created and exposed by this directive.
25184 *
25185 * `ngModel` is responsible for:
25186 *
25187 * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
25188 * require.
25189 * - Providing validation behavior (i.e. required, number, email, url).
25190 * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors).
25191 * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, `ng-untouched`) including animations.
25192 * - Registering the control with its parent {@link ng.directive:form form}.
25193 *
25194 * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
25195 * current scope. If the property doesn't already exist on this scope, it will be created
25196 * implicitly and added to the scope.
25197 *
25198 * For best practices on using `ngModel`, see:
25199 *
25200 * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes)
25201 *
25202 * For basic examples, how to use `ngModel`, see:
25203 *
25204 * - {@link ng.directive:input input}
25205 * - {@link input[text] text}
25206 * - {@link input[checkbox] checkbox}
25207 * - {@link input[radio] radio}
25208 * - {@link input[number] number}
25209 * - {@link input[email] email}
25210 * - {@link input[url] url}
25211 * - {@link input[date] date}
25212 * - {@link input[datetime-local] datetime-local}
25213 * - {@link input[time] time}
25214 * - {@link input[month] month}
25215 * - {@link input[week] week}
25216 * - {@link ng.directive:select select}
25217 * - {@link ng.directive:textarea textarea}
25218 *
25219 * # CSS classes
25220 * The following CSS classes are added and removed on the associated input/select/textarea element
25221 * depending on the validity of the model.
25222 *
25223 * - `ng-valid`: the model is valid
25224 * - `ng-invalid`: the model is invalid
25225 * - `ng-valid-[key]`: for each valid key added by `$setValidity`
25226 * - `ng-invalid-[key]`: for each invalid key added by `$setValidity`
25227 * - `ng-pristine`: the control hasn't been interacted with yet
25228 * - `ng-dirty`: the control has been interacted with
25229 * - `ng-touched`: the control has been blurred
25230 * - `ng-untouched`: the control hasn't been blurred
25231 * - `ng-pending`: any `$asyncValidators` are unfulfilled
25232 *
25233 * Keep in mind that ngAnimate can detect each of these classes when added and removed.
25234 *
25235 * ## Animation Hooks
25236 *
25237 * Animations within models are triggered when any of the associated CSS classes are added and removed
25238 * on the input element which is attached to the model. These classes are: `.ng-pristine`, `.ng-dirty`,
25239 * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself.
25240 * The animations that are triggered within ngModel are similar to how they work in ngClass and
25241 * animations can be hooked into using CSS transitions, keyframes as well as JS animations.
25242 *
25243 * The following example shows a simple way to utilize CSS transitions to style an input element
25244 * that has been rendered as invalid after it has been validated:
25245 *
25246 * <pre>
25247 * //be sure to include ngAnimate as a module to hook into more
25248 * //advanced animations
25249 * .my-input {
25250 * transition:0.5s linear all;
25251 * background: white;
25252 * }
25253 * .my-input.ng-invalid {
25254 * background: red;
25255 * color:white;
25256 * }
25257 * </pre>
25258 *
25259 * @example
25260 * <example deps="angular-animate.js" animations="true" fixBase="true" module="inputExample">
25261 <file name="index.html">
25262 <script>
25263 angular.module('inputExample', [])
25264 .controller('ExampleController', ['$scope', function($scope) {
25265 $scope.val = '1';
25266 }]);
25267 </script>
25268 <style>
25269 .my-input {
25270 -webkit-transition:all linear 0.5s;
25271 transition:all linear 0.5s;
25272 background: transparent;
25273 }
25274 .my-input.ng-invalid {
25275 color:white;
25276 background: red;
25277 }
25278 </style>
25279 <p id="inputDescription">
25280 Update input to see transitions when valid/invalid.
25281 Integer is a valid value.
25282 </p>
25283 <form name="testForm" ng-controller="ExampleController">
25284 <input ng-model="val" ng-pattern="/^\d+$/" name="anim" class="my-input"
25285 aria-describedby="inputDescription" />
25286 </form>
25287 </file>
25288 * </example>
25289 *
25290 * ## Binding to a getter/setter
25291 *
25292 * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a
25293 * function that returns a representation of the model when called with zero arguments, and sets
25294 * the internal state of a model when called with an argument. It's sometimes useful to use this
25295 * for models that have an internal representation that's different from what the model exposes
25296 * to the view.
25297 *
25298 * <div class="alert alert-success">
25299 * **Best Practice:** It's best to keep getters fast because Angular is likely to call them more
25300 * frequently than other parts of your code.
25301 * </div>
25302 *
25303 * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that
25304 * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to
25305 * a `<form>`, which will enable this behavior for all `<input>`s within it. See
25306 * {@link ng.directive:ngModelOptions `ngModelOptions`} for more.
25307 *
25308 * The following example shows how to use `ngModel` with a getter/setter:
25309 *
25310 * @example
25311 * <example name="ngModel-getter-setter" module="getterSetterExample">
25312 <file name="index.html">
25313 <div ng-controller="ExampleController">
25314 <form name="userForm">
25315 <label>Name:
25316 <input type="text" name="userName"
25317 ng-model="user.name"
25318 ng-model-options="{ getterSetter: true }" />
25319 </label>
25320 </form>
25321 <pre>user.name = <span ng-bind="user.name()"></span></pre>
25322 </div>
25323 </file>
25324 <file name="app.js">
25325 angular.module('getterSetterExample', [])
25326 .controller('ExampleController', ['$scope', function($scope) {
25327 var _name = 'Brian';
25328 $scope.user = {
25329 name: function(newName) {
25330 // Note that newName can be undefined for two reasons:
25331 // 1. Because it is called as a getter and thus called with no arguments
25332 // 2. Because the property should actually be set to undefined. This happens e.g. if the
25333 // input is invalid
25334 return arguments.length ? (_name = newName) : _name;
25335 }
25336 };
25337 }]);
25338 </file>
25339 * </example>
25340 */
25341 var ngModelDirective = ['$rootScope', function($rootScope) {
25342 return {
25343 restrict: 'A',
25344 require: ['ngModel', '^?form', '^?ngModelOptions'],
25345 controller: NgModelController,
25346 // Prelink needs to run before any input directive
25347 // so that we can set the NgModelOptions in NgModelController
25348 // before anyone else uses it.
25349 priority: 1,
25350 compile: function ngModelCompile(element) {
25351 // Setup initial state of the control
25352 element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS);
25353
25354 return {
25355 pre: function ngModelPreLink(scope, element, attr, ctrls) {
25356 var modelCtrl = ctrls[0],
25357 formCtrl = ctrls[1] || nullFormCtrl;
25358
25359 modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
25360
25361 // notify others, especially parent forms
25362 formCtrl.$addControl(modelCtrl);
25363
25364 attr.$observe('name', function(newValue) {
25365 if (modelCtrl.$name !== newValue) {
25366 formCtrl.$$renameControl(modelCtrl, newValue);
25367 }
25368 });
25369
25370 scope.$on('$destroy', function() {
25371 formCtrl.$removeControl(modelCtrl);
25372 });
25373 },
25374 post: function ngModelPostLink(scope, element, attr, ctrls) {
25375 var modelCtrl = ctrls[0];
25376 if (modelCtrl.$options && modelCtrl.$options.updateOn) {
25377 element.on(modelCtrl.$options.updateOn, function(ev) {
25378 modelCtrl.$$debounceViewValueCommit(ev && ev.type);
25379 });
25380 }
25381
25382 element.on('blur', function(ev) {
25383 if (modelCtrl.$touched) return;
25384
25385 if ($rootScope.$$phase) {
25386 scope.$evalAsync(modelCtrl.$setTouched);
25387 } else {
25388 scope.$apply(modelCtrl.$setTouched);
25389 }
25390 });
25391 }
25392 };
25393 }
25394 };
25395 }];
25396
25397 var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/;
25398
25399 /**
25400 * @ngdoc directive
25401 * @name ngModelOptions
25402 *
25403 * @description
25404 * Allows tuning how model updates are done. Using `ngModelOptions` you can specify a custom list of
25405 * events that will trigger a model update and/or a debouncing delay so that the actual update only
25406 * takes place when a timer expires; this timer will be reset after another change takes place.
25407 *
25408 * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might
25409 * be different from the value in the actual model. This means that if you update the model you
25410 * should also invoke {@link ngModel.NgModelController `$rollbackViewValue`} on the relevant input field in
25411 * order to make sure it is synchronized with the model and that any debounced action is canceled.
25412 *
25413 * The easiest way to reference the control's {@link ngModel.NgModelController `$rollbackViewValue`}
25414 * method is by making sure the input is placed inside a form that has a `name` attribute. This is
25415 * important because `form` controllers are published to the related scope under the name in their
25416 * `name` attribute.
25417 *
25418 * Any pending changes will take place immediately when an enclosing form is submitted via the
25419 * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
25420 * to have access to the updated model.
25421 *
25422 * `ngModelOptions` has an effect on the element it's declared on and its descendants.
25423 *
25424 * @param {Object} ngModelOptions options to apply to the current model. Valid keys are:
25425 * - `updateOn`: string specifying which event should the input be bound to. You can set several
25426 * events using an space delimited list. There is a special event called `default` that
25427 * matches the default events belonging of the control.
25428 * - `debounce`: integer value which contains the debounce model update value in milliseconds. A
25429 * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a
25430 * custom value for each event. For example:
25431 * `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 500, 'blur': 0 } }"`
25432 * - `allowInvalid`: boolean value which indicates that the model can be set with values that did
25433 * not validate correctly instead of the default behavior of setting the model to undefined.
25434 * - `getterSetter`: boolean value which determines whether or not to treat functions bound to
25435 `ngModel` as getters/setters.
25436 * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for
25437 * `<input type="date">`, `<input type="time">`, ... . It understands UTC/GMT and the
25438 * continental US time zone abbreviations, but for general use, use a time zone offset, for
25439 * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian)
25440 * If not specified, the timezone of the browser will be used.
25441 *
25442 * @example
25443
25444 The following example shows how to override immediate updates. Changes on the inputs within the
25445 form will update the model only when the control loses focus (blur event). If `escape` key is
25446 pressed while the input field is focused, the value is reset to the value in the current model.
25447
25448 <example name="ngModelOptions-directive-blur" module="optionsExample">
25449 <file name="index.html">
25450 <div ng-controller="ExampleController">
25451 <form name="userForm">
25452 <label>Name:
25453 <input type="text" name="userName"
25454 ng-model="user.name"
25455 ng-model-options="{ updateOn: 'blur' }"
25456 ng-keyup="cancel($event)" />
25457 </label><br />
25458 <label>Other data:
25459 <input type="text" ng-model="user.data" />
25460 </label><br />
25461 </form>
25462 <pre>user.name = <span ng-bind="user.name"></span></pre>
25463 </div>
25464 </file>
25465 <file name="app.js">
25466 angular.module('optionsExample', [])
25467 .controller('ExampleController', ['$scope', function($scope) {
25468 $scope.user = { name: 'say', data: '' };
25469
25470 $scope.cancel = function(e) {
25471 if (e.keyCode == 27) {
25472 $scope.userForm.userName.$rollbackViewValue();
25473 }
25474 };
25475 }]);
25476 </file>
25477 <file name="protractor.js" type="protractor">
25478 var model = element(by.binding('user.name'));
25479 var input = element(by.model('user.name'));
25480 var other = element(by.model('user.data'));
25481
25482 it('should allow custom events', function() {
25483 input.sendKeys(' hello');
25484 input.click();
25485 expect(model.getText()).toEqual('say');
25486 other.click();
25487 expect(model.getText()).toEqual('say hello');
25488 });
25489
25490 it('should $rollbackViewValue when model changes', function() {
25491 input.sendKeys(' hello');
25492 expect(input.getAttribute('value')).toEqual('say hello');
25493 input.sendKeys(protractor.Key.ESCAPE);
25494 expect(input.getAttribute('value')).toEqual('say');
25495 other.click();
25496 expect(model.getText()).toEqual('say');
25497 });
25498 </file>
25499 </example>
25500
25501 This one shows how to debounce model changes. Model will be updated only 1 sec after last change.
25502 If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty.
25503
25504 <example name="ngModelOptions-directive-debounce" module="optionsExample">
25505 <file name="index.html">
25506 <div ng-controller="ExampleController">
25507 <form name="userForm">
25508 <label>Name:
25509 <input type="text" name="userName"
25510 ng-model="user.name"
25511 ng-model-options="{ debounce: 1000 }" />
25512 </label>
25513 <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button>
25514 <br />
25515 </form>
25516 <pre>user.name = <span ng-bind="user.name"></span></pre>
25517 </div>
25518 </file>
25519 <file name="app.js">
25520 angular.module('optionsExample', [])
25521 .controller('ExampleController', ['$scope', function($scope) {
25522 $scope.user = { name: 'say' };
25523 }]);
25524 </file>
25525 </example>
25526
25527 This one shows how to bind to getter/setters:
25528
25529 <example name="ngModelOptions-directive-getter-setter" module="getterSetterExample">
25530 <file name="index.html">
25531 <div ng-controller="ExampleController">
25532 <form name="userForm">
25533 <label>Name:
25534 <input type="text" name="userName"
25535 ng-model="user.name"
25536 ng-model-options="{ getterSetter: true }" />
25537 </label>
25538 </form>
25539 <pre>user.name = <span ng-bind="user.name()"></span></pre>
25540 </div>
25541 </file>
25542 <file name="app.js">
25543 angular.module('getterSetterExample', [])
25544 .controller('ExampleController', ['$scope', function($scope) {
25545 var _name = 'Brian';
25546 $scope.user = {
25547 name: function(newName) {
25548 // Note that newName can be undefined for two reasons:
25549 // 1. Because it is called as a getter and thus called with no arguments
25550 // 2. Because the property should actually be set to undefined. This happens e.g. if the
25551 // input is invalid
25552 return arguments.length ? (_name = newName) : _name;
25553 }
25554 };
25555 }]);
25556 </file>
25557 </example>
25558 */
25559 var ngModelOptionsDirective = function() {
25560 return {
25561 restrict: 'A',
25562 controller: ['$scope', '$attrs', function($scope, $attrs) {
25563 var that = this;
25564 this.$options = copy($scope.$eval($attrs.ngModelOptions));
25565 // Allow adding/overriding bound events
25566 if (this.$options.updateOn !== undefined) {
25567 this.$options.updateOnDefault = false;
25568 // extract "default" pseudo-event from list of events that can trigger a model update
25569 this.$options.updateOn = trim(this.$options.updateOn.replace(DEFAULT_REGEXP, function() {
25570 that.$options.updateOnDefault = true;
25571 return ' ';
25572 }));
25573 } else {
25574 this.$options.updateOnDefault = true;
25575 }
25576 }]
25577 };
25578 };
25579
25580
25581
25582 // helper methods
25583 function addSetValidityMethod(context) {
25584 var ctrl = context.ctrl,
25585 $element = context.$element,
25586 classCache = {},
25587 set = context.set,
25588 unset = context.unset,
25589 parentForm = context.parentForm,
25590 $animate = context.$animate;
25591
25592 classCache[INVALID_CLASS] = !(classCache[VALID_CLASS] = $element.hasClass(VALID_CLASS));
25593
25594 ctrl.$setValidity = setValidity;
25595
25596 function setValidity(validationErrorKey, state, controller) {
25597 if (state === undefined) {
25598 createAndSet('$pending', validationErrorKey, controller);
25599 } else {
25600 unsetAndCleanup('$pending', validationErrorKey, controller);
25601 }
25602 if (!isBoolean(state)) {
25603 unset(ctrl.$error, validationErrorKey, controller);
25604 unset(ctrl.$$success, validationErrorKey, controller);
25605 } else {
25606 if (state) {
25607 unset(ctrl.$error, validationErrorKey, controller);
25608 set(ctrl.$$success, validationErrorKey, controller);
25609 } else {
25610 set(ctrl.$error, validationErrorKey, controller);
25611 unset(ctrl.$$success, validationErrorKey, controller);
25612 }
25613 }
25614 if (ctrl.$pending) {
25615 cachedToggleClass(PENDING_CLASS, true);
25616 ctrl.$valid = ctrl.$invalid = undefined;
25617 toggleValidationCss('', null);
25618 } else {
25619 cachedToggleClass(PENDING_CLASS, false);
25620 ctrl.$valid = isObjectEmpty(ctrl.$error);
25621 ctrl.$invalid = !ctrl.$valid;
25622 toggleValidationCss('', ctrl.$valid);
25623 }
25624
25625 // re-read the state as the set/unset methods could have
25626 // combined state in ctrl.$error[validationError] (used for forms),
25627 // where setting/unsetting only increments/decrements the value,
25628 // and does not replace it.
25629 var combinedState;
25630 if (ctrl.$pending && ctrl.$pending[validationErrorKey]) {
25631 combinedState = undefined;
25632 } else if (ctrl.$error[validationErrorKey]) {
25633 combinedState = false;
25634 } else if (ctrl.$$success[validationErrorKey]) {
25635 combinedState = true;
25636 } else {
25637 combinedState = null;
25638 }
25639
25640 toggleValidationCss(validationErrorKey, combinedState);
25641 parentForm.$setValidity(validationErrorKey, combinedState, ctrl);
25642 }
25643
25644 function createAndSet(name, value, controller) {
25645 if (!ctrl[name]) {
25646 ctrl[name] = {};
25647 }
25648 set(ctrl[name], value, controller);
25649 }
25650
25651 function unsetAndCleanup(name, value, controller) {
25652 if (ctrl[name]) {
25653 unset(ctrl[name], value, controller);
25654 }
25655 if (isObjectEmpty(ctrl[name])) {
25656 ctrl[name] = undefined;
25657 }
25658 }
25659
25660 function cachedToggleClass(className, switchValue) {
25661 if (switchValue && !classCache[className]) {
25662 $animate.addClass($element, className);
25663 classCache[className] = true;
25664 } else if (!switchValue && classCache[className]) {
25665 $animate.removeClass($element, className);
25666 classCache[className] = false;
25667 }
25668 }
25669
25670 function toggleValidationCss(validationErrorKey, isValid) {
25671 validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
25672
25673 cachedToggleClass(VALID_CLASS + validationErrorKey, isValid === true);
25674 cachedToggleClass(INVALID_CLASS + validationErrorKey, isValid === false);
25675 }
25676 }
25677
25678 function isObjectEmpty(obj) {
25679 if (obj) {
25680 for (var prop in obj) {
25681 if (obj.hasOwnProperty(prop)) {
25682 return false;
25683 }
25684 }
25685 }
25686 return true;
25687 }
25688
25689 /**
25690 * @ngdoc directive
25691 * @name ngNonBindable
25692 * @restrict AC
25693 * @priority 1000
25694 *
25695 * @description
25696 * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
25697 * DOM element. This is useful if the element contains what appears to be Angular directives and
25698 * bindings but which should be ignored by Angular. This could be the case if you have a site that
25699 * displays snippets of code, for instance.
25700 *
25701 * @element ANY
25702 *
25703 * @example
25704 * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
25705 * but the one wrapped in `ngNonBindable` is left alone.
25706 *
25707 * @example
25708 <example>
25709 <file name="index.html">
25710 <div>Normal: {{1 + 2}}</div>
25711 <div ng-non-bindable>Ignored: {{1 + 2}}</div>
25712 </file>
25713 <file name="protractor.js" type="protractor">
25714 it('should check ng-non-bindable', function() {
25715 expect(element(by.binding('1 + 2')).getText()).toContain('3');
25716 expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/);
25717 });
25718 </file>
25719 </example>
25720 */
25721 var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
25722
25723 /* global jqLiteRemove */
25724
25725 var ngOptionsMinErr = minErr('ngOptions');
25726
25727 /**
25728 * @ngdoc directive
25729 * @name ngOptions
25730 * @restrict A
25731 *
25732 * @description
25733 *
25734 * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
25735 * elements for the `<select>` element using the array or object obtained by evaluating the
25736 * `ngOptions` comprehension expression.
25737 *
25738 * In many cases, `ngRepeat` can be used on `<option>` elements instead of `ngOptions` to achieve a
25739 * similar result. However, `ngOptions` provides some benefits such as reducing memory and
25740 * increasing speed by not creating a new scope for each repeated instance, as well as providing
25741 * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
25742 * comprehension expression. `ngOptions` should be used when the `<select>` model needs to be bound
25743 * to a non-string value. This is because an option element can only be bound to string values at
25744 * present.
25745 *
25746 * When an item in the `<select>` menu is selected, the array element or object property
25747 * represented by the selected option will be bound to the model identified by the `ngModel`
25748 * directive.
25749 *
25750 * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
25751 * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
25752 * option. See example below for demonstration.
25753 *
25754 * ## Complex Models (objects or collections)
25755 *
25756 * **Note:** By default, `ngModel` watches the model by reference, not value. This is important when
25757 * binding any input directive to a model that is an object or a collection.
25758 *
25759 * Since this is a common situation for `ngOptions` the directive additionally watches the model using
25760 * `$watchCollection` when the select has the `multiple` attribute or when there is a `track by` clause in
25761 * the options expression. This allows ngOptions to trigger a re-rendering of the options even if the actual
25762 * object/collection has not changed identity but only a property on the object or an item in the collection
25763 * changes.
25764 *
25765 * Note that `$watchCollection` does a shallow comparison of the properties of the object (or the items in the collection
25766 * if the model is an array). This means that changing a property deeper inside the object/collection that the
25767 * first level will not trigger a re-rendering.
25768 *
25769 *
25770 * ## `select` **`as`**
25771 *
25772 * Using `select` **`as`** will bind the result of the `select` expression to the model, but
25773 * the value of the `<select>` and `<option>` html elements will be either the index (for array data sources)
25774 * or property name (for object data sources) of the value within the collection. If a **`track by`** expression
25775 * is used, the result of that expression will be set as the value of the `option` and `select` elements.
25776 *
25777 *
25778 * ### `select` **`as`** and **`track by`**
25779 *
25780 * <div class="alert alert-warning">
25781 * Do not use `select` **`as`** and **`track by`** in the same expression. They are not designed to work together.
25782 * </div>
25783 *
25784 * Consider the following example:
25785 *
25786 * ```html
25787 * <select ng-options="item.subItem as item.label for item in values track by item.id" ng-model="selected">
25788 * ```
25789 *
25790 * ```js
25791 * $scope.values = [{
25792 * id: 1,
25793 * label: 'aLabel',
25794 * subItem: { name: 'aSubItem' }
25795 * }, {
25796 * id: 2,
25797 * label: 'bLabel',
25798 * subItem: { name: 'bSubItem' }
25799 * }];
25800 *
25801 * $scope.selected = { name: 'aSubItem' };
25802 * ```
25803 *
25804 * With the purpose of preserving the selection, the **`track by`** expression is always applied to the element
25805 * of the data source (to `item` in this example). To calculate whether an element is selected, we do the
25806 * following:
25807 *
25808 * 1. Apply **`track by`** to the elements in the array. In the example: `[1, 2]`
25809 * 2. Apply **`track by`** to the already selected value in `ngModel`.
25810 * In the example: this is not possible as **`track by`** refers to `item.id`, but the selected
25811 * value from `ngModel` is `{name: 'aSubItem'}`, so the **`track by`** expression is applied to
25812 * a wrong object, the selected element can't be found, `<select>` is always reset to the "not
25813 * selected" option.
25814 *
25815 *
25816 * @param {string} ngModel Assignable angular expression to data-bind to.
25817 * @param {string=} name Property name of the form under which the control is published.
25818 * @param {string=} required The control is considered valid only if value is entered.
25819 * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
25820 * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
25821 * `required` when you want to data-bind to the `required` attribute.
25822 * @param {comprehension_expression=} ngOptions in one of the following forms:
25823 *
25824 * * for array data sources:
25825 * * `label` **`for`** `value` **`in`** `array`
25826 * * `select` **`as`** `label` **`for`** `value` **`in`** `array`
25827 * * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
25828 * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array`
25829 * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
25830 * * `label` **`disable when`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
25831 * * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
25832 * (for including a filter with `track by`)
25833 * * for object data sources:
25834 * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
25835 * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
25836 * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
25837 * * `label` **`disable when`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object`
25838 * * `select` **`as`** `label` **`group by`** `group`
25839 * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
25840 * * `select` **`as`** `label` **`disable when`** `disable`
25841 * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
25842 *
25843 * Where:
25844 *
25845 * * `array` / `object`: an expression which evaluates to an array / object to iterate over.
25846 * * `value`: local variable which will refer to each item in the `array` or each property value
25847 * of `object` during iteration.
25848 * * `key`: local variable which will refer to a property name in `object` during iteration.
25849 * * `label`: The result of this expression will be the label for `<option>` element. The
25850 * `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
25851 * * `select`: The result of this expression will be bound to the model of the parent `<select>`
25852 * element. If not specified, `select` expression will default to `value`.
25853 * * `group`: The result of this expression will be used to group options using the `<optgroup>`
25854 * DOM element.
25855 * * `disable`: The result of this expression will be used to disable the rendered `<option>`
25856 * element. Return `true` to disable.
25857 * * `trackexpr`: Used when working with an array of objects. The result of this expression will be
25858 * used to identify the objects in the array. The `trackexpr` will most likely refer to the
25859 * `value` variable (e.g. `value.propertyName`). With this the selection is preserved
25860 * even when the options are recreated (e.g. reloaded from the server).
25861 *
25862 * @example
25863 <example module="selectExample">
25864 <file name="index.html">
25865 <script>
25866 angular.module('selectExample', [])
25867 .controller('ExampleController', ['$scope', function($scope) {
25868 $scope.colors = [
25869 {name:'black', shade:'dark'},
25870 {name:'white', shade:'light', notAnOption: true},
25871 {name:'red', shade:'dark'},
25872 {name:'blue', shade:'dark', notAnOption: true},
25873 {name:'yellow', shade:'light', notAnOption: false}
25874 ];
25875 $scope.myColor = $scope.colors[2]; // red
25876 }]);
25877 </script>
25878 <div ng-controller="ExampleController">
25879 <ul>
25880 <li ng-repeat="color in colors">
25881 <label>Name: <input ng-model="color.name"></label>
25882 <label><input type="checkbox" ng-model="color.notAnOption"> Disabled?</label>
25883 <button ng-click="colors.splice($index, 1)" aria-label="Remove">X</button>
25884 </li>
25885 <li>
25886 <button ng-click="colors.push({})">add</button>
25887 </li>
25888 </ul>
25889 <hr/>
25890 <label>Color (null not allowed):
25891 <select ng-model="myColor" ng-options="color.name for color in colors"></select>
25892 </label><br/>
25893 <label>Color (null allowed):
25894 <span class="nullable">
25895 <select ng-model="myColor" ng-options="color.name for color in colors">
25896 <option value="">-- choose color --</option>
25897 </select>
25898 </span></label><br/>
25899
25900 <label>Color grouped by shade:
25901 <select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
25902 </select>
25903 </label><br/>
25904
25905 <label>Color grouped by shade, with some disabled:
25906 <select ng-model="myColor"
25907 ng-options="color.name group by color.shade disable when color.notAnOption for color in colors">
25908 </select>
25909 </label><br/>
25910
25911
25912
25913 Select <button ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</button>.
25914 <br/>
25915 <hr/>
25916 Currently selected: {{ {selected_color:myColor} }}
25917 <div style="border:solid 1px black; height:20px"
25918 ng-style="{'background-color':myColor.name}">
25919 </div>
25920 </div>
25921 </file>
25922 <file name="protractor.js" type="protractor">
25923 it('should check ng-options', function() {
25924 expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('red');
25925 element.all(by.model('myColor')).first().click();
25926 element.all(by.css('select[ng-model="myColor"] option')).first().click();
25927 expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('black');
25928 element(by.css('.nullable select[ng-model="myColor"]')).click();
25929 element.all(by.css('.nullable select[ng-model="myColor"] option')).first().click();
25930 expect(element(by.binding('{selected_color:myColor}')).getText()).toMatch('null');
25931 });
25932 </file>
25933 </example>
25934 */
25935
25936 // jshint maxlen: false
25937 // //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999
25938 var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
25939 // 1: value expression (valueFn)
25940 // 2: label expression (displayFn)
25941 // 3: group by expression (groupByFn)
25942 // 4: disable when expression (disableWhenFn)
25943 // 5: array item variable name
25944 // 6: object item key variable name
25945 // 7: object item value variable name
25946 // 8: collection expression
25947 // 9: track by expression
25948 // jshint maxlen: 100
25949
25950
25951 var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
25952
25953 function parseOptionsExpression(optionsExp, selectElement, scope) {
25954
25955 var match = optionsExp.match(NG_OPTIONS_REGEXP);
25956 if (!(match)) {
25957 throw ngOptionsMinErr('iexp',
25958 "Expected expression in form of " +
25959 "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
25960 " but got '{0}'. Element: {1}",
25961 optionsExp, startingTag(selectElement));
25962 }
25963
25964 // Extract the parts from the ngOptions expression
25965
25966 // The variable name for the value of the item in the collection
25967 var valueName = match[5] || match[7];
25968 // The variable name for the key of the item in the collection
25969 var keyName = match[6];
25970
25971 // An expression that generates the viewValue for an option if there is a label expression
25972 var selectAs = / as /.test(match[0]) && match[1];
25973 // An expression that is used to track the id of each object in the options collection
25974 var trackBy = match[9];
25975 // An expression that generates the viewValue for an option if there is no label expression
25976 var valueFn = $parse(match[2] ? match[1] : valueName);
25977 var selectAsFn = selectAs && $parse(selectAs);
25978 var viewValueFn = selectAsFn || valueFn;
25979 var trackByFn = trackBy && $parse(trackBy);
25980
25981 // Get the value by which we are going to track the option
25982 // if we have a trackFn then use that (passing scope and locals)
25983 // otherwise just hash the given viewValue
25984 var getTrackByValueFn = trackBy ?
25985 function(value, locals) { return trackByFn(scope, locals); } :
25986 function getHashOfValue(value) { return hashKey(value); };
25987 var getTrackByValue = function(value, key) {
25988 return getTrackByValueFn(value, getLocals(value, key));
25989 };
25990
25991 var displayFn = $parse(match[2] || match[1]);
25992 var groupByFn = $parse(match[3] || '');
25993 var disableWhenFn = $parse(match[4] || '');
25994 var valuesFn = $parse(match[8]);
25995
25996 var locals = {};
25997 var getLocals = keyName ? function(value, key) {
25998 locals[keyName] = key;
25999 locals[valueName] = value;
26000 return locals;
26001 } : function(value) {
26002 locals[valueName] = value;
26003 return locals;
26004 };
26005
26006
26007 function Option(selectValue, viewValue, label, group, disabled) {
26008 this.selectValue = selectValue;
26009 this.viewValue = viewValue;
26010 this.label = label;
26011 this.group = group;
26012 this.disabled = disabled;
26013 }
26014
26015 function getOptionValuesKeys(optionValues) {
26016 var optionValuesKeys;
26017
26018 if (!keyName && isArrayLike(optionValues)) {
26019 optionValuesKeys = optionValues;
26020 } else {
26021 // if object, extract keys, in enumeration order, unsorted
26022 optionValuesKeys = [];
26023 for (var itemKey in optionValues) {
26024 if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
26025 optionValuesKeys.push(itemKey);
26026 }
26027 }
26028 }
26029 return optionValuesKeys;
26030 }
26031
26032 return {
26033 trackBy: trackBy,
26034 getTrackByValue: getTrackByValue,
26035 getWatchables: $parse(valuesFn, function(optionValues) {
26036 // Create a collection of things that we would like to watch (watchedArray)
26037 // so that they can all be watched using a single $watchCollection
26038 // that only runs the handler once if anything changes
26039 var watchedArray = [];
26040 optionValues = optionValues || [];
26041
26042 var optionValuesKeys = getOptionValuesKeys(optionValues);
26043 var optionValuesLength = optionValuesKeys.length;
26044 for (var index = 0; index < optionValuesLength; index++) {
26045 var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
26046 var value = optionValues[key];
26047
26048 var locals = getLocals(optionValues[key], key);
26049 var selectValue = getTrackByValueFn(optionValues[key], locals);
26050 watchedArray.push(selectValue);
26051
26052 // Only need to watch the displayFn if there is a specific label expression
26053 if (match[2] || match[1]) {
26054 var label = displayFn(scope, locals);
26055 watchedArray.push(label);
26056 }
26057
26058 // Only need to watch the disableWhenFn if there is a specific disable expression
26059 if (match[4]) {
26060 var disableWhen = disableWhenFn(scope, locals);
26061 watchedArray.push(disableWhen);
26062 }
26063 }
26064 return watchedArray;
26065 }),
26066
26067 getOptions: function() {
26068
26069 var optionItems = [];
26070 var selectValueMap = {};
26071
26072 // The option values were already computed in the `getWatchables` fn,
26073 // which must have been called to trigger `getOptions`
26074 var optionValues = valuesFn(scope) || [];
26075 var optionValuesKeys = getOptionValuesKeys(optionValues);
26076 var optionValuesLength = optionValuesKeys.length;
26077
26078 for (var index = 0; index < optionValuesLength; index++) {
26079 var key = (optionValues === optionValuesKeys) ? index : optionValuesKeys[index];
26080 var value = optionValues[key];
26081 var locals = getLocals(value, key);
26082 var viewValue = viewValueFn(scope, locals);
26083 var selectValue = getTrackByValueFn(viewValue, locals);
26084 var label = displayFn(scope, locals);
26085 var group = groupByFn(scope, locals);
26086 var disabled = disableWhenFn(scope, locals);
26087 var optionItem = new Option(selectValue, viewValue, label, group, disabled);
26088
26089 optionItems.push(optionItem);
26090 selectValueMap[selectValue] = optionItem;
26091 }
26092
26093 return {
26094 items: optionItems,
26095 selectValueMap: selectValueMap,
26096 getOptionFromViewValue: function(value) {
26097 return selectValueMap[getTrackByValue(value)];
26098 },
26099 getViewValueFromOption: function(option) {
26100 // If the viewValue could be an object that may be mutated by the application,
26101 // we need to make a copy and not return the reference to the value on the option.
26102 return trackBy ? angular.copy(option.viewValue) : option.viewValue;
26103 }
26104 };
26105 }
26106 };
26107 }
26108
26109
26110 // we can't just jqLite('<option>') since jqLite is not smart enough
26111 // to create it in <select> and IE barfs otherwise.
26112 var optionTemplate = document.createElement('option'),
26113 optGroupTemplate = document.createElement('optgroup');
26114
26115 return {
26116 restrict: 'A',
26117 terminal: true,
26118 require: ['select', '?ngModel'],
26119 link: function(scope, selectElement, attr, ctrls) {
26120
26121 // if ngModel is not defined, we don't need to do anything
26122 var ngModelCtrl = ctrls[1];
26123 if (!ngModelCtrl) return;
26124
26125 var selectCtrl = ctrls[0];
26126 var multiple = attr.multiple;
26127
26128 // The emptyOption allows the application developer to provide their own custom "empty"
26129 // option when the viewValue does not match any of the option values.
26130 var emptyOption;
26131 for (var i = 0, children = selectElement.children(), ii = children.length; i < ii; i++) {
26132 if (children[i].value === '') {
26133 emptyOption = children.eq(i);
26134 break;
26135 }
26136 }
26137
26138 var providedEmptyOption = !!emptyOption;
26139
26140 var unknownOption = jqLite(optionTemplate.cloneNode(false));
26141 unknownOption.val('?');
26142
26143 var options;
26144 var ngOptions = parseOptionsExpression(attr.ngOptions, selectElement, scope);
26145
26146
26147 var renderEmptyOption = function() {
26148 if (!providedEmptyOption) {
26149 selectElement.prepend(emptyOption);
26150 }
26151 selectElement.val('');
26152 emptyOption.prop('selected', true); // needed for IE
26153 emptyOption.attr('selected', true);
26154 };
26155
26156 var removeEmptyOption = function() {
26157 if (!providedEmptyOption) {
26158 emptyOption.remove();
26159 }
26160 };
26161
26162
26163 var renderUnknownOption = function() {
26164 selectElement.prepend(unknownOption);
26165 selectElement.val('?');
26166 unknownOption.prop('selected', true); // needed for IE
26167 unknownOption.attr('selected', true);
26168 };
26169
26170 var removeUnknownOption = function() {
26171 unknownOption.remove();
26172 };
26173
26174
26175 // Update the controller methods for multiple selectable options
26176 if (!multiple) {
26177
26178 selectCtrl.writeValue = function writeNgOptionsValue(value) {
26179 var option = options.getOptionFromViewValue(value);
26180
26181 if (option && !option.disabled) {
26182 if (selectElement[0].value !== option.selectValue) {
26183 removeUnknownOption();
26184 removeEmptyOption();
26185
26186 selectElement[0].value = option.selectValue;
26187 option.element.selected = true;
26188 option.element.setAttribute('selected', 'selected');
26189 }
26190 } else {
26191 if (value === null || providedEmptyOption) {
26192 removeUnknownOption();
26193 renderEmptyOption();
26194 } else {
26195 removeEmptyOption();
26196 renderUnknownOption();
26197 }
26198 }
26199 };
26200
26201 selectCtrl.readValue = function readNgOptionsValue() {
26202
26203 var selectedOption = options.selectValueMap[selectElement.val()];
26204
26205 if (selectedOption && !selectedOption.disabled) {
26206 removeEmptyOption();
26207 removeUnknownOption();
26208 return options.getViewValueFromOption(selectedOption);
26209 }
26210 return null;
26211 };
26212
26213 // If we are using `track by` then we must watch the tracked value on the model
26214 // since ngModel only watches for object identity change
26215 if (ngOptions.trackBy) {
26216 scope.$watch(
26217 function() { return ngOptions.getTrackByValue(ngModelCtrl.$viewValue); },
26218 function() { ngModelCtrl.$render(); }
26219 );
26220 }
26221
26222 } else {
26223
26224 ngModelCtrl.$isEmpty = function(value) {
26225 return !value || value.length === 0;
26226 };
26227
26228
26229 selectCtrl.writeValue = function writeNgOptionsMultiple(value) {
26230 options.items.forEach(function(option) {
26231 option.element.selected = false;
26232 });
26233
26234 if (value) {
26235 value.forEach(function(item) {
26236 var option = options.getOptionFromViewValue(item);
26237 if (option && !option.disabled) option.element.selected = true;
26238 });
26239 }
26240 };
26241
26242
26243 selectCtrl.readValue = function readNgOptionsMultiple() {
26244 var selectedValues = selectElement.val() || [],
26245 selections = [];
26246
26247 forEach(selectedValues, function(value) {
26248 var option = options.selectValueMap[value];
26249 if (!option.disabled) selections.push(options.getViewValueFromOption(option));
26250 });
26251
26252 return selections;
26253 };
26254
26255 // If we are using `track by` then we must watch these tracked values on the model
26256 // since ngModel only watches for object identity change
26257 if (ngOptions.trackBy) {
26258
26259 scope.$watchCollection(function() {
26260 if (isArray(ngModelCtrl.$viewValue)) {
26261 return ngModelCtrl.$viewValue.map(function(value) {
26262 return ngOptions.getTrackByValue(value);
26263 });
26264 }
26265 }, function() {
26266 ngModelCtrl.$render();
26267 });
26268
26269 }
26270 }
26271
26272
26273 if (providedEmptyOption) {
26274
26275 // we need to remove it before calling selectElement.empty() because otherwise IE will
26276 // remove the label from the element. wtf?
26277 emptyOption.remove();
26278
26279 // compile the element since there might be bindings in it
26280 $compile(emptyOption)(scope);
26281
26282 // remove the class, which is added automatically because we recompile the element and it
26283 // becomes the compilation root
26284 emptyOption.removeClass('ng-scope');
26285 } else {
26286 emptyOption = jqLite(optionTemplate.cloneNode(false));
26287 }
26288
26289 // We need to do this here to ensure that the options object is defined
26290 // when we first hit it in writeNgOptionsValue
26291 updateOptions();
26292
26293 // We will re-render the option elements if the option values or labels change
26294 scope.$watchCollection(ngOptions.getWatchables, updateOptions);
26295
26296 // ------------------------------------------------------------------ //
26297
26298
26299 function updateOptionElement(option, element) {
26300 option.element = element;
26301 element.disabled = option.disabled;
26302 if (option.value !== element.value) element.value = option.selectValue;
26303 if (option.label !== element.label) {
26304 element.label = option.label;
26305 element.textContent = option.label;
26306 }
26307 }
26308
26309 function addOrReuseElement(parent, current, type, templateElement) {
26310 var element;
26311 // Check whether we can reuse the next element
26312 if (current && lowercase(current.nodeName) === type) {
26313 // The next element is the right type so reuse it
26314 element = current;
26315 } else {
26316 // The next element is not the right type so create a new one
26317 element = templateElement.cloneNode(false);
26318 if (!current) {
26319 // There are no more elements so just append it to the select
26320 parent.appendChild(element);
26321 } else {
26322 // The next element is not a group so insert the new one
26323 parent.insertBefore(element, current);
26324 }
26325 }
26326 return element;
26327 }
26328
26329
26330 function removeExcessElements(current) {
26331 var next;
26332 while (current) {
26333 next = current.nextSibling;
26334 jqLiteRemove(current);
26335 current = next;
26336 }
26337 }
26338
26339
26340 function skipEmptyAndUnknownOptions(current) {
26341 var emptyOption_ = emptyOption && emptyOption[0];
26342 var unknownOption_ = unknownOption && unknownOption[0];
26343
26344 if (emptyOption_ || unknownOption_) {
26345 while (current &&
26346 (current === emptyOption_ ||
26347 current === unknownOption_)) {
26348 current = current.nextSibling;
26349 }
26350 }
26351 return current;
26352 }
26353
26354
26355 function updateOptions() {
26356
26357 var previousValue = options && selectCtrl.readValue();
26358
26359 options = ngOptions.getOptions();
26360
26361 var groupMap = {};
26362 var currentElement = selectElement[0].firstChild;
26363
26364 // Ensure that the empty option is always there if it was explicitly provided
26365 if (providedEmptyOption) {
26366 selectElement.prepend(emptyOption);
26367 }
26368
26369 currentElement = skipEmptyAndUnknownOptions(currentElement);
26370
26371 options.items.forEach(function updateOption(option) {
26372 var group;
26373 var groupElement;
26374 var optionElement;
26375
26376 if (option.group) {
26377
26378 // This option is to live in a group
26379 // See if we have already created this group
26380 group = groupMap[option.group];
26381
26382 if (!group) {
26383
26384 // We have not already created this group
26385 groupElement = addOrReuseElement(selectElement[0],
26386 currentElement,
26387 'optgroup',
26388 optGroupTemplate);
26389 // Move to the next element
26390 currentElement = groupElement.nextSibling;
26391
26392 // Update the label on the group element
26393 groupElement.label = option.group;
26394
26395 // Store it for use later
26396 group = groupMap[option.group] = {
26397 groupElement: groupElement,
26398 currentOptionElement: groupElement.firstChild
26399 };
26400
26401 }
26402
26403 // So now we have a group for this option we add the option to the group
26404 optionElement = addOrReuseElement(group.groupElement,
26405 group.currentOptionElement,
26406 'option',
26407 optionTemplate);
26408 updateOptionElement(option, optionElement);
26409 // Move to the next element
26410 group.currentOptionElement = optionElement.nextSibling;
26411
26412 } else {
26413
26414 // This option is not in a group
26415 optionElement = addOrReuseElement(selectElement[0],
26416 currentElement,
26417 'option',
26418 optionTemplate);
26419 updateOptionElement(option, optionElement);
26420 // Move to the next element
26421 currentElement = optionElement.nextSibling;
26422 }
26423 });
26424
26425
26426 // Now remove all excess options and group
26427 Object.keys(groupMap).forEach(function(key) {
26428 removeExcessElements(groupMap[key].currentOptionElement);
26429 });
26430 removeExcessElements(currentElement);
26431
26432 ngModelCtrl.$render();
26433
26434 // Check to see if the value has changed due to the update to the options
26435 if (!ngModelCtrl.$isEmpty(previousValue)) {
26436 var nextValue = selectCtrl.readValue();
26437 if (ngOptions.trackBy ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
26438 ngModelCtrl.$setViewValue(nextValue);
26439 ngModelCtrl.$render();
26440 }
26441 }
26442
26443 }
26444
26445 }
26446 };
26447 }];
26448
26449 /**
26450 * @ngdoc directive
26451 * @name ngPluralize
26452 * @restrict EA
26453 *
26454 * @description
26455 * `ngPluralize` is a directive that displays messages according to en-US localization rules.
26456 * These rules are bundled with angular.js, but can be overridden
26457 * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
26458 * by specifying the mappings between
26459 * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
26460 * and the strings to be displayed.
26461 *
26462 * # Plural categories and explicit number rules
26463 * There are two
26464 * [plural categories](http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html)
26465 * in Angular's default en-US locale: "one" and "other".
26466 *
26467 * While a plural category may match many numbers (for example, in en-US locale, "other" can match
26468 * any number that is not 1), an explicit number rule can only match one number. For example, the
26469 * explicit number rule for "3" matches the number 3. There are examples of plural categories
26470 * and explicit number rules throughout the rest of this documentation.
26471 *
26472 * # Configuring ngPluralize
26473 * You configure ngPluralize by providing 2 attributes: `count` and `when`.
26474 * You can also provide an optional attribute, `offset`.
26475 *
26476 * The value of the `count` attribute can be either a string or an {@link guide/expression
26477 * Angular expression}; these are evaluated on the current scope for its bound value.
26478 *
26479 * The `when` attribute specifies the mappings between plural categories and the actual
26480 * string to be displayed. The value of the attribute should be a JSON object.
26481 *
26482 * The following example shows how to configure ngPluralize:
26483 *
26484 * ```html
26485 * <ng-pluralize count="personCount"
26486 when="{'0': 'Nobody is viewing.',
26487 * 'one': '1 person is viewing.',
26488 * 'other': '{} people are viewing.'}">
26489 * </ng-pluralize>
26490 *```
26491 *
26492 * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
26493 * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
26494 * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
26495 * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
26496 * show "a dozen people are viewing".
26497 *
26498 * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
26499 * into pluralized strings. In the previous example, Angular will replace `{}` with
26500 * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
26501 * for <span ng-non-bindable>{{numberExpression}}</span>.
26502 *
26503 * If no rule is defined for a category, then an empty string is displayed and a warning is generated.
26504 * Note that some locales define more categories than `one` and `other`. For example, fr-fr defines `few` and `many`.
26505 *
26506 * # Configuring ngPluralize with offset
26507 * The `offset` attribute allows further customization of pluralized text, which can result in
26508 * a better user experience. For example, instead of the message "4 people are viewing this document",
26509 * you might display "John, Kate and 2 others are viewing this document".
26510 * The offset attribute allows you to offset a number by any desired value.
26511 * Let's take a look at an example:
26512 *
26513 * ```html
26514 * <ng-pluralize count="personCount" offset=2
26515 * when="{'0': 'Nobody is viewing.',
26516 * '1': '{{person1}} is viewing.',
26517 * '2': '{{person1}} and {{person2}} are viewing.',
26518 * 'one': '{{person1}}, {{person2}} and one other person are viewing.',
26519 * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
26520 * </ng-pluralize>
26521 * ```
26522 *
26523 * Notice that we are still using two plural categories(one, other), but we added
26524 * three explicit number rules 0, 1 and 2.
26525 * When one person, perhaps John, views the document, "John is viewing" will be shown.
26526 * When three people view the document, no explicit number rule is found, so
26527 * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
26528 * In this case, plural category 'one' is matched and "John, Mary and one other person are viewing"
26529 * is shown.
26530 *
26531 * Note that when you specify offsets, you must provide explicit number rules for
26532 * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
26533 * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
26534 * plural categories "one" and "other".
26535 *
26536 * @param {string|expression} count The variable to be bound to.
26537 * @param {string} when The mapping between plural category to its corresponding strings.
26538 * @param {number=} offset Offset to deduct from the total number.
26539 *
26540 * @example
26541 <example module="pluralizeExample">
26542 <file name="index.html">
26543 <script>
26544 angular.module('pluralizeExample', [])
26545 .controller('ExampleController', ['$scope', function($scope) {
26546 $scope.person1 = 'Igor';
26547 $scope.person2 = 'Misko';
26548 $scope.personCount = 1;
26549 }]);
26550 </script>
26551 <div ng-controller="ExampleController">
26552 <label>Person 1:<input type="text" ng-model="person1" value="Igor" /></label><br/>
26553 <label>Person 2:<input type="text" ng-model="person2" value="Misko" /></label><br/>
26554 <label>Number of People:<input type="text" ng-model="personCount" value="1" /></label><br/>
26555
26556 <!--- Example with simple pluralization rules for en locale --->
26557 Without Offset:
26558 <ng-pluralize count="personCount"
26559 when="{'0': 'Nobody is viewing.',
26560 'one': '1 person is viewing.',
26561 'other': '{} people are viewing.'}">
26562 </ng-pluralize><br>
26563
26564 <!--- Example with offset --->
26565 With Offset(2):
26566 <ng-pluralize count="personCount" offset=2
26567 when="{'0': 'Nobody is viewing.',
26568 '1': '{{person1}} is viewing.',
26569 '2': '{{person1}} and {{person2}} are viewing.',
26570 'one': '{{person1}}, {{person2}} and one other person are viewing.',
26571 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
26572 </ng-pluralize>
26573 </div>
26574 </file>
26575 <file name="protractor.js" type="protractor">
26576 it('should show correct pluralized string', function() {
26577 var withoutOffset = element.all(by.css('ng-pluralize')).get(0);
26578 var withOffset = element.all(by.css('ng-pluralize')).get(1);
26579 var countInput = element(by.model('personCount'));
26580
26581 expect(withoutOffset.getText()).toEqual('1 person is viewing.');
26582 expect(withOffset.getText()).toEqual('Igor is viewing.');
26583
26584 countInput.clear();
26585 countInput.sendKeys('0');
26586
26587 expect(withoutOffset.getText()).toEqual('Nobody is viewing.');
26588 expect(withOffset.getText()).toEqual('Nobody is viewing.');
26589
26590 countInput.clear();
26591 countInput.sendKeys('2');
26592
26593 expect(withoutOffset.getText()).toEqual('2 people are viewing.');
26594 expect(withOffset.getText()).toEqual('Igor and Misko are viewing.');
26595
26596 countInput.clear();
26597 countInput.sendKeys('3');
26598
26599 expect(withoutOffset.getText()).toEqual('3 people are viewing.');
26600 expect(withOffset.getText()).toEqual('Igor, Misko and one other person are viewing.');
26601
26602 countInput.clear();
26603 countInput.sendKeys('4');
26604
26605 expect(withoutOffset.getText()).toEqual('4 people are viewing.');
26606 expect(withOffset.getText()).toEqual('Igor, Misko and 2 other people are viewing.');
26607 });
26608 it('should show data-bound names', function() {
26609 var withOffset = element.all(by.css('ng-pluralize')).get(1);
26610 var personCount = element(by.model('personCount'));
26611 var person1 = element(by.model('person1'));
26612 var person2 = element(by.model('person2'));
26613 personCount.clear();
26614 personCount.sendKeys('4');
26615 person1.clear();
26616 person1.sendKeys('Di');
26617 person2.clear();
26618 person2.sendKeys('Vojta');
26619 expect(withOffset.getText()).toEqual('Di, Vojta and 2 other people are viewing.');
26620 });
26621 </file>
26622 </example>
26623 */
26624 var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale, $interpolate, $log) {
26625 var BRACE = /{}/g,
26626 IS_WHEN = /^when(Minus)?(.+)$/;
26627
26628 return {
26629 link: function(scope, element, attr) {
26630 var numberExp = attr.count,
26631 whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
26632 offset = attr.offset || 0,
26633 whens = scope.$eval(whenExp) || {},
26634 whensExpFns = {},
26635 startSymbol = $interpolate.startSymbol(),
26636 endSymbol = $interpolate.endSymbol(),
26637 braceReplacement = startSymbol + numberExp + '-' + offset + endSymbol,
26638 watchRemover = angular.noop,
26639 lastCount;
26640
26641 forEach(attr, function(expression, attributeName) {
26642 var tmpMatch = IS_WHEN.exec(attributeName);
26643 if (tmpMatch) {
26644 var whenKey = (tmpMatch[1] ? '-' : '') + lowercase(tmpMatch[2]);
26645 whens[whenKey] = element.attr(attr.$attr[attributeName]);
26646 }
26647 });
26648 forEach(whens, function(expression, key) {
26649 whensExpFns[key] = $interpolate(expression.replace(BRACE, braceReplacement));
26650
26651 });
26652
26653 scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
26654 var count = parseFloat(newVal);
26655 var countIsNaN = isNaN(count);
26656
26657 if (!countIsNaN && !(count in whens)) {
26658 // If an explicit number rule such as 1, 2, 3... is defined, just use it.
26659 // Otherwise, check it against pluralization rules in $locale service.
26660 count = $locale.pluralCat(count - offset);
26661 }
26662
26663 // If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
26664 // In JS `NaN !== NaN`, so we have to exlicitly check.
26665 if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {
26666 watchRemover();
26667 var whenExpFn = whensExpFns[count];
26668 if (isUndefined(whenExpFn)) {
26669 if (newVal != null) {
26670 $log.debug("ngPluralize: no rule defined for '" + count + "' in " + whenExp);
26671 }
26672 watchRemover = noop;
26673 updateElementText();
26674 } else {
26675 watchRemover = scope.$watch(whenExpFn, updateElementText);
26676 }
26677 lastCount = count;
26678 }
26679 });
26680
26681 function updateElementText(newText) {
26682 element.text(newText || '');
26683 }
26684 }
26685 };
26686 }];
26687
26688 /**
26689 * @ngdoc directive
26690 * @name ngRepeat
26691 * @multiElement
26692 *
26693 * @description
26694 * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
26695 * instance gets its own scope, where the given loop variable is set to the current collection item,
26696 * and `$index` is set to the item index or key.
26697 *
26698 * Special properties are exposed on the local scope of each template instance, including:
26699 *
26700 * | Variable | Type | Details |
26701 * |-----------|-----------------|-----------------------------------------------------------------------------|
26702 * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) |
26703 * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. |
26704 * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
26705 * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. |
26706 * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). |
26707 * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). |
26708 *
26709 * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}.
26710 * This may be useful when, for instance, nesting ngRepeats.
26711 *
26712 *
26713 * # Iterating over object properties
26714 *
26715 * It is possible to get `ngRepeat` to iterate over the properties of an object using the following
26716 * syntax:
26717 *
26718 * ```js
26719 * <div ng-repeat="(key, value) in myObj"> ... </div>
26720 * ```
26721 *
26722 * You need to be aware that the JavaScript specification does not define the order of keys
26723 * returned for an object. (To mitigate this in Angular 1.3 the `ngRepeat` directive
26724 * used to sort the keys alphabetically.)
26725 *
26726 * Version 1.4 removed the alphabetic sorting. We now rely on the order returned by the browser
26727 * when running `for key in myObj`. It seems that browsers generally follow the strategy of providing
26728 * keys in the order in which they were defined, although there are exceptions when keys are deleted
26729 * and reinstated. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_issues
26730 *
26731 * If this is not desired, the recommended workaround is to convert your object into an array
26732 * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could
26733 * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter)
26734 * or implement a `$watch` on the object yourself.
26735 *
26736 *
26737 * # Tracking and Duplicates
26738 *
26739 * When the contents of the collection change, `ngRepeat` makes the corresponding changes to the DOM:
26740 *
26741 * * When an item is added, a new instance of the template is added to the DOM.
26742 * * When an item is removed, its template instance is removed from the DOM.
26743 * * When items are reordered, their respective templates are reordered in the DOM.
26744 *
26745 * By default, `ngRepeat` does not allow duplicate items in arrays. This is because when
26746 * there are duplicates, it is not possible to maintain a one-to-one mapping between collection
26747 * items and DOM elements.
26748 *
26749 * If you do need to repeat duplicate items, you can substitute the default tracking behavior
26750 * with your own using the `track by` expression.
26751 *
26752 * For example, you may track items by the index of each item in the collection, using the
26753 * special scope property `$index`:
26754 * ```html
26755 * <div ng-repeat="n in [42, 42, 43, 43] track by $index">
26756 * {{n}}
26757 * </div>
26758 * ```
26759 *
26760 * You may use arbitrary expressions in `track by`, including references to custom functions
26761 * on the scope:
26762 * ```html
26763 * <div ng-repeat="n in [42, 42, 43, 43] track by myTrackingFunction(n)">
26764 * {{n}}
26765 * </div>
26766 * ```
26767 *
26768 * If you are working with objects that have an identifier property, you can track
26769 * by the identifier instead of the whole object. Should you reload your data later, `ngRepeat`
26770 * will not have to rebuild the DOM elements for items it has already rendered, even if the
26771 * JavaScript objects in the collection have been substituted for new ones:
26772 * ```html
26773 * <div ng-repeat="model in collection track by model.id">
26774 * {{model.name}}
26775 * </div>
26776 * ```
26777 *
26778 * When no `track by` expression is provided, it is equivalent to tracking by the built-in
26779 * `$id` function, which tracks items by their identity:
26780 * ```html
26781 * <div ng-repeat="obj in collection track by $id(obj)">
26782 * {{obj.prop}}
26783 * </div>
26784 * ```
26785 *
26786 * <div class="alert alert-warning">
26787 * **Note:** `track by` must always be the last expression:
26788 * </div>
26789 * ```
26790 * <div ng-repeat="model in collection | orderBy: 'id' as filtered_result track by model.id">
26791 * {{model.name}}
26792 * </div>
26793 * ```
26794 *
26795 * # Special repeat start and end points
26796 * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
26797 * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
26798 * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
26799 * up to and including the ending HTML tag where **ng-repeat-end** is placed.
26800 *
26801 * The example below makes use of this feature:
26802 * ```html
26803 * <header ng-repeat-start="item in items">
26804 * Header {{ item }}
26805 * </header>
26806 * <div class="body">
26807 * Body {{ item }}
26808 * </div>
26809 * <footer ng-repeat-end>
26810 * Footer {{ item }}
26811 * </footer>
26812 * ```
26813 *
26814 * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
26815 * ```html
26816 * <header>
26817 * Header A
26818 * </header>
26819 * <div class="body">
26820 * Body A
26821 * </div>
26822 * <footer>
26823 * Footer A
26824 * </footer>
26825 * <header>
26826 * Header B
26827 * </header>
26828 * <div class="body">
26829 * Body B
26830 * </div>
26831 * <footer>
26832 * Footer B
26833 * </footer>
26834 * ```
26835 *
26836 * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
26837 * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
26838 *
26839 * @animations
26840 * **.enter** - when a new item is added to the list or when an item is revealed after a filter
26841 *
26842 * **.leave** - when an item is removed from the list or when an item is filtered out
26843 *
26844 * **.move** - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
26845 *
26846 * @element ANY
26847 * @scope
26848 * @priority 1000
26849 * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
26850 * formats are currently supported:
26851 *
26852 * * `variable in expression` – where variable is the user defined loop variable and `expression`
26853 * is a scope expression giving the collection to enumerate.
26854 *
26855 * For example: `album in artist.albums`.
26856 *
26857 * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
26858 * and `expression` is the scope expression giving the collection to enumerate.
26859 *
26860 * For example: `(name, age) in {'adam':10, 'amalie':12}`.
26861 *
26862 * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression
26863 * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression
26864 * is specified, ng-repeat associates elements by identity. It is an error to have
26865 * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are
26866 * mapped to the same DOM element, which is not possible.)
26867 *
26868 * Note that the tracking expression must come last, after any filters, and the alias expression.
26869 *
26870 * For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
26871 * will be associated by item identity in the array.
26872 *
26873 * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
26874 * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
26875 * with the corresponding item in the array by identity. Moving the same object in array would move the DOM
26876 * element in the same way in the DOM.
26877 *
26878 * For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
26879 * case the object identity does not matter. Two objects are considered equivalent as long as their `id`
26880 * property is same.
26881 *
26882 * For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
26883 * to items in conjunction with a tracking expression.
26884 *
26885 * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the
26886 * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
26887 * when a filter is active on the repeater, but the filtered result set is empty.
26888 *
26889 * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
26890 * the items have been processed through the filter.
26891 *
26892 * Please note that `as [variable name] is not an operator but rather a part of ngRepeat micro-syntax so it can be used only at the end
26893 * (and not as operator, inside an expression).
26894 *
26895 * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results` .
26896 *
26897 * @example
26898 * This example initializes the scope to a list of names and
26899 * then uses `ngRepeat` to display every person:
26900 <example module="ngAnimate" deps="angular-animate.js" animations="true">
26901 <file name="index.html">
26902 <div ng-init="friends = [
26903 {name:'John', age:25, gender:'boy'},
26904 {name:'Jessie', age:30, gender:'girl'},
26905 {name:'Johanna', age:28, gender:'girl'},
26906 {name:'Joy', age:15, gender:'girl'},
26907 {name:'Mary', age:28, gender:'girl'},
26908 {name:'Peter', age:95, gender:'boy'},
26909 {name:'Sebastian', age:50, gender:'boy'},
26910 {name:'Erika', age:27, gender:'girl'},
26911 {name:'Patrick', age:40, gender:'boy'},
26912 {name:'Samantha', age:60, gender:'girl'}
26913 ]">
26914 I have {{friends.length}} friends. They are:
26915 <input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
26916 <ul class="example-animate-container">
26917 <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
26918 [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
26919 </li>
26920 <li class="animate-repeat" ng-if="results.length == 0">
26921 <strong>No results found...</strong>
26922 </li>
26923 </ul>
26924 </div>
26925 </file>
26926 <file name="animations.css">
26927 .example-animate-container {
26928 background:white;
26929 border:1px solid black;
26930 list-style:none;
26931 margin:0;
26932 padding:0 10px;
26933 }
26934
26935 .animate-repeat {
26936 line-height:40px;
26937 list-style:none;
26938 box-sizing:border-box;
26939 }
26940
26941 .animate-repeat.ng-move,
26942 .animate-repeat.ng-enter,
26943 .animate-repeat.ng-leave {
26944 -webkit-transition:all linear 0.5s;
26945 transition:all linear 0.5s;
26946 }
26947
26948 .animate-repeat.ng-leave.ng-leave-active,
26949 .animate-repeat.ng-move,
26950 .animate-repeat.ng-enter {
26951 opacity:0;
26952 max-height:0;
26953 }
26954
26955 .animate-repeat.ng-leave,
26956 .animate-repeat.ng-move.ng-move-active,
26957 .animate-repeat.ng-enter.ng-enter-active {
26958 opacity:1;
26959 max-height:40px;
26960 }
26961 </file>
26962 <file name="protractor.js" type="protractor">
26963 var friends = element.all(by.repeater('friend in friends'));
26964
26965 it('should render initial data set', function() {
26966 expect(friends.count()).toBe(10);
26967 expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.');
26968 expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.');
26969 expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.');
26970 expect(element(by.binding('friends.length')).getText())
26971 .toMatch("I have 10 friends. They are:");
26972 });
26973
26974 it('should update repeater when filter predicate changes', function() {
26975 expect(friends.count()).toBe(10);
26976
26977 element(by.model('q')).sendKeys('ma');
26978
26979 expect(friends.count()).toBe(2);
26980 expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.');
26981 expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.');
26982 });
26983 </file>
26984 </example>
26985 */
26986 var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
26987 var NG_REMOVED = '$$NG_REMOVED';
26988 var ngRepeatMinErr = minErr('ngRepeat');
26989
26990 var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) {
26991 // TODO(perf): generate setters to shave off ~40ms or 1-1.5%
26992 scope[valueIdentifier] = value;
26993 if (keyIdentifier) scope[keyIdentifier] = key;
26994 scope.$index = index;
26995 scope.$first = (index === 0);
26996 scope.$last = (index === (arrayLength - 1));
26997 scope.$middle = !(scope.$first || scope.$last);
26998 // jshint bitwise: false
26999 scope.$odd = !(scope.$even = (index&1) === 0);
27000 // jshint bitwise: true
27001 };
27002
27003 var getBlockStart = function(block) {
27004 return block.clone[0];
27005 };
27006
27007 var getBlockEnd = function(block) {
27008 return block.clone[block.clone.length - 1];
27009 };
27010
27011
27012 return {
27013 restrict: 'A',
27014 multiElement: true,
27015 transclude: 'element',
27016 priority: 1000,
27017 terminal: true,
27018 $$tlb: true,
27019 compile: function ngRepeatCompile($element, $attr) {
27020 var expression = $attr.ngRepeat;
27021 var ngRepeatEndComment = document.createComment(' end ngRepeat: ' + expression + ' ');
27022
27023 var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
27024
27025 if (!match) {
27026 throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
27027 expression);
27028 }
27029
27030 var lhs = match[1];
27031 var rhs = match[2];
27032 var aliasAs = match[3];
27033 var trackByExp = match[4];
27034
27035 match = lhs.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
27036
27037 if (!match) {
27038 throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
27039 lhs);
27040 }
27041 var valueIdentifier = match[3] || match[1];
27042 var keyIdentifier = match[2];
27043
27044 if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
27045 /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) {
27046 throw ngRepeatMinErr('badident', "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.",
27047 aliasAs);
27048 }
27049
27050 var trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn;
27051 var hashFnLocals = {$id: hashKey};
27052
27053 if (trackByExp) {
27054 trackByExpGetter = $parse(trackByExp);
27055 } else {
27056 trackByIdArrayFn = function(key, value) {
27057 return hashKey(value);
27058 };
27059 trackByIdObjFn = function(key) {
27060 return key;
27061 };
27062 }
27063
27064 return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
27065
27066 if (trackByExpGetter) {
27067 trackByIdExpFn = function(key, value, index) {
27068 // assign key, value, and $index to the locals so that they can be used in hash functions
27069 if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
27070 hashFnLocals[valueIdentifier] = value;
27071 hashFnLocals.$index = index;
27072 return trackByExpGetter($scope, hashFnLocals);
27073 };
27074 }
27075
27076 // Store a list of elements from previous run. This is a hash where key is the item from the
27077 // iterator, and the value is objects with following properties.
27078 // - scope: bound scope
27079 // - element: previous element.
27080 // - index: position
27081 //
27082 // We are using no-proto object so that we don't need to guard against inherited props via
27083 // hasOwnProperty.
27084 var lastBlockMap = createMap();
27085
27086 //watch props
27087 $scope.$watchCollection(rhs, function ngRepeatAction(collection) {
27088 var index, length,
27089 previousNode = $element[0], // node that cloned nodes should be inserted after
27090 // initialized to the comment node anchor
27091 nextNode,
27092 // Same as lastBlockMap but it has the current state. It will become the
27093 // lastBlockMap on the next iteration.
27094 nextBlockMap = createMap(),
27095 collectionLength,
27096 key, value, // key/value of iteration
27097 trackById,
27098 trackByIdFn,
27099 collectionKeys,
27100 block, // last object information {scope, element, id}
27101 nextBlockOrder,
27102 elementsToRemove;
27103
27104 if (aliasAs) {
27105 $scope[aliasAs] = collection;
27106 }
27107
27108 if (isArrayLike(collection)) {
27109 collectionKeys = collection;
27110 trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
27111 } else {
27112 trackByIdFn = trackByIdExpFn || trackByIdObjFn;
27113 // if object, extract keys, in enumeration order, unsorted
27114 collectionKeys = [];
27115 for (var itemKey in collection) {
27116 if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
27117 collectionKeys.push(itemKey);
27118 }
27119 }
27120 }
27121
27122 collectionLength = collectionKeys.length;
27123 nextBlockOrder = new Array(collectionLength);
27124
27125 // locate existing items
27126 for (index = 0; index < collectionLength; index++) {
27127 key = (collection === collectionKeys) ? index : collectionKeys[index];
27128 value = collection[key];
27129 trackById = trackByIdFn(key, value, index);
27130 if (lastBlockMap[trackById]) {
27131 // found previously seen block
27132 block = lastBlockMap[trackById];
27133 delete lastBlockMap[trackById];
27134 nextBlockMap[trackById] = block;
27135 nextBlockOrder[index] = block;
27136 } else if (nextBlockMap[trackById]) {
27137 // if collision detected. restore lastBlockMap and throw an error
27138 forEach(nextBlockOrder, function(block) {
27139 if (block && block.scope) lastBlockMap[block.id] = block;
27140 });
27141 throw ngRepeatMinErr('dupes',
27142 "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
27143 expression, trackById, value);
27144 } else {
27145 // new never before seen block
27146 nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined};
27147 nextBlockMap[trackById] = true;
27148 }
27149 }
27150
27151 // remove leftover items
27152 for (var blockKey in lastBlockMap) {
27153 block = lastBlockMap[blockKey];
27154 elementsToRemove = getBlockNodes(block.clone);
27155 $animate.leave(elementsToRemove);
27156 if (elementsToRemove[0].parentNode) {
27157 // if the element was not removed yet because of pending animation, mark it as deleted
27158 // so that we can ignore it later
27159 for (index = 0, length = elementsToRemove.length; index < length; index++) {
27160 elementsToRemove[index][NG_REMOVED] = true;
27161 }
27162 }
27163 block.scope.$destroy();
27164 }
27165
27166 // we are not using forEach for perf reasons (trying to avoid #call)
27167 for (index = 0; index < collectionLength; index++) {
27168 key = (collection === collectionKeys) ? index : collectionKeys[index];
27169 value = collection[key];
27170 block = nextBlockOrder[index];
27171
27172 if (block.scope) {
27173 // if we have already seen this object, then we need to reuse the
27174 // associated scope/element
27175
27176 nextNode = previousNode;
27177
27178 // skip nodes that are already pending removal via leave animation
27179 do {
27180 nextNode = nextNode.nextSibling;
27181 } while (nextNode && nextNode[NG_REMOVED]);
27182
27183 if (getBlockStart(block) != nextNode) {
27184 // existing item which got moved
27185 $animate.move(getBlockNodes(block.clone), null, jqLite(previousNode));
27186 }
27187 previousNode = getBlockEnd(block);
27188 updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
27189 } else {
27190 // new item which we don't know about
27191 $transclude(function ngRepeatTransclude(clone, scope) {
27192 block.scope = scope;
27193 // http://jsperf.com/clone-vs-createcomment
27194 var endNode = ngRepeatEndComment.cloneNode(false);
27195 clone[clone.length++] = endNode;
27196
27197 // TODO(perf): support naked previousNode in `enter` to avoid creation of jqLite wrapper?
27198 $animate.enter(clone, null, jqLite(previousNode));
27199 previousNode = endNode;
27200 // Note: We only need the first/last node of the cloned nodes.
27201 // However, we need to keep the reference to the jqlite wrapper as it might be changed later
27202 // by a directive with templateUrl when its template arrives.
27203 block.clone = clone;
27204 nextBlockMap[block.id] = block;
27205 updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength);
27206 });
27207 }
27208 }
27209 lastBlockMap = nextBlockMap;
27210 });
27211 };
27212 }
27213 };
27214 }];
27215
27216 var NG_HIDE_CLASS = 'ng-hide';
27217 var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate';
27218 /**
27219 * @ngdoc directive
27220 * @name ngShow
27221 * @multiElement
27222 *
27223 * @description
27224 * The `ngShow` directive shows or hides the given HTML element based on the expression
27225 * provided to the `ngShow` attribute. The element is shown or hidden by removing or adding
27226 * the `.ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
27227 * in AngularJS and sets the display style to none (using an !important flag).
27228 * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
27229 *
27230 * ```html
27231 * <!-- when $scope.myValue is truthy (element is visible) -->
27232 * <div ng-show="myValue"></div>
27233 *
27234 * <!-- when $scope.myValue is falsy (element is hidden) -->
27235 * <div ng-show="myValue" class="ng-hide"></div>
27236 * ```
27237 *
27238 * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added to the class
27239 * attribute on the element causing it to become hidden. When truthy, the `.ng-hide` CSS class is removed
27240 * from the element causing the element not to appear hidden.
27241 *
27242 * ## Why is !important used?
27243 *
27244 * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
27245 * can be easily overridden by heavier selectors. For example, something as simple
27246 * as changing the display style on a HTML list item would make hidden elements appear visible.
27247 * This also becomes a bigger issue when dealing with CSS frameworks.
27248 *
27249 * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
27250 * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
27251 * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
27252 *
27253 * ### Overriding `.ng-hide`
27254 *
27255 * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
27256 * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
27257 * class CSS. Note that the selector that needs to be used is actually `.ng-hide:not(.ng-hide-animate)` to cope
27258 * with extra animation classes that can be added.
27259 *
27260 * ```css
27261 * .ng-hide:not(.ng-hide-animate) {
27262 * /&#42; this is just another form of hiding an element &#42;/
27263 * display: block!important;
27264 * position: absolute;
27265 * top: -9999px;
27266 * left: -9999px;
27267 * }
27268 * ```
27269 *
27270 * By default you don't need to override in CSS anything and the animations will work around the display style.
27271 *
27272 * ## A note about animations with `ngShow`
27273 *
27274 * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
27275 * is true and false. This system works like the animation system present with ngClass except that
27276 * you must also include the !important flag to override the display property
27277 * so that you can perform an animation when the element is hidden during the time of the animation.
27278 *
27279 * ```css
27280 * //
27281 * //a working example can be found at the bottom of this page
27282 * //
27283 * .my-element.ng-hide-add, .my-element.ng-hide-remove {
27284 * /&#42; this is required as of 1.3x to properly
27285 * apply all styling in a show/hide animation &#42;/
27286 * transition: 0s linear all;
27287 * }
27288 *
27289 * .my-element.ng-hide-add-active,
27290 * .my-element.ng-hide-remove-active {
27291 * /&#42; the transition is defined in the active class &#42;/
27292 * transition: 1s linear all;
27293 * }
27294 *
27295 * .my-element.ng-hide-add { ... }
27296 * .my-element.ng-hide-add.ng-hide-add-active { ... }
27297 * .my-element.ng-hide-remove { ... }
27298 * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
27299 * ```
27300 *
27301 * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
27302 * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
27303 *
27304 * @animations
27305 * addClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a truthy value and the just before contents are set to visible
27306 * removeClass: `.ng-hide` - happens after the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden
27307 *
27308 * @element ANY
27309 * @param {expression} ngShow If the {@link guide/expression expression} is truthy
27310 * then the element is shown or hidden respectively.
27311 *
27312 * @example
27313 <example module="ngAnimate" deps="angular-animate.js" animations="true">
27314 <file name="index.html">
27315 Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngHide"><br/>
27316 <div>
27317 Show:
27318 <div class="check-element animate-show" ng-show="checked">
27319 <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
27320 </div>
27321 </div>
27322 <div>
27323 Hide:
27324 <div class="check-element animate-show" ng-hide="checked">
27325 <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
27326 </div>
27327 </div>
27328 </file>
27329 <file name="glyphicons.css">
27330 @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
27331 </file>
27332 <file name="animations.css">
27333 .animate-show {
27334 line-height: 20px;
27335 opacity: 1;
27336 padding: 10px;
27337 border: 1px solid black;
27338 background: white;
27339 }
27340
27341 .animate-show.ng-hide-add.ng-hide-add-active,
27342 .animate-show.ng-hide-remove.ng-hide-remove-active {
27343 -webkit-transition: all linear 0.5s;
27344 transition: all linear 0.5s;
27345 }
27346
27347 .animate-show.ng-hide {
27348 line-height: 0;
27349 opacity: 0;
27350 padding: 0 10px;
27351 }
27352
27353 .check-element {
27354 padding: 10px;
27355 border: 1px solid black;
27356 background: white;
27357 }
27358 </file>
27359 <file name="protractor.js" type="protractor">
27360 var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
27361 var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
27362
27363 it('should check ng-show / ng-hide', function() {
27364 expect(thumbsUp.isDisplayed()).toBeFalsy();
27365 expect(thumbsDown.isDisplayed()).toBeTruthy();
27366
27367 element(by.model('checked')).click();
27368
27369 expect(thumbsUp.isDisplayed()).toBeTruthy();
27370 expect(thumbsDown.isDisplayed()).toBeFalsy();
27371 });
27372 </file>
27373 </example>
27374 */
27375 var ngShowDirective = ['$animate', function($animate) {
27376 return {
27377 restrict: 'A',
27378 multiElement: true,
27379 link: function(scope, element, attr) {
27380 scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
27381 // we're adding a temporary, animation-specific class for ng-hide since this way
27382 // we can control when the element is actually displayed on screen without having
27383 // to have a global/greedy CSS selector that breaks when other animations are run.
27384 // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
27385 $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
27386 tempClasses: NG_HIDE_IN_PROGRESS_CLASS
27387 });
27388 });
27389 }
27390 };
27391 }];
27392
27393
27394 /**
27395 * @ngdoc directive
27396 * @name ngHide
27397 * @multiElement
27398 *
27399 * @description
27400 * The `ngHide` directive shows or hides the given HTML element based on the expression
27401 * provided to the `ngHide` attribute. The element is shown or hidden by removing or adding
27402 * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
27403 * in AngularJS and sets the display style to none (using an !important flag).
27404 * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
27405 *
27406 * ```html
27407 * <!-- when $scope.myValue is truthy (element is hidden) -->
27408 * <div ng-hide="myValue" class="ng-hide"></div>
27409 *
27410 * <!-- when $scope.myValue is falsy (element is visible) -->
27411 * <div ng-hide="myValue"></div>
27412 * ```
27413 *
27414 * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added to the class
27415 * attribute on the element causing it to become hidden. When falsy, the `.ng-hide` CSS class is removed
27416 * from the element causing the element not to appear hidden.
27417 *
27418 * ## Why is !important used?
27419 *
27420 * You may be wondering why !important is used for the `.ng-hide` CSS class. This is because the `.ng-hide` selector
27421 * can be easily overridden by heavier selectors. For example, something as simple
27422 * as changing the display style on a HTML list item would make hidden elements appear visible.
27423 * This also becomes a bigger issue when dealing with CSS frameworks.
27424 *
27425 * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
27426 * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
27427 * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
27428 *
27429 * ### Overriding `.ng-hide`
27430 *
27431 * By default, the `.ng-hide` class will style the element with `display: none!important`. If you wish to change
27432 * the hide behavior with ngShow/ngHide then this can be achieved by restating the styles for the `.ng-hide`
27433 * class in CSS:
27434 *
27435 * ```css
27436 * .ng-hide {
27437 * /&#42; this is just another form of hiding an element &#42;/
27438 * display: block!important;
27439 * position: absolute;
27440 * top: -9999px;
27441 * left: -9999px;
27442 * }
27443 * ```
27444 *
27445 * By default you don't need to override in CSS anything and the animations will work around the display style.
27446 *
27447 * ## A note about animations with `ngHide`
27448 *
27449 * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
27450 * is true and false. This system works like the animation system present with ngClass, except that the `.ng-hide`
27451 * CSS class is added and removed for you instead of your own CSS class.
27452 *
27453 * ```css
27454 * //
27455 * //a working example can be found at the bottom of this page
27456 * //
27457 * .my-element.ng-hide-add, .my-element.ng-hide-remove {
27458 * transition: 0.5s linear all;
27459 * }
27460 *
27461 * .my-element.ng-hide-add { ... }
27462 * .my-element.ng-hide-add.ng-hide-add-active { ... }
27463 * .my-element.ng-hide-remove { ... }
27464 * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
27465 * ```
27466 *
27467 * Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
27468 * property to block during animation states--ngAnimate will handle the style toggling automatically for you.
27469 *
27470 * @animations
27471 * removeClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden
27472 * addClass: `.ng-hide` - happens after the `ngHide` expression evaluates to a non truthy value and just before the contents are set to visible
27473 *
27474 * @element ANY
27475 * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
27476 * the element is shown or hidden respectively.
27477 *
27478 * @example
27479 <example module="ngAnimate" deps="angular-animate.js" animations="true">
27480 <file name="index.html">
27481 Click me: <input type="checkbox" ng-model="checked" aria-label="Toggle ngShow"><br/>
27482 <div>
27483 Show:
27484 <div class="check-element animate-hide" ng-show="checked">
27485 <span class="glyphicon glyphicon-thumbs-up"></span> I show up when your checkbox is checked.
27486 </div>
27487 </div>
27488 <div>
27489 Hide:
27490 <div class="check-element animate-hide" ng-hide="checked">
27491 <span class="glyphicon glyphicon-thumbs-down"></span> I hide when your checkbox is checked.
27492 </div>
27493 </div>
27494 </file>
27495 <file name="glyphicons.css">
27496 @import url(../../components/bootstrap-3.1.1/css/bootstrap.css);
27497 </file>
27498 <file name="animations.css">
27499 .animate-hide {
27500 -webkit-transition: all linear 0.5s;
27501 transition: all linear 0.5s;
27502 line-height: 20px;
27503 opacity: 1;
27504 padding: 10px;
27505 border: 1px solid black;
27506 background: white;
27507 }
27508
27509 .animate-hide.ng-hide {
27510 line-height: 0;
27511 opacity: 0;
27512 padding: 0 10px;
27513 }
27514
27515 .check-element {
27516 padding: 10px;
27517 border: 1px solid black;
27518 background: white;
27519 }
27520 </file>
27521 <file name="protractor.js" type="protractor">
27522 var thumbsUp = element(by.css('span.glyphicon-thumbs-up'));
27523 var thumbsDown = element(by.css('span.glyphicon-thumbs-down'));
27524
27525 it('should check ng-show / ng-hide', function() {
27526 expect(thumbsUp.isDisplayed()).toBeFalsy();
27527 expect(thumbsDown.isDisplayed()).toBeTruthy();
27528
27529 element(by.model('checked')).click();
27530
27531 expect(thumbsUp.isDisplayed()).toBeTruthy();
27532 expect(thumbsDown.isDisplayed()).toBeFalsy();
27533 });
27534 </file>
27535 </example>
27536 */
27537 var ngHideDirective = ['$animate', function($animate) {
27538 return {
27539 restrict: 'A',
27540 multiElement: true,
27541 link: function(scope, element, attr) {
27542 scope.$watch(attr.ngHide, function ngHideWatchAction(value) {
27543 // The comment inside of the ngShowDirective explains why we add and
27544 // remove a temporary class for the show/hide animation
27545 $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, {
27546 tempClasses: NG_HIDE_IN_PROGRESS_CLASS
27547 });
27548 });
27549 }
27550 };
27551 }];
27552
27553 /**
27554 * @ngdoc directive
27555 * @name ngStyle
27556 * @restrict AC
27557 *
27558 * @description
27559 * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
27560 *
27561 * @element ANY
27562 * @param {expression} ngStyle
27563 *
27564 * {@link guide/expression Expression} which evals to an
27565 * object whose keys are CSS style names and values are corresponding values for those CSS
27566 * keys.
27567 *
27568 * Since some CSS style names are not valid keys for an object, they must be quoted.
27569 * See the 'background-color' style in the example below.
27570 *
27571 * @example
27572 <example>
27573 <file name="index.html">
27574 <input type="button" value="set color" ng-click="myStyle={color:'red'}">
27575 <input type="button" value="set background" ng-click="myStyle={'background-color':'blue'}">
27576 <input type="button" value="clear" ng-click="myStyle={}">
27577 <br/>
27578 <span ng-style="myStyle">Sample Text</span>
27579 <pre>myStyle={{myStyle}}</pre>
27580 </file>
27581 <file name="style.css">
27582 span {
27583 color: black;
27584 }
27585 </file>
27586 <file name="protractor.js" type="protractor">
27587 var colorSpan = element(by.css('span'));
27588
27589 it('should check ng-style', function() {
27590 expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
27591 element(by.css('input[value=\'set color\']')).click();
27592 expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)');
27593 element(by.css('input[value=clear]')).click();
27594 expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)');
27595 });
27596 </file>
27597 </example>
27598 */
27599 var ngStyleDirective = ngDirective(function(scope, element, attr) {
27600 scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
27601 if (oldStyles && (newStyles !== oldStyles)) {
27602 forEach(oldStyles, function(val, style) { element.css(style, '');});
27603 }
27604 if (newStyles) element.css(newStyles);
27605 }, true);
27606 });
27607
27608 /**
27609 * @ngdoc directive
27610 * @name ngSwitch
27611 * @restrict EA
27612 *
27613 * @description
27614 * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
27615 * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
27616 * as specified in the template.
27617 *
27618 * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
27619 * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element
27620 * matches the value obtained from the evaluated expression. In other words, you define a container element
27621 * (where you place the directive), place an expression on the **`on="..."` attribute**
27622 * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
27623 * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
27624 * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
27625 * attribute is displayed.
27626 *
27627 * <div class="alert alert-info">
27628 * Be aware that the attribute values to match against cannot be expressions. They are interpreted
27629 * as literal string values to match against.
27630 * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
27631 * value of the expression `$scope.someVal`.
27632 * </div>
27633
27634 * @animations
27635 * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
27636 * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
27637 *
27638 * @usage
27639 *
27640 * ```
27641 * <ANY ng-switch="expression">
27642 * <ANY ng-switch-when="matchValue1">...</ANY>
27643 * <ANY ng-switch-when="matchValue2">...</ANY>
27644 * <ANY ng-switch-default>...</ANY>
27645 * </ANY>
27646 * ```
27647 *
27648 *
27649 * @scope
27650 * @priority 1200
27651 * @param {*} ngSwitch|on expression to match against <code>ng-switch-when</code>.
27652 * On child elements add:
27653 *
27654 * * `ngSwitchWhen`: the case statement to match against. If match then this
27655 * case will be displayed. If the same match appears multiple times, all the
27656 * elements will be displayed.
27657 * * `ngSwitchDefault`: the default case when no other case match. If there
27658 * are multiple default cases, all of them will be displayed when no other
27659 * case match.
27660 *
27661 *
27662 * @example
27663 <example module="switchExample" deps="angular-animate.js" animations="true">
27664 <file name="index.html">
27665 <div ng-controller="ExampleController">
27666 <select ng-model="selection" ng-options="item for item in items">
27667 </select>
27668 <code>selection={{selection}}</code>
27669 <hr/>
27670 <div class="animate-switch-container"
27671 ng-switch on="selection">
27672 <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
27673 <div class="animate-switch" ng-switch-when="home">Home Span</div>
27674 <div class="animate-switch" ng-switch-default>default</div>
27675 </div>
27676 </div>
27677 </file>
27678 <file name="script.js">
27679 angular.module('switchExample', ['ngAnimate'])
27680 .controller('ExampleController', ['$scope', function($scope) {
27681 $scope.items = ['settings', 'home', 'other'];
27682 $scope.selection = $scope.items[0];
27683 }]);
27684 </file>
27685 <file name="animations.css">
27686 .animate-switch-container {
27687 position:relative;
27688 background:white;
27689 border:1px solid black;
27690 height:40px;
27691 overflow:hidden;
27692 }
27693
27694 .animate-switch {
27695 padding:10px;
27696 }
27697
27698 .animate-switch.ng-animate {
27699 -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
27700 transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
27701
27702 position:absolute;
27703 top:0;
27704 left:0;
27705 right:0;
27706 bottom:0;
27707 }
27708
27709 .animate-switch.ng-leave.ng-leave-active,
27710 .animate-switch.ng-enter {
27711 top:-50px;
27712 }
27713 .animate-switch.ng-leave,
27714 .animate-switch.ng-enter.ng-enter-active {
27715 top:0;
27716 }
27717 </file>
27718 <file name="protractor.js" type="protractor">
27719 var switchElem = element(by.css('[ng-switch]'));
27720 var select = element(by.model('selection'));
27721
27722 it('should start in settings', function() {
27723 expect(switchElem.getText()).toMatch(/Settings Div/);
27724 });
27725 it('should change to home', function() {
27726 select.all(by.css('option')).get(1).click();
27727 expect(switchElem.getText()).toMatch(/Home Span/);
27728 });
27729 it('should select default', function() {
27730 select.all(by.css('option')).get(2).click();
27731 expect(switchElem.getText()).toMatch(/default/);
27732 });
27733 </file>
27734 </example>
27735 */
27736 var ngSwitchDirective = ['$animate', function($animate) {
27737 return {
27738 require: 'ngSwitch',
27739
27740 // asks for $scope to fool the BC controller module
27741 controller: ['$scope', function ngSwitchController() {
27742 this.cases = {};
27743 }],
27744 link: function(scope, element, attr, ngSwitchController) {
27745 var watchExpr = attr.ngSwitch || attr.on,
27746 selectedTranscludes = [],
27747 selectedElements = [],
27748 previousLeaveAnimations = [],
27749 selectedScopes = [];
27750
27751 var spliceFactory = function(array, index) {
27752 return function() { array.splice(index, 1); };
27753 };
27754
27755 scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
27756 var i, ii;
27757 for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) {
27758 $animate.cancel(previousLeaveAnimations[i]);
27759 }
27760 previousLeaveAnimations.length = 0;
27761
27762 for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
27763 var selected = getBlockNodes(selectedElements[i].clone);
27764 selectedScopes[i].$destroy();
27765 var promise = previousLeaveAnimations[i] = $animate.leave(selected);
27766 promise.then(spliceFactory(previousLeaveAnimations, i));
27767 }
27768
27769 selectedElements.length = 0;
27770 selectedScopes.length = 0;
27771
27772 if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
27773 forEach(selectedTranscludes, function(selectedTransclude) {
27774 selectedTransclude.transclude(function(caseElement, selectedScope) {
27775 selectedScopes.push(selectedScope);
27776 var anchor = selectedTransclude.element;
27777 caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');
27778 var block = { clone: caseElement };
27779
27780 selectedElements.push(block);
27781 $animate.enter(caseElement, anchor.parent(), anchor);
27782 });
27783 });
27784 }
27785 });
27786 }
27787 };
27788 }];
27789
27790 var ngSwitchWhenDirective = ngDirective({
27791 transclude: 'element',
27792 priority: 1200,
27793 require: '^ngSwitch',
27794 multiElement: true,
27795 link: function(scope, element, attrs, ctrl, $transclude) {
27796 ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
27797 ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
27798 }
27799 });
27800
27801 var ngSwitchDefaultDirective = ngDirective({
27802 transclude: 'element',
27803 priority: 1200,
27804 require: '^ngSwitch',
27805 multiElement: true,
27806 link: function(scope, element, attr, ctrl, $transclude) {
27807 ctrl.cases['?'] = (ctrl.cases['?'] || []);
27808 ctrl.cases['?'].push({ transclude: $transclude, element: element });
27809 }
27810 });
27811
27812 /**
27813 * @ngdoc directive
27814 * @name ngTransclude
27815 * @restrict EAC
27816 *
27817 * @description
27818 * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
27819 *
27820 * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
27821 *
27822 * @element ANY
27823 *
27824 * @example
27825 <example module="transcludeExample">
27826 <file name="index.html">
27827 <script>
27828 angular.module('transcludeExample', [])
27829 .directive('pane', function(){
27830 return {
27831 restrict: 'E',
27832 transclude: true,
27833 scope: { title:'@' },
27834 template: '<div style="border: 1px solid black;">' +
27835 '<div style="background-color: gray">{{title}}</div>' +
27836 '<ng-transclude></ng-transclude>' +
27837 '</div>'
27838 };
27839 })
27840 .controller('ExampleController', ['$scope', function($scope) {
27841 $scope.title = 'Lorem Ipsum';
27842 $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
27843 }]);
27844 </script>
27845 <div ng-controller="ExampleController">
27846 <input ng-model="title" aria-label="title"> <br/>
27847 <textarea ng-model="text" aria-label="text"></textarea> <br/>
27848 <pane title="{{title}}">{{text}}</pane>
27849 </div>
27850 </file>
27851 <file name="protractor.js" type="protractor">
27852 it('should have transcluded', function() {
27853 var titleElement = element(by.model('title'));
27854 titleElement.clear();
27855 titleElement.sendKeys('TITLE');
27856 var textElement = element(by.model('text'));
27857 textElement.clear();
27858 textElement.sendKeys('TEXT');
27859 expect(element(by.binding('title')).getText()).toEqual('TITLE');
27860 expect(element(by.binding('text')).getText()).toEqual('TEXT');
27861 });
27862 </file>
27863 </example>
27864 *
27865 */
27866 var ngTranscludeDirective = ngDirective({
27867 restrict: 'EAC',
27868 link: function($scope, $element, $attrs, controller, $transclude) {
27869 if (!$transclude) {
27870 throw minErr('ngTransclude')('orphan',
27871 'Illegal use of ngTransclude directive in the template! ' +
27872 'No parent directive that requires a transclusion found. ' +
27873 'Element: {0}',
27874 startingTag($element));
27875 }
27876
27877 $transclude(function(clone) {
27878 $element.empty();
27879 $element.append(clone);
27880 });
27881 }
27882 });
27883
27884 /**
27885 * @ngdoc directive
27886 * @name script
27887 * @restrict E
27888 *
27889 * @description
27890 * Load the content of a `<script>` element into {@link ng.$templateCache `$templateCache`}, so that the
27891 * template can be used by {@link ng.directive:ngInclude `ngInclude`},
27892 * {@link ngRoute.directive:ngView `ngView`}, or {@link guide/directive directives}. The type of the
27893 * `<script>` element must be specified as `text/ng-template`, and a cache name for the template must be
27894 * assigned through the element's `id`, which can then be used as a directive's `templateUrl`.
27895 *
27896 * @param {string} type Must be set to `'text/ng-template'`.
27897 * @param {string} id Cache name of the template.
27898 *
27899 * @example
27900 <example>
27901 <file name="index.html">
27902 <script type="text/ng-template" id="/tpl.html">
27903 Content of the template.
27904 </script>
27905
27906 <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
27907 <div id="tpl-content" ng-include src="currentTpl"></div>
27908 </file>
27909 <file name="protractor.js" type="protractor">
27910 it('should load template defined inside script tag', function() {
27911 element(by.css('#tpl-link')).click();
27912 expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/);
27913 });
27914 </file>
27915 </example>
27916 */
27917 var scriptDirective = ['$templateCache', function($templateCache) {
27918 return {
27919 restrict: 'E',
27920 terminal: true,
27921 compile: function(element, attr) {
27922 if (attr.type == 'text/ng-template') {
27923 var templateUrl = attr.id,
27924 text = element[0].text;
27925
27926 $templateCache.put(templateUrl, text);
27927 }
27928 }
27929 };
27930 }];
27931
27932 var noopNgModelController = { $setViewValue: noop, $render: noop };
27933
27934 /**
27935 * @ngdoc type
27936 * @name select.SelectController
27937 * @description
27938 * The controller for the `<select>` directive. This provides support for reading
27939 * and writing the selected value(s) of the control and also coordinates dynamically
27940 * added `<option>` elements, perhaps by an `ngRepeat` directive.
27941 */
27942 var SelectController =
27943 ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
27944
27945 var self = this,
27946 optionsMap = new HashMap();
27947
27948 // If the ngModel doesn't get provided then provide a dummy noop version to prevent errors
27949 self.ngModelCtrl = noopNgModelController;
27950
27951 // The "unknown" option is one that is prepended to the list if the viewValue
27952 // does not match any of the options. When it is rendered the value of the unknown
27953 // option is '? XXX ?' where XXX is the hashKey of the value that is not known.
27954 //
27955 // We can't just jqLite('<option>') since jqLite is not smart enough
27956 // to create it in <select> and IE barfs otherwise.
27957 self.unknownOption = jqLite(document.createElement('option'));
27958 self.renderUnknownOption = function(val) {
27959 var unknownVal = '? ' + hashKey(val) + ' ?';
27960 self.unknownOption.val(unknownVal);
27961 $element.prepend(self.unknownOption);
27962 $element.val(unknownVal);
27963 };
27964
27965 $scope.$on('$destroy', function() {
27966 // disable unknown option so that we don't do work when the whole select is being destroyed
27967 self.renderUnknownOption = noop;
27968 });
27969
27970 self.removeUnknownOption = function() {
27971 if (self.unknownOption.parent()) self.unknownOption.remove();
27972 };
27973
27974
27975 // Read the value of the select control, the implementation of this changes depending
27976 // upon whether the select can have multiple values and whether ngOptions is at work.
27977 self.readValue = function readSingleValue() {
27978 self.removeUnknownOption();
27979 return $element.val();
27980 };
27981
27982
27983 // Write the value to the select control, the implementation of this changes depending
27984 // upon whether the select can have multiple values and whether ngOptions is at work.
27985 self.writeValue = function writeSingleValue(value) {
27986 if (self.hasOption(value)) {
27987 self.removeUnknownOption();
27988 $element.val(value);
27989 if (value === '') self.emptyOption.prop('selected', true); // to make IE9 happy
27990 } else {
27991 if (value == null && self.emptyOption) {
27992 self.removeUnknownOption();
27993 $element.val('');
27994 } else {
27995 self.renderUnknownOption(value);
27996 }
27997 }
27998 };
27999
28000
28001 // Tell the select control that an option, with the given value, has been added
28002 self.addOption = function(value, element) {
28003 assertNotHasOwnProperty(value, '"option value"');
28004 if (value === '') {
28005 self.emptyOption = element;
28006 }
28007 var count = optionsMap.get(value) || 0;
28008 optionsMap.put(value, count + 1);
28009 };
28010
28011 // Tell the select control that an option, with the given value, has been removed
28012 self.removeOption = function(value) {
28013 var count = optionsMap.get(value);
28014 if (count) {
28015 if (count === 1) {
28016 optionsMap.remove(value);
28017 if (value === '') {
28018 self.emptyOption = undefined;
28019 }
28020 } else {
28021 optionsMap.put(value, count - 1);
28022 }
28023 }
28024 };
28025
28026 // Check whether the select control has an option matching the given value
28027 self.hasOption = function(value) {
28028 return !!optionsMap.get(value);
28029 };
28030 }];
28031
28032 /**
28033 * @ngdoc directive
28034 * @name select
28035 * @restrict E
28036 *
28037 * @description
28038 * HTML `SELECT` element with angular data-binding.
28039 *
28040 * In many cases, `ngRepeat` can be used on `<option>` elements instead of {@link ng.directive:ngOptions
28041 * ngOptions} to achieve a similar result. However, `ngOptions` provides some benefits such as reducing
28042 * memory and increasing speed by not creating a new scope for each repeated instance, as well as providing
28043 * more flexibility in how the `<select>`'s model is assigned via the `select` **`as`** part of the
28044 * comprehension expression.
28045 *
28046 * When an item in the `<select>` menu is selected, the array element or object property
28047 * represented by the selected option will be bound to the model identified by the `ngModel`
28048 * directive.
28049 *
28050 * If the viewValue contains a value that doesn't match any of the options then the control
28051 * will automatically add an "unknown" option, which it then removes when this is resolved.
28052 *
28053 * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
28054 * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
28055 * option. See example below for demonstration.
28056 *
28057 * <div class="alert alert-info">
28058 * The value of a `select` directive used without `ngOptions` is always a string.
28059 * When the model needs to be bound to a non-string value, you must either explictly convert it
28060 * using a directive (see example below) or use `ngOptions` to specify the set of options.
28061 * This is because an option element can only be bound to string values at present.
28062 * </div>
28063 *
28064 * ### Example (binding `select` to a non-string value)
28065 *
28066 * <example name="select-with-non-string-options" module="nonStringSelect">
28067 * <file name="index.html">
28068 * <select ng-model="model.id" convert-to-number>
28069 * <option value="0">Zero</option>
28070 * <option value="1">One</option>
28071 * <option value="2">Two</option>
28072 * </select>
28073 * {{ model }}
28074 * </file>
28075 * <file name="app.js">
28076 * angular.module('nonStringSelect', [])
28077 * .run(function($rootScope) {
28078 * $rootScope.model = { id: 2 };
28079 * })
28080 * .directive('convertToNumber', function() {
28081 * return {
28082 * require: 'ngModel',
28083 * link: function(scope, element, attrs, ngModel) {
28084 * ngModel.$parsers.push(function(val) {
28085 * return parseInt(val, 10);
28086 * });
28087 * ngModel.$formatters.push(function(val) {
28088 * return '' + val;
28089 * });
28090 * }
28091 * };
28092 * });
28093 * </file>
28094 * <file name="protractor.js" type="protractor">
28095 * it('should initialize to model', function() {
28096 * var select = element(by.css('select'));
28097 * expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two');
28098 * });
28099 * </file>
28100 * </example>
28101 *
28102 */
28103 var selectDirective = function() {
28104
28105 return {
28106 restrict: 'E',
28107 require: ['select', '?ngModel'],
28108 controller: SelectController,
28109 link: function(scope, element, attr, ctrls) {
28110
28111 // if ngModel is not defined, we don't need to do anything
28112 var ngModelCtrl = ctrls[1];
28113 if (!ngModelCtrl) return;
28114
28115 var selectCtrl = ctrls[0];
28116
28117 selectCtrl.ngModelCtrl = ngModelCtrl;
28118
28119 // We delegate rendering to the `writeValue` method, which can be changed
28120 // if the select can have multiple selected values or if the options are being
28121 // generated by `ngOptions`
28122 ngModelCtrl.$render = function() {
28123 selectCtrl.writeValue(ngModelCtrl.$viewValue);
28124 };
28125
28126 // When the selected item(s) changes we delegate getting the value of the select control
28127 // to the `readValue` method, which can be changed if the select can have multiple
28128 // selected values or if the options are being generated by `ngOptions`
28129 element.on('change', function() {
28130 scope.$apply(function() {
28131 ngModelCtrl.$setViewValue(selectCtrl.readValue());
28132 });
28133 });
28134
28135 // If the select allows multiple values then we need to modify how we read and write
28136 // values from and to the control; also what it means for the value to be empty and
28137 // we have to add an extra watch since ngModel doesn't work well with arrays - it
28138 // doesn't trigger rendering if only an item in the array changes.
28139 if (attr.multiple) {
28140
28141 // Read value now needs to check each option to see if it is selected
28142 selectCtrl.readValue = function readMultipleValue() {
28143 var array = [];
28144 forEach(element.find('option'), function(option) {
28145 if (option.selected) {
28146 array.push(option.value);
28147 }
28148 });
28149 return array;
28150 };
28151
28152 // Write value now needs to set the selected property of each matching option
28153 selectCtrl.writeValue = function writeMultipleValue(value) {
28154 var items = new HashMap(value);
28155 forEach(element.find('option'), function(option) {
28156 option.selected = isDefined(items.get(option.value));
28157 });
28158 };
28159
28160 // we have to do it on each watch since ngModel watches reference, but
28161 // we need to work of an array, so we need to see if anything was inserted/removed
28162 var lastView, lastViewRef = NaN;
28163 scope.$watch(function selectMultipleWatch() {
28164 if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) {
28165 lastView = shallowCopy(ngModelCtrl.$viewValue);
28166 ngModelCtrl.$render();
28167 }
28168 lastViewRef = ngModelCtrl.$viewValue;
28169 });
28170
28171 // If we are a multiple select then value is now a collection
28172 // so the meaning of $isEmpty changes
28173 ngModelCtrl.$isEmpty = function(value) {
28174 return !value || value.length === 0;
28175 };
28176
28177 }
28178 }
28179 };
28180 };
28181
28182
28183 // The option directive is purely designed to communicate the existence (or lack of)
28184 // of dynamically created (and destroyed) option elements to their containing select
28185 // directive via its controller.
28186 var optionDirective = ['$interpolate', function($interpolate) {
28187
28188 function chromeHack(optionElement) {
28189 // Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
28190 // Adding an <option selected="selected"> element to a <select required="required"> should
28191 // automatically select the new element
28192 if (optionElement[0].hasAttribute('selected')) {
28193 optionElement[0].selected = true;
28194 }
28195 }
28196
28197 return {
28198 restrict: 'E',
28199 priority: 100,
28200 compile: function(element, attr) {
28201
28202 // If the value attribute is not defined then we fall back to the
28203 // text content of the option element, which may be interpolated
28204 if (isUndefined(attr.value)) {
28205 var interpolateFn = $interpolate(element.text(), true);
28206 if (!interpolateFn) {
28207 attr.$set('value', element.text());
28208 }
28209 }
28210
28211 return function(scope, element, attr) {
28212
28213 // This is an optimization over using ^^ since we don't want to have to search
28214 // all the way to the root of the DOM for every single option element
28215 var selectCtrlName = '$selectController',
28216 parent = element.parent(),
28217 selectCtrl = parent.data(selectCtrlName) ||
28218 parent.parent().data(selectCtrlName); // in case we are in optgroup
28219
28220 // Only update trigger option updates if this is an option within a `select`
28221 // that also has `ngModel` attached
28222 if (selectCtrl && selectCtrl.ngModelCtrl) {
28223
28224 if (interpolateFn) {
28225 scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
28226 attr.$set('value', newVal);
28227 if (oldVal !== newVal) {
28228 selectCtrl.removeOption(oldVal);
28229 }
28230 selectCtrl.addOption(newVal, element);
28231 selectCtrl.ngModelCtrl.$render();
28232 chromeHack(element);
28233 });
28234 } else {
28235 selectCtrl.addOption(attr.value, element);
28236 selectCtrl.ngModelCtrl.$render();
28237 chromeHack(element);
28238 }
28239
28240 element.on('$destroy', function() {
28241 selectCtrl.removeOption(attr.value);
28242 selectCtrl.ngModelCtrl.$render();
28243 });
28244 }
28245 };
28246 }
28247 };
28248 }];
28249
28250 var styleDirective = valueFn({
28251 restrict: 'E',
28252 terminal: false
28253 });
28254
28255 var requiredDirective = function() {
28256 return {
28257 restrict: 'A',
28258 require: '?ngModel',
28259 link: function(scope, elm, attr, ctrl) {
28260 if (!ctrl) return;
28261 attr.required = true; // force truthy in case we are on non input element
28262
28263 ctrl.$validators.required = function(modelValue, viewValue) {
28264 return !attr.required || !ctrl.$isEmpty(viewValue);
28265 };
28266
28267 attr.$observe('required', function() {
28268 ctrl.$validate();
28269 });
28270 }
28271 };
28272 };
28273
28274
28275 var patternDirective = function() {
28276 return {
28277 restrict: 'A',
28278 require: '?ngModel',
28279 link: function(scope, elm, attr, ctrl) {
28280 if (!ctrl) return;
28281
28282 var regexp, patternExp = attr.ngPattern || attr.pattern;
28283 attr.$observe('pattern', function(regex) {
28284 if (isString(regex) && regex.length > 0) {
28285 regex = new RegExp('^' + regex + '$');
28286 }
28287
28288 if (regex && !regex.test) {
28289 throw minErr('ngPattern')('noregexp',
28290 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
28291 regex, startingTag(elm));
28292 }
28293
28294 regexp = regex || undefined;
28295 ctrl.$validate();
28296 });
28297
28298 ctrl.$validators.pattern = function(value) {
28299 return ctrl.$isEmpty(value) || isUndefined(regexp) || regexp.test(value);
28300 };
28301 }
28302 };
28303 };
28304
28305
28306 var maxlengthDirective = function() {
28307 return {
28308 restrict: 'A',
28309 require: '?ngModel',
28310 link: function(scope, elm, attr, ctrl) {
28311 if (!ctrl) return;
28312
28313 var maxlength = -1;
28314 attr.$observe('maxlength', function(value) {
28315 var intVal = toInt(value);
28316 maxlength = isNaN(intVal) ? -1 : intVal;
28317 ctrl.$validate();
28318 });
28319 ctrl.$validators.maxlength = function(modelValue, viewValue) {
28320 return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);
28321 };
28322 }
28323 };
28324 };
28325
28326 var minlengthDirective = function() {
28327 return {
28328 restrict: 'A',
28329 require: '?ngModel',
28330 link: function(scope, elm, attr, ctrl) {
28331 if (!ctrl) return;
28332
28333 var minlength = 0;
28334 attr.$observe('minlength', function(value) {
28335 minlength = toInt(value) || 0;
28336 ctrl.$validate();
28337 });
28338 ctrl.$validators.minlength = function(modelValue, viewValue) {
28339 return ctrl.$isEmpty(viewValue) || viewValue.length >= minlength;
28340 };
28341 }
28342 };
28343 };
28344
28345 if (window.angular.bootstrap) {
28346 //AngularJS is already loaded, so we can return here...
28347 console.log('WARNING: Tried to load angular more than once.');
28348 return;
28349 }
28350
28351 //try to bind to jquery now so that one can write jqLite(document).ready()
28352 //but we will rebind on bootstrap again.
28353 bindJQuery();
28354
28355 publishExternalAPI(angular);
28356
28357 jqLite(document).ready(function() {
28358 angularInit(document, bootstrap);
28359 });
28360
28361 })(window, document);
28362
28363 !window.angular.$$csp() && window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
+0
-290
faraday/server/www/script/angular.min.js less more
0 /*
1 AngularJS v1.4.3
2 (c) 2010-2015 Google, Inc. http://angularjs.org
3 License: MIT
4 */
5 (function(O,U,t){'use strict';function J(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.3/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){c=c+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,e;e=arguments[a];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;c+=d(e)}return Error(c)}}function Ea(b){if(null==b||Wa(b))return!1;var a="length"in Object(b)&&b.length;
6 return b.nodeType===qa&&a?!0:L(b)||G(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function m(b,a,c){var d,e;if(b)if(z(b))for(d in b)"prototype"==d||"length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d)||a.call(c,b[d],d,b);else if(G(b)||Ea(b)){var f="object"!==typeof b;d=0;for(e=b.length;d<e;d++)(f||d in b)&&a.call(c,b[d],d,b)}else if(b.forEach&&b.forEach!==m)b.forEach(a,c,b);else if(nc(b))for(d in b)a.call(c,b[d],d,b);else if("function"===typeof b.hasOwnProperty)for(d in b)b.hasOwnProperty(d)&&
7 a.call(c,b[d],d,b);else for(d in b)Xa.call(b,d)&&a.call(c,b[d],d,b);return b}function oc(b,a,c){for(var d=Object.keys(b).sort(),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function pc(b){return function(a,c){b(c,a)}}function Ud(){return++nb}function qc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function Nb(b,a,c){for(var d=b.$$hashKey,e=0,f=a.length;e<f;++e){var g=a[e];if(H(g)||z(g))for(var h=Object.keys(g),l=0,k=h.length;l<k;l++){var n=h[l],r=g[n];c&&H(r)?aa(r)?b[n]=new Date(r.valueOf()):(H(b[n])||
8 (b[n]=G(r)?[]:{}),Nb(b[n],[r],!0)):b[n]=r}}qc(b,d);return b}function P(b){return Nb(b,za.call(arguments,1),!1)}function Vd(b){return Nb(b,za.call(arguments,1),!0)}function W(b){return parseInt(b,10)}function Ob(b,a){return P(Object.create(b),a)}function v(){}function Ya(b){return b}function ra(b){return function(){return b}}function rc(b){return z(b.toString)&&b.toString!==Object.prototype.toString}function A(b){return"undefined"===typeof b}function w(b){return"undefined"!==typeof b}function H(b){return null!==
9 b&&"object"===typeof b}function nc(b){return null!==b&&"object"===typeof b&&!sc(b)}function L(b){return"string"===typeof b}function V(b){return"number"===typeof b}function aa(b){return"[object Date]"===sa.call(b)}function z(b){return"function"===typeof b}function Za(b){return"[object RegExp]"===sa.call(b)}function Wa(b){return b&&b.window===b}function $a(b){return b&&b.$evalAsync&&b.$watch}function ab(b){return"boolean"===typeof b}function tc(b){return!(!b||!(b.nodeName||b.prop&&b.attr&&b.find))}
10 function Wd(b){var a={};b=b.split(",");var c;for(c=0;c<b.length;c++)a[b[c]]=!0;return a}function ta(b){return M(b.nodeName||b[0]&&b[0].nodeName)}function bb(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return c}function fa(b,a,c,d){if(Wa(b)||$a(b))throw Fa("cpws");if(uc.test(sa.call(a)))throw Fa("cpta");if(a){if(b===a)throw Fa("cpi");c=c||[];d=d||[];H(b)&&(c.push(b),d.push(a));var e;if(G(b))for(e=a.length=0;e<b.length;e++)a.push(fa(b[e],null,c,d));else{var f=a.$$hashKey;G(a)?a.length=0:m(a,function(b,
11 c){delete a[c]});if(nc(b))for(e in b)a[e]=fa(b[e],null,c,d);else if(b&&"function"===typeof b.hasOwnProperty)for(e in b)b.hasOwnProperty(e)&&(a[e]=fa(b[e],null,c,d));else for(e in b)Xa.call(b,e)&&(a[e]=fa(b[e],null,c,d));qc(a,f)}}else if(a=b,H(b)){if(c&&-1!==(f=c.indexOf(b)))return d[f];if(G(b))return fa(b,[],c,d);if(uc.test(sa.call(b)))a=new b.constructor(b);else if(aa(b))a=new Date(b.getTime());else if(Za(b))a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex;else return e=
12 Object.create(sc(b)),fa(b,e,c,d);d&&(c.push(b),d.push(a))}return a}function ia(b,a){if(G(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(H(b))for(c in a=a||{},b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=b[c];return a||b}function ka(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(G(b)){if(!G(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ka(b[d],a[d]))return!1;return!0}}else{if(aa(b))return aa(a)?
13 ka(b.getTime(),a.getTime()):!1;if(Za(b))return Za(a)?b.toString()==a.toString():!1;if($a(b)||$a(a)||Wa(b)||Wa(a)||G(a)||aa(a)||Za(a))return!1;c=ga();for(d in b)if("$"!==d.charAt(0)&&!z(b[d])){if(!ka(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!(d in c||"$"===d.charAt(0)||a[d]===t||z(a[d])))return!1;return!0}return!1}function cb(b,a,c){return b.concat(za.call(a,c))}function vc(b,a){var c=2<arguments.length?za.call(arguments,2):[];return!z(a)||a instanceof RegExp?a:c.length?function(){return arguments.length?
14 a.apply(b,cb(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Xd(b,a){var c=a;"string"===typeof b&&"$"===b.charAt(0)&&"$"===b.charAt(1)?c=t:Wa(a)?c="$WINDOW":a&&U===a?c="$DOCUMENT":$a(a)&&(c="$SCOPE");return c}function db(b,a){if("undefined"===typeof b)return t;V(a)||(a=a?2:null);return JSON.stringify(b,Xd,a)}function wc(b){return L(b)?JSON.parse(b):b}function xc(b,a){var c=Date.parse("Jan 01, 1970 00:00:00 "+b)/6E4;return isNaN(c)?a:c}function Pb(b,
15 a,c){c=c?-1:1;var d=xc(a,b.getTimezoneOffset());a=b;b=c*(d-b.getTimezoneOffset());a=new Date(a.getTime());a.setMinutes(a.getMinutes()+b);return a}function ua(b){b=y(b).clone();try{b.empty()}catch(a){}var c=y("<div>").append(b).html();try{return b[0].nodeType===Na?M(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+M(b)})}catch(d){return M(c)}}function yc(b){try{return decodeURIComponent(b)}catch(a){}}function zc(b){var a={},c,d;m((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,
16 "%20").split("="),d=yc(c[0]),w(d)&&(b=w(c[1])?yc(c[1]):!0,Xa.call(a,d)?G(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Qb(b){var a=[];m(b,function(b,d){G(b)?m(b,function(b){a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))}):a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))});return a.length?a.join("&"):""}function ob(b){return ma(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ma(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,
17 "$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Yd(b,a){var c,d,e=Oa.length;for(d=0;d<e;++d)if(c=Oa[d]+a,L(c=b.getAttribute(c)))return c;return null}function Zd(b,a){var c,d,e={};m(Oa,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});m(Oa,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Yd(c,"strict-di"),a(c,d?[d]:[],e))}function Ac(b,a,c){H(c)||
18 (c={});c=P({strictDi:!1},c);var d=function(){b=y(b);if(b.injector()){var d=b[0]===U?"document":ua(b);throw Fa("btstrpd",d.replace(/</,"&lt;").replace(/>/,"&gt;"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=eb(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d},e=
19 /^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;O&&e.test(O.name)&&(c.debugInfoEnabled=!0,O.name=O.name.replace(e,""));if(O&&!f.test(O.name))return d();O.name=O.name.replace(f,"");ca.resumeBootstrap=function(b){m(b,function(b){a.push(b)});return d()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function $d(){O.name="NG_ENABLE_DEBUG_INFO!"+O.name;O.location.reload()}function ae(b){b=ca.element(b).injector();if(!b)throw Fa("test");return b.get("$$testability")}function Bc(b,a){a=a||
20 "_";return b.replace(be,function(b,d){return(d?a:"")+b.toLowerCase()})}function ce(){var b;if(!Cc){var a=pb();la=O.jQuery;w(a)&&(la=null===a?t:O[a]);la&&la.fn.on?(y=la,P(la.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),b=la.cleanData,la.cleanData=function(a){var d;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=a[e]);e++)(d=la._data(f,"events"))&&d.$destroy&&la(f).triggerHandler("$destroy");b(a)}):y=Q;ca.element=y;Cc=!0}}function Sb(b,
21 a,c){if(!b)throw Fa("areq",a||"?",c||"required");return b}function Qa(b,a,c){c&&G(b)&&(b=b[b.length-1]);Sb(z(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ra(b,a){if("hasOwnProperty"===b)throw Fa("badname",a);}function Dc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&z(b)?vc(e,b):b}function qb(b){var a=b[0];b=b[b.length-1];var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!==
22 b);return y(c)}function ga(){return Object.create(null)}function de(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=J("$injector"),d=J("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||J;return a(b,"module",function(){var b={};return function(f,g,h){if("hasOwnProperty"===f)throw d("badname","module");g&&b.hasOwnProperty(f)&&(b[f]=null);return a(b,f,function(){function a(b,c,e,f){f||(f=d);return function(){f[e||"push"]([b,c,arguments]);return C}}function b(a,c){return function(b,e){e&&z(e)&&
23 (e.$$moduleName=f);d.push([a,c,arguments]);return C}}if(!g)throw c("nomod",f);var d=[],e=[],s=[],x=a("$injector","invoke","push",e),C={_invokeQueue:d,_configBlocks:e,_runBlocks:s,requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide","decorator"),animation:b("$animateProvider","register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider",
24 "register"),directive:b("$compileProvider","directive"),config:x,run:function(a){s.push(a);return this}};h&&x(h);return C})}})}function ee(b){P(b,{bootstrap:Ac,copy:fa,extend:P,merge:Vd,equals:ka,element:y,forEach:m,injector:eb,noop:v,bind:vc,toJson:db,fromJson:wc,identity:Ya,isUndefined:A,isDefined:w,isString:L,isFunction:z,isObject:H,isNumber:V,isElement:tc,isArray:G,version:fe,isDate:aa,lowercase:M,uppercase:rb,callbacks:{counter:0},getTestability:ae,$$minErr:J,$$csp:fb,reloadWithDebugInfo:$d});
25 gb=de(O);try{gb("ngLocale")}catch(a){gb("ngLocale",[]).provider("$locale",ge)}gb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:he});a.provider("$compile",Ec).directive({a:ie,input:Fc,textarea:Fc,form:je,script:ke,select:le,style:me,option:ne,ngBind:oe,ngBindHtml:pe,ngBindTemplate:qe,ngClass:re,ngClassEven:se,ngClassOdd:te,ngCloak:ue,ngController:ve,ngForm:we,ngHide:xe,ngIf:ye,ngInclude:ze,ngInit:Ae,ngNonBindable:Be,ngPluralize:Ce,ngRepeat:De,ngShow:Ee,ngStyle:Fe,ngSwitch:Ge,
26 ngSwitchWhen:He,ngSwitchDefault:Ie,ngOptions:Je,ngTransclude:Ke,ngModel:Le,ngList:Me,ngChange:Ne,pattern:Gc,ngPattern:Gc,required:Hc,ngRequired:Hc,minlength:Ic,ngMinlength:Ic,maxlength:Jc,ngMaxlength:Jc,ngValue:Oe,ngModelOptions:Pe}).directive({ngInclude:Qe}).directive(sb).directive(Kc);a.provider({$anchorScroll:Re,$animate:Se,$$animateQueue:Te,$$AnimateRunner:Ue,$browser:Ve,$cacheFactory:We,$controller:Xe,$document:Ye,$exceptionHandler:Ze,$filter:Lc,$interpolate:$e,$interval:af,$http:bf,$httpParamSerializer:cf,
27 $httpParamSerializerJQLike:df,$httpBackend:ef,$location:ff,$log:gf,$parse:hf,$rootScope:jf,$q:kf,$$q:lf,$sce:mf,$sceDelegate:nf,$sniffer:of,$templateCache:pf,$templateRequest:qf,$$testability:rf,$timeout:sf,$window:tf,$$rAF:uf,$$jqLite:vf,$$HashMap:wf,$$cookieReader:xf})}])}function hb(b){return b.replace(yf,function(a,b,d,e){return e?d.toUpperCase():d}).replace(zf,"Moz$1")}function Mc(b){b=b.nodeType;return b===qa||!b||9===b}function Nc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Tb.test(b)){c=
28 c||e.appendChild(a.createElement("div"));d=(Af.exec(b)||["",""])[1].toLowerCase();d=na[d]||na._default;c.innerHTML=d[1]+b.replace(Bf,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=cb(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";m(f,function(a){e.appendChild(a)});return e}function Q(b){if(b instanceof Q)return b;var a;L(b)&&(b=R(b),a=!0);if(!(this instanceof Q)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new Q(b)}if(a){a=U;
29 var c;b=(c=Cf.exec(b))?[a.createElement(c[1])]:(c=Nc(b,a))?c.childNodes:[]}Oc(this,b)}function Vb(b){return b.cloneNode(!0)}function tb(b,a){a||ub(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d<e;d++)ub(c[d])}function Pc(b,a,c,d){if(w(d))throw Ub("offargs");var e=(d=vb(b))&&d.events,f=d&&d.handle;if(f)if(a)m(a.split(" "),function(a){if(w(c)){var d=e[a];bb(d||[],c);if(d&&0<d.length)return}b.removeEventListener(a,f,!1);delete e[a]});else for(a in e)"$destroy"!==a&&b.removeEventListener(a,
30 f,!1),delete e[a]}function ub(b,a){var c=b.ng339,d=c&&ib[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Pc(b)),delete ib[c],b.ng339=t))}function vb(b,a){var c=b.ng339,c=c&&ib[c];a&&!c&&(b.ng339=c=++Df,c=ib[c]={events:{},data:{},handle:t});return c}function Wb(b,a,c){if(Mc(b)){var d=w(c),e=!d&&a&&!H(a),f=!a;b=(b=vb(b,!e))&&b.data;if(d)b[a]=c;else{if(f)return b;if(e)return b&&b[a];P(b,a)}}}function wb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+
31 " ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function xb(b,a){a&&b.setAttribute&&m(a.split(" "),function(a){b.setAttribute("class",R((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+R(a)+" "," ")))})}function yb(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");m(a.split(" "),function(a){a=R(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",R(c))}}function Oc(b,a){if(a)if(a.nodeType)b[b.length++]=a;else{var c=
32 a.length;if("number"===typeof c&&a.window!==a){if(c)for(var d=0;d<c;d++)b[b.length++]=a[d]}else b[b.length++]=a}}function Qc(b,a){return zb(b,"$"+(a||"ngController")+"Controller")}function zb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=G(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=y.data(b,a[d]))!==t)return c;b=b.parentNode||11===b.nodeType&&b.host}}function Rc(b){for(tb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}function Xb(b,a){a||tb(b);var c=b.parentNode;c&&c.removeChild(b)}function Ef(b,
33 a){a=a||O;if("complete"===a.document.readyState)a.setTimeout(b);else y(a).on("load",b)}function Sc(b,a){var c=Ab[a.toLowerCase()];return c&&Tc[ta(b)]&&c}function Ff(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Uc[a]}function Gf(b,a){var c=function(c,e){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=a[e||c.type],g=f?f.length:0;if(g){if(A(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=
34 !0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};1<g&&(f=ia(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||f[l].call(b,c)}};c.elem=b;return c}function vf(){this.$get=function(){return P(Q,{hasClass:function(b,a){b.attr&&(b=b[0]);return wb(b,a)},addClass:function(b,a){b.attr&&(b=b[0]);return yb(b,a)},removeClass:function(b,a){b.attr&&(b=b[0]);return xb(b,a)}})}}function Ga(b,a){var c=b&&b.$$hashKey;
35 if(c)return"function"===typeof c&&(c=b.$$hashKey()),c;c=typeof b;return c="function"==c||"object"==c&&null!==b?b.$$hashKey=c+":"+(a||Ud)():c+":"+b}function Sa(b,a){if(a){var c=0;this.nextUid=function(){return++c}}m(b,this.put,this)}function Hf(b){return(b=b.toString().replace(Vc,"").match(Wc))?"function("+(b[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function eb(b,a){function c(a){return function(b,c){if(H(b))m(b,pc(a));else return a(b,c)}}function d(a,b){Ra(a,"service");if(z(b)||G(b))b=s.instantiate(b);
36 if(!b.$get)throw Ha("pget",a);return r[a+"Provider"]=b}function e(a,b){return function(){var c=C.invoke(b,this);if(A(c))throw Ha("undef",a);return c}}function f(a,b,c){return d(a,{$get:!1!==c?e(a,b):b})}function g(a){var b=[],c;m(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=s.get(e[0]);f[e[1]].apply(f,e[2])}}if(!n.get(a)){n.put(a,!0);try{L(a)?(c=gb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(s.invoke(a)):G(a)?
37 b.push(s.invoke(a)):Qa(a,"module")}catch(e){throw G(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ha("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a,e){if(b.hasOwnProperty(a)){if(b[a]===l)throw Ha("cdep",a+" <- "+k.join(" <- "));return b[a]}try{return k.unshift(a),b[a]=l,b[a]=c(a,e)}catch(f){throw b[a]===l&&delete b[a],f;}finally{k.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var h=[],k=eb.$$annotate(b,
38 a,g),l,s,n;s=0;for(l=k.length;s<l;s++){n=k[s];if("string"!==typeof n)throw Ha("itkn",n);h.push(f&&f.hasOwnProperty(n)?f[n]:d(n,g))}G(b)&&(b=b[l]);return b.apply(c,h)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((G(a)?a[a.length-1]:a).prototype||null);a=e(a,d,b,c);return H(a)||z(a)?a:d},get:d,annotate:eb.$$annotate,has:function(a){return r.hasOwnProperty(a+"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var l={},k=[],n=new Sa([],!0),r={$provide:{provider:c(d),factory:c(f),service:c(function(a,
39 b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:c(function(a,b){return f(a,ra(b),!1)}),constant:c(function(a,b){Ra(a,"constant");r[a]=b;x[a]=b}),decorator:function(a,b){var c=s.get(a+"Provider"),d=c.$get;c.$get=function(){var a=C.invoke(d,c);return C.invoke(b,null,{$delegate:a})}}}},s=r.$injector=h(r,function(a,b){ca.isString(b)&&k.push(b);throw Ha("unpr",k.join(" <- "));}),x={},C=x.$injector=h(x,function(a,b){var c=s.get(a+"Provider",b);return C.invoke(c.$get,c,t,a)});m(g(b),
40 function(a){a&&C.invoke(a)});return C}function Re(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===ta(a))return b=a,!0});return b}function f(b){if(b){b.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():tc(c)?(c=c[0],c="fixed"!==a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):V(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0,
41 0)}function g(a){a=L(a)?a:c.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(a,b){a===b&&""===a||Ef(function(){d.$evalAsync(g)})});return g}]}function jb(b,a){if(!b&&!a)return"";if(!b)return a;if(!a)return b;G(b)&&(b=b.join(" "));G(a)&&(a=a.join(" "));return b+" "+a}function If(b){L(b)&&(b=b.split(" "));var a=ga();m(b,function(b){b.length&&(a[b]=!0)});return a}function Ia(b){return H(b)?
42 b:{}}function Jf(b,a,c,d){function e(a){try{a.apply(null,za.call(arguments,1))}finally{if(C--,0===C)for(;F.length;)try{F.pop()()}catch(b){c.error(b)}}}function f(){g();h()}function g(){a:{try{u=n.state;break a}catch(a){}u=void 0}u=A(u)?null:u;ka(u,D)&&(u=D);D=u}function h(){if(K!==l.url()||p!==u)K=l.url(),p=u,m(B,function(a){a(l.url(),u)})}var l=this,k=b.location,n=b.history,r=b.setTimeout,s=b.clearTimeout,x={};l.isMock=!1;var C=0,F=[];l.$$completeOutstandingRequest=e;l.$$incOutstandingRequestCount=
43 function(){C++};l.notifyWhenNoOutstandingRequests=function(a){0===C?a():F.push(a)};var u,p,K=k.href,q=a.find("base"),I=null;g();p=u;l.url=function(a,c,e){A(e)&&(e=null);k!==b.location&&(k=b.location);n!==b.history&&(n=b.history);if(a){var f=p===e;if(K===a&&(!d.history||f))return l;var h=K&&Ja(K)===Ja(a);K=a;p=e;if(!d.history||h&&f){if(!h||I)I=a;c?k.replace(a):h?(c=k,e=a.indexOf("#"),a=-1===e?"":a.substr(e),c.hash=a):k.href=a}else n[c?"replaceState":"pushState"](e,"",a),g(),p=u;return l}return I||
44 k.href.replace(/%27/g,"'")};l.state=function(){return u};var B=[],N=!1,D=null;l.onUrlChange=function(a){if(!N){if(d.history)y(b).on("popstate",f);y(b).on("hashchange",f);N=!0}B.push(a);return a};l.$$applicationDestroyed=function(){y(b).off("hashchange popstate",f)};l.$$checkUrlChange=h;l.baseHref=function(){var a=q.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};l.defer=function(a,b){var c;C++;c=r(function(){delete x[c];e(a)},b||0);x[c]=!0;return c};l.defer.cancel=function(a){return x[a]?
45 (delete x[a],s(a),e(v),!0):!1}}function Ve(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new Jf(b,d,a,c)}]}function We(){this.$get=function(){function b(b,d){function e(a){a!=r&&(s?s==a&&(s=a.n):s=a,f(a.n,a.p),f(a,r),r=a,r.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw J("$cacheFactory")("iid",b);var g=0,h=P({},d,{id:b}),l={},k=d&&d.capacity||Number.MAX_VALUE,n={},r=null,s=null;return a[b]={put:function(a,b){if(!A(b)){if(k<Number.MAX_VALUE){var c=
46 n[a]||(n[a]={key:a});e(c)}a in l||g++;l[a]=b;g>k&&this.remove(s.key);return b}},get:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;e(b)}return l[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;b==r&&(r=b.p);b==s&&(s=b.n);f(b.n,b.p);delete n[a]}delete l[a];g--},removeAll:function(){l={};g=0;n={};r=s=null},destroy:function(){n=h=l=null;delete a[b]},info:function(){return P({},h,{size:g})}}}var a={};b.info=function(){var b={};m(a,function(a,e){b[e]=a.info()});return b};
47 b.get=function(b){return a[b]};return b}}function pf(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Ec(b,a){function c(a,b,c){var d=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,e={};m(a,function(a,f){var g=a.match(d);if(!g)throw ea("iscp",b,f,a,c?"controller bindings definition":"isolate scope definition");e[f]={mode:g[1][0],collection:"*"===g[2],optional:"?"===g[3],attrName:g[4]||f}});return e}function d(a){var b=a.charAt(0);if(!b||b!==M(b))throw ea("baddir",a);if(a!==a.trim())throw ea("baddir",
48 a);}var e={},f=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,g=/(([\w\-]+)(?:\:([^;]+))?;?)/,h=Wd("ngSrc,ngSrcset,src,srcset"),l=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,k=/^(on[a-z]+|formaction)$/;this.directive=function s(a,f){Ra(a,"directive");L(a)?(d(a),Sb(f,"directiveFactory"),e.hasOwnProperty(a)||(e[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,d){var f=[];m(e[a],function(e,g){try{var h=b.invoke(e);z(h)?h={compile:ra(h)}:!h.compile&&h.link&&(h.compile=ra(h.link));h.priority=h.priority||
49 0;h.index=g;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";var k=h,l=h,s=h.name,n={isolateScope:null,bindToController:null};H(l.scope)&&(!0===l.bindToController?(n.bindToController=c(l.scope,s,!0),n.isolateScope={}):n.isolateScope=c(l.scope,s,!1));H(l.bindToController)&&(n.bindToController=c(l.bindToController,s,!0));if(H(n.bindToController)){var C=l.controller,$=l.controllerAs;if(!C)throw ea("noctrl",s);var ha;a:if($&&L($))ha=$;else{if(L(C)){var m=Xc.exec(C);
50 if(m){ha=m[3];break a}}ha=void 0}if(!ha)throw ea("noident",s);}var q=k.$$bindings=n;H(q.isolateScope)&&(h.$$isolateBindings=q.isolateScope);h.$$moduleName=e.$$moduleName;f.push(h)}catch(t){d(t)}});return f}])),e[a].push(f)):m(a,pc(s));return this};this.aHrefSanitizationWhitelist=function(b){return w(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return w(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};
51 var n=!0;this.debugInfoEnabled=function(a){return w(a)?(n=a,this):n};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,d,u,p,K,q,I,B,N){function D(a,b){try{a.addClass(b)}catch(c){}}function Z(a,b,c,d,e){a instanceof y||(a=y(a));m(a,function(b,c){b.nodeType==Na&&b.nodeValue.match(/\S+/)&&(a[c]=y(b).wrap("<span></span>").parent()[0])});var f=S(a,b,a,c,d,e);Z.$$addScopeClass(a);
52 var g=null;return function(b,c,d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ta(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?y(Yb(g,y("<div>").append(a).html())):c?Pa.clone.call(a):a;if(h)for(var k in h)d.data("$"+k+"Controller",h[k].instance);Z.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function S(a,b,c,d,e,f){function g(a,
53 c,d,e){var f,k,l,s,n,B,C;if(p)for(C=Array(c.length),s=0;s<h.length;s+=3)f=h[s],C[f]=c[f];else C=c;s=0;for(n=h.length;s<n;)if(k=C[h[s++]],c=h[s++],f=h[s++],c){if(c.scope){if(l=a.$new(),Z.$$addScopeInfo(y(k),l),B=c.$$destroyBindings)c.$$destroyBindings=null,l.$on("$destroyed",B)}else l=a;B=c.transcludeOnThisElement?$(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?$(a,b):null;c(f,l,k,d,B,c)}else f&&f(a,k.childNodes,t,e)}for(var h=[],k,l,s,n,p,B=0;B<a.length;B++){k=new aa;l=ha(a[B],[],k,0===B?
54 d:t,e);(f=l.length?E(l,a[B],k,b,c,null,[],[],f):null)&&f.scope&&Z.$$addScopeClass(k.$$element);k=f&&f.terminal||!(s=a[B].childNodes)||!s.length?null:S(s,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(B,f,k),n=!0,p=p||f;f=null}return n?g:null}function $(a,b,c){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function ha(a,b,c,d,e){var h=c.$attr,k;switch(a.nodeType){case qa:w(b,
55 wa(ta(a)),"E",d,e);for(var l,s,n,p=a.attributes,B=0,C=p&&p.length;B<C;B++){var x=!1,S=!1;l=p[B];k=l.name;s=R(l.value);l=wa(k);if(n=ia.test(l))k=k.replace(Zc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});var F=l.replace(/(Start|End)$/,"");A(F)&&l===F+"Start"&&(x=k,S=k.substr(0,k.length-5)+"end",k=k.substr(0,k.length-6));l=wa(k.toLowerCase());h[l]=k;if(n||!c.hasOwnProperty(l))c[l]=s,Sc(a,l)&&(c[l]=!0);V(a,b,s,l,n);w(b,l,"A",d,e,x,S)}a=a.className;H(a)&&(a=a.animVal);if(L(a)&&
56 ""!==a)for(;k=g.exec(a);)l=wa(k[2]),w(b,l,"C",d,e)&&(c[l]=R(k[3])),a=a.substr(k.index+k[0].length);break;case Na:if(11===Ua)for(;a.parentNode&&a.nextSibling&&a.nextSibling.nodeType===Na;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);xa(b,a.nodeValue);break;case 8:try{if(k=f.exec(a.nodeValue))l=wa(k[1]),w(b,l,"M",d,e)&&(c[l]=R(k[2]))}catch($){}}b.sort(Aa);return b}function va(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ea("uterdir",b,c);
57 a.nodeType==qa&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return y(d)}function Yc(a,b,c){return function(d,e,f,g,h){e=va(e[0],b,c);return a(d,e,f,g,h)}}function E(a,b,d,e,f,g,h,k,s){function n(a,b,c,d){if(a){c&&(a=Yc(a,c,d));a.require=E.require;a.directiveName=w;if(u===E||E.$$isolateScope)a=X(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=Yc(b,c,d));b.require=E.require;b.directiveName=w;if(u===E||E.$$isolateScope)b=X(b,{isolateScope:!0});k.push(b)}}
58 function B(a,b,c,d){var e;if(L(b)){var f=b.match(l);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&e.instance;e||(d="$"+b+"Controller",e=g?c.inheritedData(d):c.data(d));if(!e&&!f)throw ea("ctreq",b,a);}else if(G(b))for(e=[],g=0,f=b.length;g<f;g++)e[g]=B(a,b[g],c,d);return e||null}function x(a,b,c,d,e,f){var g=ga(),h;for(h in d){var k=d[h],l={$scope:k===u||k.$$isolateScope?e:f,$element:a,$attrs:b,$transclude:c},s=k.controller;"@"==s&&(s=b[k.name]);l=p(s,
59 l,!0,k.controllerAs);g[k.name]=l;q||a.data("$"+k.name+"Controller",l.instance)}return g}function S(a,c,e,f,g,l){function s(a,b,c){var d;$a(a)||(c=b,b=a,a=t);q&&(d=m);c||(c=q?ja.parent():ja);return g(a,b,d,c,va)}var n,p,C,F,m,ha,ja;b===e?(f=d,ja=d.$$element):(ja=y(e),f=new aa(ja,d));u&&(F=c.$new(!0));g&&(ha=s,ha.$$boundTransclude=g);N&&(m=x(ja,f,ha,N,F,c));u&&(Z.$$addScopeInfo(ja,F,!0,!(D&&(D===u||D===u.$$originalDirective))),Z.$$addScopeClass(ja,!0),F.$$isolateBindings=u.$$isolateBindings,W(c,f,F,
60 F.$$isolateBindings,u,F));if(m){var K=u||$,I;K&&m[K.name]&&(p=K.$$bindings.bindToController,(C=m[K.name])&&C.identifier&&p&&(I=C,l.$$destroyBindings=W(c,f,C.instance,p,K)));for(n in m){C=m[n];var E=C();E!==C.instance&&(C.instance=E,ja.data("$"+n+"Controller",E),C===I&&(l.$$destroyBindings(),l.$$destroyBindings=W(c,f,E,p,K)))}}n=0;for(l=h.length;n<l;n++)p=h[n],Y(p,p.isolateScope?F:c,ja,f,p.require&&B(p.directiveName,p.require,ja,m),ha);var va=c;u&&(u.template||null===u.templateUrl)&&(va=F);a&&a(va,
61 e.childNodes,t,g);for(n=k.length-1;0<=n;n--)p=k[n],Y(p,p.isolateScope?F:c,ja,f,p.require&&B(p.directiveName,p.require,ja,m),ha)}s=s||{};for(var F=-Number.MAX_VALUE,$=s.newScopeDirective,N=s.controllerDirectives,u=s.newIsolateScopeDirective,D=s.templateDirective,m=s.nonTlbTranscludeDirective,K=!1,I=!1,q=s.hasElementTranscludeDirective,ba=d.$$element=y(b),E,w,v,A=e,Aa,xa=0,Ta=a.length;xa<Ta;xa++){E=a[xa];var M=E.$$start,P=E.$$end;M&&(ba=va(b,M,P));v=t;if(F>E.priority)break;if(v=E.scope)E.templateUrl||
62 (H(v)?(O("new/isolated scope",u||$,E,ba),u=E):O("new/isolated scope",u,E,ba)),$=$||E;w=E.name;!E.templateUrl&&E.controller&&(v=E.controller,N=N||ga(),O("'"+w+"' controller",N[w],E,ba),N[w]=E);if(v=E.transclude)K=!0,E.$$tlb||(O("transclusion",m,E,ba),m=E),"element"==v?(q=!0,F=E.priority,v=ba,ba=d.$$element=y(U.createComment(" "+w+": "+d[w]+" ")),b=ba[0],T(f,za.call(v,0),b),A=Z(v,e,F,g&&g.name,{nonTlbTranscludeDirective:m})):(v=y(Vb(b)).contents(),ba.empty(),A=Z(v,e));if(E.template)if(I=!0,O("template",
63 D,E,ba),D=E,v=z(E.template)?E.template(ba,d):E.template,v=fa(v),E.replace){g=E;v=Tb.test(v)?$c(Yb(E.templateNamespace,R(v))):[];b=v[0];if(1!=v.length||b.nodeType!==qa)throw ea("tplrt",w,"");T(f,ba,b);Ta={$attr:{}};v=ha(b,[],Ta);var Q=a.splice(xa+1,a.length-(xa+1));u&&ad(v);a=a.concat(v).concat(Q);J(d,Ta);Ta=a.length}else ba.html(v);if(E.templateUrl)I=!0,O("template",D,E,ba),D=E,E.replace&&(g=E),S=Lf(a.splice(xa,a.length-xa),ba,d,f,K&&A,h,k,{controllerDirectives:N,newScopeDirective:$!==E&&$,newIsolateScopeDirective:u,
64 templateDirective:D,nonTlbTranscludeDirective:m}),Ta=a.length;else if(E.compile)try{Aa=E.compile(ba,d,A),z(Aa)?n(null,Aa,M,P):Aa&&n(Aa.pre,Aa.post,M,P)}catch(Kf){c(Kf,ua(ba))}E.terminal&&(S.terminal=!0,F=Math.max(F,E.priority))}S.scope=$&&!0===$.scope;S.transcludeOnThisElement=K;S.templateOnThisElement=I;S.transclude=A;s.hasElementTranscludeDirective=q;return S}function ad(a){for(var b=0,c=a.length;b<c;b++)a[b]=Ob(a[b],{$$isolateScope:!0})}function w(b,d,f,g,h,k,l){if(d===h)return null;h=null;if(e.hasOwnProperty(d)){var n;
65 d=a.get(d+"Directive");for(var p=0,B=d.length;p<B;p++)try{n=d[p],(g===t||g>n.priority)&&-1!=n.restrict.indexOf(f)&&(k&&(n=Ob(n,{$$start:k,$$end:l})),b.push(n),h=n)}catch(x){c(x)}}return h}function A(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d<f;d++)if(b=c[d],b.multiElement)return!0;return!1}function J(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;m(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});m(b,function(b,f){"class"==
66 f?(D(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function Lf(a,b,c,e,f,g,h,k){var l=[],s,n,p=b[0],B=a.shift(),C=Ob(B,{templateUrl:null,transclude:null,replace:null,$$originalDirective:B}),x=z(B.templateUrl)?B.templateUrl(b,c):B.templateUrl,N=B.templateNamespace;b.empty();d(x).then(function(d){var F,u;d=fa(d);if(B.replace){d=Tb.test(d)?$c(Yb(N,R(d))):
67 [];F=d[0];if(1!=d.length||F.nodeType!==qa)throw ea("tplrt",B.name,x);d={$attr:{}};T(e,b,F);var K=ha(F,[],d);H(B.scope)&&ad(K);a=K.concat(a);J(c,d)}else F=p,b.html(d);a.unshift(C);s=E(a,F,c,f,b,B,g,h,k);m(e,function(a,c){a==F&&(e[c]=b[0])});for(n=S(b[0].childNodes,f);l.length;){d=l.shift();u=l.shift();var I=l.shift(),va=l.shift(),K=b[0];if(!d.$$destroyed){if(u!==p){var Z=u.className;k.hasElementTranscludeDirective&&B.replace||(K=Vb(F));T(I,y(u),K);D(y(K),Z)}u=s.transcludeOnThisElement?$(d,s.transclude,
68 va):va;s(n,d,K,e,u,s)}}l=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(s.transcludeOnThisElement&&(a=$(b,s.transclude,e)),s(n,b,c,d,a,s)))}}function Aa(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function O(a,b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw ea("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,ua(d));}function xa(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=
69 a.parent();var b=!!a.length;b&&Z.$$addBindingClass(a);return function(a,c){var e=c.parent();b||Z.$$addBindingClass(e);Z.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Yb(a,b){a=M(a||"html");switch(a){case "svg":case "math":var c=U.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function Q(a,b){if("srcdoc"==b)return I.HTML;var c=ta(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||
70 "ngSrc"==b))return I.RESOURCE_URL}function V(a,c,d,e,f){var g=Q(a,e);f=h[e]||f;var l=b(d,!0,g,f);if(l){if("multiple"===e&&"select"===ta(a))throw ea("selmulti",ua(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers={});if(k.test(e))throw ea("nodomevents");var s=h[e];s!==d&&(l=s&&b(s,!0,g,f),d=s);l&&(h[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e,
71 a)}))}}}})}}function T(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var k=a.length;g<k;g++,h++)h<k?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=U.createDocumentFragment();a.appendChild(d);y.hasData(d)&&(y(c).data(y(d).data()),la?(Rb=!0,la.cleanData([d])):delete y.cache[d[y.expando]]);d=1;for(e=b.length;d<e;d++)f=b[d],y(f).remove(),a.appendChild(f),delete b[d];b[0]=c;b.length=1}function X(a,
72 b){return P(function(){return a.apply(null,arguments)},a,b)}function Y(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,ua(d))}}function W(a,c,d,e,f,g){var h;m(e,function(e,g){var k=e.attrName,l=e.optional,s=e.mode,n,p,B,C;Xa.call(c,k)||(c[k]=t);switch(s){case "@":c[k]||l||(d[g]=t);c.$observe(k,function(a){d[g]=a});c.$$observers[k].$$scope=a;c[k]&&(d[g]=b(c[k])(a));break;case "=":if(l&&!c[k])break;p=u(c[k]);C=p.literal?ka:function(a,b){return a===b||a!==a&&b!==b};B=p.assign||function(){n=d[g]=p(a);throw ea("nonassign",
73 c[k],f.name);};n=d[g]=p(a);l=function(b){C(b,d[g])||(C(b,n)?B(a,b=d[g]):d[g]=b);return n=b};l.$stateful=!0;l=e.collection?a.$watchCollection(c[k],l):a.$watch(u(c[k],l),null,p.literal);h=h||[];h.push(l);break;case "&":p=u(c[k]);if(p===v&&l)break;d[g]=function(b){return p(a,b)}}});e=h?function(){for(var a=0,b=h.length;a<b;++a)h[a]()}:v;return g&&e!==v?(g.$on("$destroy",e),v):e}var aa=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=
74 a};aa.prototype={$normalize:wa,$addClass:function(a){a&&0<a.length&&B.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&B.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=bd(a,b);c&&c.length&&B.addClass(this.$$element,c);(c=bd(b,a))&&c.length&&B.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Sc(f,a),h=Ff(f,a),f=a;g?(this.$$element.prop(a,b),e=g):h&&(this[h]=b,f=h);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=Bc(a,
75 "-"));g=ta(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=N(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",h=R(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(h)?k:/(,)/,h=h.split(k),k=Math.floor(h.length/2),l=0;l<k;l++)var s=2*l,g=g+N(R(h[s]),!0),g=g+(" "+R(h[s+1]));h=R(h[2*l]).split(/\s/);g+=N(R(h[0]),!0);2===h.length&&(g+=" "+R(h[1]));this[a]=b=g}!1!==d&&(null===b||b===t?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&m(a[f],
76 function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ga()),e=d[a]||(d[a]=[]);e.push(b);K.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])});return function(){bb(e,b)}}};var ca=b.startSymbol(),da=b.endSymbol(),fa="{{"==ca||"}}"==da?Ya:function(a){return a.replace(/\{\{/g,ca).replace(/}}/g,da)},ia=/^ngAttr[A-Z]/;Z.$$addBindingInfo=n?function(a,b){var c=a.data("$binding")||[];G(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:v;Z.$$addBindingClass=
77 n?function(a){D(a,"ng-binding")}:v;Z.$$addScopeInfo=n?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:v;Z.$$addScopeClass=n?function(a,b){D(a,b?"ng-isolate-scope":"ng-scope")}:v;return Z}]}function wa(b){return hb(b.replace(Zc,""))}function bd(b,a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function $c(b){b=y(b);var a=b.length;if(1>=a)return b;for(;a--;)8===
78 b[a].nodeType&&Mf.call(b,a,1);return b}function Xe(){var b={},a=!1;this.register=function(a,d){Ra(a,"controller");H(a)?P(b,a):b[a]=d};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(c,d){function e(a,b,c,d){if(!a||!H(a.$scope))throw J("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,l){var k,n,r;h=!0===h;l&&L(l)&&(r=l);if(L(f)){l=f.match(Xc);if(!l)throw Nf("ctrlfmt",f);n=l[1];r=r||l[3];f=b.hasOwnProperty(n)?b[n]:Dc(g.$scope,n,!0)||(a?Dc(d,n,!0):t);Qa(f,
79 n,!0)}if(h)return h=(G(f)?f[f.length-1]:f).prototype,k=Object.create(h||null),r&&e(g,r,k,n||f.name),P(function(){var a=c.invoke(f,k,g,n);a!==k&&(H(a)||z(a))&&(k=a,r&&e(g,r,k,n||f.name));return k},{instance:k,identifier:r});k=c.instantiate(f,g,n);r&&e(g,r,k,n||f.name);return k}}]}function Ye(){this.$get=["$window",function(b){return y(b.document)}]}function Ze(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b){return H(b)?aa(b)?b.toISOString():db(b):b}
80 function cf(){this.$get=function(){return function(b){if(!b)return"";var a=[];oc(b,function(b,d){null===b||A(b)||(G(b)?m(b,function(b,c){a.push(ma(d)+"="+ma(Zb(b)))}):a.push(ma(d)+"="+ma(Zb(b))))});return a.join("&")}}}function df(){this.$get=function(){return function(b){function a(b,e,f){null===b||A(b)||(G(b)?m(b,function(b){a(b,e+"[]")}):H(b)&&!aa(b)?oc(b,function(b,c){a(b,e+(f?"":"[")+c+(f?"":"]"))}):c.push(ma(e)+"="+ma(Zb(b))))}if(!b)return"";var c=[];a(b,"",!0);return c.join("&")}}}function $b(b,
81 a){if(L(b)){var c=b.replace(Of,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(cd))||(d=(d=c.match(Pf))&&Qf[d[0]].test(c));d&&(b=wc(c))}}return b}function dd(b){var a=ga(),c;L(b)?m(b.split("\n"),function(b){c=b.indexOf(":");var e=M(R(b.substr(0,c)));b=R(b.substr(c+1));e&&(a[e]=a[e]?a[e]+", "+b:b)}):H(b)&&m(b,function(b,c){var f=M(c),g=R(b);f&&(a[f]=a[f]?a[f]+", "+g:g)});return a}function ed(b){var a;return function(c){a||(a=dd(b));return c?(c=a[M(c)],void 0===c&&(c=null),c):a}}function fd(b,
82 a,c,d){if(z(d))return d(b,a,c);m(d,function(d){b=d(b,a,c)});return b}function bf(){var b=this.defaults={transformResponse:[$b],transformRequest:[function(a){return H(a)&&"[object File]"!==sa.call(a)&&"[object Blob]"!==sa.call(a)&&"[object FormData]"!==sa.call(a)?db(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ia(ac),put:ia(ac),patch:ia(ac)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},a=!1;this.useApplyAsync=function(b){return w(b)?
83 (a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=P({},a);b.data=a.data?fd(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a,b){var c,e={};m(a,function(a,d){z(a)?(c=a(b),null!=c&&(e[d]=c)):e[d]=a});return e}if(!ca.isObject(a))throw J("$http")("badreq",a);var e=P({method:"get",transformRequest:b.transformRequest,
84 transformResponse:b.transformResponse,paramSerializer:b.paramSerializer},a);e.headers=function(a){var c=b.headers,e=P({},a.headers),f,g,h,c=P({},c.common,c[M(a.method)]);a:for(f in c){g=M(f);for(h in e)if(M(h)===g)continue a;e[f]=c[f]}return d(e,ia(a))}(a);e.method=rb(e.method);e.paramSerializer=L(e.paramSerializer)?l.get(e.paramSerializer):e.paramSerializer;var f=[function(a){var d=a.headers,e=fd(a.data,ed(d),t,a.transformRequest);A(e)&&m(d,function(a,b){"content-type"===M(b)&&delete d[b]});A(a.withCredentials)&&
85 !A(b.withCredentials)&&(a.withCredentials=b.withCredentials);return n(a,e).then(c,c)},t],g=h.when(e);for(m(x,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),g=g.then(a,k)}g.success=function(a){Qa(a,"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){Qa(a,"fn");g.then(null,function(b){a(b.data,b.status,b.headers,e)});return g};return g}
86 function n(c,f){function l(b,c,d,e){function f(){n(c,b,d,e)}N&&(200<=b&&300>b?N.put(S,[b,c,dd(d),e]):N.remove(S));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function n(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?I.resolve:I.reject)({data:a,status:b,headers:ed(d),config:c,statusText:e})}function x(a){n(a.data,a.status,ia(a.headers()),a.statusText)}function m(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var I=h.defer(),B=I.promise,N,D,q=c.headers,S=r(c.url,c.paramSerializer(c.params));
87 k.pendingRequests.push(c);B.then(m,m);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(N=H(c.cache)?c.cache:H(b.cache)?b.cache:s);N&&(D=N.get(S),w(D)?D&&z(D.then)?D.then(x,x):G(D)?n(D[1],D[0],ia(D[2]),D[3]):n(D,200,{},"OK"):N.put(S,B));A(D)&&((D=gd(c.url)?e()[c.xsrfCookieName||b.xsrfCookieName]:t)&&(q[c.xsrfHeaderName||b.xsrfHeaderName]=D),d(c.method,S,f,l,q,c.timeout,c.withCredentials,c.responseType));return B}function r(a,b){0<b.length&&(a+=(-1==a.indexOf("?")?"?":"&")+b);
88 return a}var s=f("$http");b.paramSerializer=L(b.paramSerializer)?l.get(b.paramSerializer):b.paramSerializer;var x=[];m(c,function(a){x.unshift(L(a)?l.get(a):l.invoke(a))});k.pendingRequests=[];(function(a){m(arguments,function(a){k[a]=function(b,c){return k(P({},c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){m(arguments,function(a){k[a]=function(b,c,d){return k(P({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");k.defaults=b;return k}]}function Rf(){return new O.XMLHttpRequest}
89 function ef(){this.$get=["$browser","$window","$document",function(b,a,c){return Sf(b,Rf,b.defer,a.angular.callbacks,c[0])}]}function Sf(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),n=null;f.type="text/javascript";f.src=a;f.async=!0;n=function(a){f.removeEventListener("load",n,!1);f.removeEventListener("error",n,!1);e.body.removeChild(f);f=null;var g=-1,x="unknown";a&&("load"!==a.type||d[b].called||(a={type:"error"}),x=a.type,g="error"===a.type?404:200);c&&c(g,x)};f.addEventListener("load",
90 n,!1);f.addEventListener("error",n,!1);e.body.appendChild(f);return n}return function(e,h,l,k,n,r,s,x){function C(){p&&p();K&&K.abort()}function F(a,d,e,f,g){I!==t&&c.cancel(I);p=K=null;a(d,e,f,g);b.$$completeOutstandingRequest(v)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==M(e)){var u="_"+(d.counter++).toString(36);d[u]=function(a){d[u].data=a;d[u].called=!0};var p=f(h.replace("JSON_CALLBACK","angular.callbacks."+u),u,function(a,b){F(k,a,d[u].data,"",b);d[u]=v})}else{var K=a();K.open(e,
91 h,!0);m(n,function(a,b){w(a)&&K.setRequestHeader(b,a)});K.onload=function(){var a=K.statusText||"",b="response"in K?K.response:K.responseText,c=1223===K.status?204:K.status;0===c&&(c=b?200:"file"==Ba(h).protocol?404:0);F(k,c,b,K.getAllResponseHeaders(),a)};e=function(){F(k,-1,null,null,"")};K.onerror=e;K.onabort=e;s&&(K.withCredentials=!0);if(x)try{K.responseType=x}catch(q){if("json"!==x)throw q;}K.send(l)}if(0<r)var I=c(C,r);else r&&z(r.then)&&r.then(C)}}function $e(){var b="{{",a="}}";this.startSymbol=
92 function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(n,b).replace(r,a)}function h(f,h,n,r){function u(a){try{var b=a;a=n?e.getTrusted(n,b):e.valueOf(b);var c;if(r&&!w(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=db(a)}c=a}return c}catch(g){d(Ka.interr(f,g))}}r=!!r;for(var p,m,q=0,I=
93 [],B=[],N=f.length,D=[],t=[];q<N;)if(-1!=(p=f.indexOf(b,q))&&-1!=(m=f.indexOf(a,p+l)))q!==p&&D.push(g(f.substring(q,p))),q=f.substring(p+l,m),I.push(q),B.push(c(q,u)),q=m+k,t.push(D.length),D.push("");else{q!==N&&D.push(g(f.substring(q)));break}n&&1<D.length&&Ka.throwNoconcat(f);if(!h||I.length){var S=function(a){for(var b=0,c=I.length;b<c;b++){if(r&&A(a[b]))return;D[t[b]]=a[b]}return D.join("")};return P(function(a){var b=0,c=I.length,e=Array(c);try{for(;b<c;b++)e[b]=B[b](a);return S(e)}catch(g){d(Ka.interr(f,
94 g))}},{exp:f,expressions:I,$$watchDelegate:function(a,b){var c;return a.$watchGroup(B,function(d,e){var f=S(d);z(b)&&b.call(this,f,d!==e?c:f,a);c=f})}})}}var l=b.length,k=a.length,n=new RegExp(b.replace(/./g,f),"g"),r=new RegExp(a.replace(/./g,f),"g");h.startSymbol=function(){return b};h.endSymbol=function(){return a};return h}]}function af(){this.$get=["$rootScope","$window","$q","$$q",function(b,a,c,d){function e(e,h,l,k){var n=4<arguments.length,r=n?za.call(arguments,4):[],s=a.setInterval,x=a.clearInterval,
95 C=0,F=w(k)&&!k,u=(F?d:c).defer(),p=u.promise;l=w(l)?l:0;p.then(null,null,n?function(){e.apply(null,r)}:e);p.$$intervalId=s(function(){u.notify(C++);0<l&&C>=l&&(u.resolve(C),x(p.$$intervalId),delete f[p.$$intervalId]);F||b.$apply()},h);f[p.$$intervalId]=u;return p}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function ge(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",
96 GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),
97 SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=ob(b[a]);return b.join("/")}function hd(b,a){var c=Ba(b);a.$$protocol=c.protocol;
98 a.$$host=c.hostname;a.$$port=W(c.port)||Tf[c.protocol]||null}function id(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Ba(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=zc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ya(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ja(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Bb(b){return b.replace(/(#.+)|#$/,
99 "$1")}function cc(b){return b.substr(0,Ja(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);hd(b,this);this.$$parse=function(a){var b=ya(c,a);if(!L(b))throw Cb("ipthprfx",a,c);id(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),
100 !0;var f,g;(f=ya(b,d))!==t?(g=f,g=(f=ya(a,f))!==t?c+(ya("/",f)||f):b+g):(f=ya(c,d))!==t?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);hd(b,this);this.$$parse=function(d){var e=ya(b,d)||ya(c,d),f;A(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",A(e)&&(b=d,this.replace())):(f=ya(a,e),A(f)&&(f=e));id(f,this);d=this.$$path;var e=b,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(d=(f=g.exec(d))?f[1]:d);this.$$path=d;this.$$compose()};this.$$compose=
101 function(){var c=Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ja(b)==Ja(a)?(this.$$parse(a),!0):!1}}function jd(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ja(d)?f=d:(g=ya(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c=
102 Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Db(b){return function(){return this[b]}}function kd(b,a){return function(c){if(A(c))return this[b];this[b]=a(c);this.$$compose();return this}}function ff(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return w(a)?(b=a,this):b};this.html5Mode=function(b){return ab(b)?(a.enabled=b,this):H(b)?(ab(b.enabled)&&(a.enabled=b.enabled),
103 ab(b.requireBase)&&(a.requireBase=b.requireBase),ab(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,n;n=d.baseHref();var r=d.url(),s;if(a.enabled){if(!n&&a.requireBase)throw Cb("nobase");s=r.substring(0,
104 r.indexOf("/",r.indexOf("//")+2))+(n||"/");n=e.history?dc:jd}else s=Ja(r),n=ec;k=new n(s,"#"+b);k.$$parseLinkUrl(r,r);k.$$state=d.state();var x=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=y(b.target);"a"!==ta(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");H(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Ba(h.animVal).href);x.test(h)||
105 !h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h,l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Bb(k.absUrl())!=Bb(r)&&d.url(k.absUrl(),!0);var C=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(C=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a=
106 Bb(d.url()),b=Bb(k.absUrl()),f=d.state(),g=k.$$replace,n=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(C||n)C=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(n&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function gf(){var b=!0,a=this;this.debugEnabled=function(a){return w(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&
107 (a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||v;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];m(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}
108 function Ca(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw da("isecfld",a);return b}function oa(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b.window===b)throw da("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw da("isecdom",a);if(b===Object)throw da("isecobj",a);}return b}function ld(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b===Uf||b===Vf||b===Wf)throw da("isecff",a);
109 }}function Xf(b,a){return"undefined"!==typeof b?b:a}function md(b,a){return"undefined"===typeof b?a:"undefined"===typeof a?b:b+a}function T(b,a){var c,d;switch(b.type){case q.Program:c=!0;m(b.body,function(b){T(b.expression,a);c=c&&b.expression.constant});b.constant=c;break;case q.Literal:b.constant=!0;b.toWatch=[];break;case q.UnaryExpression:T(b.argument,a);b.constant=b.argument.constant;b.toWatch=b.argument.toWatch;break;case q.BinaryExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&
110 b.right.constant;b.toWatch=b.left.toWatch.concat(b.right.toWatch);break;case q.LogicalExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.constant?[]:[b];break;case q.ConditionalExpression:T(b.test,a);T(b.alternate,a);T(b.consequent,a);b.constant=b.test.constant&&b.alternate.constant&&b.consequent.constant;b.toWatch=b.constant?[]:[b];break;case q.Identifier:b.constant=!1;b.toWatch=[b];break;case q.MemberExpression:T(b.object,a);b.computed&&T(b.property,a);
111 b.constant=b.object.constant&&(!b.computed||b.property.constant);b.toWatch=[b];break;case q.CallExpression:c=b.filter?!a(b.callee.name).$stateful:!1;d=[];m(b.arguments,function(b){T(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=b.filter&&!a(b.callee.name).$stateful?d:[b];break;case q.AssignmentExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=[b];break;case q.ArrayExpression:c=!0;d=[];m(b.elements,function(b){T(b,a);c=
112 c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=d;break;case q.ObjectExpression:c=!0;d=[];m(b.properties,function(b){T(b.value,a);c=c&&b.value.constant;b.value.constant||d.push.apply(d,b.value.toWatch)});b.constant=c;b.toWatch=d;break;case q.ThisExpression:b.constant=!1,b.toWatch=[]}}function nd(b){if(1==b.length){b=b[0].expression;var a=b.toWatch;return 1!==a.length?a:a[0]!==b?a:t}}function od(b){return b.type===q.Identifier||b.type===q.MemberExpression}function pd(b){if(1===
113 b.body.length&&od(b.body[0].expression))return{type:q.AssignmentExpression,left:b.body[0].expression,right:{type:q.NGValueParameter},operator:"="}}function qd(b){return 0===b.body.length||1===b.body.length&&(b.body[0].expression.type===q.Literal||b.body[0].expression.type===q.ArrayExpression||b.body[0].expression.type===q.ObjectExpression)}function rd(b,a){this.astBuilder=b;this.$filter=a}function sd(b,a){this.astBuilder=b;this.$filter=a}function Eb(b,a,c,d){oa(b,d);a=a.split(".");for(var e,f=0;1<
114 a.length;f++){e=Ca(a.shift(),d);var g=oa(b[e],d);g||(g={},b[e]=g);b=g}e=Ca(a.shift(),d);oa(b[e],d);return b[e]=c}function Fb(b){return"constructor"==b}function fc(b){return z(b.valueOf)?b.valueOf():Yf.call(b)}function hf(){var b=ga(),a=ga();this.$get=["$filter","$sniffer",function(c,d){function e(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=fc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function f(a,b,c,d,f){var g=d.inputs,h;if(1===g.length){var k=e,g=g[0];return a.$watch(function(a){var b=
115 g(a);e(b,k)||(h=d(a,t,t,[b]),k=b&&fc(b));return h},b,c,f)}for(var l=[],n=[],r=0,m=g.length;r<m;r++)l[r]=e,n[r]=null;return a.$watch(function(a){for(var b=!1,c=0,f=g.length;c<f;c++){var k=g[c](a);if(b||(b=!e(k,l[c])))n[c]=k,l[c]=k&&fc(k)}b&&(h=d(a,t,t,n));return h},b,c,f)}function g(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);w(a)&&d.$$postDigest(function(){w(f)&&e()})},c)}function h(a,b,c,d){function e(a){var b=!0;m(a,function(a){w(a)||
116 (b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function l(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){z(b)&&b.apply(this,arguments);e()},c)}function k(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==h&&c!==g?function(c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}:function(c,d,e,f){e=a(c,d,e,f);c=b(e,c,d);return w(e)?c:e};a.$$watchDelegate&&a.$$watchDelegate!==
117 f?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=f,c.inputs=a.inputs?a.inputs:[a]);return c}var n={csp:d.csp,expensiveChecks:!1},r={csp:d.csp,expensiveChecks:!0};return function(d,e,C){var m,u,p;switch(typeof d){case "string":p=d=d.trim();var q=C?a:b;m=q[p];m||(":"===d.charAt(0)&&":"===d.charAt(1)&&(u=!0,d=d.substring(2)),C=C?r:n,m=new gc(C),m=(new hc(m,c,C)).parse(d),m.constant?m.$$watchDelegate=l:u?m.$$watchDelegate=m.literal?h:g:m.inputs&&(m.$$watchDelegate=f),q[p]=m);return k(m,
118 e);case "function":return k(d,e);default:return v}}}]}function kf(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return td(function(a){b.$evalAsync(a)},a)}]}function lf(){this.$get=["$browser","$exceptionHandler",function(b,a){return td(function(a){b.defer(a)},a)}]}function td(b,a){function c(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function d(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&&
119 c.pending&&(c.processScheduled=!0,b(function(){var b,d,e;e=c.pending;c.processScheduled=!1;c.pending=t;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status];try{z(b)?d.resolve(b(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),a(h)}}}))}function g(){this.promise=new d;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=J("$q",TypeError);d.prototype={then:function(a,b,c){var d=new g;this.$$state.pending=this.$$state.pending||
120 [];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}};g.prototype={resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(b){var d,e;e=c(this,this.$$resolve,this.$$reject);try{if(H(b)||z(b))d=b&&b.then;z(d)?(this.promise.$$state.status=
121 -1,d.call(b,e[0],e[1],this.notify)):(this.promise.$$state.value=b,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),a(g)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;f<g;f++){e=d[f][0];b=d[f][3];try{e.notify(z(b)?
122 b(c):c)}catch(h){a(h)}}})}};var l=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return l(e,!1)}return d&&z(d.then)?d.then(function(){return l(a,b)},function(a){return l(a,!1)}):l(a,b)},n=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},r=function x(a){if(!z(a))throw h("norslvr",a);if(!(this instanceof x))return new x(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};
123 r.defer=function(){return new g};r.reject=function(a){var b=new g;b.reject(a);return b.promise};r.when=n;r.resolve=n;r.all=function(a){var b=new g,c=0,d=G(a)?[]:{};m(a,function(a,e){c++;n(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return r}function uf(){this.$get=["$window","$timeout",function(b,a){function c(){for(var a=0;a<n.length;a++){var b=n[a];b&&(n[a]=null,b())}k=n.length=0}function d(a){var b=
124 n.length;k++;n.push(a);0===b&&(l=h(c));return function(){0<=b&&(b=n[b]=null,0===--k&&l&&(l(),l=null,n.length=0))}}var e=b.requestAnimationFrame||b.webkitRequestAnimationFrame,f=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,g=!!e,h=g?function(a){var b=e(a);return function(){f(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};d.supported=g;var l,k=0,n=[];return d}]}function jf(){function b(a){function b(){this.$$watchers=this.$$nextSibling=
125 this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++nb;this.$$ChildScope=null}b.prototype=a;return b}var a=10,c=J("$rootScope"),d=null,e=null;this.digestTtl=function(b){arguments.length&&(a=b);return a};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(f,g,h,l){function k(a){a.currentScope.$$destroyed=!0}function n(){this.$id=++nb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=
126 this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$$isolateBindings=null}function r(a){if(p.$$phase)throw c("inprog",p.$$phase);p.$$phase=a}function s(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function x(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function q(){}function F(){for(;I.length;)try{I.shift()()}catch(a){g(a)}e=null}function u(){null===e&&(e=
127 l.defer(function(){p.$apply(F)}))}n.prototype={constructor:n,$new:function(a,c){var d;c=c||this;a?(d=new n,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=b(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(a||c!=this)&&d.$on("$destroy",k);return d},$watch:function(a,b,c,e){var f=h(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,c,f,a);var g=this,k=g.$$watchers,l=
128 {fn:b,last:q,get:f,exp:e||a,eq:!!c};d=null;z(b)||(l.fn=v);k||(k=g.$$watchers=[]);k.unshift(l);s(this,1);return function(){0<=bb(k,l)&&s(g,-1);d=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,k=!0;if(!a.length){var l=!0;g.$evalAsync(function(){l&&b(e,e,g)});return function(){l=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});m(a,function(a,b){var k=g.$watch(a,function(a,
129 f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(k)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!A(e)){if(H(e))if(Ea(e))for(f!==r&&(f=r,m=f.length=0,l++),a=e.length,m!==a&&(l++,f.length=m=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==s&&(f=s={},m=0,l++);a=0;for(b in e)e.hasOwnProperty(b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(m++,f[b]=g,l++));if(m>a)for(b in l++,f)e.hasOwnProperty(b)||
130 (m--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,g,k=1<b.length,l=0,n=h(a,c),r=[],s={},p=!0,m=0;return this.$watch(n,function(){p?(p=!1,b(e,e,d)):b(e,g,d);if(k)if(H(e))if(Ea(e)){g=Array(e.length);for(var a=0;a<e.length;a++)g[a]=e[a]}else for(a in g={},e)Xa.call(e,a)&&(g[a]=e[a]);else g=e})},$digest:function(){var b,f,h,k,n,s,m=a,x,u=[],E,I;r("$digest");l.$$checkUrlChange();this===p&&null!==e&&(l.defer.cancel(e),F());d=null;do{s=!1;for(x=this;t.length;){try{I=t.shift(),
131 I.scope.$eval(I.expression,I.locals)}catch(v){g(v)}d=null}a:do{if(k=x.$$watchers)for(n=k.length;n--;)try{if(b=k[n])if((f=b.get(x))!==(h=b.last)&&!(b.eq?ka(f,h):"number"===typeof f&&"number"===typeof h&&isNaN(f)&&isNaN(h)))s=!0,d=b,b.last=b.eq?fa(f,null):f,b.fn(f,h===q?f:h,x),5>m&&(E=4-m,u[E]||(u[E]=[]),u[E].push({msg:z(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b===d){s=!1;break a}}catch(A){g(A)}if(!(k=x.$$watchersCount&&x.$$childHead||x!==this&&x.$$nextSibling))for(;x!==
132 this&&!(k=x.$$nextSibling);)x=x.$parent}while(x=k);if((s||t.length)&&!m--)throw p.$$phase=null,c("infdig",a,u);}while(s||t.length);for(p.$$phase=null;w.length;)try{w.shift()()}catch(y){g(y)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===p&&l.$$applicationDestroyed();s(this,-this.$$watchersCount);for(var b in this.$$listenerCount)x(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==
133 this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=v;this.$on=this.$watch=this.$watchGroup=function(){return v};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}},$eval:function(a,b){return h(a)(this,b)},
134 $evalAsync:function(a,b){p.$$phase||t.length||l.defer(function(){t.length&&p.$digest()});t.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){w.push(a)},$apply:function(a){try{return r("$apply"),this.$eval(a)}catch(b){g(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&I.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||
135 (d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,x(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,h={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=cb([h],arguments,1),l,n;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(n=d.length;l<n;l++)if(d[l])try{d[l].apply(null,k)}catch(r){g(r)}else d.splice(l,1),l--,n--;if(f)return h.currentScope=
136 null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var f=cb([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,f)}catch(l){g(l)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=
137 c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var p=new n,t=p.$$asyncQueue=[],w=p.$$postDigestQueue=[],I=p.$$applyAsyncQueue=[];return p}]}function he(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(a){return w(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return w(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Ba(c).href;return""===f||f.match(e)?c:"unsafe:"+
138 f}}}function Zf(b){if("self"===b)return b;if(L(b)){if(-1<b.indexOf("***"))throw Da("iwcard",b);b=ud(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(Za(b))return new RegExp("^"+b.source+"$");throw Da("imatcher");}function vd(b){var a=[];w(b)&&m(b,function(b){a.push(Zf(b))});return a}function nf(){this.SCE_CONTEXTS=pa;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=vd(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&&
139 (a=vd(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?gd(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw Da("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[pa.HTML]=e(g);h[pa.CSS]=e(g);h[pa.URL]=
140 e(g);h[pa.JS]=e(g);h[pa.RESOURCE_URL]=e(h[pa.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Da("icontext",a,b);if(null===b||b===t||""===b)return b;if("string"!==typeof b)throw Da("itype",a);return new c(b)},getTrusted:function(c,e){if(null===e||e===t||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(c===pa.RESOURCE_URL){var g=Ba(e.toString()),r,s,m=!1;r=0;for(s=b.length;r<s;r++)if(d(b[r],g)){m=!0;break}if(m)for(r=
141 0,s=a.length;r<s;r++)if(d(a[r],g)){m=!1;break}if(m)return e;throw Da("insecurl",e.toString());}if(c===pa.HTML)return f(e);throw Da("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function mf(){var b=!0;this.enabled=function(a){arguments.length&&(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&8>Ua)throw Da("iequirks");var d=ia(pa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=
142 d.getTrusted=function(a,b){return b},d.valueOf=Ya);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;m(pa,function(a,b){var c=M(b);d[hb("parse_as_"+c)]=function(b){return e(a,b)};d[hb("get_trusted_"+c)]=function(b){return f(a,b)};d[hb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function of(){this.$get=["$window","$document",function(b,a){var c={},d=W((/android (\d+)/.exec(M((b.navigator||
143 {}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,n=!1;if(l){for(var r in l)if(k=h.exec(r)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);n=!!("animation"in l||g+"Animation"in l);!d||k&&n||(k=L(l.webkitTransition),n=L(l.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===
144 a&&11>=Ua)return!1;if(A(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:fb(),vendorPrefix:g,transitions:k,animations:n,android:d}}]}function qf(){this.$get=["$templateCache","$http","$q","$sce",function(b,a,c,d){function e(f,g){e.totalPendingRequests++;L(f)&&b.get(f)||(f=d.getTrustedResourceUrl(f));var h=a.defaults&&a.defaults.transformResponse;G(h)?h=h.filter(function(a){return a!==$b}):h===$b&&(h=null);return a.get(f,{cache:b,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(a){b.put(f,
145 a.data);return a.data},function(a){if(!g)throw ea("tpload",f,a.status,a.statusText);return c.reject(a)})}e.totalPendingRequests=0;return e}]}function rf(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];m(a,function(a){var d=ca.element(a).data("$binding");d&&m(d,function(d){c?(new RegExp("(^|\\s)"+ud(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a,
146 b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var l=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(l.length)return l}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function sf(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,l,k){z(f)||(k=l,l=f,f=v);var n=za.call(arguments,3),r=w(k)&&!k,s=(r?d:c).defer(),
147 m=s.promise,q;q=a.defer(function(){try{s.resolve(f.apply(null,n))}catch(a){s.reject(a),e(a)}finally{delete g[m.$$timeoutId]}r||b.$apply()},l);m.$$timeoutId=q;g[q]=s;return m}var g={};f.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),delete g[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return f}]}function Ba(b){Ua&&(X.setAttribute("href",b),b=X.href);X.setAttribute("href",b);return{href:X.href,protocol:X.protocol?X.protocol.replace(/:$/,""):"",host:X.host,
148 search:X.search?X.search.replace(/^\?/,""):"",hash:X.hash?X.hash.replace(/^#/,""):"",hostname:X.hostname,port:X.port,pathname:"/"===X.pathname.charAt(0)?X.pathname:"/"+X.pathname}}function gd(b){b=L(b)?Ba(b):b;return b.protocol===wd.protocol&&b.host===wd.host}function tf(){this.$get=ra(O)}function xd(b){function a(a){try{return decodeURIComponent(a)}catch(b){return a}}var c=b[0]||{},d={},e="";return function(){var b,g,h,l,k;b=c.cookie||"";if(b!==e)for(e=b,b=e.split("; "),d={},h=0;h<b.length;h++)g=
149 b[h],l=g.indexOf("="),0<l&&(k=a(g.substring(0,l)),d[k]===t&&(d[k]=a(g.substring(l+1))));return d}}function xf(){this.$get=xd}function Lc(b){function a(c,d){if(H(c)){var e={};m(c,function(b,c){e[c]=a(c,b)});return e}return b.factory(c+"Filter",d)}this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];a("currency",yd);a("date",zd);a("filter",$f);a("json",ag);a("limitTo",bg);a("lowercase",cg);a("number",Ad);a("orderBy",Bd);a("uppercase",dg)}function $f(){return function(b,
150 a,c){if(!Ea(b)){if(null==b)return b;throw J("filter")("notarray",b);}var d;switch(ic(a)){case "function":break;case "boolean":case "null":case "number":case "string":d=!0;case "object":a=eg(a,c,d);break;default:return b}return Array.prototype.filter.call(b,a)}}function eg(b,a,c){var d=H(b)&&"$"in b;!0===a?a=ka:z(a)||(a=function(a,b){if(A(a))return!1;if(null===a||null===b)return a===b;if(H(b)||H(a)&&!rc(a))return!1;a=M(""+a);b=M(""+b);return-1!==a.indexOf(b)});return function(e){return d&&!H(e)?La(e,
151 b.$,a,!1):La(e,b,a,c)}}function La(b,a,c,d,e){var f=ic(b),g=ic(a);if("string"===g&&"!"===a.charAt(0))return!La(b,a.substring(1),c,d);if(G(b))return b.some(function(b){return La(b,a,c,d)});switch(f){case "object":var h;if(d){for(h in b)if("$"!==h.charAt(0)&&La(b[h],a,c,!0))return!0;return e?!1:La(b,a,c,!1)}if("object"===g){for(h in a)if(e=a[h],!z(e)&&!A(e)&&(f="$"===h,!La(f?b:b[h],e,c,f,f)))return!1;return!0}return c(b,a);case "function":return!1;default:return c(b,a)}}function ic(b){return null===
152 b?"null":typeof b}function yd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){A(d)&&(d=a.CURRENCY_SYM);A(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:Cd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function Ad(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==b?b:Cd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Cd(b,a,c,d,e){if(H(b))return"";var f=0>b;b=Math.abs(b);var g=Infinity===b;if(!g&&!isFinite(b))return"";var h=b+"",l="",k=!1,n=[];g&&(l="\u221e");
153 if(!g&&-1!==h.indexOf("e")){var r=h.match(/([\d\.]+)e(-?)(\d+)/);r&&"-"==r[2]&&r[3]>e+1?b=0:(l=h,k=!0)}if(g||k)0<e&&1>b&&(l=b.toFixed(e),b=parseFloat(l));else{g=(h.split(Dd)[1]||"").length;A(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(Dd),h=g[0],g=g[1]||"",r=0,s=a.lgSize,m=a.gSize;if(h.length>=s+m)for(r=h.length-s,k=0;k<r;k++)0===(r-k)%m&&0!==k&&(l+=c),l+=h.charAt(k);for(k=r;k<h.length;k++)0===(h.length-k)%s&&0!==k&&
154 (l+=c),l+=h.charAt(k);for(;g.length<e;)g+="0";e&&"0"!==e&&(l+=d+g.substr(0,e))}0===b&&(f=!1);n.push(f?a.negPre:a.posPre,l,f?a.negSuf:a.posSuf);return n.join("")}function Gb(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function Y(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=c;0===e&&-12==c&&(e=12);return Gb(e,a,d)}}function Hb(b,a){return function(c,d){var e=c["get"+b](),f=rb(a?"SHORT"+b:b);return d[f][e]}}function Ed(b){var a=
155 (new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Fd(b){return function(a){var c=Ed(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Gb(a,b)}}function jc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function zd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=W(b[9]+b[10]),g=W(b[9]+b[11]));h.call(a,W(b[1]),
156 W(b[2])-1,W(b[3]));f=W(b[4]||0)-f;g=W(b[5]||0)-g;h=W(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;L(c)&&(c=fg.test(c)?W(c):a(c));V(c)&&(c=new Date(c));if(!aa(c)||!isFinite(c.getTime()))return c;for(;e;)(k=gg.exec(e))?(h=cb(h,k,1),e=h.pop()):(h.push(e),e=null);var n=c.getTimezoneOffset();
157 f&&(n=xc(f,c.getTimezoneOffset()),c=Pb(c,f,!0));m(h,function(a){l=hg[a];g+=l?l(c,b.DATETIME_FORMATS,n):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function ag(){return function(b,a){A(a)&&(a=2);return db(b,a)}}function bg(){return function(b,a,c){a=Infinity===Math.abs(Number(a))?Number(a):W(a);if(isNaN(a))return b;V(b)&&(b=b.toString());if(!G(b)&&!L(b))return b;c=!c||isNaN(c)?0:W(c);c=0>c&&c>=-b.length?b.length+c:c;return 0<=a?b.slice(c,c+a):0===c?b.slice(a,b.length):b.slice(Math.max(0,
158 c+a),c)}}function Bd(b){function a(a,c){c=c?-1:1;return a.map(function(a){var d=1,h=Ya;if(z(a))h=a;else if(L(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))d="-"==a.charAt(0)?-1:1,a=a.substring(1);if(""!==a&&(h=b(a),h.constant))var l=h(),h=function(a){return a[l]}}return{get:h,descending:d*c}})}function c(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}return function(b,e,f){if(!Ea(b))return b;G(e)||(e=[e]);0===e.length&&(e=["+"]);var g=a(e,f);b=Array.prototype.map.call(b,
159 function(a,b){return{value:a,predicateValues:g.map(function(d){var e=d.get(a);d=typeof e;if(null===e)d="string",e="null";else if("string"===d)e=e.toLowerCase();else if("object"===d)a:{if("function"===typeof e.valueOf&&(e=e.valueOf(),c(e)))break a;if(rc(e)&&(e=e.toString(),c(e)))break a;e=b}return{value:e,type:d}})}});b.sort(function(a,b){for(var c=0,d=0,e=g.length;d<e;++d){var c=a.predicateValues[d],f=b.predicateValues[d],m=0;c.type===f.type?c.value!==f.value&&(m=c.value<f.value?-1:1):m=c.type<f.type?
160 -1:1;if(c=m*g[d].descending)break}return c});return b=b.map(function(a){return a.value})}}function Ma(b){z(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ra(b)}function Gd(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Ib;f.$error={};f.$$success={};f.$pending=t;f.$name=e(a.name||a.ngForm||"")(c);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;h.$addControl(f);f.$rollbackViewValue=function(){m(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=
161 function(){m(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ra(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a)};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];m(f.$pending,function(b,c){f.$setValidity(c,null,a)});m(f.$error,function(b,c){f.$setValidity(c,null,a)});m(f.$$success,function(b,c){f.$setValidity(c,null,a)});bb(g,a)};Hd({ctrl:this,$element:b,set:function(a,b,
162 c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(bb(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Va);d.addClass(b,Jb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Va,Jb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;m(g,function(a){a.$setPristine()})};f.$setUntouched=function(){m(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b,
163 "ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function kc(b){b.$formatters.push(function(a){return b.$isEmpty(a)?a:a.toString()})}function kb(b,a,c,d,e,f){var g=M(a[0].type);if(!e.android){var h=!1;a.on("compositionstart",function(a){h=!0});a.on("compositionend",function(){h=!1;l()})}var l=function(b){k&&(f.defer.cancel(k),k=null);if(!h){var e=a.val();b=b&&b.type;"password"===g||c.ngTrim&&"false"===c.ngTrim||(e=R(e));(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,b)}};
164 if(e.hasEvent("input"))a.on("input",l);else{var k,n=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||n(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",n)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Kb(b,a){return function(c,d){var e,f;if(aa(c))return c;if(L(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));
165 if(ig.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},m(e,function(b,c){c<a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function lb(b,a,c,d){return function(e,f,g,h,l,k,n){function r(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function s(a){return w(a)?
166 aa(a)?a:c(a):t}Id(e,f,g,h);kb(e,f,g,h,l,k);var m=h&&h.$options&&h.$options.timezone,q;h.$$parserName=b;h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,q),m&&(b=Pb(b,m)),b):t});h.$formatters.push(function(a){if(a&&!aa(a))throw Lb("datefmt",a);if(r(a))return(q=a)&&m&&(q=Pb(q,m,!0)),n("date")(a,d,m);q=null;return""});if(w(g.min)||g.ngMin){var F;h.$validators.min=function(a){return!r(a)||A(F)||c(a)>=F};g.$observe("min",function(a){F=s(a);h.$validate()})}if(w(g.max)||g.ngMax){var u;
167 h.$validators.max=function(a){return!r(a)||A(u)||c(a)<=u};g.$observe("max",function(a){u=s(a);h.$validate()})}}}function Id(b,a,c,d){(d.$$hasNativeValidators=H(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?t:b})}function Jd(b,a,c,d,e){if(w(d)){b=b(d);if(!b.constant)throw J("ngModel")("constexpr",c,d);return b(a)}return e}function lc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=
168 a[d],n=0;n<b.length;n++)if(e==b[n])continue a;c.push(e)}return c}function e(a){var b=[];return G(a)?(m(a,function(a){b=b.concat(e(a))}),b):L(a)?a.split(" "):H(a)?(m(a,function(a,c){a&&(b=b.concat(c.split(" ")))}),b):a}return{restrict:"AC",link:function(f,g,h){function l(a,b){var c=g.data("$classCounts")||ga(),d=[];m(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!n){var m=
169 l(k,1);h.$addClass(m)}else if(!ka(b,n)){var q=e(n),m=d(k,q),k=d(q,k),m=l(m,1),k=l(k,-1);m&&m.length&&c.addClass(g,m);k&&k.length&&c.removeClass(g,k)}}n=ia(b)}var n;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=l(k,1),h.$addClass(g)):(g=l(k,-1),h.$removeClass(g))}})}}}]}function Hd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}
170 function c(b,c){b=b?"-"+Bc(b,"-"):"";a(mb+b,!0===c);a(Kd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[Kd]=!(f[mb]=e.hasClass(mb));d.$setValidity=function(b,e,f){e===t?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&&h(d.$pending,b,f),Ld(d.$pending)&&(d.$pending=t));ab(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success,b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(Md,!0),d.$valid=d.$invalid=t,c("",null)):(a(Md,
171 !1),d.$valid=Ld(d.$error),d.$invalid=!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?t:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function Ld(b){if(b)for(var a in b)if(b.hasOwnProperty(a))return!1;return!0}var jg=/^\/(.+)\/([a-z]*)$/,M=function(b){return L(b)?b.toLowerCase():b},Xa=Object.prototype.hasOwnProperty,rb=function(b){return L(b)?b.toUpperCase():b},Ua,y,la,za=[].slice,Mf=[].splice,kg=[].push,sa=Object.prototype.toString,sc=Object.getPrototypeOf,Fa=J("ng"),ca=
172 O.angular||(O.angular={}),gb,nb=0;Ua=U.documentMode;v.$inject=[];Ya.$inject=[];var G=Array.isArray,uc=/^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/,R=function(b){return L(b)?b.trim():b},ud=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},fb=function(){if(w(fb.isActive_))return fb.isActive_;var b=!(!U.querySelector("[ng-csp]")&&!U.querySelector("[data-ng-csp]"));if(!b)try{new Function("")}catch(a){b=!0}return fb.isActive_=
173 b},pb=function(){if(w(pb.name_))return pb.name_;var b,a,c=Oa.length,d,e;for(a=0;a<c;++a)if(d=Oa[a],b=U.querySelector("["+d.replace(":","\\:")+"jq]")){e=b.getAttribute(d+"jq");break}return pb.name_=e},Oa=["ng-","data-ng-","ng:","x-ng-"],be=/[A-Z]/g,Cc=!1,Rb,qa=1,Na=3,fe={full:"1.4.3",major:1,minor:4,dot:3,codeName:"foam-acceleration"};Q.expando="ng339";var ib=Q.cache={},Df=1;Q._data=function(b){return this.cache[b[this.expando]]||{}};var yf=/([\:\-\_]+(.))/g,zf=/^moz([A-Z])/,lg={mouseleave:"mouseout",
174 mouseenter:"mouseover"},Ub=J("jqLite"),Cf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,Af=/<([\w:]+)/,Bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,na={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};na.optgroup=na.option;na.tbody=na.tfoot=na.colgroup=na.caption=na.thead;
175 na.th=na.td;var Pa=Q.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===U.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),Q(O).on("load",a))},toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?y(this[b]):y(this[this.length+b])},length:0,push:kg,sort:[].sort,splice:[].splice},Ab={};m("multiple selected checked disabled readOnly required open".split(" "),function(b){Ab[M(b)]=b});var Tc={};m("input select option textarea button form details".split(" "),
176 function(b){Tc[b]=!0});var Uc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};m({data:Wb,removeData:ub,hasData:function(b){for(var a in ib[b.ng339])return!0;return!1}},function(b,a){Q[a]=b});m({data:Wb,inheritedData:zb,scope:function(b){return y.data(b,"$scope")||zb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return y.data(b,"$isolateScope")||y.data(b,"$isolateScopeNoTemplate")},controller:Qc,injector:function(b){return zb(b,
177 "$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:wb,css:function(b,a,c){a=hb(a);if(w(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==Na&&2!==d&&8!==d)if(d=M(a),Ab[d])if(w(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||v).specified?d:t;else if(w(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(w(c))b[a]=c;else return b[a]},
178 text:function(){function b(a,b){if(A(b)){var d=a.nodeType;return d===qa||d===Na?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(A(a)){if(b.multiple&&"select"===ta(b)){var c=[];m(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(A(a))return b.innerHTML;tb(b,!0);b.innerHTML=a},empty:Rc},function(b,a){Q.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Rc&&(2==b.length&&b!==wb&&b!==Qc?
179 a:d)===t){if(H(a)){for(e=0;e<g;e++)if(b===Wb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===t?Math.min(g,1):g;for(f=0;f<g;f++){var h=b(this[f],a,d);e=e?e+h:h}return e}for(e=0;e<g;e++)b(this[e],a,d);return this}});m({removeData:ub,on:function a(c,d,e,f){if(w(f))throw Ub("onargs");if(Mc(c)){var g=vb(c,!0);f=g.events;var h=g.handle;h||(h=g.handle=Gf(c,f));for(var g=0<=d.indexOf(" ")?d.split(" "):[d],l=g.length;l--;){d=g[l];var k=f[d];k||(f[d]=[],"mouseenter"===d||"mouseleave"===
180 d?a(c,lg[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),k=f[d]);k.push(e)}}},off:Pc,one:function(a,c,d){a=y(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c,d)},replaceWith:function(a,c){var d,e=a.parentNode;tb(a);m(new Q(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];m(a.childNodes,function(a){a.nodeType===qa&&c.push(a)});return c},contents:function(a){return a.contentDocument||
181 a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===qa||11===d){c=new Q(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===qa){var d=a.firstChild;m(new Q(c),function(c){a.insertBefore(c,d)})}},wrap:function(a,c){c=y(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Xb,detach:function(a){Xb(a,!0)},after:function(a,c){var d=a,e=a.parentNode;c=new Q(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h,
182 d.nextSibling);d=h}},addClass:yb,removeClass:xb,toggleClass:function(a,c,d){c&&m(c.split(" "),function(c){var f=d;A(f)&&(f=!wb(a,c));(f?yb:xb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Vb,triggerHandler:function(a,c,d){var e,f,g=c.type||c,h=vb(a);if(h=(h=h&&h.events)&&h[g])e={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===
183 this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:v,type:g,target:a},c.type&&(e=P(e,c)),c=ia(h),f=d?[e].concat(d):[e],m(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){Q.prototype[c]=function(c,e,f){for(var g,h=0,l=this.length;h<l;h++)A(g)?(g=a(this[h],c,e,f),w(g)&&(g=y(g))):Oc(g,a(this[h],c,e,f));return w(g)?g:this};Q.prototype.bind=
184 Q.prototype.on;Q.prototype.unbind=Q.prototype.off});Sa.prototype={put:function(a,c){this[Ga(a,this.nextUid)]=c},get:function(a){return this[Ga(a,this.nextUid)]},remove:function(a){var c=this[a=Ga(a,this.nextUid)];delete this[a];return c}};var wf=[function(){this.$get=[function(){return Sa}]}],Wc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,mg=/,/,ng=/^\s*(_?)(\S+?)\1\s*$/,Vc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ha=J("$injector");eb.$$annotate=function(a,c,d){var e;if("function"===typeof a){if(!(e=a.$inject)){e=
185 [];if(a.length){if(c)throw L(d)&&d||(d=a.name||Hf(a)),Ha("strictdi",d);c=a.toString().replace(Vc,"");c=c.match(Wc);m(c[1].split(mg),function(a){a.replace(ng,function(a,c,d){e.push(d)})})}a.$inject=e}}else G(a)?(c=a.length-1,Qa(a[c],"fn"),e=a.slice(0,c)):Qa(a,"fn",!0);return e};var Nd=J("$animate"),Ue=function(){this.$get=["$q","$$rAF",function(a,c){function d(){}d.all=v;d.chain=v;d.prototype={end:v,cancel:v,resume:v,pause:v,complete:v,then:function(d,f){return a(function(a){c(function(){a()})}).then(d,
186 f)}};return d}]},Te=function(){var a=new Sa,c=[];this.$get=["$$AnimateRunner","$rootScope",function(d,e){function f(d,f,l){var k=a.get(d);k||(a.put(d,k={}),c.push(d));f&&m(f.split(" "),function(a){a&&(k[a]=!0)});l&&m(l.split(" "),function(a){a&&(k[a]=!1)});1<c.length||e.$$postDigest(function(){m(c,function(c){var d=a.get(c);if(d){var e=If(c.attr("class")),f="",g="";m(d,function(a,c){a!==!!e[c]&&(a?f+=(f.length?" ":"")+c:g+=(g.length?" ":"")+c)});m(c,function(a){f&&yb(a,f);g&&xb(a,g)});a.remove(c)}});
187 c.length=0})}return{enabled:v,on:v,off:v,pin:v,push:function(a,c,e,k){k&&k();e=e||{};e.from&&a.css(e.from);e.to&&a.css(e.to);(e.addClass||e.removeClass)&&f(a,e.addClass,e.removeClass);return new d}}}]},Se=["$provide",function(a){var c=this;this.$$registeredAnimations=Object.create(null);this.register=function(d,e){if(d&&"."!==d.charAt(0))throw Nd("notcsel",d);var f=d+"-animation";c.$$registeredAnimations[d.substr(1)]=f;a.factory(f,e)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter=
188 a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Nd("nongcls","ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function c(a,d,e){if(e){var l;a:{for(l=0;l<e.length;l++){var k=e[l];if(1===k.nodeType){l=k;break a}}l=void 0}!l||l.parentNode||l.previousElementSibling||(e=null)}e?e.after(a):d.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},enter:function(f,g,h,l){g=
189 g&&y(g);h=h&&y(h);g=g||h.parent();c(f,g,h);return a.push(f,"enter",Ia(l))},move:function(f,g,h,l){g=g&&y(g);h=h&&y(h);g=g||h.parent();c(f,g,h);return a.push(f,"move",Ia(l))},leave:function(c,e){return a.push(c,"leave",Ia(e),function(){c.remove()})},addClass:function(c,e,h){h=Ia(h);h.addClass=jb(h.addclass,e);return a.push(c,"addClass",h)},removeClass:function(c,e,h){h=Ia(h);h.removeClass=jb(h.removeClass,e);return a.push(c,"removeClass",h)},setClass:function(c,e,h,l){l=Ia(l);l.addClass=jb(l.addClass,
190 e);l.removeClass=jb(l.removeClass,h);return a.push(c,"setClass",l)},animate:function(c,e,h,l,k){k=Ia(k);k.from=k.from?P(k.from,e):e;k.to=k.to?P(k.to,h):h;k.tempClasses=jb(k.tempClasses,l||"ng-inline-animate");return a.push(c,"animate",k)}}}]}],ea=J("$compile");Ec.$inject=["$provide","$$sanitizeUriProvider"];var Zc=/^((?:x|data)[\:\-_])/i,Nf=J("$controller"),Xc=/^(\S+)(\s+as\s+(\w+))?$/,cd="application/json",ac={"Content-Type":cd+";charset=utf-8"},Pf=/^\[|^\{(?!\{)/,Qf={"[":/]$/,"{":/}$/},Of=/^\)\]\}',?\n/,
191 Ka=ca.$interpolateMinErr=J("$interpolate");Ka.throwNoconcat=function(a){throw Ka("noconcat",a);};Ka.interr=function(a,c){return Ka("interr",a,c.toString())};var og=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,Tf={http:80,https:443,ftp:21},Cb=J("$location"),pg={$$html5:!1,$$replace:!1,absUrl:Db("$$absUrl"),url:function(a){if(A(a))return this.$$url;var c=og.exec(a);(c[1]||""===a)&&this.path(decodeURIComponent(c[1]));(c[2]||c[1]||""===a)&&this.search(c[3]||"");this.hash(c[5]||"");return this},protocol:Db("$$protocol"),
192 host:Db("$$host"),port:Db("$$port"),path:kd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;case 1:if(L(a)||V(a))a=a.toString(),this.$$search=zc(a);else if(H(a))a=fa(a,{}),m(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw Cb("isrcharg");break;default:A(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:kd("$$hash",function(a){return null!==
193 a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};m([jd,ec,dc],function(a){a.prototype=Object.create(pg);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==dc||!this.$$html5)throw Cb("nostate");this.$$state=A(c)?null:c;return this}});var da=J("$parse"),Uf=Function.prototype.call,Vf=Function.prototype.apply,Wf=Function.prototype.bind,Mb=ga();m("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Mb[a]=!0});var qg={n:"\n",f:"\f",r:"\r",
194 t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;
195 else{var c=a+this.peek(),d=c+this.peek(2),e=Mb[c],f=Mb[d];Mb[a]||e||f?(a=f?d:e?c:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,c){return-1!==c.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||
196 "\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=w(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw da("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=M(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var e=this.peek();
197 if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:c,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a=this.index;this.index<this.text.length;){var c=this.text.charAt(this.index);if(!this.isIdent(c)&&!this.isNumber(c))break;this.index++}this.tokens.push({index:a,
198 text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(f=this.text.substring(this.index+1,this.index+5),f.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+f+"]"),this.index+=4,d+=String.fromCharCode(parseInt(f,16))):d+=qg[g]||g,f=!1;else if("\\"===g)f=!0;else{if(g===a){this.index++;this.tokens.push({index:c,text:e,constant:!0,
199 value:d});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var q=function(a,c){this.lexer=a;this.options=c};q.Program="Program";q.ExpressionStatement="ExpressionStatement";q.AssignmentExpression="AssignmentExpression";q.ConditionalExpression="ConditionalExpression";q.LogicalExpression="LogicalExpression";q.BinaryExpression="BinaryExpression";q.UnaryExpression="UnaryExpression";q.CallExpression="CallExpression";q.MemberExpression="MemberExpression";q.Identifier="Identifier";q.Literal=
200 "Literal";q.ArrayExpression="ArrayExpression";q.Property="Property";q.ObjectExpression="ObjectExpression";q.ThisExpression="ThisExpression";q.NGValueParameter="NGValueParameter";q.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),!this.expect(";"))return{type:q.Program,
201 body:a}},expressionStatement:function(){return{type:q.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();this.expect("=")&&(a={type:q.AssignmentExpression,left:a,right:this.assignment(),operator:"="});return a},ternary:function(){var a=this.logicalOR(),c,d;return this.expect("?")&&(c=this.expression(),this.consume(":"))?
202 (d=this.expression(),{type:q.ConditionalExpression,test:a,alternate:c,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a={type:q.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:q.LogicalExpression,operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),c;c=this.expect("==","!=","===","!==");)a={type:q.BinaryExpression,
203 operator:c.text,left:a,right:this.relational()};return a},relational:function(){for(var a=this.additive(),c;c=this.expect("<",">","<=",">=");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a={type:q.BinaryExpression,operator:c.text,
204 left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:q.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=fa(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():
205 this.throwError("not a primary expression",this.peek());for(var c;c=this.expect("(","[",".");)"("===c.text?(a={type:q.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===c.text?(a={type:q.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===c.text?a={type:q.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var c={type:q.CallExpression,callee:this.identifier(),
206 arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return c},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:q.Identifier,name:a.text}},constant:function(){return{type:q.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;
207 a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:q.ArrayExpression,elements:a}},object:function(){var a=[],c;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;c={type:q.Property,kind:"init"};this.peek().constant?c.key=this.constant():this.peek().identifier?c.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");c.value=this.expression();a.push(c)}while(this.expect(","))}this.consume("}");return{type:q.ObjectExpression,properties:a}},
208 throwError:function(a,c){throw da("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},consume:function(a){if(0===this.tokens.length)throw da("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},peekToken:function(){if(0===this.tokens.length)throw da("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];
209 var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},constants:{"true":{type:q.Literal,value:!0},"false":{type:q.Literal,value:!1},"null":{type:q.Literal,value:null},undefined:{type:q.Literal,value:t},"this":{type:q.ThisExpression}}};rd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:c,fn:{vars:[],body:[],own:{}},assign:{vars:[],
210 body:[],own:{}},inputs:[]};T(e,d.$filter);var f="",g;this.stage="assign";if(g=pd(e))this.state.computing="assign",f=this.nextId(),this.recurse(g,f),f="fn.assign="+this.generateFunction("assign","s,v,l");g=nd(e.body);d.stage="inputs";m(g,function(a,c){var e="fn"+c;d.state[e]={vars:[],body:[],own:{}};d.state.computing=e;var f=d.nextId();d.recurse(a,f);d.return_(f);d.state.inputs.push(e);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(e);f='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+
211 "var fn="+this.generateFunction("fn","s,l,a,i")+f+this.watchFns()+"return fn;";f=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","ifDefined","plus","text",f))(this.$filter,Ca,oa,ld,Xf,md,a);this.state=this.stage=t;f.literal=qd(e);f.constant=e.constant;return f},USE:"use",STRICT:"strict",watchFns:function(){var a=[],c=this.state.inputs,d=this;m(c,function(c){a.push("var "+c+"="+d.generateFunction(c,"s"))});c.length&&a.push("fn.inputs=["+c.join(",")+"];");return a.join("")},
212 generateFunction:function(a,c){return"function("+c+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],c=this;m(this.state.filters,function(d,e){a.push(d+"=$filter("+c.escape(e)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,c,d,e,f,g){var h,l,k=this,n,r;e=e||v;if(!g&&w(a.watchId))c=c||this.nextId(),this.if_("i",
213 this.lazyAssign(c,this.computedMember("i",a.watchId)),this.lazyRecurse(a,c,d,e,f,!0));else switch(a.type){case q.Program:m(a.body,function(c,d){k.recurse(c.expression,t,t,function(a){l=a});d!==a.body.length-1?k.current().body.push(l,";"):k.return_(l)});break;case q.Literal:r=this.escape(a.value);this.assign(c,r);e(r);break;case q.UnaryExpression:this.recurse(a.argument,t,t,function(a){l=a});r=a.operator+"("+this.ifDefined(l,0)+")";this.assign(c,r);e(r);break;case q.BinaryExpression:this.recurse(a.left,
214 t,t,function(a){h=a});this.recurse(a.right,t,t,function(a){l=a});r="+"===a.operator?this.plus(h,l):"-"===a.operator?this.ifDefined(h,0)+a.operator+this.ifDefined(l,0):"("+h+")"+a.operator+"("+l+")";this.assign(c,r);e(r);break;case q.LogicalExpression:c=c||this.nextId();k.recurse(a.left,c);k.if_("&&"===a.operator?c:k.not(c),k.lazyRecurse(a.right,c));e(c);break;case q.ConditionalExpression:c=c||this.nextId();k.recurse(a.test,c);k.if_(c,k.lazyRecurse(a.alternate,c),k.lazyRecurse(a.consequent,c));e(c);
215 break;case q.Identifier:c=c||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Ca(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){f&&1!==f&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(c,k.nonComputedMember("s",a.name))})},c&&k.lazyAssign(c,k.nonComputedMember("l",
216 a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(c);e(c);break;case q.MemberExpression:h=d&&(d.context=this.nextId())||this.nextId();c=c||this.nextId();k.recurse(a.object,h,t,function(){k.if_(k.notNull(h),function(){if(a.computed)l=k.nextId(),k.recurse(a.property,l),k.addEnsureSafeMemberName(l),f&&1!==f&&k.if_(k.not(k.computedMember(h,l)),k.lazyAssign(k.computedMember(h,l),"{}")),r=k.ensureSafeObject(k.computedMember(h,l)),k.assign(c,r),d&&(d.computed=!0,d.name=l);else{Ca(a.property.name);
217 f&&1!==f&&k.if_(k.not(k.nonComputedMember(h,a.property.name)),k.lazyAssign(k.nonComputedMember(h,a.property.name),"{}"));r=k.nonComputedMember(h,a.property.name);if(k.state.expensiveChecks||Fb(a.property.name))r=k.ensureSafeObject(r);k.assign(c,r);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(c,"undefined")});e(c)},!!f);break;case q.CallExpression:c=c||this.nextId();a.filter?(l=k.filter(a.callee.name),n=[],m(a.arguments,function(a){var c=k.nextId();k.recurse(a,c);n.push(c)}),r=l+
218 "("+n.join(",")+")",k.assign(c,r),e(c)):(l=k.nextId(),h={},n=[],k.recurse(a.callee,l,h,function(){k.if_(k.notNull(l),function(){k.addEnsureSafeFunction(l);m(a.arguments,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(k.ensureSafeObject(a))})});h.name?(k.state.expensiveChecks||k.addEnsureSafeObject(h.context),r=k.member(h.context,h.name,h.computed)+"("+n.join(",")+")"):r=l+"("+n.join(",")+")";r=k.ensureSafeObject(r);k.assign(c,r)},function(){k.assign(c,"undefined")});e(c)}));break;case q.AssignmentExpression:l=
219 this.nextId();h={};if(!od(a.left))throw da("lval");this.recurse(a.left,t,h,function(){k.if_(k.notNull(h.context),function(){k.recurse(a.right,l);k.addEnsureSafeObject(k.member(h.context,h.name,h.computed));r=k.member(h.context,h.name,h.computed)+a.operator+l;k.assign(c,r);e(c||r)})},1);break;case q.ArrayExpression:n=[];m(a.elements,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(a)})});r="["+n.join(",")+"]";this.assign(c,r);e(r);break;case q.ObjectExpression:n=[];m(a.properties,function(a){k.recurse(a.value,
220 k.nextId(),t,function(c){n.push(k.escape(a.key.type===q.Identifier?a.key.name:""+a.key.value)+":"+c)})});r="{"+n.join(",")+"}";this.assign(c,r);e(r);break;case q.ThisExpression:this.assign(c,"s");e("s");break;case q.NGValueParameter:this.assign(c,"v"),e("v")}},getHasOwnProperty:function(a,c){var d=a+"."+c,e=this.current().own;e.hasOwnProperty(d)||(e[d]=this.nextId(!1,a+"&&("+this.escape(c)+" in "+a+")"));return e[d]},assign:function(a,c){if(a)return this.current().body.push(a,"=",c,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||
221 (this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,c){return"ifDefined("+a+","+this.escape(c)+")"},plus:function(a,c){return"plus("+a+","+c+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,c,d){if(!0===a)c();else{var e=this.current().body;e.push("if(",a,"){");c();e.push("}");d&&(e.push("else{"),d(),e.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,c){return a+
222 "."+c},computedMember:function(a,c){return a+"["+c+"]"},member:function(a,c,d){return d?this.computedMember(a,c):this.nonComputedMember(a,c)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+
223 a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},lazyRecurse:function(a,c,d,e,f,g){var h=this;return function(){h.recurse(a,c,d,e,f,g)}},lazyAssign:function(a,c){var d=this;return function(){d.assign(a,c)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(L(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(V(a))return a.toString();if(!0===a)return"true";
224 if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw da("esc");},nextId:function(a,c){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(c?"="+c:""));return d},current:function(){return this.state[this.state.computing]}};sd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=c;T(e,d.$filter);var f,g;if(f=pd(e))g=this.recurse(f);f=nd(e.body);var h;f&&(h=[],m(f,function(a,c){var e=d.recurse(a);
225 a.input=e;h.push(e);a.watchId=c}));var l=[];m(e.body,function(a){l.push(d.recurse(a.expression))});f=0===e.body.length?function(){}:1===e.body.length?l[0]:function(a,c){var d;m(l,function(e){d=e(a,c)});return d};g&&(f.assign=function(a,c,d){return g(a,d,c)});h&&(f.inputs=h);f.literal=qd(e);f.constant=e.constant;return f},recurse:function(a,c,d){var e,f,g=this,h;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case q.Literal:return this.value(a.value,c);case q.UnaryExpression:return f=
226 this.recurse(a.argument),this["unary"+a.operator](f,c);case q.BinaryExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.LogicalExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),c);case q.Identifier:return Ca(a.name,g.expression),g.identifier(a.name,g.expensiveChecks||Fb(a.name),
227 c,d,g.expression);case q.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Ca(a.property.name,g.expression),f=a.property.name),a.computed&&(f=this.recurse(a.property)),a.computed?this.computedMember(e,f,c,d,g.expression):this.nonComputedMember(e,f,g.expensiveChecks,c,d,g.expression);case q.CallExpression:return h=[],m(a.arguments,function(a){h.push(g.recurse(a))}),a.filter&&(f=this.$filter(a.callee.name)),a.filter||(f=this.recurse(a.callee,!0)),a.filter?function(a,d,e,g){for(var m=
228 [],q=0;q<h.length;++q)m.push(h[q](a,d,e,g));a=f.apply(t,m,g);return c?{context:t,name:t,value:a}:a}:function(a,d,e,r){var m=f(a,d,e,r),q;if(null!=m.value){oa(m.context,g.expression);ld(m.value,g.expression);q=[];for(var t=0;t<h.length;++t)q.push(oa(h[t](a,d,e,r),g.expression));q=oa(m.value.apply(m.context,q),g.expression)}return c?{value:q}:q};case q.AssignmentExpression:return e=this.recurse(a.left,!0,1),f=this.recurse(a.right),function(a,d,h,r){var m=e(a,d,h,r);a=f(a,d,h,r);oa(m.value,g.expression);
229 m.context[m.name]=a;return c?{value:a}:a};case q.ArrayExpression:return h=[],m(a.elements,function(a){h.push(g.recurse(a))}),function(a,d,e,f){for(var g=[],m=0;m<h.length;++m)g.push(h[m](a,d,e,f));return c?{value:g}:g};case q.ObjectExpression:return h=[],m(a.properties,function(a){h.push({key:a.key.type===q.Identifier?a.key.name:""+a.key.value,value:g.recurse(a.value)})}),function(a,d,e,f){for(var g={},m=0;m<h.length;++m)g[h[m].key]=h[m].value(a,d,e,f);return c?{value:g}:g};case q.ThisExpression:return function(a){return c?
230 {value:a}:a};case q.NGValueParameter:return function(a,d,e,f){return c?{value:e}:e}}},"unary+":function(a,c){return function(d,e,f,g){d=a(d,e,f,g);d=w(d)?+d:0;return c?{value:d}:d}},"unary-":function(a,c){return function(d,e,f,g){d=a(d,e,f,g);d=w(d)?-d:0;return c?{value:d}:d}},"unary!":function(a,c){return function(d,e,f,g){d=!a(d,e,f,g);return c?{value:d}:d}},"binary+":function(a,c,d){return function(e,f,g,h){var l=a(e,f,g,h);e=c(e,f,g,h);l=md(l,e);return d?{value:l}:l}},"binary-":function(a,c,d){return function(e,
231 f,g,h){var l=a(e,f,g,h);e=c(e,f,g,h);l=(w(l)?l:0)-(w(e)?e:0);return d?{value:l}:l}},"binary*":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)*c(e,f,g,h);return d?{value:e}:e}},"binary/":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)/c(e,f,g,h);return d?{value:e}:e}},"binary%":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)%c(e,f,g,h);return d?{value:e}:e}},"binary===":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)===c(e,f,g,h);return d?{value:e}:e}},"binary!==":function(a,
232 c,d){return function(e,f,g,h){e=a(e,f,g,h)!==c(e,f,g,h);return d?{value:e}:e}},"binary==":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)==c(e,f,g,h);return d?{value:e}:e}},"binary!=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)!=c(e,f,g,h);return d?{value:e}:e}},"binary<":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)<c(e,f,g,h);return d?{value:e}:e}},"binary>":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>c(e,f,g,h);return d?{value:e}:e}},"binary<=":function(a,c,d){return function(e,
233 f,g,h){e=a(e,f,g,h)<=c(e,f,g,h);return d?{value:e}:e}},"binary>=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>=c(e,f,g,h);return d?{value:e}:e}},"binary&&":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)&&c(e,f,g,h);return d?{value:e}:e}},"binary||":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)||c(e,f,g,h);return d?{value:e}:e}},"ternary?:":function(a,c,d,e){return function(f,g,h,l){f=a(f,g,h,l)?c(f,g,h,l):d(f,g,h,l);return e?{value:f}:f}},value:function(a,c){return function(){return c?
234 {context:t,name:t,value:a}:a}},identifier:function(a,c,d,e,f){return function(g,h,l,k){g=h&&a in h?h:g;e&&1!==e&&g&&!g[a]&&(g[a]={});h=g?g[a]:t;c&&oa(h,f);return d?{context:g,name:a,value:h}:h}},computedMember:function(a,c,d,e,f){return function(g,h,l,k){var n=a(g,h,l,k),m,s;null!=n&&(m=c(g,h,l,k),Ca(m,f),e&&1!==e&&n&&!n[m]&&(n[m]={}),s=n[m],oa(s,f));return d?{context:n,name:m,value:s}:s}},nonComputedMember:function(a,c,d,e,f,g){return function(h,l,k,n){h=a(h,l,k,n);f&&1!==f&&h&&!h[c]&&(h[c]={});
235 l=null!=h?h[c]:t;(d||Fb(c))&&oa(l,g);return e?{context:h,name:c,value:l}:l}},inputs:function(a,c){return function(d,e,f,g){return g?g[c]:a(d,e,f)}}};var hc=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d;this.ast=new q(this.lexer);this.astCompiler=d.csp?new sd(this.ast,c):new rd(this.ast,c)};hc.prototype={constructor:hc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};ga();ga();var Yf=Object.prototype.valueOf,Da=J("$sce"),pa={HTML:"html",CSS:"css",URL:"url",
236 RESOURCE_URL:"resourceUrl",JS:"js"},ea=J("$compile"),X=U.createElement("a"),wd=Ba(O.location.href);xd.$inject=["$document"];Lc.$inject=["$provide"];yd.$inject=["$locale"];Ad.$inject=["$locale"];var Dd=".",hg={yyyy:Y("FullYear",4),yy:Y("FullYear",2,0,!0),y:Y("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:Y("Month",2,1),M:Y("Month",1,1),dd:Y("Date",2),d:Y("Date",1),HH:Y("Hours",2),H:Y("Hours",1),hh:Y("Hours",2,-12),h:Y("Hours",1,-12),mm:Y("Minutes",2),m:Y("Minutes",1),ss:Y("Seconds",2),s:Y("Seconds",
237 1),sss:Y("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a,c,d){a=-1*d;return a=(0<=a?"+":"")+(Gb(Math[0<a?"floor":"ceil"](a/60),2)+Gb(Math.abs(a%60),2))},ww:Fd(2),w:Fd(1),G:jc,GG:jc,GGG:jc,GGGG:function(a,c){return 0>=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},gg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,fg=/^\-?\d+$/;zd.$inject=["$locale"];var cg=ra(M),dg=ra(rb);Bd.$inject=
238 ["$parse"];var ie=ra({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===sa.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),sb={};m(Ab,function(a,c){function d(a,d,f){a.$watch(f[e],function(a){f.$set(c,!!a)})}if("multiple"!=a){var e=wa("ng-"+c),f=d;"checked"===a&&(f=function(a,c,f){f.ngModel!==f[e]&&d(a,c,f)});sb[e]=function(){return{restrict:"A",
239 priority:100,link:f}}}});m(Uc,function(a,c){sb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(jg))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});m(["src","srcset","href"],function(a){var c=wa("ng-"+a);sb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===sa.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",
240 g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ua&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Ib={$addControl:v,$$renameControl:function(a,c){a.$name=c},$removeControl:v,$setValidity:v,$setDirty:v,$setPristine:v,$setSubmitted:v};Gd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Od=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Gd,compile:function(d,e){d.addClass(Va).addClass(mb);var f=e.name?"name":a&&e.ngForm?"ngForm":
241 !1;return{pre:function(a,d,e,k){if(!("action"in e)){var n=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",n,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",n,!1)},0,!1)})}var m=k.$$parentForm;f&&(Eb(a,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(Eb(a,k.$name,t,k.$name),m.$$renameControl(k,c),Eb(a,k.$name,k,k.$name))}));d.on("$destroy",function(){m.$removeControl(k);f&&Eb(a,e[f],t,
242 k.$name);P(k,Ib)})}}}}}]},je=Od(),we=Od(!0),ig=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,rg=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,sg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,tg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Pd=/^(\d{4})-(\d{2})-(\d{2})$/,Qd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,mc=/^(\d{4})-W(\d\d)$/,Rd=/^(\d{4})-(\d\d)$/,
243 Sd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Td={text:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e)},date:lb("date",Pd,Kb(Pd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":lb("datetimelocal",Qd,Kb(Qd,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:lb("time",Sd,Kb(Sd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:lb("week",mc,function(a,c){if(aa(a))return a;if(L(a)){mc.lastIndex=0;var d=mc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=Ed(e),f=7*(f-1);c&&(d=c.getHours(),g=
244 c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:lb("month",Rd,Kb(Rd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){Id(a,c,d,e);kb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:tg.test(a)?parseFloat(a):t});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Lb("numfmt",a);a=a.toString()}return a});if(w(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||
245 A(h)||a>=h};d.$observe("min",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:t;e.$validate()})}if(w(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||A(l)||a<=l};d.$observe("max",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:t;e.$validate()})}},url:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||rg.test(d)}},email:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e);
246 e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||sg.test(d)}},radio:function(a,c,d,e){A(d.name)&&c.attr("name",++nb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=Jd(l,a,"ngTrueValue",d.ngTrueValue,!0),n=Jd(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&
247 a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ka(a,k)});e.$parsers.push(function(a){return a?k:n})},hidden:v,button:v,submit:v,reset:v,file:v},Fc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Td[M(h.type)]||Td.text)(f,g,h,l[0],c,a,d,e)}}}}],ug=/^(true|false|\d+)$/,Oe=function(){return{restrict:"A",priority:100,compile:function(a,
248 c){return ug.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},oe=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===t?"":a})}}}}],qe=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));
249 c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===t?"":a})}}}}],pe=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],Ne=ra({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),
250 re=lc("",!0),te=lc("Odd",0),se=lc("Even",1),ue=Ma({compile:function(a,c){c.$set("ngCloak",t);a.removeClass("ng-cloak")}}),ve=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Kc={},vg={blur:!0,focus:!0};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=wa("ng-"+a);Kc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=
251 d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};vg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ye=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=U.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=
252 qb(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],ze=["$templateRequest","$anchorScroll","$animate",function(a,c,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(e,f){var g=f.ngInclude||f.src,h=f.onload||"",l=f.autoscroll;return function(e,f,m,s,q){var t=0,F,u,p,v=function(){u&&(u.remove(),u=null);F&&(F.$destroy(),F=null);p&&(d.leave(p).then(function(){u=null}),u=p,p=null)};e.$watch(g,function(g){var m=function(){!w(l)||l&&!e.$eval(l)||
253 c()},r=++t;g?(a(g,!0).then(function(a){if(r===t){var c=e.$new();s.template=a;a=q(c,function(a){v();d.enter(a,null,f).then(m)});F=c;p=a;F.$emit("$includeContentLoaded",g);e.$eval(h)}},function(){r===t&&(v(),e.$emit("$includeContentError",g))}),e.$emit("$includeContentRequested",g)):(v(),s.template=null)})}}}}],Qe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Nc(f.template,U).childNodes)(c,function(a){d.append(a)},
254 {futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],Ae=Ma({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Me=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?R(f):f;e.$parsers.push(function(a){if(!A(a)){var c=[];a&&m(a.split(h),function(a){a&&c.push(g?R(a):a)});return c}});e.$formatters.push(function(a){return G(a)?a.join(f):t});e.$isEmpty=function(a){return!a||
255 !a.length}}}},mb="ng-valid",Kd="ng-invalid",Va="ng-pristine",Jb="ng-dirty",Md="ng-pending",Lb=new J("ngModel"),wg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,n){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=t;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=
256 !1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=t;this.$name=n(d.name||"",!1)(a);var r=f(d.ngModel),s=r.assign,q=r,C=s,F=null,u,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");q=function(a){var d=r(a);z(d)&&(d=c(a));return d};C=function(a,c){z(r(a))?g(a,{$$$p:p.$modelValue}):s(a,p.$modelValue)}}else if(!r.assign)throw Lb("nonassign",d.ngModel,ua(e));};this.$render=v;this.$isEmpty=function(a){return A(a)||
257 ""===a||null===a||a!==a};var K=e.inheritedData("$formController")||Ib,y=0;Hd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:K,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Jb);g.addClass(e,Va)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Va);g.addClass(e,Jb);K.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=
258 function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(F);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:t,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators=
259 function(a,c,d){function e(){var d=!0;m(p.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(m(p.$asyncValidators,function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;m(p.$asyncValidators,function(f,h){var k=f(a,c);if(!k||!z(k.then))throw Lb("$asyncValidators",k);g(h,t);d.push(k.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},v):h(!0)}function g(a,c){l===y&&p.$setValidity(a,c)}function h(a){l===y&&d(a)}y++;var l=y;(function(){var a=
260 p.$$parserName||"parse";if(u===t)g(a,null);else return u||(m(p.$validators,function(a,c){g(c,null)}),m(p.$asyncValidators,function(a,c){g(c,null)})),g(a,u),u;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(F);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue;if(u=A(c)?t:!0)for(var d=
261 0;d<p.$parsers.length;d++)if(c=p.$parsers[d](c),A(c)){u=!1;break}V(p.$modelValue)&&isNaN(p.$modelValue)&&(p.$modelValue=q(a));var e=p.$modelValue,f=p.$options&&p.$options.allowInvalid;p.$$rawModelValue=c;f&&(p.$modelValue=c,p.$modelValue!==e&&p.$$writeModelToScope());p.$$runValidators(c,p.$$lastCommittedViewValue,function(a){f||(p.$modelValue=a?c:t,p.$modelValue!==e&&p.$$writeModelToScope())})};this.$$writeModelToScope=function(){C(a,p.$modelValue);m(p.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};
262 this.$setViewValue=function(a,c){p.$viewValue=a;p.$options&&!p.$options.updateOnDefault||p.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=p.$options;e&&w(e.debounce)&&(e=e.debounce,V(e)?d=e:V(e[c])?d=e[c]:V(e["default"])&&(d=e["default"]));h.cancel(F);d?F=h(function(){p.$commitViewValue()},d):l.$$phase?p.$commitViewValue():a.$apply(function(){p.$commitViewValue()})};a.$watch(function(){var c=q(a);if(c!==p.$modelValue&&(p.$modelValue===p.$modelValue||c===c)){p.$modelValue=
263 p.$$rawModelValue=c;u=t;for(var d=p.$formatters,e=d.length,f=c;e--;)f=d[e](f);p.$viewValue!==f&&(p.$viewValue=p.$$lastCommittedViewValue=f,p.$render(),p.$$runValidators(c,f,v))}return c})}],Le=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:wg,priority:1,compile:function(c){c.addClass(Va).addClass("ng-untouched").addClass(mb);return{pre:function(a,c,f,g){var h=g[0],l=g[1]||Ib;h.$$setOptions(g[2]&&g[2].$options);l.$addControl(h);f.$observe("name",
264 function(a){h.$name!==a&&l.$$renameControl(h,a)});a.$on("$destroy",function(){l.$removeControl(h)})},post:function(c,e,f,g){var h=g[0];if(h.$options&&h.$options.updateOn)e.on(h.$options.updateOn,function(a){h.$$debounceViewValueCommit(a&&a.type)});e.on("blur",function(e){h.$touched||(a.$$phase?c.$evalAsync(h.$setTouched):c.$apply(h.$setTouched))})}}}}}],xg=/(\s+|^)default(\s+|$)/,Pe=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=fa(a.$eval(c.ngModelOptions));
265 this.$options.updateOn!==t?(this.$options.updateOnDefault=!1,this.$options.updateOn=R(this.$options.updateOn.replace(xg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},Be=Ma({terminal:!0,priority:1E3}),yg=J("ngOptions"),zg=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
266 Je=["$compile","$parse",function(a,c){function d(a,d,e){function f(a,c,d,e,g){this.selectValue=a;this.viewValue=c;this.label=d;this.group=e;this.disabled=g}function n(a){var c;if(!q&&Ea(a))c=a;else{c=[];for(var d in a)a.hasOwnProperty(d)&&"$"!==d.charAt(0)&&c.push(d)}return c}var m=a.match(zg);if(!m)throw yg("iexp",a,ua(d));var s=m[5]||m[7],q=m[6];a=/ as /.test(m[0])&&m[1];var t=m[9];d=c(m[2]?m[1]:s);var v=a&&c(a)||d,u=t&&c(t),p=t?function(a,c){return u(e,c)}:function(a){return Ga(a)},w=function(a,
267 c){return p(a,z(a,c))},y=c(m[2]||m[1]),A=c(m[3]||""),B=c(m[4]||""),N=c(m[8]),D={},z=q?function(a,c){D[q]=c;D[s]=a;return D}:function(a){D[s]=a;return D};return{trackBy:t,getTrackByValue:w,getWatchables:c(N,function(a){var c=[];a=a||[];for(var d=n(a),f=d.length,g=0;g<f;g++){var h=a===d?g:d[g],k=z(a[h],h),h=p(a[h],k);c.push(h);if(m[2]||m[1])h=y(e,k),c.push(h);m[4]&&(k=B(e,k),c.push(k))}return c}),getOptions:function(){for(var a=[],c={},d=N(e)||[],g=n(d),h=g.length,m=0;m<h;m++){var r=d===g?m:g[m],s=
268 z(d[r],r),q=v(e,s),r=p(q,s),u=y(e,s),x=A(e,s),s=B(e,s),q=new f(r,q,u,x,s);a.push(q);c[r]=q}return{items:a,selectValueMap:c,getOptionFromViewValue:function(a){return c[w(a)]},getViewValueFromOption:function(a){return t?ca.copy(a.viewValue):a.viewValue}}}}}var e=U.createElement("option"),f=U.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","?ngModel"],link:function(c,h,l,k){function n(a,c){a.element=c;c.disabled=a.disabled;a.value!==c.value&&(c.value=a.selectValue);a.label!==
269 c.label&&(c.label=a.label,c.textContent=a.label)}function r(a,c,d,e){c&&M(c.nodeName)===d?d=c:(d=e.cloneNode(!1),c?a.insertBefore(d,c):a.appendChild(d));return d}function s(a){for(var c;a;)c=a.nextSibling,Xb(a),a=c}function q(a){var c=p&&p[0],d=N&&N[0];if(c||d)for(;a&&(a===c||a===d);)a=a.nextSibling;return a}function t(){var a=D&&u.readValue();D=z.getOptions();var c={},d=h[0].firstChild;B&&h.prepend(p);d=q(d);D.items.forEach(function(a){var g,k;a.group?(g=c[a.group],g||(g=r(h[0],d,"optgroup",f),d=
270 g.nextSibling,g.label=a.group,g=c[a.group]={groupElement:g,currentOptionElement:g.firstChild}),k=r(g.groupElement,g.currentOptionElement,"option",e),n(a,k),g.currentOptionElement=k.nextSibling):(k=r(h[0],d,"option",e),n(a,k),d=k.nextSibling)});Object.keys(c).forEach(function(a){s(c[a].currentOptionElement)});s(d);v.$render();if(!v.$isEmpty(a)){var g=u.readValue();(z.trackBy?ka(a,g):a===g)||(v.$setViewValue(g),v.$render())}}var v=k[1];if(v){var u=k[0];k=l.multiple;for(var p,w=0,A=h.children(),I=A.length;w<
271 I;w++)if(""===A[w].value){p=A.eq(w);break}var B=!!p,N=y(e.cloneNode(!1));N.val("?");var D,z=d(l.ngOptions,h,c);k?(v.$isEmpty=function(a){return!a||0===a.length},u.writeValue=function(a){D.items.forEach(function(a){a.element.selected=!1});a&&a.forEach(function(a){(a=D.getOptionFromViewValue(a))&&!a.disabled&&(a.element.selected=!0)})},u.readValue=function(){var a=h.val()||[],c=[];m(a,function(a){a=D.selectValueMap[a];a.disabled||c.push(D.getViewValueFromOption(a))});return c},z.trackBy&&c.$watchCollection(function(){if(G(v.$viewValue))return v.$viewValue.map(function(a){return z.getTrackByValue(a)})},
272 function(){v.$render()})):(u.writeValue=function(a){var c=D.getOptionFromViewValue(a);c&&!c.disabled?h[0].value!==c.selectValue&&(N.remove(),B||p.remove(),h[0].value=c.selectValue,c.element.selected=!0,c.element.setAttribute("selected","selected")):null===a||B?(N.remove(),B||h.prepend(p),h.val(""),p.prop("selected",!0),p.attr("selected",!0)):(B||p.remove(),h.prepend(N),h.val("?"),N.prop("selected",!0),N.attr("selected",!0))},u.readValue=function(){var a=D.selectValueMap[h.val()];return a&&!a.disabled?
273 (B||p.remove(),N.remove(),D.getViewValueFromOption(a)):null},z.trackBy&&c.$watch(function(){return z.getTrackByValue(v.$viewValue)},function(){v.$render()}));B?(p.remove(),a(p)(c),p.removeClass("ng-scope")):p=y(e.cloneNode(!1));t();c.$watchCollection(z.getWatchables,t)}}}}],Ce=["$locale","$interpolate","$log",function(a,c,d){var e=/{}/g,f=/^when(Minus)?(.+)$/;return{link:function(g,h,l){function k(a){h.text(a||"")}var n=l.count,r=l.$attr.when&&h.attr(l.$attr.when),s=l.offset||0,q=g.$eval(r)||{},t=
274 {},w=c.startSymbol(),u=c.endSymbol(),p=w+n+"-"+s+u,y=ca.noop,z;m(l,function(a,c){var d=f.exec(c);d&&(d=(d[1]?"-":"")+M(d[2]),q[d]=h.attr(l.$attr[c]))});m(q,function(a,d){t[d]=c(a.replace(e,p))});g.$watch(n,function(c){var e=parseFloat(c),f=isNaN(e);f||e in q||(e=a.pluralCat(e-s));e===z||f&&V(z)&&isNaN(z)||(y(),f=t[e],A(f)?(null!=c&&d.debug("ngPluralize: no rule defined for '"+e+"' in "+r),y=v,k()):y=g.$watch(f,k),z=e)})}}}],De=["$parse","$animate",function(a,c){var d=J("ngRepeat"),e=function(a,c,
275 d,e,k,m,r){a[d]=e;k&&(a[k]=m);a.$index=c;a.$first=0===c;a.$last=c===r-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=U.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",h);var n=k[1],r=k[2],s=k[3],q=k[4],k=n.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
276 if(!k)throw d("iidexp",n);var v=k[3]||k[1],w=k[2];if(s&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(s)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(s)))throw d("badident",s);var u,p,z,A,I={$id:Ga};q?u=a(q):(z=function(a,c){return Ga(c)},A=function(a){return a});return function(a,f,g,k,n){u&&(p=function(c,d,e){w&&(I[w]=c);I[v]=d;I.$index=e;return u(a,I)});var q=ga();a.$watchCollection(r,function(g){var k,r,u=f[0],x,D=ga(),I,H,L,G,M,J,O;s&&(a[s]=g);if(Ea(g))M=
277 g,r=p||z;else for(O in r=p||A,M=[],g)g.hasOwnProperty(O)&&"$"!==O.charAt(0)&&M.push(O);I=M.length;O=Array(I);for(k=0;k<I;k++)if(H=g===M?k:M[k],L=g[H],G=r(H,L,k),q[G])J=q[G],delete q[G],D[G]=J,O[k]=J;else{if(D[G])throw m(O,function(a){a&&a.scope&&(q[a.id]=a)}),d("dupes",h,G,L);O[k]={id:G,scope:t,clone:t};D[G]=!0}for(x in q){J=q[x];G=qb(J.clone);c.leave(G);if(G[0].parentNode)for(k=0,r=G.length;k<r;k++)G[k].$$NG_REMOVED=!0;J.scope.$destroy()}for(k=0;k<I;k++)if(H=g===M?k:M[k],L=g[H],J=O[k],J.scope){x=
278 u;do x=x.nextSibling;while(x&&x.$$NG_REMOVED);J.clone[0]!=x&&c.move(qb(J.clone),null,y(u));u=J.clone[J.clone.length-1];e(J.scope,k,v,L,w,H,I)}else n(function(a,d){J.scope=d;var f=l.cloneNode(!1);a[a.length++]=f;c.enter(a,null,y(u));u=f;J.clone=a;D[J.id]=J;e(J.scope,k,v,L,w,H,I)});q=D})}}}}],Ee=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngShow,function(c){a[c?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],xe=["$animate",
279 function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngHide,function(c){a[c?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Fe=Ma(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&m(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Ge=["$animate",function(a){return{require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],l=[],k=[],n=function(a,c){return function(){a.splice(c,1)}};c.$watch(e.ngSwitch||
280 e.on,function(c){var d,e;d=0;for(e=l.length;d<e;++d)a.cancel(l[d]);d=l.length=0;for(e=k.length;d<e;++d){var q=qb(h[d].clone);k[d].$destroy();(l[d]=a.leave(q)).then(n(l,d))}h.length=0;k.length=0;(g=f.cases["!"+c]||f.cases["?"])&&m(g,function(c){c.transclude(function(d,e){k.push(e);var f=c.element;d[d.length++]=U.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],He=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,
281 f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,element:c})}}),Ie=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||[];e.cases["?"].push({transclude:f,element:c})}}),Ke=Ma({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw J("ngTransclude")("orphan",ua(c));f(function(a){c.empty();c.append(a)})}}),ke=["$templateCache",function(a){return{restrict:"E",terminal:!0,
282 compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],Ag={$setViewValue:v,$render:v},Bg=["$element","$scope","$attrs",function(a,c,d){var e=this,f=new Sa;e.ngModelCtrl=Ag;e.unknownOption=y(U.createElement("option"));e.renderUnknownOption=function(c){c="? "+Ga(c)+" ?";e.unknownOption.val(c);a.prepend(e.unknownOption);a.val(c)};c.$on("$destroy",function(){e.renderUnknownOption=v});e.removeUnknownOption=function(){e.unknownOption.parent()&&e.unknownOption.remove()};e.readValue=
283 function(){e.removeUnknownOption();return a.val()};e.writeValue=function(c){e.hasOption(c)?(e.removeUnknownOption(),a.val(c),""===c&&e.emptyOption.prop("selected",!0)):null==c&&e.emptyOption?(e.removeUnknownOption(),a.val("")):e.renderUnknownOption(c)};e.addOption=function(a,c){Ra(a,'"option value"');""===a&&(e.emptyOption=c);var d=f.get(a)||0;f.put(a,d+1)};e.removeOption=function(a){var c=f.get(a);c&&(1===c?(f.remove(a),""===a&&(e.emptyOption=t)):f.put(a,c-1))};e.hasOption=function(a){return!!f.get(a)}}],
284 le=function(){return{restrict:"E",require:["select","?ngModel"],controller:Bg,link:function(a,c,d,e){var f=e[1];if(f){var g=e[0];g.ngModelCtrl=f;f.$render=function(){g.writeValue(f.$viewValue)};c.on("change",function(){a.$apply(function(){f.$setViewValue(g.readValue())})});if(d.multiple){g.readValue=function(){var a=[];m(c.find("option"),function(c){c.selected&&a.push(c.value)});return a};g.writeValue=function(a){var d=new Sa(a);m(c.find("option"),function(a){a.selected=w(d.get(a.value))})};var h,
285 l=NaN;a.$watch(function(){l!==f.$viewValue||ka(h,f.$viewValue)||(h=ia(f.$viewValue),f.$render());l=f.$viewValue});f.$isEmpty=function(a){return!a||0===a.length}}}}}},ne=["$interpolate",function(a){function c(a){a[0].hasAttribute("selected")&&(a[0].selected=!0)}return{restrict:"E",priority:100,compile:function(d,e){if(A(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k=d.parent(),m=k.data("$selectController")||k.parent().data("$selectController");m&&m.ngModelCtrl&&
286 (f?a.$watch(f,function(a,f){e.$set("value",a);f!==a&&m.removeOption(f);m.addOption(a,d);m.ngModelCtrl.$render();c(d)}):(m.addOption(e.value,d),m.ngModelCtrl.$render(),c(d)),d.on("$destroy",function(){m.removeOption(e.value);m.ngModelCtrl.$render()}))}}}}],me=ra({restrict:"E",terminal:!1}),Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){e&&(d.required=!0,e.$validators.required=function(a,c){return!d.required||!e.$isEmpty(c)},d.$observe("required",function(){e.$validate()}))}}},
287 Gc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f,g=d.ngPattern||d.pattern;d.$observe("pattern",function(a){L(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw J("ngPattern")("noregexp",g,a,ua(c));f=a||t;e.$validate()});e.$validators.pattern=function(a){return e.$isEmpty(a)||A(f)||f.test(a)}}}}},Jc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=W(a);f=isNaN(a)?-1:a;e.$validate()});
288 e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}}},Ic=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=W(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};O.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(ce(),ee(ca),y(U).ready(function(){Zd(U,Ac)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
289 //# sourceMappingURL=angular.min.js.map
+0
-3181
faraday/server/www/script/animate.css less more
0 @charset "UTF-8";
1
2 /*!
3 Animate.css - http://daneden.me/animate
4 Licensed under the MIT license - http://opensource.org/licenses/MIT
5
6 Copyright (c) 2015 Daniel Eden
7 */
8
9 .animated {
10 -webkit-animation-duration: 1s;
11 animation-duration: 1s;
12 -webkit-animation-fill-mode: both;
13 animation-fill-mode: both;
14 }
15
16 .animated.infinite {
17 -webkit-animation-iteration-count: infinite;
18 animation-iteration-count: infinite;
19 }
20
21 .animated.hinge {
22 -webkit-animation-duration: 2s;
23 animation-duration: 2s;
24 }
25
26 .animated.bounceIn,
27 .animated.bounceOut {
28 -webkit-animation-duration: .75s;
29 animation-duration: .75s;
30 }
31
32 .animated.flipOutX,
33 .animated.flipOutY {
34 -webkit-animation-duration: .75s;
35 animation-duration: .75s;
36 }
37
38 @-webkit-keyframes bounce {
39 0%, 20%, 53%, 80%, 100% {
40 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
41 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
42 -webkit-transform: translate3d(0,0,0);
43 transform: translate3d(0,0,0);
44 }
45
46 40%, 43% {
47 -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
48 transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
49 -webkit-transform: translate3d(0, -30px, 0);
50 transform: translate3d(0, -30px, 0);
51 }
52
53 70% {
54 -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
55 transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
56 -webkit-transform: translate3d(0, -15px, 0);
57 transform: translate3d(0, -15px, 0);
58 }
59
60 90% {
61 -webkit-transform: translate3d(0,-4px,0);
62 transform: translate3d(0,-4px,0);
63 }
64 }
65
66 @keyframes bounce {
67 0%, 20%, 53%, 80%, 100% {
68 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
69 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
70 -webkit-transform: translate3d(0,0,0);
71 transform: translate3d(0,0,0);
72 }
73
74 40%, 43% {
75 -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
76 transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
77 -webkit-transform: translate3d(0, -30px, 0);
78 transform: translate3d(0, -30px, 0);
79 }
80
81 70% {
82 -webkit-transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
83 transition-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
84 -webkit-transform: translate3d(0, -15px, 0);
85 transform: translate3d(0, -15px, 0);
86 }
87
88 90% {
89 -webkit-transform: translate3d(0,-4px,0);
90 transform: translate3d(0,-4px,0);
91 }
92 }
93
94 .bounce {
95 -webkit-animation-name: bounce;
96 animation-name: bounce;
97 -webkit-transform-origin: center bottom;
98 transform-origin: center bottom;
99 }
100
101 @-webkit-keyframes flash {
102 0%, 50%, 100% {
103 opacity: 1;
104 }
105
106 25%, 75% {
107 opacity: 0;
108 }
109 }
110
111 @keyframes flash {
112 0%, 50%, 100% {
113 opacity: 1;
114 }
115
116 25%, 75% {
117 opacity: 0;
118 }
119 }
120
121 .flash {
122 -webkit-animation-name: flash;
123 animation-name: flash;
124 }
125
126 /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
127
128 @-webkit-keyframes pulse {
129 0% {
130 -webkit-transform: scale3d(1, 1, 1);
131 transform: scale3d(1, 1, 1);
132 }
133
134 50% {
135 -webkit-transform: scale3d(1.05, 1.05, 1.05);
136 transform: scale3d(1.05, 1.05, 1.05);
137 }
138
139 100% {
140 -webkit-transform: scale3d(1, 1, 1);
141 transform: scale3d(1, 1, 1);
142 }
143 }
144
145 @keyframes pulse {
146 0% {
147 -webkit-transform: scale3d(1, 1, 1);
148 transform: scale3d(1, 1, 1);
149 }
150
151 50% {
152 -webkit-transform: scale3d(1.05, 1.05, 1.05);
153 transform: scale3d(1.05, 1.05, 1.05);
154 }
155
156 100% {
157 -webkit-transform: scale3d(1, 1, 1);
158 transform: scale3d(1, 1, 1);
159 }
160 }
161
162 .pulse {
163 -webkit-animation-name: pulse;
164 animation-name: pulse;
165 }
166
167 @-webkit-keyframes rubberBand {
168 0% {
169 -webkit-transform: scale3d(1, 1, 1);
170 transform: scale3d(1, 1, 1);
171 }
172
173 30% {
174 -webkit-transform: scale3d(1.25, 0.75, 1);
175 transform: scale3d(1.25, 0.75, 1);
176 }
177
178 40% {
179 -webkit-transform: scale3d(0.75, 1.25, 1);
180 transform: scale3d(0.75, 1.25, 1);
181 }
182
183 50% {
184 -webkit-transform: scale3d(1.15, 0.85, 1);
185 transform: scale3d(1.15, 0.85, 1);
186 }
187
188 65% {
189 -webkit-transform: scale3d(.95, 1.05, 1);
190 transform: scale3d(.95, 1.05, 1);
191 }
192
193 75% {
194 -webkit-transform: scale3d(1.05, .95, 1);
195 transform: scale3d(1.05, .95, 1);
196 }
197
198 100% {
199 -webkit-transform: scale3d(1, 1, 1);
200 transform: scale3d(1, 1, 1);
201 }
202 }
203
204 @keyframes rubberBand {
205 0% {
206 -webkit-transform: scale3d(1, 1, 1);
207 transform: scale3d(1, 1, 1);
208 }
209
210 30% {
211 -webkit-transform: scale3d(1.25, 0.75, 1);
212 transform: scale3d(1.25, 0.75, 1);
213 }
214
215 40% {
216 -webkit-transform: scale3d(0.75, 1.25, 1);
217 transform: scale3d(0.75, 1.25, 1);
218 }
219
220 50% {
221 -webkit-transform: scale3d(1.15, 0.85, 1);
222 transform: scale3d(1.15, 0.85, 1);
223 }
224
225 65% {
226 -webkit-transform: scale3d(.95, 1.05, 1);
227 transform: scale3d(.95, 1.05, 1);
228 }
229
230 75% {
231 -webkit-transform: scale3d(1.05, .95, 1);
232 transform: scale3d(1.05, .95, 1);
233 }
234
235 100% {
236 -webkit-transform: scale3d(1, 1, 1);
237 transform: scale3d(1, 1, 1);
238 }
239 }
240
241 .rubberBand {
242 -webkit-animation-name: rubberBand;
243 animation-name: rubberBand;
244 }
245
246 @-webkit-keyframes shake {
247 0%, 100% {
248 -webkit-transform: translate3d(0, 0, 0);
249 transform: translate3d(0, 0, 0);
250 }
251
252 10%, 30%, 50%, 70%, 90% {
253 -webkit-transform: translate3d(-10px, 0, 0);
254 transform: translate3d(-10px, 0, 0);
255 }
256
257 20%, 40%, 60%, 80% {
258 -webkit-transform: translate3d(10px, 0, 0);
259 transform: translate3d(10px, 0, 0);
260 }
261 }
262
263 @keyframes shake {
264 0%, 100% {
265 -webkit-transform: translate3d(0, 0, 0);
266 transform: translate3d(0, 0, 0);
267 }
268
269 10%, 30%, 50%, 70%, 90% {
270 -webkit-transform: translate3d(-10px, 0, 0);
271 transform: translate3d(-10px, 0, 0);
272 }
273
274 20%, 40%, 60%, 80% {
275 -webkit-transform: translate3d(10px, 0, 0);
276 transform: translate3d(10px, 0, 0);
277 }
278 }
279
280 .shake {
281 -webkit-animation-name: shake;
282 animation-name: shake;
283 }
284
285 @-webkit-keyframes swing {
286 20% {
287 -webkit-transform: rotate3d(0, 0, 1, 15deg);
288 transform: rotate3d(0, 0, 1, 15deg);
289 }
290
291 40% {
292 -webkit-transform: rotate3d(0, 0, 1, -10deg);
293 transform: rotate3d(0, 0, 1, -10deg);
294 }
295
296 60% {
297 -webkit-transform: rotate3d(0, 0, 1, 5deg);
298 transform: rotate3d(0, 0, 1, 5deg);
299 }
300
301 80% {
302 -webkit-transform: rotate3d(0, 0, 1, -5deg);
303 transform: rotate3d(0, 0, 1, -5deg);
304 }
305
306 100% {
307 -webkit-transform: rotate3d(0, 0, 1, 0deg);
308 transform: rotate3d(0, 0, 1, 0deg);
309 }
310 }
311
312 @keyframes swing {
313 20% {
314 -webkit-transform: rotate3d(0, 0, 1, 15deg);
315 transform: rotate3d(0, 0, 1, 15deg);
316 }
317
318 40% {
319 -webkit-transform: rotate3d(0, 0, 1, -10deg);
320 transform: rotate3d(0, 0, 1, -10deg);
321 }
322
323 60% {
324 -webkit-transform: rotate3d(0, 0, 1, 5deg);
325 transform: rotate3d(0, 0, 1, 5deg);
326 }
327
328 80% {
329 -webkit-transform: rotate3d(0, 0, 1, -5deg);
330 transform: rotate3d(0, 0, 1, -5deg);
331 }
332
333 100% {
334 -webkit-transform: rotate3d(0, 0, 1, 0deg);
335 transform: rotate3d(0, 0, 1, 0deg);
336 }
337 }
338
339 .swing {
340 -webkit-transform-origin: top center;
341 transform-origin: top center;
342 -webkit-animation-name: swing;
343 animation-name: swing;
344 }
345
346 @-webkit-keyframes tada {
347 0% {
348 -webkit-transform: scale3d(1, 1, 1);
349 transform: scale3d(1, 1, 1);
350 }
351
352 10%, 20% {
353 -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
354 transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
355 }
356
357 30%, 50%, 70%, 90% {
358 -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
359 transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
360 }
361
362 40%, 60%, 80% {
363 -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
364 transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
365 }
366
367 100% {
368 -webkit-transform: scale3d(1, 1, 1);
369 transform: scale3d(1, 1, 1);
370 }
371 }
372
373 @keyframes tada {
374 0% {
375 -webkit-transform: scale3d(1, 1, 1);
376 transform: scale3d(1, 1, 1);
377 }
378
379 10%, 20% {
380 -webkit-transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
381 transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
382 }
383
384 30%, 50%, 70%, 90% {
385 -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
386 transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
387 }
388
389 40%, 60%, 80% {
390 -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
391 transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
392 }
393
394 100% {
395 -webkit-transform: scale3d(1, 1, 1);
396 transform: scale3d(1, 1, 1);
397 }
398 }
399
400 .tada {
401 -webkit-animation-name: tada;
402 animation-name: tada;
403 }
404
405 /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
406
407 @-webkit-keyframes wobble {
408 0% {
409 -webkit-transform: none;
410 transform: none;
411 }
412
413 15% {
414 -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
415 transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
416 }
417
418 30% {
419 -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
420 transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
421 }
422
423 45% {
424 -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
425 transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
426 }
427
428 60% {
429 -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
430 transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
431 }
432
433 75% {
434 -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
435 transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
436 }
437
438 100% {
439 -webkit-transform: none;
440 transform: none;
441 }
442 }
443
444 @keyframes wobble {
445 0% {
446 -webkit-transform: none;
447 transform: none;
448 }
449
450 15% {
451 -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
452 transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
453 }
454
455 30% {
456 -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
457 transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
458 }
459
460 45% {
461 -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
462 transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
463 }
464
465 60% {
466 -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
467 transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
468 }
469
470 75% {
471 -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
472 transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
473 }
474
475 100% {
476 -webkit-transform: none;
477 transform: none;
478 }
479 }
480
481 .wobble {
482 -webkit-animation-name: wobble;
483 animation-name: wobble;
484 }
485
486 @-webkit-keyframes bounceIn {
487 0%, 20%, 40%, 60%, 80%, 100% {
488 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
489 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
490 }
491
492 0% {
493 opacity: 0;
494 -webkit-transform: scale3d(.3, .3, .3);
495 transform: scale3d(.3, .3, .3);
496 }
497
498 20% {
499 -webkit-transform: scale3d(1.1, 1.1, 1.1);
500 transform: scale3d(1.1, 1.1, 1.1);
501 }
502
503 40% {
504 -webkit-transform: scale3d(.9, .9, .9);
505 transform: scale3d(.9, .9, .9);
506 }
507
508 60% {
509 opacity: 1;
510 -webkit-transform: scale3d(1.03, 1.03, 1.03);
511 transform: scale3d(1.03, 1.03, 1.03);
512 }
513
514 80% {
515 -webkit-transform: scale3d(.97, .97, .97);
516 transform: scale3d(.97, .97, .97);
517 }
518
519 100% {
520 opacity: 1;
521 -webkit-transform: scale3d(1, 1, 1);
522 transform: scale3d(1, 1, 1);
523 }
524 }
525
526 @keyframes bounceIn {
527 0%, 20%, 40%, 60%, 80%, 100% {
528 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
529 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
530 }
531
532 0% {
533 opacity: 0;
534 -webkit-transform: scale3d(.3, .3, .3);
535 transform: scale3d(.3, .3, .3);
536 }
537
538 20% {
539 -webkit-transform: scale3d(1.1, 1.1, 1.1);
540 transform: scale3d(1.1, 1.1, 1.1);
541 }
542
543 40% {
544 -webkit-transform: scale3d(.9, .9, .9);
545 transform: scale3d(.9, .9, .9);
546 }
547
548 60% {
549 opacity: 1;
550 -webkit-transform: scale3d(1.03, 1.03, 1.03);
551 transform: scale3d(1.03, 1.03, 1.03);
552 }
553
554 80% {
555 -webkit-transform: scale3d(.97, .97, .97);
556 transform: scale3d(.97, .97, .97);
557 }
558
559 100% {
560 opacity: 1;
561 -webkit-transform: scale3d(1, 1, 1);
562 transform: scale3d(1, 1, 1);
563 }
564 }
565
566 .bounceIn {
567 -webkit-animation-name: bounceIn;
568 animation-name: bounceIn;
569 }
570
571 @-webkit-keyframes bounceInDown {
572 0%, 60%, 75%, 90%, 100% {
573 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
574 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
575 }
576
577 0% {
578 opacity: 0;
579 -webkit-transform: translate3d(0, -3000px, 0);
580 transform: translate3d(0, -3000px, 0);
581 }
582
583 60% {
584 opacity: 1;
585 -webkit-transform: translate3d(0, 25px, 0);
586 transform: translate3d(0, 25px, 0);
587 }
588
589 75% {
590 -webkit-transform: translate3d(0, -10px, 0);
591 transform: translate3d(0, -10px, 0);
592 }
593
594 90% {
595 -webkit-transform: translate3d(0, 5px, 0);
596 transform: translate3d(0, 5px, 0);
597 }
598
599 100% {
600 -webkit-transform: none;
601 transform: none;
602 }
603 }
604
605 @keyframes bounceInDown {
606 0%, 60%, 75%, 90%, 100% {
607 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
608 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
609 }
610
611 0% {
612 opacity: 0;
613 -webkit-transform: translate3d(0, -3000px, 0);
614 transform: translate3d(0, -3000px, 0);
615 }
616
617 60% {
618 opacity: 1;
619 -webkit-transform: translate3d(0, 25px, 0);
620 transform: translate3d(0, 25px, 0);
621 }
622
623 75% {
624 -webkit-transform: translate3d(0, -10px, 0);
625 transform: translate3d(0, -10px, 0);
626 }
627
628 90% {
629 -webkit-transform: translate3d(0, 5px, 0);
630 transform: translate3d(0, 5px, 0);
631 }
632
633 100% {
634 -webkit-transform: none;
635 transform: none;
636 }
637 }
638
639 .bounceInDown {
640 -webkit-animation-name: bounceInDown;
641 animation-name: bounceInDown;
642 }
643
644 @-webkit-keyframes bounceInLeft {
645 0%, 60%, 75%, 90%, 100% {
646 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
647 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
648 }
649
650 0% {
651 opacity: 0;
652 -webkit-transform: translate3d(-3000px, 0, 0);
653 transform: translate3d(-3000px, 0, 0);
654 }
655
656 60% {
657 opacity: 1;
658 -webkit-transform: translate3d(25px, 0, 0);
659 transform: translate3d(25px, 0, 0);
660 }
661
662 75% {
663 -webkit-transform: translate3d(-10px, 0, 0);
664 transform: translate3d(-10px, 0, 0);
665 }
666
667 90% {
668 -webkit-transform: translate3d(5px, 0, 0);
669 transform: translate3d(5px, 0, 0);
670 }
671
672 100% {
673 -webkit-transform: none;
674 transform: none;
675 }
676 }
677
678 @keyframes bounceInLeft {
679 0%, 60%, 75%, 90%, 100% {
680 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
681 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
682 }
683
684 0% {
685 opacity: 0;
686 -webkit-transform: translate3d(-3000px, 0, 0);
687 transform: translate3d(-3000px, 0, 0);
688 }
689
690 60% {
691 opacity: 1;
692 -webkit-transform: translate3d(25px, 0, 0);
693 transform: translate3d(25px, 0, 0);
694 }
695
696 75% {
697 -webkit-transform: translate3d(-10px, 0, 0);
698 transform: translate3d(-10px, 0, 0);
699 }
700
701 90% {
702 -webkit-transform: translate3d(5px, 0, 0);
703 transform: translate3d(5px, 0, 0);
704 }
705
706 100% {
707 -webkit-transform: none;
708 transform: none;
709 }
710 }
711
712 .bounceInLeft {
713 -webkit-animation-name: bounceInLeft;
714 animation-name: bounceInLeft;
715 }
716
717 @-webkit-keyframes bounceInRight {
718 0%, 60%, 75%, 90%, 100% {
719 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
720 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
721 }
722
723 0% {
724 opacity: 0;
725 -webkit-transform: translate3d(3000px, 0, 0);
726 transform: translate3d(3000px, 0, 0);
727 }
728
729 60% {
730 opacity: 1;
731 -webkit-transform: translate3d(-25px, 0, 0);
732 transform: translate3d(-25px, 0, 0);
733 }
734
735 75% {
736 -webkit-transform: translate3d(10px, 0, 0);
737 transform: translate3d(10px, 0, 0);
738 }
739
740 90% {
741 -webkit-transform: translate3d(-5px, 0, 0);
742 transform: translate3d(-5px, 0, 0);
743 }
744
745 100% {
746 -webkit-transform: none;
747 transform: none;
748 }
749 }
750
751 @keyframes bounceInRight {
752 0%, 60%, 75%, 90%, 100% {
753 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
754 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
755 }
756
757 0% {
758 opacity: 0;
759 -webkit-transform: translate3d(3000px, 0, 0);
760 transform: translate3d(3000px, 0, 0);
761 }
762
763 60% {
764 opacity: 1;
765 -webkit-transform: translate3d(-25px, 0, 0);
766 transform: translate3d(-25px, 0, 0);
767 }
768
769 75% {
770 -webkit-transform: translate3d(10px, 0, 0);
771 transform: translate3d(10px, 0, 0);
772 }
773
774 90% {
775 -webkit-transform: translate3d(-5px, 0, 0);
776 transform: translate3d(-5px, 0, 0);
777 }
778
779 100% {
780 -webkit-transform: none;
781 transform: none;
782 }
783 }
784
785 .bounceInRight {
786 -webkit-animation-name: bounceInRight;
787 animation-name: bounceInRight;
788 }
789
790 @-webkit-keyframes bounceInUp {
791 0%, 60%, 75%, 90%, 100% {
792 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
793 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
794 }
795
796 0% {
797 opacity: 0;
798 -webkit-transform: translate3d(0, 3000px, 0);
799 transform: translate3d(0, 3000px, 0);
800 }
801
802 60% {
803 opacity: 1;
804 -webkit-transform: translate3d(0, -20px, 0);
805 transform: translate3d(0, -20px, 0);
806 }
807
808 75% {
809 -webkit-transform: translate3d(0, 10px, 0);
810 transform: translate3d(0, 10px, 0);
811 }
812
813 90% {
814 -webkit-transform: translate3d(0, -5px, 0);
815 transform: translate3d(0, -5px, 0);
816 }
817
818 100% {
819 -webkit-transform: translate3d(0, 0, 0);
820 transform: translate3d(0, 0, 0);
821 }
822 }
823
824 @keyframes bounceInUp {
825 0%, 60%, 75%, 90%, 100% {
826 -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
827 transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
828 }
829
830 0% {
831 opacity: 0;
832 -webkit-transform: translate3d(0, 3000px, 0);
833 transform: translate3d(0, 3000px, 0);
834 }
835
836 60% {
837 opacity: 1;
838 -webkit-transform: translate3d(0, -20px, 0);
839 transform: translate3d(0, -20px, 0);
840 }
841
842 75% {
843 -webkit-transform: translate3d(0, 10px, 0);
844 transform: translate3d(0, 10px, 0);
845 }
846
847 90% {
848 -webkit-transform: translate3d(0, -5px, 0);
849 transform: translate3d(0, -5px, 0);
850 }
851
852 100% {
853 -webkit-transform: translate3d(0, 0, 0);
854 transform: translate3d(0, 0, 0);
855 }
856 }
857
858 .bounceInUp {
859 -webkit-animation-name: bounceInUp;
860 animation-name: bounceInUp;
861 }
862
863 @-webkit-keyframes bounceOut {
864 20% {
865 -webkit-transform: scale3d(.9, .9, .9);
866 transform: scale3d(.9, .9, .9);
867 }
868
869 50%, 55% {
870 opacity: 1;
871 -webkit-transform: scale3d(1.1, 1.1, 1.1);
872 transform: scale3d(1.1, 1.1, 1.1);
873 }
874
875 100% {
876 opacity: 0;
877 -webkit-transform: scale3d(.3, .3, .3);
878 transform: scale3d(.3, .3, .3);
879 }
880 }
881
882 @keyframes bounceOut {
883 20% {
884 -webkit-transform: scale3d(.9, .9, .9);
885 transform: scale3d(.9, .9, .9);
886 }
887
888 50%, 55% {
889 opacity: 1;
890 -webkit-transform: scale3d(1.1, 1.1, 1.1);
891 transform: scale3d(1.1, 1.1, 1.1);
892 }
893
894 100% {
895 opacity: 0;
896 -webkit-transform: scale3d(.3, .3, .3);
897 transform: scale3d(.3, .3, .3);
898 }
899 }
900
901 .bounceOut {
902 -webkit-animation-name: bounceOut;
903 animation-name: bounceOut;
904 }
905
906 @-webkit-keyframes bounceOutDown {
907 20% {
908 -webkit-transform: translate3d(0, 10px, 0);
909 transform: translate3d(0, 10px, 0);
910 }
911
912 40%, 45% {
913 opacity: 1;
914 -webkit-transform: translate3d(0, -20px, 0);
915 transform: translate3d(0, -20px, 0);
916 }
917
918 100% {
919 opacity: 0;
920 -webkit-transform: translate3d(0, 2000px, 0);
921 transform: translate3d(0, 2000px, 0);
922 }
923 }
924
925 @keyframes bounceOutDown {
926 20% {
927 -webkit-transform: translate3d(0, 10px, 0);
928 transform: translate3d(0, 10px, 0);
929 }
930
931 40%, 45% {
932 opacity: 1;
933 -webkit-transform: translate3d(0, -20px, 0);
934 transform: translate3d(0, -20px, 0);
935 }
936
937 100% {
938 opacity: 0;
939 -webkit-transform: translate3d(0, 2000px, 0);
940 transform: translate3d(0, 2000px, 0);
941 }
942 }
943
944 .bounceOutDown {
945 -webkit-animation-name: bounceOutDown;
946 animation-name: bounceOutDown;
947 }
948
949 @-webkit-keyframes bounceOutLeft {
950 20% {
951 opacity: 1;
952 -webkit-transform: translate3d(20px, 0, 0);
953 transform: translate3d(20px, 0, 0);
954 }
955
956 100% {
957 opacity: 0;
958 -webkit-transform: translate3d(-2000px, 0, 0);
959 transform: translate3d(-2000px, 0, 0);
960 }
961 }
962
963 @keyframes bounceOutLeft {
964 20% {
965 opacity: 1;
966 -webkit-transform: translate3d(20px, 0, 0);
967 transform: translate3d(20px, 0, 0);
968 }
969
970 100% {
971 opacity: 0;
972 -webkit-transform: translate3d(-2000px, 0, 0);
973 transform: translate3d(-2000px, 0, 0);
974 }
975 }
976
977 .bounceOutLeft {
978 -webkit-animation-name: bounceOutLeft;
979 animation-name: bounceOutLeft;
980 }
981
982 @-webkit-keyframes bounceOutRight {
983 20% {
984 opacity: 1;
985 -webkit-transform: translate3d(-20px, 0, 0);
986 transform: translate3d(-20px, 0, 0);
987 }
988
989 100% {
990 opacity: 0;
991 -webkit-transform: translate3d(2000px, 0, 0);
992 transform: translate3d(2000px, 0, 0);
993 }
994 }
995
996 @keyframes bounceOutRight {
997 20% {
998 opacity: 1;
999 -webkit-transform: translate3d(-20px, 0, 0);
1000 transform: translate3d(-20px, 0, 0);
1001 }
1002
1003 100% {
1004 opacity: 0;
1005 -webkit-transform: translate3d(2000px, 0, 0);
1006 transform: translate3d(2000px, 0, 0);
1007 }
1008 }
1009
1010 .bounceOutRight {
1011 -webkit-animation-name: bounceOutRight;
1012 animation-name: bounceOutRight;
1013 }
1014
1015 @-webkit-keyframes bounceOutUp {
1016 20% {
1017 -webkit-transform: translate3d(0, -10px, 0);
1018 transform: translate3d(0, -10px, 0);
1019 }
1020
1021 40%, 45% {
1022 opacity: 1;
1023 -webkit-transform: translate3d(0, 20px, 0);
1024 transform: translate3d(0, 20px, 0);
1025 }
1026
1027 100% {
1028 opacity: 0;
1029 -webkit-transform: translate3d(0, -2000px, 0);
1030 transform: translate3d(0, -2000px, 0);
1031 }
1032 }
1033
1034 @keyframes bounceOutUp {
1035 20% {
1036 -webkit-transform: translate3d(0, -10px, 0);
1037 transform: translate3d(0, -10px, 0);
1038 }
1039
1040 40%, 45% {
1041 opacity: 1;
1042 -webkit-transform: translate3d(0, 20px, 0);
1043 transform: translate3d(0, 20px, 0);
1044 }
1045
1046 100% {
1047 opacity: 0;
1048 -webkit-transform: translate3d(0, -2000px, 0);
1049 transform: translate3d(0, -2000px, 0);
1050 }
1051 }
1052
1053 .bounceOutUp {
1054 -webkit-animation-name: bounceOutUp;
1055 animation-name: bounceOutUp;
1056 }
1057
1058 @-webkit-keyframes fadeIn {
1059 0% {
1060 opacity: 0;
1061 }
1062
1063 100% {
1064 opacity: 1;
1065 }
1066 }
1067
1068 @keyframes fadeIn {
1069 0% {
1070 opacity: 0;
1071 }
1072
1073 100% {
1074 opacity: 1;
1075 }
1076 }
1077
1078 .fadeIn {
1079 -webkit-animation-name: fadeIn;
1080 animation-name: fadeIn;
1081 }
1082
1083 @-webkit-keyframes fadeInDown {
1084 0% {
1085 opacity: 0;
1086 -webkit-transform: translate3d(0, -100%, 0);
1087 transform: translate3d(0, -100%, 0);
1088 }
1089
1090 100% {
1091 opacity: 1;
1092 -webkit-transform: none;
1093 transform: none;
1094 }
1095 }
1096
1097 @keyframes fadeInDown {
1098 0% {
1099 opacity: 0;
1100 -webkit-transform: translate3d(0, -100%, 0);
1101 transform: translate3d(0, -100%, 0);
1102 }
1103
1104 100% {
1105 opacity: 1;
1106 -webkit-transform: none;
1107 transform: none;
1108 }
1109 }
1110
1111 .fadeInDown {
1112 -webkit-animation-name: fadeInDown;
1113 animation-name: fadeInDown;
1114 }
1115
1116 @-webkit-keyframes fadeInDownBig {
1117 0% {
1118 opacity: 0;
1119 -webkit-transform: translate3d(0, -2000px, 0);
1120 transform: translate3d(0, -2000px, 0);
1121 }
1122
1123 100% {
1124 opacity: 1;
1125 -webkit-transform: none;
1126 transform: none;
1127 }
1128 }
1129
1130 @keyframes fadeInDownBig {
1131 0% {
1132 opacity: 0;
1133 -webkit-transform: translate3d(0, -2000px, 0);
1134 transform: translate3d(0, -2000px, 0);
1135 }
1136
1137 100% {
1138 opacity: 1;
1139 -webkit-transform: none;
1140 transform: none;
1141 }
1142 }
1143
1144 .fadeInDownBig {
1145 -webkit-animation-name: fadeInDownBig;
1146 animation-name: fadeInDownBig;
1147 }
1148
1149 @-webkit-keyframes fadeInLeft {
1150 0% {
1151 opacity: 0;
1152 -webkit-transform: translate3d(-100%, 0, 0);
1153 transform: translate3d(-100%, 0, 0);
1154 }
1155
1156 100% {
1157 opacity: 1;
1158 -webkit-transform: none;
1159 transform: none;
1160 }
1161 }
1162
1163 @keyframes fadeInLeft {
1164 0% {
1165 opacity: 0;
1166 -webkit-transform: translate3d(-100%, 0, 0);
1167 transform: translate3d(-100%, 0, 0);
1168 }
1169
1170 100% {
1171 opacity: 1;
1172 -webkit-transform: none;
1173 transform: none;
1174 }
1175 }
1176
1177 .fadeInLeft {
1178 -webkit-animation-name: fadeInLeft;
1179 animation-name: fadeInLeft;
1180 }
1181
1182 @-webkit-keyframes fadeInLeftBig {
1183 0% {
1184 opacity: 0;
1185 -webkit-transform: translate3d(-2000px, 0, 0);
1186 transform: translate3d(-2000px, 0, 0);
1187 }
1188
1189 100% {
1190 opacity: 1;
1191 -webkit-transform: none;
1192 transform: none;
1193 }
1194 }
1195
1196 @keyframes fadeInLeftBig {
1197 0% {
1198 opacity: 0;
1199 -webkit-transform: translate3d(-2000px, 0, 0);
1200 transform: translate3d(-2000px, 0, 0);
1201 }
1202
1203 100% {
1204 opacity: 1;
1205 -webkit-transform: none;
1206 transform: none;
1207 }
1208 }
1209
1210 .fadeInLeftBig {
1211 -webkit-animation-name: fadeInLeftBig;
1212 animation-name: fadeInLeftBig;
1213 }
1214
1215 @-webkit-keyframes fadeInRight {
1216 0% {
1217 opacity: 0;
1218 -webkit-transform: translate3d(100%, 0, 0);
1219 transform: translate3d(100%, 0, 0);
1220 }
1221
1222 100% {
1223 opacity: 1;
1224 -webkit-transform: none;
1225 transform: none;
1226 }
1227 }
1228
1229 @keyframes fadeInRight {
1230 0% {
1231 opacity: 0;
1232 -webkit-transform: translate3d(100%, 0, 0);
1233 transform: translate3d(100%, 0, 0);
1234 }
1235
1236 100% {
1237 opacity: 1;
1238 -webkit-transform: none;
1239 transform: none;
1240 }
1241 }
1242
1243 .fadeInRight {
1244 -webkit-animation-name: fadeInRight;
1245 animation-name: fadeInRight;
1246 }
1247
1248 @-webkit-keyframes fadeInRightBig {
1249 0% {
1250 opacity: 0;
1251 -webkit-transform: translate3d(2000px, 0, 0);
1252 transform: translate3d(2000px, 0, 0);
1253 }
1254
1255 100% {
1256 opacity: 1;
1257 -webkit-transform: none;
1258 transform: none;
1259 }
1260 }
1261
1262 @keyframes fadeInRightBig {
1263 0% {
1264 opacity: 0;
1265 -webkit-transform: translate3d(2000px, 0, 0);
1266 transform: translate3d(2000px, 0, 0);
1267 }
1268
1269 100% {
1270 opacity: 1;
1271 -webkit-transform: none;
1272 transform: none;
1273 }
1274 }
1275
1276 .fadeInRightBig {
1277 -webkit-animation-name: fadeInRightBig;
1278 animation-name: fadeInRightBig;
1279 }
1280
1281 @-webkit-keyframes fadeInUp {
1282 0% {
1283 opacity: 0;
1284 -webkit-transform: translate3d(0, 100%, 0);
1285 transform: translate3d(0, 100%, 0);
1286 }
1287
1288 100% {
1289 opacity: 1;
1290 -webkit-transform: none;
1291 transform: none;
1292 }
1293 }
1294
1295 @keyframes fadeInUp {
1296 0% {
1297 opacity: 0;
1298 -webkit-transform: translate3d(0, 100%, 0);
1299 transform: translate3d(0, 100%, 0);
1300 }
1301
1302 100% {
1303 opacity: 1;
1304 -webkit-transform: none;
1305 transform: none;
1306 }
1307 }
1308
1309 .fadeInUp {
1310 -webkit-animation-name: fadeInUp;
1311 animation-name: fadeInUp;
1312 }
1313
1314 @-webkit-keyframes fadeInUpBig {
1315 0% {
1316 opacity: 0;
1317 -webkit-transform: translate3d(0, 2000px, 0);
1318 transform: translate3d(0, 2000px, 0);
1319 }
1320
1321 100% {
1322 opacity: 1;
1323 -webkit-transform: none;
1324 transform: none;
1325 }
1326 }
1327
1328 @keyframes fadeInUpBig {
1329 0% {
1330 opacity: 0;
1331 -webkit-transform: translate3d(0, 2000px, 0);
1332 transform: translate3d(0, 2000px, 0);
1333 }
1334
1335 100% {
1336 opacity: 1;
1337 -webkit-transform: none;
1338 transform: none;
1339 }
1340 }
1341
1342 .fadeInUpBig {
1343 -webkit-animation-name: fadeInUpBig;
1344 animation-name: fadeInUpBig;
1345 }
1346
1347 @-webkit-keyframes fadeOut {
1348 0% {
1349 opacity: 1;
1350 }
1351
1352 100% {
1353 opacity: 0;
1354 }
1355 }
1356
1357 @keyframes fadeOut {
1358 0% {
1359 opacity: 1;
1360 }
1361
1362 100% {
1363 opacity: 0;
1364 }
1365 }
1366
1367 .fadeOut {
1368 -webkit-animation-name: fadeOut;
1369 animation-name: fadeOut;
1370 }
1371
1372 @-webkit-keyframes fadeOutDown {
1373 0% {
1374 opacity: 1;
1375 }
1376
1377 100% {
1378 opacity: 0;
1379 -webkit-transform: translate3d(0, 100%, 0);
1380 transform: translate3d(0, 100%, 0);
1381 }
1382 }
1383
1384 @keyframes fadeOutDown {
1385 0% {
1386 opacity: 1;
1387 }
1388
1389 100% {
1390 opacity: 0;
1391 -webkit-transform: translate3d(0, 100%, 0);
1392 transform: translate3d(0, 100%, 0);
1393 }
1394 }
1395
1396 .fadeOutDown {
1397 -webkit-animation-name: fadeOutDown;
1398 animation-name: fadeOutDown;
1399 }
1400
1401 @-webkit-keyframes fadeOutDownBig {
1402 0% {
1403 opacity: 1;
1404 }
1405
1406 100% {
1407 opacity: 0;
1408 -webkit-transform: translate3d(0, 2000px, 0);
1409 transform: translate3d(0, 2000px, 0);
1410 }
1411 }
1412
1413 @keyframes fadeOutDownBig {
1414 0% {
1415 opacity: 1;
1416 }
1417
1418 100% {
1419 opacity: 0;
1420 -webkit-transform: translate3d(0, 2000px, 0);
1421 transform: translate3d(0, 2000px, 0);
1422 }
1423 }
1424
1425 .fadeOutDownBig {
1426 -webkit-animation-name: fadeOutDownBig;
1427 animation-name: fadeOutDownBig;
1428 }
1429
1430 @-webkit-keyframes fadeOutLeft {
1431 0% {
1432 opacity: 1;
1433 }
1434
1435 100% {
1436 opacity: 0;
1437 -webkit-transform: translate3d(-100%, 0, 0);
1438 transform: translate3d(-100%, 0, 0);
1439 }
1440 }
1441
1442 @keyframes fadeOutLeft {
1443 0% {
1444 opacity: 1;
1445 }
1446
1447 100% {
1448 opacity: 0;
1449 -webkit-transform: translate3d(-100%, 0, 0);
1450 transform: translate3d(-100%, 0, 0);
1451 }
1452 }
1453
1454 .fadeOutLeft {
1455 -webkit-animation-name: fadeOutLeft;
1456 animation-name: fadeOutLeft;
1457 }
1458
1459 @-webkit-keyframes fadeOutLeftBig {
1460 0% {
1461 opacity: 1;
1462 }
1463
1464 100% {
1465 opacity: 0;
1466 -webkit-transform: translate3d(-2000px, 0, 0);
1467 transform: translate3d(-2000px, 0, 0);
1468 }
1469 }
1470
1471 @keyframes fadeOutLeftBig {
1472 0% {
1473 opacity: 1;
1474 }
1475
1476 100% {
1477 opacity: 0;
1478 -webkit-transform: translate3d(-2000px, 0, 0);
1479 transform: translate3d(-2000px, 0, 0);
1480 }
1481 }
1482
1483 .fadeOutLeftBig {
1484 -webkit-animation-name: fadeOutLeftBig;
1485 animation-name: fadeOutLeftBig;
1486 }
1487
1488 @-webkit-keyframes fadeOutRight {
1489 0% {
1490 opacity: 1;
1491 }
1492
1493 100% {
1494 opacity: 0;
1495 -webkit-transform: translate3d(100%, 0, 0);
1496 transform: translate3d(100%, 0, 0);
1497 }
1498 }
1499
1500 @keyframes fadeOutRight {
1501 0% {
1502 opacity: 1;
1503 }
1504
1505 100% {
1506 opacity: 0;
1507 -webkit-transform: translate3d(100%, 0, 0);
1508 transform: translate3d(100%, 0, 0);
1509 }
1510 }
1511
1512 .fadeOutRight {
1513 -webkit-animation-name: fadeOutRight;
1514 animation-name: fadeOutRight;
1515 }
1516
1517 @-webkit-keyframes fadeOutRightBig {
1518 0% {
1519 opacity: 1;
1520 }
1521
1522 100% {
1523 opacity: 0;
1524 -webkit-transform: translate3d(2000px, 0, 0);
1525 transform: translate3d(2000px, 0, 0);
1526 }
1527 }
1528
1529 @keyframes fadeOutRightBig {
1530 0% {
1531 opacity: 1;
1532 }
1533
1534 100% {
1535 opacity: 0;
1536 -webkit-transform: translate3d(2000px, 0, 0);
1537 transform: translate3d(2000px, 0, 0);
1538 }
1539 }
1540
1541 .fadeOutRightBig {
1542 -webkit-animation-name: fadeOutRightBig;
1543 animation-name: fadeOutRightBig;
1544 }
1545
1546 @-webkit-keyframes fadeOutUp {
1547 0% {
1548 opacity: 1;
1549 }
1550
1551 100% {
1552 opacity: 0;
1553 -webkit-transform: translate3d(0, -100%, 0);
1554 transform: translate3d(0, -100%, 0);
1555 }
1556 }
1557
1558 @keyframes fadeOutUp {
1559 0% {
1560 opacity: 1;
1561 }
1562
1563 100% {
1564 opacity: 0;
1565 -webkit-transform: translate3d(0, -100%, 0);
1566 transform: translate3d(0, -100%, 0);
1567 }
1568 }
1569
1570 .fadeOutUp {
1571 -webkit-animation-name: fadeOutUp;
1572 animation-name: fadeOutUp;
1573 }
1574
1575 @-webkit-keyframes fadeOutUpBig {
1576 0% {
1577 opacity: 1;
1578 }
1579
1580 100% {
1581 opacity: 0;
1582 -webkit-transform: translate3d(0, -2000px, 0);
1583 transform: translate3d(0, -2000px, 0);
1584 }
1585 }
1586
1587 @keyframes fadeOutUpBig {
1588 0% {
1589 opacity: 1;
1590 }
1591
1592 100% {
1593 opacity: 0;
1594 -webkit-transform: translate3d(0, -2000px, 0);
1595 transform: translate3d(0, -2000px, 0);
1596 }
1597 }
1598
1599 .fadeOutUpBig {
1600 -webkit-animation-name: fadeOutUpBig;
1601 animation-name: fadeOutUpBig;
1602 }
1603
1604 @-webkit-keyframes flip {
1605 0% {
1606 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
1607 transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
1608 -webkit-animation-timing-function: ease-out;
1609 animation-timing-function: ease-out;
1610 }
1611
1612 40% {
1613 -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
1614 transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
1615 -webkit-animation-timing-function: ease-out;
1616 animation-timing-function: ease-out;
1617 }
1618
1619 50% {
1620 -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
1621 transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
1622 -webkit-animation-timing-function: ease-in;
1623 animation-timing-function: ease-in;
1624 }
1625
1626 80% {
1627 -webkit-transform: perspective(400px) scale3d(.95, .95, .95);
1628 transform: perspective(400px) scale3d(.95, .95, .95);
1629 -webkit-animation-timing-function: ease-in;
1630 animation-timing-function: ease-in;
1631 }
1632
1633 100% {
1634 -webkit-transform: perspective(400px);
1635 transform: perspective(400px);
1636 -webkit-animation-timing-function: ease-in;
1637 animation-timing-function: ease-in;
1638 }
1639 }
1640
1641 @keyframes flip {
1642 0% {
1643 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
1644 transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
1645 -webkit-animation-timing-function: ease-out;
1646 animation-timing-function: ease-out;
1647 }
1648
1649 40% {
1650 -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
1651 transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
1652 -webkit-animation-timing-function: ease-out;
1653 animation-timing-function: ease-out;
1654 }
1655
1656 50% {
1657 -webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
1658 transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
1659 -webkit-animation-timing-function: ease-in;
1660 animation-timing-function: ease-in;
1661 }
1662
1663 80% {
1664 -webkit-transform: perspective(400px) scale3d(.95, .95, .95);
1665 transform: perspective(400px) scale3d(.95, .95, .95);
1666 -webkit-animation-timing-function: ease-in;
1667 animation-timing-function: ease-in;
1668 }
1669
1670 100% {
1671 -webkit-transform: perspective(400px);
1672 transform: perspective(400px);
1673 -webkit-animation-timing-function: ease-in;
1674 animation-timing-function: ease-in;
1675 }
1676 }
1677
1678 .animated.flip {
1679 -webkit-backface-visibility: visible;
1680 backface-visibility: visible;
1681 -webkit-animation-name: flip;
1682 animation-name: flip;
1683 }
1684
1685 @-webkit-keyframes flipInX {
1686 0% {
1687 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1688 transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1689 -webkit-transition-timing-function: ease-in;
1690 transition-timing-function: ease-in;
1691 opacity: 0;
1692 }
1693
1694 40% {
1695 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1696 transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1697 -webkit-transition-timing-function: ease-in;
1698 transition-timing-function: ease-in;
1699 }
1700
1701 60% {
1702 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
1703 transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
1704 opacity: 1;
1705 }
1706
1707 80% {
1708 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
1709 transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
1710 }
1711
1712 100% {
1713 -webkit-transform: perspective(400px);
1714 transform: perspective(400px);
1715 }
1716 }
1717
1718 @keyframes flipInX {
1719 0% {
1720 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1721 transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1722 -webkit-transition-timing-function: ease-in;
1723 transition-timing-function: ease-in;
1724 opacity: 0;
1725 }
1726
1727 40% {
1728 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1729 transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1730 -webkit-transition-timing-function: ease-in;
1731 transition-timing-function: ease-in;
1732 }
1733
1734 60% {
1735 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
1736 transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
1737 opacity: 1;
1738 }
1739
1740 80% {
1741 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
1742 transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
1743 }
1744
1745 100% {
1746 -webkit-transform: perspective(400px);
1747 transform: perspective(400px);
1748 }
1749 }
1750
1751 .flipInX {
1752 -webkit-backface-visibility: visible !important;
1753 backface-visibility: visible !important;
1754 -webkit-animation-name: flipInX;
1755 animation-name: flipInX;
1756 }
1757
1758 @-webkit-keyframes flipInY {
1759 0% {
1760 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
1761 transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
1762 -webkit-transition-timing-function: ease-in;
1763 transition-timing-function: ease-in;
1764 opacity: 0;
1765 }
1766
1767 40% {
1768 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
1769 transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
1770 -webkit-transition-timing-function: ease-in;
1771 transition-timing-function: ease-in;
1772 }
1773
1774 60% {
1775 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
1776 transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
1777 opacity: 1;
1778 }
1779
1780 80% {
1781 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
1782 transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
1783 }
1784
1785 100% {
1786 -webkit-transform: perspective(400px);
1787 transform: perspective(400px);
1788 }
1789 }
1790
1791 @keyframes flipInY {
1792 0% {
1793 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
1794 transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
1795 -webkit-transition-timing-function: ease-in;
1796 transition-timing-function: ease-in;
1797 opacity: 0;
1798 }
1799
1800 40% {
1801 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
1802 transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
1803 -webkit-transition-timing-function: ease-in;
1804 transition-timing-function: ease-in;
1805 }
1806
1807 60% {
1808 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
1809 transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
1810 opacity: 1;
1811 }
1812
1813 80% {
1814 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
1815 transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
1816 }
1817
1818 100% {
1819 -webkit-transform: perspective(400px);
1820 transform: perspective(400px);
1821 }
1822 }
1823
1824 .flipInY {
1825 -webkit-backface-visibility: visible !important;
1826 backface-visibility: visible !important;
1827 -webkit-animation-name: flipInY;
1828 animation-name: flipInY;
1829 }
1830
1831 @-webkit-keyframes flipOutX {
1832 0% {
1833 -webkit-transform: perspective(400px);
1834 transform: perspective(400px);
1835 }
1836
1837 30% {
1838 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1839 transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1840 opacity: 1;
1841 }
1842
1843 100% {
1844 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1845 transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1846 opacity: 0;
1847 }
1848 }
1849
1850 @keyframes flipOutX {
1851 0% {
1852 -webkit-transform: perspective(400px);
1853 transform: perspective(400px);
1854 }
1855
1856 30% {
1857 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1858 transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
1859 opacity: 1;
1860 }
1861
1862 100% {
1863 -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1864 transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
1865 opacity: 0;
1866 }
1867 }
1868
1869 .flipOutX {
1870 -webkit-animation-name: flipOutX;
1871 animation-name: flipOutX;
1872 -webkit-backface-visibility: visible !important;
1873 backface-visibility: visible !important;
1874 }
1875
1876 @-webkit-keyframes flipOutY {
1877 0% {
1878 -webkit-transform: perspective(400px);
1879 transform: perspective(400px);
1880 }
1881
1882 30% {
1883 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
1884 transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
1885 opacity: 1;
1886 }
1887
1888 100% {
1889 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
1890 transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
1891 opacity: 0;
1892 }
1893 }
1894
1895 @keyframes flipOutY {
1896 0% {
1897 -webkit-transform: perspective(400px);
1898 transform: perspective(400px);
1899 }
1900
1901 30% {
1902 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
1903 transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
1904 opacity: 1;
1905 }
1906
1907 100% {
1908 -webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
1909 transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
1910 opacity: 0;
1911 }
1912 }
1913
1914 .flipOutY {
1915 -webkit-backface-visibility: visible !important;
1916 backface-visibility: visible !important;
1917 -webkit-animation-name: flipOutY;
1918 animation-name: flipOutY;
1919 }
1920
1921 @-webkit-keyframes lightSpeedIn {
1922 0% {
1923 -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
1924 transform: translate3d(100%, 0, 0) skewX(-30deg);
1925 opacity: 0;
1926 }
1927
1928 60% {
1929 -webkit-transform: skewX(20deg);
1930 transform: skewX(20deg);
1931 opacity: 1;
1932 }
1933
1934 80% {
1935 -webkit-transform: skewX(-5deg);
1936 transform: skewX(-5deg);
1937 opacity: 1;
1938 }
1939
1940 100% {
1941 -webkit-transform: none;
1942 transform: none;
1943 opacity: 1;
1944 }
1945 }
1946
1947 @keyframes lightSpeedIn {
1948 0% {
1949 -webkit-transform: translate3d(100%, 0, 0) skewX(-30deg);
1950 transform: translate3d(100%, 0, 0) skewX(-30deg);
1951 opacity: 0;
1952 }
1953
1954 60% {
1955 -webkit-transform: skewX(20deg);
1956 transform: skewX(20deg);
1957 opacity: 1;
1958 }
1959
1960 80% {
1961 -webkit-transform: skewX(-5deg);
1962 transform: skewX(-5deg);
1963 opacity: 1;
1964 }
1965
1966 100% {
1967 -webkit-transform: none;
1968 transform: none;
1969 opacity: 1;
1970 }
1971 }
1972
1973 .lightSpeedIn {
1974 -webkit-animation-name: lightSpeedIn;
1975 animation-name: lightSpeedIn;
1976 -webkit-animation-timing-function: ease-out;
1977 animation-timing-function: ease-out;
1978 }
1979
1980 @-webkit-keyframes lightSpeedOut {
1981 0% {
1982 opacity: 1;
1983 }
1984
1985 100% {
1986 -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
1987 transform: translate3d(100%, 0, 0) skewX(30deg);
1988 opacity: 0;
1989 }
1990 }
1991
1992 @keyframes lightSpeedOut {
1993 0% {
1994 opacity: 1;
1995 }
1996
1997 100% {
1998 -webkit-transform: translate3d(100%, 0, 0) skewX(30deg);
1999 transform: translate3d(100%, 0, 0) skewX(30deg);
2000 opacity: 0;
2001 }
2002 }
2003
2004 .lightSpeedOut {
2005 -webkit-animation-name: lightSpeedOut;
2006 animation-name: lightSpeedOut;
2007 -webkit-animation-timing-function: ease-in;
2008 animation-timing-function: ease-in;
2009 }
2010
2011 @-webkit-keyframes rotateIn {
2012 0% {
2013 -webkit-transform-origin: center;
2014 transform-origin: center;
2015 -webkit-transform: rotate3d(0, 0, 1, -200deg);
2016 transform: rotate3d(0, 0, 1, -200deg);
2017 opacity: 0;
2018 }
2019
2020 100% {
2021 -webkit-transform-origin: center;
2022 transform-origin: center;
2023 -webkit-transform: none;
2024 transform: none;
2025 opacity: 1;
2026 }
2027 }
2028
2029 @keyframes rotateIn {
2030 0% {
2031 -webkit-transform-origin: center;
2032 transform-origin: center;
2033 -webkit-transform: rotate3d(0, 0, 1, -200deg);
2034 transform: rotate3d(0, 0, 1, -200deg);
2035 opacity: 0;
2036 }
2037
2038 100% {
2039 -webkit-transform-origin: center;
2040 transform-origin: center;
2041 -webkit-transform: none;
2042 transform: none;
2043 opacity: 1;
2044 }
2045 }
2046
2047 .rotateIn {
2048 -webkit-animation-name: rotateIn;
2049 animation-name: rotateIn;
2050 }
2051
2052 @-webkit-keyframes rotateInDownLeft {
2053 0% {
2054 -webkit-transform-origin: left bottom;
2055 transform-origin: left bottom;
2056 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2057 transform: rotate3d(0, 0, 1, -45deg);
2058 opacity: 0;
2059 }
2060
2061 100% {
2062 -webkit-transform-origin: left bottom;
2063 transform-origin: left bottom;
2064 -webkit-transform: none;
2065 transform: none;
2066 opacity: 1;
2067 }
2068 }
2069
2070 @keyframes rotateInDownLeft {
2071 0% {
2072 -webkit-transform-origin: left bottom;
2073 transform-origin: left bottom;
2074 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2075 transform: rotate3d(0, 0, 1, -45deg);
2076 opacity: 0;
2077 }
2078
2079 100% {
2080 -webkit-transform-origin: left bottom;
2081 transform-origin: left bottom;
2082 -webkit-transform: none;
2083 transform: none;
2084 opacity: 1;
2085 }
2086 }
2087
2088 .rotateInDownLeft {
2089 -webkit-animation-name: rotateInDownLeft;
2090 animation-name: rotateInDownLeft;
2091 }
2092
2093 @-webkit-keyframes rotateInDownRight {
2094 0% {
2095 -webkit-transform-origin: right bottom;
2096 transform-origin: right bottom;
2097 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2098 transform: rotate3d(0, 0, 1, 45deg);
2099 opacity: 0;
2100 }
2101
2102 100% {
2103 -webkit-transform-origin: right bottom;
2104 transform-origin: right bottom;
2105 -webkit-transform: none;
2106 transform: none;
2107 opacity: 1;
2108 }
2109 }
2110
2111 @keyframes rotateInDownRight {
2112 0% {
2113 -webkit-transform-origin: right bottom;
2114 transform-origin: right bottom;
2115 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2116 transform: rotate3d(0, 0, 1, 45deg);
2117 opacity: 0;
2118 }
2119
2120 100% {
2121 -webkit-transform-origin: right bottom;
2122 transform-origin: right bottom;
2123 -webkit-transform: none;
2124 transform: none;
2125 opacity: 1;
2126 }
2127 }
2128
2129 .rotateInDownRight {
2130 -webkit-animation-name: rotateInDownRight;
2131 animation-name: rotateInDownRight;
2132 }
2133
2134 @-webkit-keyframes rotateInUpLeft {
2135 0% {
2136 -webkit-transform-origin: left bottom;
2137 transform-origin: left bottom;
2138 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2139 transform: rotate3d(0, 0, 1, 45deg);
2140 opacity: 0;
2141 }
2142
2143 100% {
2144 -webkit-transform-origin: left bottom;
2145 transform-origin: left bottom;
2146 -webkit-transform: none;
2147 transform: none;
2148 opacity: 1;
2149 }
2150 }
2151
2152 @keyframes rotateInUpLeft {
2153 0% {
2154 -webkit-transform-origin: left bottom;
2155 transform-origin: left bottom;
2156 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2157 transform: rotate3d(0, 0, 1, 45deg);
2158 opacity: 0;
2159 }
2160
2161 100% {
2162 -webkit-transform-origin: left bottom;
2163 transform-origin: left bottom;
2164 -webkit-transform: none;
2165 transform: none;
2166 opacity: 1;
2167 }
2168 }
2169
2170 .rotateInUpLeft {
2171 -webkit-animation-name: rotateInUpLeft;
2172 animation-name: rotateInUpLeft;
2173 }
2174
2175 @-webkit-keyframes rotateInUpRight {
2176 0% {
2177 -webkit-transform-origin: right bottom;
2178 transform-origin: right bottom;
2179 -webkit-transform: rotate3d(0, 0, 1, -90deg);
2180 transform: rotate3d(0, 0, 1, -90deg);
2181 opacity: 0;
2182 }
2183
2184 100% {
2185 -webkit-transform-origin: right bottom;
2186 transform-origin: right bottom;
2187 -webkit-transform: none;
2188 transform: none;
2189 opacity: 1;
2190 }
2191 }
2192
2193 @keyframes rotateInUpRight {
2194 0% {
2195 -webkit-transform-origin: right bottom;
2196 transform-origin: right bottom;
2197 -webkit-transform: rotate3d(0, 0, 1, -90deg);
2198 transform: rotate3d(0, 0, 1, -90deg);
2199 opacity: 0;
2200 }
2201
2202 100% {
2203 -webkit-transform-origin: right bottom;
2204 transform-origin: right bottom;
2205 -webkit-transform: none;
2206 transform: none;
2207 opacity: 1;
2208 }
2209 }
2210
2211 .rotateInUpRight {
2212 -webkit-animation-name: rotateInUpRight;
2213 animation-name: rotateInUpRight;
2214 }
2215
2216 @-webkit-keyframes rotateOut {
2217 0% {
2218 -webkit-transform-origin: center;
2219 transform-origin: center;
2220 opacity: 1;
2221 }
2222
2223 100% {
2224 -webkit-transform-origin: center;
2225 transform-origin: center;
2226 -webkit-transform: rotate3d(0, 0, 1, 200deg);
2227 transform: rotate3d(0, 0, 1, 200deg);
2228 opacity: 0;
2229 }
2230 }
2231
2232 @keyframes rotateOut {
2233 0% {
2234 -webkit-transform-origin: center;
2235 transform-origin: center;
2236 opacity: 1;
2237 }
2238
2239 100% {
2240 -webkit-transform-origin: center;
2241 transform-origin: center;
2242 -webkit-transform: rotate3d(0, 0, 1, 200deg);
2243 transform: rotate3d(0, 0, 1, 200deg);
2244 opacity: 0;
2245 }
2246 }
2247
2248 .rotateOut {
2249 -webkit-animation-name: rotateOut;
2250 animation-name: rotateOut;
2251 }
2252
2253 @-webkit-keyframes rotateOutDownLeft {
2254 0% {
2255 -webkit-transform-origin: left bottom;
2256 transform-origin: left bottom;
2257 opacity: 1;
2258 }
2259
2260 100% {
2261 -webkit-transform-origin: left bottom;
2262 transform-origin: left bottom;
2263 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2264 transform: rotate3d(0, 0, 1, 45deg);
2265 opacity: 0;
2266 }
2267 }
2268
2269 @keyframes rotateOutDownLeft {
2270 0% {
2271 -webkit-transform-origin: left bottom;
2272 transform-origin: left bottom;
2273 opacity: 1;
2274 }
2275
2276 100% {
2277 -webkit-transform-origin: left bottom;
2278 transform-origin: left bottom;
2279 -webkit-transform: rotate3d(0, 0, 1, 45deg);
2280 transform: rotate3d(0, 0, 1, 45deg);
2281 opacity: 0;
2282 }
2283 }
2284
2285 .rotateOutDownLeft {
2286 -webkit-animation-name: rotateOutDownLeft;
2287 animation-name: rotateOutDownLeft;
2288 }
2289
2290 @-webkit-keyframes rotateOutDownRight {
2291 0% {
2292 -webkit-transform-origin: right bottom;
2293 transform-origin: right bottom;
2294 opacity: 1;
2295 }
2296
2297 100% {
2298 -webkit-transform-origin: right bottom;
2299 transform-origin: right bottom;
2300 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2301 transform: rotate3d(0, 0, 1, -45deg);
2302 opacity: 0;
2303 }
2304 }
2305
2306 @keyframes rotateOutDownRight {
2307 0% {
2308 -webkit-transform-origin: right bottom;
2309 transform-origin: right bottom;
2310 opacity: 1;
2311 }
2312
2313 100% {
2314 -webkit-transform-origin: right bottom;
2315 transform-origin: right bottom;
2316 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2317 transform: rotate3d(0, 0, 1, -45deg);
2318 opacity: 0;
2319 }
2320 }
2321
2322 .rotateOutDownRight {
2323 -webkit-animation-name: rotateOutDownRight;
2324 animation-name: rotateOutDownRight;
2325 }
2326
2327 @-webkit-keyframes rotateOutUpLeft {
2328 0% {
2329 -webkit-transform-origin: left bottom;
2330 transform-origin: left bottom;
2331 opacity: 1;
2332 }
2333
2334 100% {
2335 -webkit-transform-origin: left bottom;
2336 transform-origin: left bottom;
2337 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2338 transform: rotate3d(0, 0, 1, -45deg);
2339 opacity: 0;
2340 }
2341 }
2342
2343 @keyframes rotateOutUpLeft {
2344 0% {
2345 -webkit-transform-origin: left bottom;
2346 transform-origin: left bottom;
2347 opacity: 1;
2348 }
2349
2350 100% {
2351 -webkit-transform-origin: left bottom;
2352 transform-origin: left bottom;
2353 -webkit-transform: rotate3d(0, 0, 1, -45deg);
2354 transform: rotate3d(0, 0, 1, -45deg);
2355 opacity: 0;
2356 }
2357 }
2358
2359 .rotateOutUpLeft {
2360 -webkit-animation-name: rotateOutUpLeft;
2361 animation-name: rotateOutUpLeft;
2362 }
2363
2364 @-webkit-keyframes rotateOutUpRight {
2365 0% {
2366 -webkit-transform-origin: right bottom;
2367 transform-origin: right bottom;
2368 opacity: 1;
2369 }
2370
2371 100% {
2372 -webkit-transform-origin: right bottom;
2373 transform-origin: right bottom;
2374 -webkit-transform: rotate3d(0, 0, 1, 90deg);
2375 transform: rotate3d(0, 0, 1, 90deg);
2376 opacity: 0;
2377 }
2378 }
2379
2380 @keyframes rotateOutUpRight {
2381 0% {
2382 -webkit-transform-origin: right bottom;
2383 transform-origin: right bottom;
2384 opacity: 1;
2385 }
2386
2387 100% {
2388 -webkit-transform-origin: right bottom;
2389 transform-origin: right bottom;
2390 -webkit-transform: rotate3d(0, 0, 1, 90deg);
2391 transform: rotate3d(0, 0, 1, 90deg);
2392 opacity: 0;
2393 }
2394 }
2395
2396 .rotateOutUpRight {
2397 -webkit-animation-name: rotateOutUpRight;
2398 animation-name: rotateOutUpRight;
2399 }
2400
2401 @-webkit-keyframes hinge {
2402 0% {
2403 -webkit-transform-origin: top left;
2404 transform-origin: top left;
2405 -webkit-animation-timing-function: ease-in-out;
2406 animation-timing-function: ease-in-out;
2407 }
2408
2409 20%, 60% {
2410 -webkit-transform: rotate3d(0, 0, 1, 80deg);
2411 transform: rotate3d(0, 0, 1, 80deg);
2412 -webkit-transform-origin: top left;
2413 transform-origin: top left;
2414 -webkit-animation-timing-function: ease-in-out;
2415 animation-timing-function: ease-in-out;
2416 }
2417
2418 40%, 80% {
2419 -webkit-transform: rotate3d(0, 0, 1, 60deg);
2420 transform: rotate3d(0, 0, 1, 60deg);
2421 -webkit-transform-origin: top left;
2422 transform-origin: top left;
2423 -webkit-animation-timing-function: ease-in-out;
2424 animation-timing-function: ease-in-out;
2425 opacity: 1;
2426 }
2427
2428 100% {
2429 -webkit-transform: translate3d(0, 700px, 0);
2430 transform: translate3d(0, 700px, 0);
2431 opacity: 0;
2432 }
2433 }
2434
2435 @keyframes hinge {
2436 0% {
2437 -webkit-transform-origin: top left;
2438 transform-origin: top left;
2439 -webkit-animation-timing-function: ease-in-out;
2440 animation-timing-function: ease-in-out;
2441 }
2442
2443 20%, 60% {
2444 -webkit-transform: rotate3d(0, 0, 1, 80deg);
2445 transform: rotate3d(0, 0, 1, 80deg);
2446 -webkit-transform-origin: top left;
2447 transform-origin: top left;
2448 -webkit-animation-timing-function: ease-in-out;
2449 animation-timing-function: ease-in-out;
2450 }
2451
2452 40%, 80% {
2453 -webkit-transform: rotate3d(0, 0, 1, 60deg);
2454 transform: rotate3d(0, 0, 1, 60deg);
2455 -webkit-transform-origin: top left;
2456 transform-origin: top left;
2457 -webkit-animation-timing-function: ease-in-out;
2458 animation-timing-function: ease-in-out;
2459 opacity: 1;
2460 }
2461
2462 100% {
2463 -webkit-transform: translate3d(0, 700px, 0);
2464 transform: translate3d(0, 700px, 0);
2465 opacity: 0;
2466 }
2467 }
2468
2469 .hinge {
2470 -webkit-animation-name: hinge;
2471 animation-name: hinge;
2472 }
2473
2474 /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
2475
2476 @-webkit-keyframes rollIn {
2477 0% {
2478 opacity: 0;
2479 -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
2480 transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
2481 }
2482
2483 100% {
2484 opacity: 1;
2485 -webkit-transform: none;
2486 transform: none;
2487 }
2488 }
2489
2490 @keyframes rollIn {
2491 0% {
2492 opacity: 0;
2493 -webkit-transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
2494 transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
2495 }
2496
2497 100% {
2498 opacity: 1;
2499 -webkit-transform: none;
2500 transform: none;
2501 }
2502 }
2503
2504 .rollIn {
2505 -webkit-animation-name: rollIn;
2506 animation-name: rollIn;
2507 }
2508
2509 /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
2510
2511 @-webkit-keyframes rollOut {
2512 0% {
2513 opacity: 1;
2514 }
2515
2516 100% {
2517 opacity: 0;
2518 -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
2519 transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
2520 }
2521 }
2522
2523 @keyframes rollOut {
2524 0% {
2525 opacity: 1;
2526 }
2527
2528 100% {
2529 opacity: 0;
2530 -webkit-transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
2531 transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
2532 }
2533 }
2534
2535 .rollOut {
2536 -webkit-animation-name: rollOut;
2537 animation-name: rollOut;
2538 }
2539
2540 @-webkit-keyframes zoomIn {
2541 0% {
2542 opacity: 0;
2543 -webkit-transform: scale3d(.3, .3, .3);
2544 transform: scale3d(.3, .3, .3);
2545 }
2546
2547 50% {
2548 opacity: 1;
2549 }
2550 }
2551
2552 @keyframes zoomIn {
2553 0% {
2554 opacity: 0;
2555 -webkit-transform: scale3d(.3, .3, .3);
2556 transform: scale3d(.3, .3, .3);
2557 }
2558
2559 50% {
2560 opacity: 1;
2561 }
2562 }
2563
2564 .zoomIn {
2565 -webkit-animation-name: zoomIn;
2566 animation-name: zoomIn;
2567 }
2568
2569 @-webkit-keyframes zoomInDown {
2570 0% {
2571 opacity: 0;
2572 -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
2573 transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
2574 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2575 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2576 }
2577
2578 60% {
2579 opacity: 1;
2580 -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
2581 transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
2582 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2583 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2584 }
2585 }
2586
2587 @keyframes zoomInDown {
2588 0% {
2589 opacity: 0;
2590 -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
2591 transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
2592 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2593 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2594 }
2595
2596 60% {
2597 opacity: 1;
2598 -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
2599 transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
2600 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2601 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2602 }
2603 }
2604
2605 .zoomInDown {
2606 -webkit-animation-name: zoomInDown;
2607 animation-name: zoomInDown;
2608 }
2609
2610 @-webkit-keyframes zoomInLeft {
2611 0% {
2612 opacity: 0;
2613 -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
2614 transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
2615 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2616 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2617 }
2618
2619 60% {
2620 opacity: 1;
2621 -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
2622 transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
2623 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2624 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2625 }
2626 }
2627
2628 @keyframes zoomInLeft {
2629 0% {
2630 opacity: 0;
2631 -webkit-transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
2632 transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
2633 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2634 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2635 }
2636
2637 60% {
2638 opacity: 1;
2639 -webkit-transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
2640 transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
2641 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2642 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2643 }
2644 }
2645
2646 .zoomInLeft {
2647 -webkit-animation-name: zoomInLeft;
2648 animation-name: zoomInLeft;
2649 }
2650
2651 @-webkit-keyframes zoomInRight {
2652 0% {
2653 opacity: 0;
2654 -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
2655 transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
2656 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2657 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2658 }
2659
2660 60% {
2661 opacity: 1;
2662 -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
2663 transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
2664 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2665 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2666 }
2667 }
2668
2669 @keyframes zoomInRight {
2670 0% {
2671 opacity: 0;
2672 -webkit-transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
2673 transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
2674 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2675 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2676 }
2677
2678 60% {
2679 opacity: 1;
2680 -webkit-transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
2681 transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
2682 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2683 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2684 }
2685 }
2686
2687 .zoomInRight {
2688 -webkit-animation-name: zoomInRight;
2689 animation-name: zoomInRight;
2690 }
2691
2692 @-webkit-keyframes zoomInUp {
2693 0% {
2694 opacity: 0;
2695 -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
2696 transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
2697 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2698 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2699 }
2700
2701 60% {
2702 opacity: 1;
2703 -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
2704 transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
2705 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2706 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2707 }
2708 }
2709
2710 @keyframes zoomInUp {
2711 0% {
2712 opacity: 0;
2713 -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
2714 transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
2715 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2716 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2717 }
2718
2719 60% {
2720 opacity: 1;
2721 -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
2722 transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
2723 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2724 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2725 }
2726 }
2727
2728 .zoomInUp {
2729 -webkit-animation-name: zoomInUp;
2730 animation-name: zoomInUp;
2731 }
2732
2733 @-webkit-keyframes zoomOut {
2734 0% {
2735 opacity: 1;
2736 }
2737
2738 50% {
2739 opacity: 0;
2740 -webkit-transform: scale3d(.3, .3, .3);
2741 transform: scale3d(.3, .3, .3);
2742 }
2743
2744 100% {
2745 opacity: 0;
2746 }
2747 }
2748
2749 @keyframes zoomOut {
2750 0% {
2751 opacity: 1;
2752 }
2753
2754 50% {
2755 opacity: 0;
2756 -webkit-transform: scale3d(.3, .3, .3);
2757 transform: scale3d(.3, .3, .3);
2758 }
2759
2760 100% {
2761 opacity: 0;
2762 }
2763 }
2764
2765 .zoomOut {
2766 -webkit-animation-name: zoomOut;
2767 animation-name: zoomOut;
2768 }
2769
2770 @-webkit-keyframes zoomOutDown {
2771 40% {
2772 opacity: 1;
2773 -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
2774 transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
2775 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2776 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2777 }
2778
2779 100% {
2780 opacity: 0;
2781 -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
2782 transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
2783 -webkit-transform-origin: center bottom;
2784 transform-origin: center bottom;
2785 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2786 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2787 }
2788 }
2789
2790 @keyframes zoomOutDown {
2791 40% {
2792 opacity: 1;
2793 -webkit-transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
2794 transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
2795 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2796 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2797 }
2798
2799 100% {
2800 opacity: 0;
2801 -webkit-transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
2802 transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
2803 -webkit-transform-origin: center bottom;
2804 transform-origin: center bottom;
2805 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2806 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2807 }
2808 }
2809
2810 .zoomOutDown {
2811 -webkit-animation-name: zoomOutDown;
2812 animation-name: zoomOutDown;
2813 }
2814
2815 @-webkit-keyframes zoomOutLeft {
2816 40% {
2817 opacity: 1;
2818 -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
2819 transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
2820 }
2821
2822 100% {
2823 opacity: 0;
2824 -webkit-transform: scale(.1) translate3d(-2000px, 0, 0);
2825 transform: scale(.1) translate3d(-2000px, 0, 0);
2826 -webkit-transform-origin: left center;
2827 transform-origin: left center;
2828 }
2829 }
2830
2831 @keyframes zoomOutLeft {
2832 40% {
2833 opacity: 1;
2834 -webkit-transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
2835 transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
2836 }
2837
2838 100% {
2839 opacity: 0;
2840 -webkit-transform: scale(.1) translate3d(-2000px, 0, 0);
2841 transform: scale(.1) translate3d(-2000px, 0, 0);
2842 -webkit-transform-origin: left center;
2843 transform-origin: left center;
2844 }
2845 }
2846
2847 .zoomOutLeft {
2848 -webkit-animation-name: zoomOutLeft;
2849 animation-name: zoomOutLeft;
2850 }
2851
2852 @-webkit-keyframes zoomOutRight {
2853 40% {
2854 opacity: 1;
2855 -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
2856 transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
2857 }
2858
2859 100% {
2860 opacity: 0;
2861 -webkit-transform: scale(.1) translate3d(2000px, 0, 0);
2862 transform: scale(.1) translate3d(2000px, 0, 0);
2863 -webkit-transform-origin: right center;
2864 transform-origin: right center;
2865 }
2866 }
2867
2868 @keyframes zoomOutRight {
2869 40% {
2870 opacity: 1;
2871 -webkit-transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
2872 transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
2873 }
2874
2875 100% {
2876 opacity: 0;
2877 -webkit-transform: scale(.1) translate3d(2000px, 0, 0);
2878 transform: scale(.1) translate3d(2000px, 0, 0);
2879 -webkit-transform-origin: right center;
2880 transform-origin: right center;
2881 }
2882 }
2883
2884 .zoomOutRight {
2885 -webkit-animation-name: zoomOutRight;
2886 animation-name: zoomOutRight;
2887 }
2888
2889 @-webkit-keyframes zoomOutUp {
2890 40% {
2891 opacity: 1;
2892 -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
2893 transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
2894 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2895 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2896 }
2897
2898 100% {
2899 opacity: 0;
2900 -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
2901 transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
2902 -webkit-transform-origin: center bottom;
2903 transform-origin: center bottom;
2904 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2905 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2906 }
2907 }
2908
2909 @keyframes zoomOutUp {
2910 40% {
2911 opacity: 1;
2912 -webkit-transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
2913 transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
2914 -webkit-animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2915 animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
2916 }
2917
2918 100% {
2919 opacity: 0;
2920 -webkit-transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
2921 transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
2922 -webkit-transform-origin: center bottom;
2923 transform-origin: center bottom;
2924 -webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2925 animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
2926 }
2927 }
2928
2929 .zoomOutUp {
2930 -webkit-animation-name: zoomOutUp;
2931 animation-name: zoomOutUp;
2932 }
2933
2934 @-webkit-keyframes slideInDown {
2935 0% {
2936 -webkit-transform: translate3d(0, -100%, 0);
2937 transform: translate3d(0, -100%, 0);
2938 visibility: visible;
2939 }
2940
2941 100% {
2942 -webkit-transform: translate3d(0, 0, 0);
2943 transform: translate3d(0, 0, 0);
2944 }
2945 }
2946
2947 @keyframes slideInDown {
2948 0% {
2949 -webkit-transform: translate3d(0, -100%, 0);
2950 transform: translate3d(0, -100%, 0);
2951 visibility: visible;
2952 }
2953
2954 100% {
2955 -webkit-transform: translate3d(0, 0, 0);
2956 transform: translate3d(0, 0, 0);
2957 }
2958 }
2959
2960 .slideInDown {
2961 -webkit-animation-name: slideInDown;
2962 animation-name: slideInDown;
2963 }
2964
2965 @-webkit-keyframes slideInLeft {
2966 0% {
2967 -webkit-transform: translate3d(-100%, 0, 0);
2968 transform: translate3d(-100%, 0, 0);
2969 visibility: visible;
2970 }
2971
2972 100% {
2973 -webkit-transform: translate3d(0, 0, 0);
2974 transform: translate3d(0, 0, 0);
2975 }
2976 }
2977
2978 @keyframes slideInLeft {
2979 0% {
2980 -webkit-transform: translate3d(-100%, 0, 0);
2981 transform: translate3d(-100%, 0, 0);
2982 visibility: visible;
2983 }
2984
2985 100% {
2986 -webkit-transform: translate3d(0, 0, 0);
2987 transform: translate3d(0, 0, 0);
2988 }
2989 }
2990
2991 .slideInLeft {
2992 -webkit-animation-name: slideInLeft;
2993 animation-name: slideInLeft;
2994 }
2995
2996 @-webkit-keyframes slideInRight {
2997 0% {
2998 -webkit-transform: translate3d(100%, 0, 0);
2999 transform: translate3d(100%, 0, 0);
3000 visibility: visible;
3001 }
3002
3003 100% {
3004 -webkit-transform: translate3d(0, 0, 0);
3005 transform: translate3d(0, 0, 0);
3006 }
3007 }
3008
3009 @keyframes slideInRight {
3010 0% {
3011 -webkit-transform: translate3d(100%, 0, 0);
3012 transform: translate3d(100%, 0, 0);
3013 visibility: visible;
3014 }
3015
3016 100% {
3017 -webkit-transform: translate3d(0, 0, 0);
3018 transform: translate3d(0, 0, 0);
3019 }
3020 }
3021
3022 .slideInRight {
3023 -webkit-animation-name: slideInRight;
3024 animation-name: slideInRight;
3025 }
3026
3027 @-webkit-keyframes slideInUp {
3028 0% {
3029 -webkit-transform: translate3d(0, 100%, 0);
3030 transform: translate3d(0, 100%, 0);
3031 visibility: visible;
3032 }
3033
3034 100% {
3035 -webkit-transform: translate3d(0, 0, 0);
3036 transform: translate3d(0, 0, 0);
3037 }
3038 }
3039
3040 @keyframes slideInUp {
3041 0% {
3042 -webkit-transform: translate3d(0, 100%, 0);
3043 transform: translate3d(0, 100%, 0);
3044 visibility: visible;
3045 }
3046
3047 100% {
3048 -webkit-transform: translate3d(0, 0, 0);
3049 transform: translate3d(0, 0, 0);
3050 }
3051 }
3052
3053 .slideInUp {
3054 -webkit-animation-name: slideInUp;
3055 animation-name: slideInUp;
3056 }
3057
3058 @-webkit-keyframes slideOutDown {
3059 0% {
3060 -webkit-transform: translate3d(0, 0, 0);
3061 transform: translate3d(0, 0, 0);
3062 }
3063
3064 100% {
3065 visibility: hidden;
3066 -webkit-transform: translate3d(0, 100%, 0);
3067 transform: translate3d(0, 100%, 0);
3068 }
3069 }
3070
3071 @keyframes slideOutDown {
3072 0% {
3073 -webkit-transform: translate3d(0, 0, 0);
3074 transform: translate3d(0, 0, 0);
3075 }
3076
3077 100% {
3078 visibility: hidden;
3079 -webkit-transform: translate3d(0, 100%, 0);
3080 transform: translate3d(0, 100%, 0);
3081 }
3082 }
3083
3084 .slideOutDown {
3085 -webkit-animation-name: slideOutDown;
3086 animation-name: slideOutDown;
3087 }
3088
3089 @-webkit-keyframes slideOutLeft {
3090 0% {
3091 -webkit-transform: translate3d(0, 0, 0);
3092 transform: translate3d(0, 0, 0);
3093 }
3094
3095 100% {
3096 visibility: hidden;
3097 -webkit-transform: translate3d(-100%, 0, 0);
3098 transform: translate3d(-100%, 0, 0);
3099 }
3100 }
3101
3102 @keyframes slideOutLeft {
3103 0% {
3104 -webkit-transform: translate3d(0, 0, 0);
3105 transform: translate3d(0, 0, 0);
3106 }
3107
3108 100% {
3109 visibility: hidden;
3110 -webkit-transform: translate3d(-100%, 0, 0);
3111 transform: translate3d(-100%, 0, 0);
3112 }
3113 }
3114
3115 .slideOutLeft {
3116 -webkit-animation-name: slideOutLeft;
3117 animation-name: slideOutLeft;
3118 }
3119
3120 @-webkit-keyframes slideOutRight {
3121 0% {
3122 -webkit-transform: translate3d(0, 0, 0);
3123 transform: translate3d(0, 0, 0);
3124 }
3125
3126 100% {
3127 visibility: hidden;
3128 -webkit-transform: translate3d(100%, 0, 0);
3129 transform: translate3d(100%, 0, 0);
3130 }
3131 }
3132
3133 @keyframes slideOutRight {
3134 0% {
3135 -webkit-transform: translate3d(0, 0, 0);
3136 transform: translate3d(0, 0, 0);
3137 }
3138
3139 100% {
3140 visibility: hidden;
3141 -webkit-transform: translate3d(100%, 0, 0);
3142 transform: translate3d(100%, 0, 0);
3143 }
3144 }
3145
3146 .slideOutRight {
3147 -webkit-animation-name: slideOutRight;
3148 animation-name: slideOutRight;
3149 }
3150
3151 @-webkit-keyframes slideOutUp {
3152 0% {
3153 -webkit-transform: translate3d(0, 0, 0);
3154 transform: translate3d(0, 0, 0);
3155 }
3156
3157 100% {
3158 visibility: hidden;
3159 -webkit-transform: translate3d(0, -100%, 0);
3160 transform: translate3d(0, -100%, 0);
3161 }
3162 }
3163
3164 @keyframes slideOutUp {
3165 0% {
3166 -webkit-transform: translate3d(0, 0, 0);
3167 transform: translate3d(0, 0, 0);
3168 }
3169
3170 100% {
3171 visibility: hidden;
3172 -webkit-transform: translate3d(0, -100%, 0);
3173 transform: translate3d(0, -100%, 0);
3174 }
3175 }
3176
3177 .slideOutUp {
3178 -webkit-animation-name: slideOutUp;
3179 animation-name: slideOutUp;
3180 }
+0
-263
faraday/server/www/script/bootstrap-glyphicons.css less more
0 /*!
1 * Bootstrap v3.0.0
2 *
3 * Copyright 2013 Twitter, Inc
4 * Licensed under the Apache License v2.0
5 * http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Designed and built with all the love in the world @twitter by @mdo and @fat.
8 */
9
10
11 article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}
12 audio,canvas,video{display:inline-block;}
13 audio:not([controls]){display:none;height:0;}
14 [hidden]{display:none;}
15 html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
16 body{margin:0;}
17 a:focus{outline:thin dotted;}
18 a:active,a:hover{outline:0;}
19 h1{font-size:2em;margin:0.67em 0;}
20 abbr[title]{border-bottom:1px dotted;}
21 b,strong{font-weight:bold;}
22 dfn{font-style:italic;}
23 hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}
24 mark{background:#ff0;color:#000;}
25 code,kbd,pre,samp{font-family:monospace, serif;font-size:1em;}
26 pre{white-space:pre-wrap;}
27 q{quotes:"\201C" "\201D" "\2018" "\2019";}
28 small{font-size:80%;}
29 sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}
30 sup{top:-0.5em;}
31 sub{bottom:-0.25em;}
32 img{border:0;}
33 svg:not(:root){overflow:hidden;}
34 figure{margin:0;}
35 fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}
36 legend{border:0;padding:0;}
37 button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}
38 button,input{line-height:normal;}
39 button,select{text-transform:none;}
40 button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}
41 button[disabled],html input[disabled]{cursor:default;}
42 input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}
43 input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}
44 input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}
45 button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
46 textarea{overflow:auto;vertical-align:top;}
47 table{border-collapse:collapse;border-spacing:0;}
48 *,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
49 html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);}
50 body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333333;background-color:#ffffff;}
51 input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;}
52 button,input,select[multiple],textarea{background-image:none;}
53 a{color:#428bca;text-decoration:none;}a:hover,a:focus{color:#2a6496;text-decoration:underline;}
54 a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
55 img{vertical-align:middle;}
56 .img-responsive{display:block;max-width:100%;height:auto;}
57 .img-rounded{border-radius:6px;}
58 .img-thumbnail{padding:4px;line-height:1.428571429;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;display:inline-block;max-width:100%;height:auto;}
59 .img-circle{border-radius:50%;}
60 hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee;}
61 .sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);border:0;}
62 @font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;}
63 .glyphicon-asterisk:before{content:"\2a";}
64 .glyphicon-plus:before{content:"\2b";}
65 .glyphicon-euro:before{content:"\20ac";}
66 .glyphicon-minus:before{content:"\2212";}
67 .glyphicon-cloud:before{content:"\2601";}
68 .glyphicon-envelope:before{content:"\2709";}
69 .glyphicon-pencil:before{content:"\270f";}
70 .glyphicon-glass:before{content:"\e001";}
71 .glyphicon-music:before{content:"\e002";}
72 .glyphicon-search:before{content:"\e003";}
73 .glyphicon-heart:before{content:"\e005";}
74 .glyphicon-star:before{content:"\e006";}
75 .glyphicon-star-empty:before{content:"\e007";}
76 .glyphicon-user:before{content:"\e008";}
77 .glyphicon-film:before{content:"\e009";}
78 .glyphicon-th-large:before{content:"\e010";}
79 .glyphicon-th:before{content:"\e011";}
80 .glyphicon-th-list:before{content:"\e012";}
81 .glyphicon-ok:before{content:"\e013";}
82 .glyphicon-remove:before{content:"\e014";}
83 .glyphicon-zoom-in:before{content:"\e015";}
84 .glyphicon-zoom-out:before{content:"\e016";}
85 .glyphicon-off:before{content:"\e017";}
86 .glyphicon-signal:before{content:"\e018";}
87 .glyphicon-cog:before{content:"\e019";}
88 .glyphicon-trash:before{content:"\e020";}
89 .glyphicon-home:before{content:"\e021";}
90 .glyphicon-file:before{content:"\e022";}
91 .glyphicon-time:before{content:"\e023";}
92 .glyphicon-road:before{content:"\e024";}
93 .glyphicon-download-alt:before{content:"\e025";}
94 .glyphicon-download:before{content:"\e026";}
95 .glyphicon-upload:before{content:"\e027";}
96 .glyphicon-inbox:before{content:"\e028";}
97 .glyphicon-play-circle:before{content:"\e029";}
98 .glyphicon-repeat:before{content:"\e030";}
99 .glyphicon-refresh:before{content:"\e031";}
100 .glyphicon-list-alt:before{content:"\e032";}
101 .glyphicon-flag:before{content:"\e034";}
102 .glyphicon-headphones:before{content:"\e035";}
103 .glyphicon-volume-off:before{content:"\e036";}
104 .glyphicon-volume-down:before{content:"\e037";}
105 .glyphicon-volume-up:before{content:"\e038";}
106 .glyphicon-qrcode:before{content:"\e039";}
107 .glyphicon-barcode:before{content:"\e040";}
108 .glyphicon-tag:before{content:"\e041";}
109 .glyphicon-tags:before{content:"\e042";}
110 .glyphicon-book:before{content:"\e043";}
111 .glyphicon-print:before{content:"\e045";}
112 .glyphicon-font:before{content:"\e047";}
113 .glyphicon-bold:before{content:"\e048";}
114 .glyphicon-italic:before{content:"\e049";}
115 .glyphicon-text-height:before{content:"\e050";}
116 .glyphicon-text-width:before{content:"\e051";}
117 .glyphicon-align-left:before{content:"\e052";}
118 .glyphicon-align-center:before{content:"\e053";}
119 .glyphicon-align-right:before{content:"\e054";}
120 .glyphicon-align-justify:before{content:"\e055";}
121 .glyphicon-list:before{content:"\e056";}
122 .glyphicon-indent-left:before{content:"\e057";}
123 .glyphicon-indent-right:before{content:"\e058";}
124 .glyphicon-facetime-video:before{content:"\e059";}
125 .glyphicon-picture:before{content:"\e060";}
126 .glyphicon-map-marker:before{content:"\e062";}
127 .glyphicon-adjust:before{content:"\e063";}
128 .glyphicon-tint:before{content:"\e064";}
129 .glyphicon-edit:before{content:"\e065";}
130 .glyphicon-share:before{content:"\e066";}
131 .glyphicon-check:before{content:"\e067";}
132 .glyphicon-move:before{content:"\e068";}
133 .glyphicon-step-backward:before{content:"\e069";}
134 .glyphicon-fast-backward:before{content:"\e070";}
135 .glyphicon-backward:before{content:"\e071";}
136 .glyphicon-play:before{content:"\e072";}
137 .glyphicon-pause:before{content:"\e073";}
138 .glyphicon-stop:before{content:"\e074";}
139 .glyphicon-forward:before{content:"\e075";}
140 .glyphicon-fast-forward:before{content:"\e076";}
141 .glyphicon-step-forward:before{content:"\e077";}
142 .glyphicon-eject:before{content:"\e078";}
143 .glyphicon-chevron-left:before{content:"\e079";}
144 .glyphicon-chevron-right:before{content:"\e080";}
145 .glyphicon-plus-sign:before{content:"\e081";}
146 .glyphicon-minus-sign:before{content:"\e082";}
147 .glyphicon-remove-sign:before{content:"\e083";}
148 .glyphicon-ok-sign:before{content:"\e084";}
149 .glyphicon-question-sign:before{content:"\e085";}
150 .glyphicon-info-sign:before{content:"\e086";}
151 .glyphicon-screenshot:before{content:"\e087";}
152 .glyphicon-remove-circle:before{content:"\e088";}
153 .glyphicon-ok-circle:before{content:"\e089";}
154 .glyphicon-ban-circle:before{content:"\e090";}
155 .glyphicon-arrow-left:before{content:"\e091";}
156 .glyphicon-arrow-right:before{content:"\e092";}
157 .glyphicon-arrow-up:before{content:"\e093";}
158 .glyphicon-arrow-down:before{content:"\e094";}
159 .glyphicon-share-alt:before{content:"\e095";}
160 .glyphicon-resize-full:before{content:"\e096";}
161 .glyphicon-resize-small:before{content:"\e097";}
162 .glyphicon-exclamation-sign:before{content:"\e101";}
163 .glyphicon-gift:before{content:"\e102";}
164 .glyphicon-leaf:before{content:"\e103";}
165 .glyphicon-eye-open:before{content:"\e105";}
166 .glyphicon-eye-close:before{content:"\e106";}
167 .glyphicon-warning-sign:before{content:"\e107";}
168 .glyphicon-plane:before{content:"\e108";}
169 .glyphicon-random:before{content:"\e110";}
170 .glyphicon-comment:before{content:"\e111";}
171 .glyphicon-magnet:before{content:"\e112";}
172 .glyphicon-chevron-up:before{content:"\e113";}
173 .glyphicon-chevron-down:before{content:"\e114";}
174 .glyphicon-retweet:before{content:"\e115";}
175 .glyphicon-shopping-cart:before{content:"\e116";}
176 .glyphicon-folder-close:before{content:"\e117";}
177 .glyphicon-folder-open:before{content:"\e118";}
178 .glyphicon-resize-vertical:before{content:"\e119";}
179 .glyphicon-resize-horizontal:before{content:"\e120";}
180 .glyphicon-hdd:before{content:"\e121";}
181 .glyphicon-bullhorn:before{content:"\e122";}
182 .glyphicon-certificate:before{content:"\e124";}
183 .glyphicon-thumbs-up:before{content:"\e125";}
184 .glyphicon-thumbs-down:before{content:"\e126";}
185 .glyphicon-hand-right:before{content:"\e127";}
186 .glyphicon-hand-left:before{content:"\e128";}
187 .glyphicon-hand-up:before{content:"\e129";}
188 .glyphicon-hand-down:before{content:"\e130";}
189 .glyphicon-circle-arrow-right:before{content:"\e131";}
190 .glyphicon-circle-arrow-left:before{content:"\e132";}
191 .glyphicon-circle-arrow-up:before{content:"\e133";}
192 .glyphicon-circle-arrow-down:before{content:"\e134";}
193 .glyphicon-globe:before{content:"\e135";}
194 .glyphicon-tasks:before{content:"\e137";}
195 .glyphicon-filter:before{content:"\e138";}
196 .glyphicon-fullscreen:before{content:"\e140";}
197 .glyphicon-dashboard:before{content:"\e141";}
198 .glyphicon-heart-empty:before{content:"\e143";}
199 .glyphicon-link:before{content:"\e144";}
200 .glyphicon-phone:before{content:"\e145";}
201 .glyphicon-usd:before{content:"\e148";}
202 .glyphicon-gbp:before{content:"\e149";}
203 .glyphicon-sort:before{content:"\e150";}
204 .glyphicon-sort-by-alphabet:before{content:"\e151";}
205 .glyphicon-sort-by-alphabet-alt:before{content:"\e152";}
206 .glyphicon-sort-by-order:before{content:"\e153";}
207 .glyphicon-sort-by-order-alt:before{content:"\e154";}
208 .glyphicon-sort-by-attributes:before{content:"\e155";}
209 .glyphicon-sort-by-attributes-alt:before{content:"\e156";}
210 .glyphicon-unchecked:before{content:"\e157";}
211 .glyphicon-expand:before{content:"\e158";}
212 .glyphicon-collapse-down:before{content:"\e159";}
213 .glyphicon-collapse-up:before{content:"\e160";}
214 .glyphicon-log-in:before{content:"\e161";}
215 .glyphicon-flash:before{content:"\e162";}
216 .glyphicon-log-out:before{content:"\e163";}
217 .glyphicon-new-window:before{content:"\e164";}
218 .glyphicon-record:before{content:"\e165";}
219 .glyphicon-save:before{content:"\e166";}
220 .glyphicon-open:before{content:"\e167";}
221 .glyphicon-saved:before{content:"\e168";}
222 .glyphicon-import:before{content:"\e169";}
223 .glyphicon-export:before{content:"\e170";}
224 .glyphicon-send:before{content:"\e171";}
225 .glyphicon-floppy-disk:before{content:"\e172";}
226 .glyphicon-floppy-saved:before{content:"\e173";}
227 .glyphicon-floppy-remove:before{content:"\e174";}
228 .glyphicon-floppy-save:before{content:"\e175";}
229 .glyphicon-floppy-open:before{content:"\e176";}
230 .glyphicon-credit-card:before{content:"\e177";}
231 .glyphicon-transfer:before{content:"\e178";}
232 .glyphicon-cutlery:before{content:"\e179";}
233 .glyphicon-header:before{content:"\e180";}
234 .glyphicon-compressed:before{content:"\e181";}
235 .glyphicon-earphone:before{content:"\e182";}
236 .glyphicon-phone-alt:before{content:"\e183";}
237 .glyphicon-tower:before{content:"\e184";}
238 .glyphicon-stats:before{content:"\e185";}
239 .glyphicon-sd-video:before{content:"\e186";}
240 .glyphicon-hd-video:before{content:"\e187";}
241 .glyphicon-subtitles:before{content:"\e188";}
242 .glyphicon-sound-stereo:before{content:"\e189";}
243 .glyphicon-sound-dolby:before{content:"\e190";}
244 .glyphicon-sound-5-1:before{content:"\e191";}
245 .glyphicon-sound-6-1:before{content:"\e192";}
246 .glyphicon-sound-7-1:before{content:"\e193";}
247 .glyphicon-copyright-mark:before{content:"\e194";}
248 .glyphicon-registration-mark:before{content:"\e195";}
249 .glyphicon-cloud-download:before{content:"\e197";}
250 .glyphicon-cloud-upload:before{content:"\e198";}
251 .glyphicon-tree-conifer:before{content:"\e199";}
252 .glyphicon-tree-deciduous:before{content:"\e200";}
253 .glyphicon-briefcase:before{content:"\1f4bc";}
254 .glyphicon-calendar:before{content:"\1f4c5";}
255 .glyphicon-pushpin:before{content:"\1f4cc";}
256 .glyphicon-paperclip:before{content:"\1f4ce";}
257 .glyphicon-camera:before{content:"\1f4f7";}
258 .glyphicon-lock:before{content:"\1f512";}
259 .glyphicon-bell:before{content:"\1f514";}
260 .glyphicon-bookmark:before{content:"\1f516";}
261 .glyphicon-fire:before{content:"\1f525";}
262 .glyphicon-wrench:before{content:"\1f527";}
+0
-6
faraday/server/www/script/bootstrap-theme.min.css less more
0 /*!
1 * Bootstrap v3.4.0 (https://getbootstrap.com/)
2 * Copyright 2011-2018 Twitter, Inc.
3 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
4 */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x;background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x;background-color:#2e6da4}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
5 /*# sourceMappingURL=bootstrap-theme.min.css.map */
+0
-6
faraday/server/www/script/bootstrap.min.css less more
0 /*!
1 * Bootstrap v3.4.0 (https://getbootstrap.com/)
2 * Copyright 2011-2018 Twitter, Inc.
3 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
4 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:"Glyphicons Halflings";src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format("embedded-opentype"),url(../fonts/glyphicons-halflings-regular.woff2) format("woff2"),url(../fonts/glyphicons-halflings-regular.woff) format("woff"),url(../fonts/glyphicons-halflings-regular.ttf) format("truetype"),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:"Glyphicons Halflings";font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:"\2014 \00A0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:""}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:"\00A0 \2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*=col-]{padding-right:0;padding-left:0}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-right:15px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-right:-15px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:12px;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;outline:0;filter:alpha(opacity=90);opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
5 /*# sourceMappingURL=bootstrap.min.css.map */
+0
-6
faraday/server/www/script/bootstrap.min.js less more
0 /*!
1 * Bootstrap v3.4.0 (https://getbootstrap.com/)
2 * Copyright 2011-2018 Twitter, Inc.
3 * Licensed under the MIT license
4 */
5 if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");!function(t){"use strict";var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||3<e[0])throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(),function(n){"use strict";n.fn.emulateTransitionEnd=function(t){var e=!1,i=this;n(this).one("bsTransitionEnd",function(){e=!0});return setTimeout(function(){e||n(i).trigger(n.support.transition.end)},t),this},n(function(){n.support.transition=function o(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in e)if(t.style[i]!==undefined)return{end:e[i]};return!1}(),n.support.transition&&(n.event.special.bsTransitionEnd={bindType:n.support.transition.end,delegateType:n.support.transition.end,handle:function(t){if(n(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}})})}(jQuery),function(s){"use strict";var e='[data-dismiss="alert"]',a=function(t){s(t).on("click",e,this.close)};a.VERSION="3.4.0",a.TRANSITION_DURATION=150,a.prototype.close=function(t){var e=s(this),i=e.attr("data-target");i||(i=(i=e.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),i="#"===i?[]:i;var o=s(document).find(i);function n(){o.detach().trigger("closed.bs.alert").remove()}t&&t.preventDefault(),o.length||(o=e.closest(".alert")),o.trigger(t=s.Event("close.bs.alert")),t.isDefaultPrevented()||(o.removeClass("in"),s.support.transition&&o.hasClass("fade")?o.one("bsTransitionEnd",n).emulateTransitionEnd(a.TRANSITION_DURATION):n())};var t=s.fn.alert;s.fn.alert=function o(i){return this.each(function(){var t=s(this),e=t.data("bs.alert");e||t.data("bs.alert",e=new a(this)),"string"==typeof i&&e[i].call(t)})},s.fn.alert.Constructor=a,s.fn.alert.noConflict=function(){return s.fn.alert=t,this},s(document).on("click.bs.alert.data-api",e,a.prototype.close)}(jQuery),function(s){"use strict";var n=function(t,e){this.$element=s(t),this.options=s.extend({},n.DEFAULTS,e),this.isLoading=!1};function i(o){return this.each(function(){var t=s(this),e=t.data("bs.button"),i="object"==typeof o&&o;e||t.data("bs.button",e=new n(this,i)),"toggle"==o?e.toggle():o&&e.setState(o)})}n.VERSION="3.4.0",n.DEFAULTS={loadingText:"loading..."},n.prototype.setState=function(t){var e="disabled",i=this.$element,o=i.is("input")?"val":"html",n=i.data();t+="Text",null==n.resetText&&i.data("resetText",i[o]()),setTimeout(s.proxy(function(){i[o](null==n[t]?this.options[t]:n[t]),"loadingText"==t?(this.isLoading=!0,i.addClass(e).attr(e,e).prop(e,!0)):this.isLoading&&(this.isLoading=!1,i.removeClass(e).removeAttr(e).prop(e,!1))},this),0)},n.prototype.toggle=function(){var t=!0,e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var i=this.$element.find("input");"radio"==i.prop("type")?(i.prop("checked")&&(t=!1),e.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==i.prop("type")&&(i.prop("checked")!==this.$element.hasClass("active")&&(t=!1),this.$element.toggleClass("active")),i.prop("checked",this.$element.hasClass("active")),t&&i.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var t=s.fn.button;s.fn.button=i,s.fn.button.Constructor=n,s.fn.button.noConflict=function(){return s.fn.button=t,this},s(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(t){var e=s(t.target).closest(".btn");i.call(e,"toggle"),s(t.target).is('input[type="radio"], input[type="checkbox"]')||(t.preventDefault(),e.is("input,button")?e.trigger("focus"):e.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(t){s(t.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(t.type))})}(jQuery),function(p){"use strict";var c=function(t,e){this.$element=p(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=e,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",p.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",p.proxy(this.pause,this)).on("mouseleave.bs.carousel",p.proxy(this.cycle,this))};function r(n){return this.each(function(){var t=p(this),e=t.data("bs.carousel"),i=p.extend({},c.DEFAULTS,t.data(),"object"==typeof n&&n),o="string"==typeof n?n:i.slide;e||t.data("bs.carousel",e=new c(this,i)),"number"==typeof n?e.to(n):o?e[o]():i.interval&&e.pause().cycle()})}c.VERSION="3.4.0",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(t){if(!/input|textarea/i.test(t.target.tagName)){switch(t.which){case 37:this.prev();break;case 39:this.next();break;default:return}t.preventDefault()}},c.prototype.cycle=function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(p.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(t){return this.$items=t.parent().children(".item"),this.$items.index(t||this.$active)},c.prototype.getItemForDirection=function(t,e){var i=this.getItemIndex(e);if(("prev"==t&&0===i||"next"==t&&i==this.$items.length-1)&&!this.options.wrap)return e;var o=(i+("prev"==t?-1:1))%this.$items.length;return this.$items.eq(o)},c.prototype.to=function(t){var e=this,i=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(t>this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(i<t?"next":"prev",this.$items.eq(t))},c.prototype.pause=function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&p.support.transition&&(this.$element.trigger(p.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(t,e){var i=this.$element.find(".item.active"),o=e||this.getItemForDirection(t,i),n=this.interval,s="next"==t?"left":"right",a=this;if(o.hasClass("active"))return this.sliding=!1;var r=o[0],l=p.Event("slide.bs.carousel",{relatedTarget:r,direction:s});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,n&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=p(this.$indicators.children()[this.getItemIndex(o)]);h&&h.addClass("active")}var d=p.Event("slid.bs.carousel",{relatedTarget:r,direction:s});return p.support.transition&&this.$element.hasClass("slide")?(o.addClass(t),"object"==typeof o&&o.length&&o[0].offsetWidth,i.addClass(s),o.addClass(s),i.one("bsTransitionEnd",function(){o.removeClass([t,s].join(" ")).addClass("active"),i.removeClass(["active",s].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger(d)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(i.removeClass("active"),o.addClass("active"),this.sliding=!1,this.$element.trigger(d)),n&&this.cycle(),this}};var t=p.fn.carousel;p.fn.carousel=r,p.fn.carousel.Constructor=c,p.fn.carousel.noConflict=function(){return p.fn.carousel=t,this};var e=function(t){var e=p(this),i=e.attr("href");i&&(i=i.replace(/.*(?=#[^\s]+$)/,""));var o=e.attr("data-target")||i,n=p(document).find(o);if(n.hasClass("carousel")){var s=p.extend({},n.data(),e.data()),a=e.attr("data-slide-to");a&&(s.interval=!1),r.call(n,s),a&&n.data("bs.carousel").to(a),t.preventDefault()}};p(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),p(window).on("load",function(){p('[data-ride="carousel"]').each(function(){var t=p(this);r.call(t,t.data())})})}(jQuery),function(a){"use strict";var r=function(t,e){this.$element=a(t),this.options=a.extend({},r.DEFAULTS,e),this.$trigger=a('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};function n(t){var e,i=t.attr("data-target")||(e=t.attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"");return a(document).find(i)}function l(o){return this.each(function(){var t=a(this),e=t.data("bs.collapse"),i=a.extend({},r.DEFAULTS,t.data(),"object"==typeof o&&o);!e&&i.toggle&&/show|hide/.test(o)&&(i.toggle=!1),e||t.data("bs.collapse",e=new r(this,i)),"string"==typeof o&&e[o]()})}r.VERSION="3.4.0",r.TRANSITION_DURATION=350,r.DEFAULTS={toggle:!0},r.prototype.dimension=function(){return this.$element.hasClass("width")?"width":"height"},r.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var t,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(t=e.data("bs.collapse"))&&t.transitioning)){var i=a.Event("show.bs.collapse");if(this.$element.trigger(i),!i.isDefaultPrevented()){e&&e.length&&(l.call(e,"hide"),t||e.data("bs.collapse",null));var o=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[o](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var n=function(){this.$element.removeClass("collapsing").addClass("collapse in")[o](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return n.call(this);var s=a.camelCase(["scroll",o].join("-"));this.$element.one("bsTransitionEnd",a.proxy(n,this)).emulateTransitionEnd(r.TRANSITION_DURATION)[o](this.$element[0][s])}}}},r.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var t=a.Event("hide.bs.collapse");if(this.$element.trigger(t),!t.isDefaultPrevented()){var e=this.dimension();this.$element[e](this.$element[e]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var i=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};if(!a.support.transition)return i.call(this);this.$element[e](0).one("bsTransitionEnd",a.proxy(i,this)).emulateTransitionEnd(r.TRANSITION_DURATION)}}},r.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},r.prototype.getParent=function(){return a(document).find(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(t,e){var i=a(e);this.addAriaAndCollapsedClass(n(i),i)},this)).end()},r.prototype.addAriaAndCollapsedClass=function(t,e){var i=t.hasClass("in");t.attr("aria-expanded",i),e.toggleClass("collapsed",!i).attr("aria-expanded",i)};var t=a.fn.collapse;a.fn.collapse=l,a.fn.collapse.Constructor=r,a.fn.collapse.noConflict=function(){return a.fn.collapse=t,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(t){var e=a(this);e.attr("data-target")||t.preventDefault();var i=n(e),o=i.data("bs.collapse")?"toggle":e.data();l.call(i,o)})}(jQuery),function(a){"use strict";var r='[data-toggle="dropdown"]',o=function(t){a(t).on("click.bs.dropdown",this.toggle)};function l(t){var e=t.attr("data-target");e||(e=(e=t.attr("href"))&&/#[A-Za-z]/.test(e)&&e.replace(/.*(?=#[^\s]*$)/,""));var i=e&&a(document).find(e);return i&&i.length?i:t.parent()}function s(o){o&&3===o.which||(a(".dropdown-backdrop").remove(),a(r).each(function(){var t=a(this),e=l(t),i={relatedTarget:this};e.hasClass("open")&&(o&&"click"==o.type&&/input|textarea/i.test(o.target.tagName)&&a.contains(e[0],o.target)||(e.trigger(o=a.Event("hide.bs.dropdown",i)),o.isDefaultPrevented()||(t.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",i)))))}))}o.VERSION="3.4.0",o.prototype.toggle=function(t){var e=a(this);if(!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(s(),!o){"ontouchstart"in document.documentElement&&!i.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",s);var n={relatedTarget:this};if(i.trigger(t=a.Event("show.bs.dropdown",n)),t.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),i.toggleClass("open").trigger(a.Event("shown.bs.dropdown",n))}return!1}},o.prototype.keydown=function(t){if(/(38|40|27|32)/.test(t.which)&&!/input|textarea/i.test(t.target.tagName)){var e=a(this);if(t.preventDefault(),t.stopPropagation(),!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(!o&&27!=t.which||o&&27==t.which)return 27==t.which&&i.find(r).trigger("focus"),e.trigger("click");var n=i.find(".dropdown-menu li:not(.disabled):visible a");if(n.length){var s=n.index(t.target);38==t.which&&0<s&&s--,40==t.which&&s<n.length-1&&s++,~s||(s=0),n.eq(s).trigger("focus")}}}};var t=a.fn.dropdown;a.fn.dropdown=function e(i){return this.each(function(){var t=a(this),e=t.data("bs.dropdown");e||t.data("bs.dropdown",e=new o(this)),"string"==typeof i&&e[i].call(t)})},a.fn.dropdown.Constructor=o,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=t,this},a(document).on("click.bs.dropdown.data-api",s).on("click.bs.dropdown.data-api",".dropdown form",function(t){t.stopPropagation()}).on("click.bs.dropdown.data-api",r,o.prototype.toggle).on("keydown.bs.dropdown.data-api",r,o.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",o.prototype.keydown)}(jQuery),function(a){"use strict";var s=function(t,e){this.options=e,this.$body=a(document.body),this.$element=a(t),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.fixedContent=".navbar-fixed-top, .navbar-fixed-bottom",this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};function r(o,n){return this.each(function(){var t=a(this),e=t.data("bs.modal"),i=a.extend({},s.DEFAULTS,t.data(),"object"==typeof o&&o);e||t.data("bs.modal",e=new s(this,i)),"string"==typeof o?e[o](n):i.show&&e.show(n)})}s.VERSION="3.4.0",s.TRANSITION_DURATION=300,s.BACKDROP_TRANSITION_DURATION=150,s.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},s.prototype.toggle=function(t){return this.isShown?this.hide():this.show(t)},s.prototype.show=function(i){var o=this,t=a.Event("show.bs.modal",{relatedTarget:i});this.$element.trigger(t),this.isShown||t.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){o.$element.one("mouseup.dismiss.bs.modal",function(t){a(t.target).is(o.$element)&&(o.ignoreBackdropClick=!0)})}),this.backdrop(function(){var t=a.support.transition&&o.$element.hasClass("fade");o.$element.parent().length||o.$element.appendTo(o.$body),o.$element.show().scrollTop(0),o.adjustDialog(),t&&o.$element[0].offsetWidth,o.$element.addClass("in"),o.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:i});t?o.$dialog.one("bsTransitionEnd",function(){o.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(s.TRANSITION_DURATION):o.$element.trigger("focus").trigger(e)}))},s.prototype.hide=function(t){t&&t.preventDefault(),t=a.Event("hide.bs.modal"),this.$element.trigger(t),this.isShown&&!t.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(s.TRANSITION_DURATION):this.hideModal())},s.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(t){document===t.target||this.$element[0]===t.target||this.$element.has(t.target).length||this.$element.trigger("focus")},this))},s.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(t){27==t.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},s.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},s.prototype.hideModal=function(){var t=this;this.$element.hide(),this.backdrop(function(){t.$body.removeClass("modal-open"),t.resetAdjustments(),t.resetScrollbar(),t.$element.trigger("hidden.bs.modal")})},s.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},s.prototype.backdrop=function(t){var e=this,i=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var o=a.support.transition&&i;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+i).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(t){this.ignoreBackdropClick?this.ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide())},this)),o&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!t)return;o?this.$backdrop.one("bsTransitionEnd",t).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):t()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var n=function(){e.removeBackdrop(),t&&t()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",n).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):n()}else t&&t()},s.prototype.handleUpdate=function(){this.adjustDialog()},s.prototype.adjustDialog=function(){var t=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth<t,this.scrollbarWidth=this.measureScrollbar()},s.prototype.setScrollbar=function(){var t=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"";var n=this.scrollbarWidth;this.bodyIsOverflowing&&(this.$body.css("padding-right",t+n),a(this.fixedContent).each(function(t,e){var i=e.style.paddingRight,o=a(e).css("padding-right");a(e).data("padding-right",i).css("padding-right",parseFloat(o)+n+"px")}))},s.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad),a(this.fixedContent).each(function(t,e){var i=a(e).data("padding-right");a(e).removeData("padding-right"),e.style.paddingRight=i||""})},s.prototype.measureScrollbar=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",this.$body.append(t);var e=t.offsetWidth-t.clientWidth;return this.$body[0].removeChild(t),e};var t=a.fn.modal;a.fn.modal=r,a.fn.modal.Constructor=s,a.fn.modal.noConflict=function(){return a.fn.modal=t,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(t){var e=a(this),i=e.attr("href"),o=e.attr("data-target")||i&&i.replace(/.*(?=#[^\s]+$)/,""),n=a(document).find(o),s=n.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(i)&&i},n.data(),e.data());e.is("a")&&t.preventDefault(),n.one("show.bs.modal",function(t){t.isDefaultPrevented()||n.one("hidden.bs.modal",function(){e.is(":visible")&&e.trigger("focus")})}),r.call(n,s,this)})}(jQuery),function(g){"use strict";var m=function(t,e){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",t,e)};m.VERSION="3.4.0",m.TRANSITION_DURATION=150,m.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){return(t=g.extend({},this.getDefaults(),this.$element.data(),t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-d<c.top?"bottom":"right"==s&&l.right+h>c.width?"left":"left"==s&&l.left-h<c.left?"right":s,o.removeClass(p).addClass(s)}var f=this.getCalculatedOffset(s,l,h,d);this.applyPlacement(f,s);var u=function(){var t=i.hoverState;i.$element.trigger("shown.bs."+i.type),i.hoverState=null,"out"==t&&i.leave(i)};g.support.transition&&this.$tip.hasClass("fade")?o.one("bsTransitionEnd",u).emulateTransitionEnd(m.TRANSITION_DURATION):u()}},m.prototype.applyPlacement=function(t,e){var i=this.tip(),o=i[0].offsetWidth,n=i[0].offsetHeight,s=parseInt(i.css("margin-top"),10),a=parseInt(i.css("margin-left"),10);isNaN(s)&&(s=0),isNaN(a)&&(a=0),t.top+=s,t.left+=a,g.offset.setOffset(i[0],g.extend({using:function(t){i.css({top:Math.round(t.top),left:Math.round(t.left)})}},t),0),i.addClass("in");var r=i[0].offsetWidth,l=i[0].offsetHeight;"top"==e&&l!=n&&(t.top=t.top+n-l);var h=this.getViewportAdjustedDelta(e,t,r,l);h.left?t.left+=h.left:t.top+=h.top;var d=/top|bottom/.test(e),p=d?2*h.left-o+r:2*h.top-n+l,c=d?"offsetWidth":"offsetHeight";i.offset(t),this.replaceArrow(p,i[0][c],d)},m.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?"left":"top",50*(1-t/e)+"%").css(i?"top":"left","")},m.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();t.find(".tooltip-inner")[this.options.html?"html":"text"](e),t.removeClass("fade in top bottom left right")},m.prototype.hide=function(t){var e=this,i=g(this.$tip),o=g.Event("hide.bs."+this.type);function n(){"in"!=e.hoverState&&i.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),t&&t()}if(this.$element.trigger(o),!o.isDefaultPrevented())return i.removeClass("in"),g.support.transition&&i.hasClass("fade")?i.one("bsTransitionEnd",n).emulateTransitionEnd(m.TRANSITION_DURATION):n(),this.hoverState=null,this},m.prototype.fixTitle=function(){var t=this.$element;(t.attr("title")||"string"!=typeof t.attr("data-original-title"))&&t.attr("data-original-title",t.attr("title")||"").attr("title","")},m.prototype.hasContent=function(){return this.getTitle()},m.prototype.getPosition=function(t){var e=(t=t||this.$element)[0],i="BODY"==e.tagName,o=e.getBoundingClientRect();null==o.width&&(o=g.extend({},o,{width:o.right-o.left,height:o.bottom-o.top}));var n=window.SVGElement&&e instanceof window.SVGElement,s=i?{top:0,left:0}:n?null:t.offset(),a={scroll:i?document.documentElement.scrollTop||document.body.scrollTop:t.scrollTop()},r=i?{width:g(window).width(),height:g(window).height()}:null;return g.extend({},o,a,r,s)},m.prototype.getCalculatedOffset=function(t,e,i,o){return"bottom"==t?{top:e.top+e.height,left:e.left+e.width/2-i/2}:"top"==t?{top:e.top-o,left:e.left+e.width/2-i/2}:"left"==t?{top:e.top+e.height/2-o/2,left:e.left-i}:{top:e.top+e.height/2-o/2,left:e.left+e.width}},m.prototype.getViewportAdjustedDelta=function(t,e,i,o){var n={top:0,left:0};if(!this.$viewport)return n;var s=this.options.viewport&&this.options.viewport.padding||0,a=this.getPosition(this.$viewport);if(/right|left/.test(t)){var r=e.top-s-a.scroll,l=e.top+s-a.scroll+o;r<a.top?n.top=a.top-r:l>a.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;h<a.left?n.left=a.left-h:d>a.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})};var t=g.fn.tooltip;g.fn.tooltip=function e(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=t,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.0",s.DEFAULTS=n.extend({},n.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();t.find(".popover-title")[this.options.html?"html":"text"](e),t.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof i?"html":"append":"text"](i),t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.0",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e<n[0])return this.activeTarget=null,this.clear();for(t=n.length;t--;)a!=s[t]&&e>=n[t]&&(n[t+1]===undefined||e<n[t+1])&&this.activate(s[t])},n.prototype.activate=function(t){this.activeTarget=t,this.clear();var e=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',i=s(e).parents("li").addClass("active");i.parent(".dropdown-menu").length&&(i=i.closest("li.dropdown").addClass("active")),i.trigger("activate.bs.scrollspy")},n.prototype.clear=function(){s(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var t=s.fn.scrollspy;s.fn.scrollspy=e,s.fn.scrollspy.Constructor=n,s.fn.scrollspy.noConflict=function(){return s.fn.scrollspy=t,this},s(window).on("load.bs.scrollspy.data-api",function(){s('[data-spy="scroll"]').each(function(){var t=s(this);e.call(t,t.data())})})}(jQuery),function(r){"use strict";var a=function(t){this.element=r(t)};function e(i){return this.each(function(){var t=r(this),e=t.data("bs.tab");e||t.data("bs.tab",e=new a(this)),"string"==typeof i&&e[i]()})}a.VERSION="3.4.0",a.TRANSITION_DURATION=150,a.prototype.show=function(){var t=this.element,e=t.closest("ul:not(.dropdown-menu)"),i=t.data("target");if(i||(i=(i=t.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),!t.parent("li").hasClass("active")){var o=e.find(".active:last a"),n=r.Event("hide.bs.tab",{relatedTarget:t[0]}),s=r.Event("show.bs.tab",{relatedTarget:o[0]});if(o.trigger(n),t.trigger(s),!s.isDefaultPrevented()&&!n.isDefaultPrevented()){var a=r(document).find(i);this.activate(t.closest("li"),e),this.activate(a,a.parent(),function(){o.trigger({type:"hidden.bs.tab",relatedTarget:t[0]}),t.trigger({type:"shown.bs.tab",relatedTarget:o[0]})})}}},a.prototype.activate=function(t,e,i){var o=e.find("> .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.0",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return n<i&&"top";if("bottom"==this.affixed)return null!=i?!(n+this.unpin<=s.top)&&"bottom":!(n+a<=t-o)&&"bottom";var r=null==this.affixed,l=r?n:s.top;return null!=i&&n<=i?"top":null!=o&&t-o<=l+(r?a:e)&&"bottom"},h.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(h.RESET).addClass("affix");var t=this.$target.scrollTop(),e=this.$element.offset();return this.pinnedOffset=e.top-t},h.prototype.checkPositionWithEventLoop=function(){setTimeout(l.proxy(this.checkPosition,this),1)},h.prototype.checkPosition=function(){if(this.$element.is(":visible")){var t=this.$element.height(),e=this.options.offset,i=e.top,o=e.bottom,n=Math.max(l(document).height(),l(document.body).height());"object"!=typeof e&&(o=i=e),"function"==typeof i&&(i=e.top(this.$element)),"function"==typeof o&&(o=e.bottom(this.$element));var s=this.getState(n,t,i,o);if(this.affixed!=s){null!=this.unpin&&this.$element.css("top","");var a="affix"+(s?"-"+s:""),r=l.Event(a+".bs.affix");if(this.$element.trigger(r),r.isDefaultPrevented())return;this.affixed=s,this.unpin="bottom"==s?this.getPinnedOffset():null,this.$element.removeClass(h.RESET).addClass(a).trigger(a.replace("affix","affixed")+".bs.affix")}"bottom"==s&&this.$element.offset({top:n-t-o})}};var t=l.fn.affix;l.fn.affix=i,l.fn.affix.Constructor=h,l.fn.affix.noConflict=function(){return l.fn.affix=t,this},l(window).on("load",function(){l('[data-spy="affix"]').each(function(){var t=l(this),e=t.data();e.offset=e.offset||{},null!=e.offsetBottom&&(e.offset.bottom=e.offsetBottom),null!=e.offsetTop&&(e.offset.top=e.offsetTop),i.call(t,e)})})}(jQuery);
+0
-15
faraday/server/www/script/cryptojs-sha1.js less more
0 /*
1 CryptoJS v3.1.2
2 code.google.com/p/crypto-js
3 (c) 2009-2013 by Jeff Mott. All rights reserved.
4 code.google.com/p/crypto-js/wiki/License
5 */
6 var CryptoJS=CryptoJS||function(e,m){var p={},j=p.lib={},l=function(){},f=j.Base={extend:function(a){l.prototype=this;var c=new l;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
7 n=j.WordArray=f.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=m?c:4*a.length},toString:function(a){return(a||h).stringify(this)},concat:function(a){var c=this.words,q=a.words,d=this.sigBytes;a=a.sigBytes;this.clamp();if(d%4)for(var b=0;b<a;b++)c[d+b>>>2]|=(q[b>>>2]>>>24-8*(b%4)&255)<<24-8*((d+b)%4);else if(65535<q.length)for(b=0;b<a;b+=4)c[d+b>>>2]=q[b>>>2];else c.push.apply(c,q);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
8 32-8*(c%4);a.length=e.ceil(c/4)},clone:function(){var a=f.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b<a;b+=4)c.push(4294967296*e.random()|0);return new n.init(c,a)}}),b=p.enc={},h=b.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d<a;d++){var f=c[d>>>2]>>>24-8*(d%4)&255;b.push((f>>>4).toString(16));b.push((f&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],d=0;d<c;d+=2)b[d>>>3]|=parseInt(a.substr(d,
9 2),16)<<24-4*(d%8);return new n.init(b,c/2)}},g=b.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d<a;d++)b.push(String.fromCharCode(c[d>>>2]>>>24-8*(d%4)&255));return b.join("")},parse:function(a){for(var c=a.length,b=[],d=0;d<c;d++)b[d>>>2]|=(a.charCodeAt(d)&255)<<24-8*(d%4);return new n.init(b,c)}},r=b.Utf8={stringify:function(a){try{return decodeURIComponent(escape(g.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return g.parse(unescape(encodeURIComponent(a)))}},
10 k=j.BufferedBlockAlgorithm=f.extend({reset:function(){this._data=new n.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=r.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,b=c.words,d=c.sigBytes,f=this.blockSize,h=d/(4*f),h=a?e.ceil(h):e.max((h|0)-this._minBufferSize,0);a=h*f;d=e.min(4*a,d);if(a){for(var g=0;g<a;g+=f)this._doProcessBlock(b,g);g=b.splice(0,a);c.sigBytes-=d}return new n.init(g,d)},clone:function(){var a=f.clone.call(this);
11 a._data=this._data.clone();return a},_minBufferSize:0});j.Hasher=k.extend({cfg:f.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){k.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(c,b){return(new a.init(b)).finalize(c)}},_createHmacHelper:function(a){return function(b,f){return(new s.HMAC.init(a,
12 f)).finalize(b)}}});var s=p.algo={};return p}(Math);
13 (function(){var e=CryptoJS,m=e.lib,p=m.WordArray,j=m.Hasher,l=[],m=e.algo.SHA1=j.extend({_doReset:function(){this._hash=new p.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(f,n){for(var b=this._hash.words,h=b[0],g=b[1],e=b[2],k=b[3],j=b[4],a=0;80>a;a++){if(16>a)l[a]=f[n+a]|0;else{var c=l[a-3]^l[a-8]^l[a-14]^l[a-16];l[a]=c<<1|c>>>31}c=(h<<5|h>>>27)+j+l[a];c=20>a?c+((g&e|~g&k)+1518500249):40>a?c+((g^e^k)+1859775393):60>a?c+((g&e|g&k|e&k)-1894007588):c+((g^e^
14 k)-899497514);j=k;k=e;e=g<<30|g>>>2;g=h;h=c}b[0]=b[0]+h|0;b[1]=b[1]+g|0;b[2]=b[2]+e|0;b[3]=b[3]+k|0;b[4]=b[4]+j|0},_doFinalize:function(){var f=this._data,e=f.words,b=8*this._nDataBytes,h=8*f.sigBytes;e[h>>>5]|=128<<24-h%32;e[(h+64>>>9<<4)+14]=Math.floor(b/4294967296);e[(h+64>>>9<<4)+15]=b;f.sigBytes=4*e.length;this._process();return this._hash},clone:function(){var e=j.clone.call(this);e._hash=this._hash.clone();return e}});e.SHA1=j._createHelper(m);e.HmacSHA1=j._createHmacHelper(m)})();
+0
-5
faraday/server/www/script/d3.min.js less more
0 !function(){function n(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function t(n){return null!=n&&!isNaN(n)}function e(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function r(n){return n.length}function u(n){for(var t=1;n*t%1;)t*=10;return t}function i(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function o(){}function a(n){return ia+n in this}function c(n){return n=ia+n,n in this&&delete this[n]}function s(){var n=[];return this.forEach(function(t){n.push(t)}),n}function l(){var n=0;for(var t in this)t.charCodeAt(0)===oa&&++n;return n}function f(){for(var n in this)if(n.charCodeAt(0)===oa)return!1;return!0}function h(){}function g(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function p(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=aa.length;r>e;++e){var u=aa[e]+t;if(u in n)return u}}function v(){}function d(){}function m(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new o;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function y(){Zo.event.preventDefault()}function x(){for(var n,t=Zo.event;n=t.sourceEvent;)t=n;return t}function M(n){for(var t=new d,e=0,r=arguments.length;++e<r;)t[arguments[e]]=m(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Zo.event;u.target=n,Zo.event=u,t[u.type].apply(e,r)}finally{Zo.event=i}}},t}function _(n){return sa(n,pa),n}function b(n){return"function"==typeof n?n:function(){return la(n,this)}}function w(n){return"function"==typeof n?n:function(){return fa(n,this)}}function S(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Zo.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function k(n){return n.trim().replace(/\s+/g," ")}function E(n){return new RegExp("(?:^|\\s+)"+Zo.requote(n)+"(?:\\s+|$)","g")}function A(n){return(n+"").trim().split(/^|\s+/)}function C(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=A(n).map(N);var u=n.length;return"function"==typeof t?r:e}function N(n){var t=E(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",k(u+" "+n))):e.setAttribute("class",k(u.replace(t," ")))}}function z(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function L(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function T(n){return"function"==typeof n?n:(n=Zo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function q(n){return{__data__:n}}function R(n){return function(){return ga(this,n)}}function D(t){return arguments.length||(t=n),function(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}}function P(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function U(n){return sa(n,da),n}function j(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function H(){var n=this.__transition__;n&&++n.active}function F(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Xo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+Zo.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=O;a>0&&(n=n.substring(0,a));var s=ya.get(n);return s&&(n=s,c=Y),a?t?u:r:t?v:i}function O(n,t){return function(e){var r=Zo.event;Zo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Zo.event=r}}}function Y(n,t){var e=O(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function I(){var n=".dragsuppress-"+ ++Ma,t="click"+n,e=Zo.select(Wo).on("touchmove"+n,y).on("dragstart"+n,y).on("selectstart"+n,y);if(xa){var r=Bo.style,u=r[xa];r[xa]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),xa&&(r[xa]=u),i&&(e.on(t,function(){y(),o()},!0),setTimeout(o,0))}}function Z(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>_a&&(Wo.scrollX||Wo.scrollY)){e=Zo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();_a=!(u.f||u.e),e.remove()}return _a?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function V(){return Zo.event.changedTouches[0].identifier}function X(){return Zo.event.target}function $(){return Wo}function B(n){return n>0?1:0>n?-1:0}function W(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function J(n){return n>1?0:-1>n?ba:Math.acos(n)}function G(n){return n>1?Sa:-1>n?-Sa:Math.asin(n)}function K(n){return((n=Math.exp(n))-1/n)/2}function Q(n){return((n=Math.exp(n))+1/n)/2}function nt(n){return((n=Math.exp(2*n))-1)/(n+1)}function tt(n){return(n=Math.sin(n/2))*n}function et(){}function rt(n,t,e){return this instanceof rt?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof rt?new rt(n.h,n.s,n.l):mt(""+n,yt,rt):new rt(n,t,e)}function ut(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new gt(u(n+120),u(n),u(n-120))}function it(n,t,e){return this instanceof it?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof it?new it(n.h,n.c,n.l):n instanceof at?st(n.l,n.a,n.b):st((n=xt((n=Zo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new it(n,t,e)}function ot(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new at(e,Math.cos(n*=Aa)*t,Math.sin(n)*t)}function at(n,t,e){return this instanceof at?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof at?new at(n.l,n.a,n.b):n instanceof it?ot(n.l,n.c,n.h):xt((n=gt(n)).r,n.g,n.b):new at(n,t,e)}function ct(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=lt(u)*ja,r=lt(r)*Ha,i=lt(i)*Fa,new gt(ht(3.2404542*u-1.5371385*r-.4985314*i),ht(-.969266*u+1.8760108*r+.041556*i),ht(.0556434*u-.2040259*r+1.0572252*i))}function st(n,t,e){return n>0?new it(Math.atan2(e,t)*Ca,Math.sqrt(t*t+e*e),n):new it(0/0,0/0,n)}function lt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function ft(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function ht(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function gt(n,t,e){return this instanceof gt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof gt?new gt(n.r,n.g,n.b):mt(""+n,gt,ut):new gt(n,t,e)}function pt(n){return new gt(n>>16,255&n>>8,255&n)}function vt(n){return pt(n)+""}function dt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function mt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(_t(u[0]),_t(u[1]),_t(u[2]))}return(i=Ia.get(n))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.substring(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function yt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new rt(r,u,c)}function xt(n,t,e){n=Mt(n),t=Mt(t),e=Mt(e);var r=ft((.4124564*n+.3575761*t+.1804375*e)/ja),u=ft((.2126729*n+.7151522*t+.072175*e)/Ha),i=ft((.0193339*n+.119192*t+.9503041*e)/Fa);return at(116*u-16,500*(r-u),200*(u-i))}function Mt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function _t(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function bt(n){return"function"==typeof n?n:function(){return n}}function wt(n){return n}function St(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),kt(t,e,n,r)}}function kt(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Zo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Wo.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Zo.event;Zo.event=n;try{o.progress.call(i,c)}finally{Zo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Xo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Zo.rebind(i,o,"on"),null==r?i:i.get(Et(r))}function Et(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function At(){var n=Ct(),t=Nt()-n;t>24?(isFinite(t)&&(clearTimeout($a),$a=setTimeout(At,t)),Xa=0):(Xa=1,Wa(At))}function Ct(){var n=Date.now();for(Ba=Za;Ba;)n>=Ba.t&&(Ba.f=Ba.c(n-Ba.t)),Ba=Ba.n;return n}function Nt(){for(var n,t=Za,e=1/0;t;)t.f?t=n?n.n=t.n:Za=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return Va=n,e}function zt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*ua(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:wt;return function(n){var e=Ga.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=Ka.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Zo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function Rt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Dt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new nc(e-1)),1),e}function i(n,e){return t(n=new nc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{nc=Rt;var r=new Rt;return r._=n,o(r,t,e)}finally{nc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Pt(n);return c.floor=c,c.round=Pt(r),c.ceil=Pt(u),c.offset=Pt(i),c.range=a,n}function Pt(n){return function(t,e){try{nc=Rt;var r=new Rt;return r._=t,n(r,e)._}finally{nc=Date}}}function Ut(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=ec[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=C[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&nc!==Rt,o=new(i?Rt:nc);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c>a;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in ec?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{nc=Rt;var t=new nc;return t._=n,r(t)}finally{nc=Date}}var r=t(n);return e.parse=function(n){try{nc=Rt;var t=r.parse(n);return t&&t._}finally{nc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=re;var x=Zo.map(),M=Ht(v),_=Ft(v),b=Ht(d),w=Ft(d),S=Ht(m),k=Ft(m),E=Ht(y),A=Ft(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return jt(n.getDate(),t,2)},e:function(n,t){return jt(n.getDate(),t,2)},H:function(n,t){return jt(n.getHours(),t,2)},I:function(n,t){return jt(n.getHours()%12||12,t,2)},j:function(n,t){return jt(1+Qa.dayOfYear(n),t,3)},L:function(n,t){return jt(n.getMilliseconds(),t,3)},m:function(n,t){return jt(n.getMonth()+1,t,2)},M:function(n,t){return jt(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return jt(n.getSeconds(),t,2)},U:function(n,t){return jt(Qa.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return jt(Qa.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return jt(n.getFullYear()%100,t,2)},Y:function(n,t){return jt(n.getFullYear()%1e4,t,4)},Z:te,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Wt,e:Wt,H:Gt,I:Gt,j:Jt,L:ne,m:Bt,M:Kt,p:l,S:Qt,U:Yt,w:Ot,W:It,x:c,X:s,y:Vt,Y:Zt,Z:Xt,"%":ee};return t}function jt(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Ht(n){return new RegExp("^(?:"+n.map(Zo.requote).join("|")+")","i")}function Ft(n){for(var t=new o,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Ot(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Yt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function It(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function Zt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Vt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.y=$t(+r[0]),e+r[0].length):-1}function Xt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=-t,e+5):-1}function $t(n){return n+(n>68?1900:2e3)}function Bt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Wt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Jt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Gt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Kt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Qt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ne(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function te(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(ua(t)/60),u=ua(t)%60;return e+jt(r,"0",2)+jt(u,"0",2)}function ee(n,t,e){uc.lastIndex=0;var r=uc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function re(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function ue(){}function ie(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function oe(n,t){n&&cc.hasOwnProperty(n.type)&&cc[n.type](n,t)}function ae(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ce(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)ae(n[e],t,1);t.polygonEnd()}function se(){function n(n,t){n*=Aa,t=t*Aa/2+ba/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);lc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;fc.point=function(o,a){fc.point=n,r=(t=o)*Aa,u=Math.cos(a=(e=a)*Aa/2+ba/4),i=Math.sin(a)},fc.lineEnd=function(){n(t,e)}}function le(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function fe(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function he(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function ge(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function pe(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function ve(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function de(n){return[Math.atan2(n[1],n[0]),G(n[2])]}function me(n,t){return ua(n[0]-t[0])<ka&&ua(n[1]-t[1])<ka}function ye(n,t){n*=Aa;var e=Math.cos(t*=Aa);xe(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function xe(n,t,e){++hc,pc+=(n-pc)/hc,vc+=(t-vc)/hc,dc+=(e-dc)/hc}function Me(){function n(n,u){n*=Aa;var i=Math.cos(u*=Aa),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);gc+=s,mc+=s*(t+(t=o)),yc+=s*(e+(e=a)),xc+=s*(r+(r=c)),xe(t,e,r)}var t,e,r;wc.point=function(u,i){u*=Aa;var o=Math.cos(i*=Aa);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),wc.point=n,xe(t,e,r)}}function _e(){wc.point=ye}function be(){function n(n,t){n*=Aa;var e=Math.cos(t*=Aa),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&&-J(g)/h,v=Math.atan2(h,g);Mc+=p*s,_c+=p*l,bc+=p*f,gc+=v,mc+=v*(r+(r=o)),yc+=v*(u+(u=a)),xc+=v*(i+(i=c)),xe(r,u,i)}var t,e,r,u,i;wc.point=function(o,a){t=o,e=a,wc.point=n,o*=Aa;var c=Math.cos(a*=Aa);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),xe(r,u,i)},wc.lineEnd=function(){n(t,e),wc.lineEnd=_e,wc.point=ye}}function we(){return!0}function Se(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(me(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new Ee(e,n,null,!0),s=new Ee(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new Ee(r,n,null,!1),s=new Ee(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),ke(i),ke(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ke(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function Ee(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ae(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r)if(1&t){n=e[0];var u,r=n.length-1,o=-1;if(r>0){for(_||(i.polygonStart(),_=!0),i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);i.lineEnd()}}else r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ce))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Zo.merge(g);var n=Le(m,p);g.length?(_||(i.polygonStart(),_=!0),Se(g,ze,n,e,i)):n&&(_||(i.polygonStart(),_=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),_&&(i.polygonEnd(),_=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ne(),M=t(x),_=!1;return y}}function Ce(n){return n.length>1}function Ne(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:v,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function ze(n,t){return((n=n.x)[0]<0?n[1]-Sa-ka:Sa-n[1])-((t=t.x)[0]<0?t[1]-Sa-ka:Sa-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;lc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+ba/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+ba/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>ba,k=p*x;if(lc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*wa:_,S^h>=e^m>=e){var E=he(le(f),le(n));ve(E);var A=he(u,E);ve(A);var C=(S^_>=0?-1:1)*G(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-ka>i||ka>i&&0>lc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?ba:-ba,c=ua(i-e);ua(c-ba)<ka?(n.point(e,r=(r+o)/2>0?Sa:-Sa),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=ba&&(ua(e-u)<ka&&(e-=u*ka),ua(i-a)<ka&&(i-=a*ka),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return ua(o)>ka?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function Re(n,t,e,r){var u;if(null==n)u=e*Sa,r.point(-ba,u),r.point(0,u),r.point(ba,u),r.point(ba,0),r.point(ba,-u),r.point(0,-u),r.point(-ba,-u),r.point(-ba,0),r.point(-ba,u);else if(ua(n[0]-t[0])>ka){var i=n[0]<t[0]?ba:-ba;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function De(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?ba:-ba),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(me(e,g)||me(p,g))&&(p[0]+=ka,p[1]+=ka,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&me(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=le(n),u=le(t),o=[1,0,0],a=he(r,u),c=fe(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=he(o,a),p=pe(o,f),v=pe(a,h);ge(p,v);var d=g,m=fe(p,d),y=fe(d,d),x=m*m-y*(fe(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=pe(d,(-m-M)/y);if(ge(_,p),_=de(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=ua(A-ba)<ka,N=C||ka>A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(ua(_[0]-w)<ka?k:E):k<=_[1]&&_[1]<=E:A>ba^(w<=_[0]&&_[0]<=S)){var z=pe(d,(-m+M)/y);return ge(z,p),[_,de(z)]}}}function u(t,e){var r=o?n:ba-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ua(i)>ka,c=sr(n,6*Aa);return Ae(t,e,c,o?[0,-n]:[-ba,n-ba])}function Pe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Ue(n,t,e,r){function u(r,u){return ua(r[0]-n)<ka?u>0?0:3:ua(r[0]-e)<ka?u>0?2:1:ua(r[1]-t)<ka?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&W(s,i,n)>0&&++t:i[1]<=r&&W(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-kc,Math.min(kc,n)),t=Math.max(-kc,Math.min(kc,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ne(),C=Pe(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Zo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&Se(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function je(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function He(n){var t=0,e=ba/3,r=tr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*ba/180,e=n[1]*ba/180):[180*(t/ba),180*(e/ba)]},u}function Fe(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,G((i-(n*n+e*e)*u*u)/(2*u))]},e}function Oe(){function n(n,t){Ac+=u*n-r*t,r=n,u=t}var t,e,r,u;Tc.point=function(i,o){Tc.point=n,t=r=i,e=u=o},Tc.lineEnd=function(){n(t,e)}}function Ye(n,t){Cc>n&&(Cc=n),n>zc&&(zc=n),Nc>t&&(Nc=t),t>Lc&&(Lc=t)}function Ie(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ze(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ze(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ze(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ve(n,t){pc+=n,vc+=t,++dc}function Xe(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);mc+=o*(t+n)/2,yc+=o*(e+r)/2,xc+=o,Ve(t=n,e=r)}var t,e;Rc.point=function(r,u){Rc.point=n,Ve(t=r,e=u)}}function $e(){Rc.point=Ve}function Be(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);mc+=o*(r+n)/2,yc+=o*(u+t)/2,xc+=o,o=u*n-r*t,Mc+=o*(r+n),_c+=o*(u+t),bc+=3*o,Ve(r=n,u=t)}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,Ve(t=r=i,e=u=o)},Rc.lineEnd=function(){n(t,e)}}function We(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,wa)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:v};return a}function Je(n){function t(n){return(a?r:e)(n)}function e(t){return Qe(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=le([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=ua(ua(w)-1)<ka||ua(r-h)<ka?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],z=C-t,L=N-e,T=x*z-y*L;(T*T/M>i||ua((y*z+x*L)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Aa),a=16;
1 return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Ge(n){var t=Je(function(t,e){return n([t*Ca,e*Ca])});return function(n){return er(t(n))}}function Ke(n){this.stream=n}function Qe(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function nr(n){return tr(function(){return n})()}function tr(n){function t(n){return n=a(n[0]*Aa,n[1]*Aa),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*Ca,n[1]*Ca]}function r(){a=je(o=ir(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=Je(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Sc,_=wt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=er(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Sc):De((b=+n)*Aa),u()):b},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Ue(n[0][0],n[0][1],n[1][0],n[1][1]):wt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Aa,d=n[1]%360*Aa,r()):[v*Ca,d*Ca]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Aa,y=n[1]%360*Aa,x=n.length>2?n[2]%360*Aa:0,r()):[m*Ca,y*Ca,x*Ca]},Zo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function er(n){return Qe(n,function(t,e){n.point(t*Aa,e*Aa)})}function rr(n,t){return[n,t]}function ur(n,t){return[n>ba?n-wa:-ba>n?n+wa:n,t]}function ir(n,t,e){return n?t||e?je(ar(n),cr(t,e)):ar(n):t||e?cr(t,e):ur}function or(n){return function(t,e){return t+=n,[t>ba?t-wa:-ba>t?t+wa:t,e]}}function ar(n){var t=or(n);return t.invert=or(-n),t}function cr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),G(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),G(l*r-a*u)]},e}function sr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=lr(e,u),i=lr(e,i),(o>0?i>u:u>i)&&(u+=o*wa)):(u=n+o*wa,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=de([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function lr(n,t){var e=le(t);e[0]-=n,ve(e);var r=J(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-ka)%(2*Math.PI)}function fr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function hr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function gr(n){return n.source}function pr(n){return n.target}function vr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(tt(r-t)+u*o*tt(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Ca,Math.atan2(o,Math.sqrt(r*r+u*u))*Ca]}:function(){return[n*Ca,t*Ca]};return p.distance=h,p}function dr(){function n(n,u){var i=Math.sin(u*=Aa),o=Math.cos(u),a=ua((n*=Aa)-t),c=Math.cos(a);Dc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Pc.point=function(u,i){t=u*Aa,e=Math.sin(i*=Aa),r=Math.cos(i),Pc.point=n},Pc.lineEnd=function(){Pc.point=Pc.lineEnd=v}}function mr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function yr(n,t){function e(n,t){o>0?-Sa+ka>t&&(t=-Sa+ka):t>Sa-ka&&(t=Sa-ka);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(ba/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=B(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Sa]},e):Mr}function xr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ua(u)<ka?rr:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-B(u)*Math.sqrt(n*n+e*e)]},e)}function Mr(n,t){return[n,Math.log(Math.tan(ba/4+t/2))]}function _r(n){var t,e=nr(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=ba*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function br(n,t){return[Math.log(Math.tan(ba/4+t/2)),-n]}function wr(n){return n[0]}function Sr(n){return n[1]}function kr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&W(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function Er(n,t){return n[0]-t[0]||n[1]-t[1]}function Ar(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Cr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Nr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function zr(){Gr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Bc.pop()||new zr;return t.site=n,t}function Tr(n){Yr(n),Vc.remove(n),Bc.push(n),Gr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&ua(e-c.circle.x)<ka&&ua(r-c.circle.cy)<ka;)i=c.P,a.unshift(c),Tr(c),c=i;a.unshift(c),Yr(c);for(var s=o;s.circle&&ua(e-s.circle.x)<ka&&ua(r-s.circle.cy)<ka;)o=s.N,a.push(s),Tr(s),s=o;a.push(s),Yr(s);var l,f=a.length;for(l=1;f>l;++l)s=a[l],c=a[l-1],Br(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Xr(c.site,s.site,null,u),Or(c),Or(s)}function Rr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Vc._;a;)if(r=Dr(a,o)-i,r>ka)a=a.L;else{if(u=i-Pr(a,o),!(u>ka)){r>-ka?(t=a.P,e=a):u>-ka?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if(Vc.insert(t,c),t||e){if(t===e)return Yr(t),e=Lr(t.site),Vc.insert(c,e),c.edge=e.edge=Xr(t.site,c.site),Or(t),Or(e),void 0;if(!e)return c.edge=Xr(t.site,c.site),void 0;Yr(t),Yr(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};Br(e.edge,s,p,M),c.edge=Xr(s,n,null,M),e.edge=Xr(n,p,null,M),Or(t),Or(e)}}function Dr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Pr(n,t){var e=n.N;if(e)return Dr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ur(n){this.site=n,this.edges=[]}function jr(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Zc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(ua(r-t)>ka||ua(u-e)>ka)&&(a.splice(o,0,new Wr($r(i.site,l,ua(r-f)<ka&&p-u>ka?{x:f,y:ua(t-f)<ka?e:p}:ua(u-p)<ka&&h-r>ka?{x:ua(e-p)<ka?t:h,y:p}:ua(r-h)<ka&&u-g>ka?{x:h,y:ua(t-h)<ka?e:g}:ua(u-g)<ka&&r-f>ka?{x:ua(e-g)<ka?t:f,y:g}:null),i.site,null)),++c)}function Hr(n,t){return t.angle-n.angle}function Fr(){Gr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Or(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h>=-Ea)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Wc.pop()||new Fr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=$c._;x;)if(m.y<x.y||m.y===x.y&&m.x<=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}$c.insert(y,m),y||(Xc=m)}}}}function Yr(n){var t=n.circle;t&&(t.P||(Xc=t.N),$c.remove(t),Wc.push(t),Gr(t),n.circle=null)}function Ir(n){for(var t,e=Ic,r=Pe(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Zr(t,n)||!r(t)||ua(t.a.x-t.b.x)<ka&&ua(t.a.y-t.b.y)<ka)&&(t.a=t.b=null,e.splice(u,1))}function Zr(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y<c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y<c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Vr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Xr(n,t,e,r){var u=new Vr(n,t);return Ic.push(u),e&&Br(u,n,t,e),r&&Br(u,t,n,r),Zc[n.i].edges.push(new Wr(u,n,t)),Zc[t.i].edges.push(new Wr(u,t,n)),u}function $r(n,t,e){var r=new Vr(n,null);return r.a=t,r.b=e,Ic.push(r),r}function Br(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Wr(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Jr(){this._=null}function Gr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Kr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Qr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function nu(n){for(;n.L;)n=n.L;return n}function tu(n,t){var e,r,u,i=n.sort(eu).pop();for(Ic=[],Zc=new Array(n.length),Vc=new Jr,$c=new Jr;;)if(u=Xc,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Zc[i.i]=new Ur(i),Rr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&&(Ir(t),jr(t));var o={cells:Zc,edges:Ic};return Vc=$c=Ic=Zc=null,o}function eu(n,t){return t.y-n.y||t.x-n.x}function ru(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function uu(n){return n.x}function iu(n){return n.y}function ou(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function au(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&au(n,c[0],e,r,o,a),c[1]&&au(n,c[1],o,r,u,a),c[2]&&au(n,c[2],e,a,o,i),c[3]&&au(n,c[3],o,a,u,i)}}function cu(n,t){n=Zo.rgb(n),t=Zo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+dt(Math.round(e+i*n))+dt(Math.round(r+o*n))+dt(Math.round(u+a*n))}}function su(n,t){var e,r={},u={};for(e in n)e in t?r[e]=hu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function lu(n,t){return t-=n=+n,function(e){return n+t*e}}function fu(n,t){var e,r,u,i=Gc.lastIndex=Kc.lastIndex=0,o=-1,a=[],c=[];for(n+="",t+="";(e=Gc.exec(n))&&(r=Kc.exec(t));)(u=r.index)>i&&(u=t.substring(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:lu(e,r)})),i=Kc.lastIndex;return i<t.length&&(u=t.substring(i),a[o]?a[o]+=u:a[++o]=u),a.length<2?c[0]?(t=c[0].x,function(n){return t(n)+""}):function(){return t}:(t=c.length,function(n){for(var e,r=0;t>r;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function hu(n,t){for(var e,r=Zo.interpolators.length;--r>=0&&!(e=Zo.interpolators[r](n,t)););return e}function gu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(hu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function pu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function vu(n){return function(t){return 1-n(1-t)}}function du(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function mu(n){return n*n}function yu(n){return n*n*n}function xu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Mu(n){return function(t){return Math.pow(t,n)}}function _u(n){return 1-Math.cos(n*Sa)}function bu(n){return Math.pow(2,10*(n-1))}function wu(n){return 1-Math.sqrt(1-n*n)}function Su(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/wa*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*wa/t)}}function ku(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Eu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Au(n,t){n=Zo.hcl(n),t=Zo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Zo.hsl(n),t=Zo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ut(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){n=Zo.lab(n),t=Zo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function zu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(Ru(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Ca,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*Ca:0}function Tu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(Tu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Ru(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Du(n,t){var e,r=[],u=[],i=Zo.transform(n),o=Zo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:lu(a[0],c[0])},{i:3,x:lu(a[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),s!=l?(s-l>180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:lu(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:lu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:lu(g[0],p[0])},{i:e-2,x:lu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Uu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function ju(n){for(var t=n.source,e=n.target,r=Fu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Hu(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Fu(n,t){if(n===t)return n;for(var e=Hu(n),r=Hu(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Ou(n){n.fixed|=2}function Yu(n){n.fixed&=-7}function Iu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Zu(n){n.fixed&=-5}function Vu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Vu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Xu(n,t){return Zo.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Ku,n}function $u(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(u=n.children)&&(r=u.length))for(var r,u;--r>=0;)e.push(u[r])}function Bu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++o<u;)e.push(i[o]);for(;null!=(n=r.pop());)t(n)}function Wu(n){return n.children}function Ju(n){return n.value}function Gu(n,t){return t.value-n.value}function Ku(n){return Zo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Qu(n){return n.x}function ni(n){return n.y}function ti(n,t,e){n.y0=t,n.y=e}function ei(n){return Zo.range(n.length)}function ri(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ui(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ii(n){return n.reduce(oi,0)}function oi(n,t){return n+t[1]}function ai(n,t){return ci(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ci(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function si(n){return[Zo.min(n),Zo.max(n)]}function li(n,t){return n.value-t.value}function fi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function hi(n,t){n._pack_next=t,t._pack_prev=n}function gi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function pi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(vi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],yi(r,u,i),t(i),fi(r,i),r._pack_prev=i,fi(i,u),u=r._pack_next,o=3;s>o;o++){yi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(gi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!gi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?hi(r,u=a):hi(r=c,u),o--):(fi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s>o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(di)}}function vi(n){n._pack_next=n._pack_prev=n}function di(n){delete n._pack_next,delete n._pack_prev}function mi(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)mi(u[i],t,e,r)}function yi(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function xi(n,t){return n.parent==t.parent?1:2}function Mi(n){var t=n.children;return t.length?t[0]:n.t}function _i(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function bi(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function wi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Si(n,t,e){return n.a.parent===t.parent?n.a:e}function ki(n){return 1+Zo.max(n,function(n){return n.y})}function Ei(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ai(n){var t=n.children;return t&&t.length?Ai(t[0]):n}function Ci(n){var t,e=n.children;return e&&(t=e.length)?Ci(e[t-1]):n}function Ni(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function zi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Li(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ti(n){return n.rangeExtent?n.rangeExtent():Li(n.range())}function qi(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Ri(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Di(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ss}function Pi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Zo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Ui(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?Pi:qi,c=r?Uu:Pu;return o=u(n,t,c,e),a=u(t,n,c,hu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(zu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Oi(n,t)},i.tickFormat=function(t,e){return Yi(n,t,e)},i.nice=function(t){return Hi(n,t),u()},i.copy=function(){return Ui(n,t,e,r)},u()}function ji(n,t){return Zo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Hi(n,t){return Ri(n,Di(Fi(n,t)[2]))}function Fi(n,t){null==t&&(t=10);var e=Li(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Oi(n,t){return Zo.range.apply(Zo,Fi(n,t))}function Yi(n,t,e){var r=Fi(n,t);if(e){var u=Ga.exec(e);if(u.shift(),"s"===u[8]){var i=Zo.formatPrefix(Math.max(ua(r[0]),ua(r[1])));return u[7]||(u[7]="."+Ii(i.scale(r[2]))),u[8]="f",e=Zo.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Zi(u[8],r)),e=u.join("")}else e=",."+Ii(r[2])+"f";return Zo.format(e)}function Ii(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Zi(n,t){var e=Ii(t[2]);return n in ls?Math.abs(e-Ii(Math.max(ua(t[0]),ua(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Vi(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Ri(r.map(u),e?Math:hs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Li(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++<l;)for(var h=f-1;h>0;h--)o.push(i(s)*h);for(s=0;o[s]<a;s++);for(l=o.length;o[l-1]>c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return fs;arguments.length<2?t=fs:"function"!=typeof t&&(t=Zo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Vi(n.copy(),t,e,r)},ji(o,n)}function Xi(n,t,e){function r(t){return n(u(t))}var u=$i(t),i=$i(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Oi(e,n)},r.tickFormat=function(n,t){return Yi(e,n,t)},r.nice=function(n){return r.domain(Hi(e,n))},r.exponent=function(o){return arguments.length?(u=$i(t=o),i=$i(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Xi(n.copy(),t,e)},ji(r,n)}function $i(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Bi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return Zo.range(n.length).map(function(n){return t+e*n})}var u,i,a;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new o;for(var i,a=-1,c=r.length;++a<c;)u.has(i=r[a])||u.set(i,n.push(i));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(i=n,a=0,t={t:"range",a:arguments},e):i},e.rangePoints=function(u,o){arguments.length<2&&(o=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+o);return i=r(n.length<2?(c+s)/2:c+l*o/2,l),a=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,o,c){arguments.length<2&&(o=0),arguments.length<3&&(c=o);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-o+2*c);return i=r(l+h*c,h),s&&i.reverse(),a=h*(1-o),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,o,c){arguments.length<2&&(o=0),arguments.length<3&&(c=o);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-o+2*c)),g=f-l-(n.length-o)*h;return i=r(l+Math.round(g/2),h),s&&i.reverse(),a=Math.round(h*(1-o)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return Li(t.a[0])},e.copy=function(){return Bi(n,t)},e.domain(n)}function Wi(e,r){function u(){var n=0,t=r.length;for(o=[];++n<t;)o[n-1]=Zo.quantile(e,n/t);return i}function i(n){return isNaN(n=+n)?void 0:r[Zo.bisect(o,n)]}var o;return i.domain=function(r){return arguments.length?(e=r.filter(t).sort(n),u()):e},i.range=function(n){return arguments.length?(r=n,u()):r},i.quantiles=function(){return o},i.invertExtent=function(n){return n=r.indexOf(n),0>n?[0/0,0/0]:[n>0?o[n-1]:e[0],n<o.length?o[n]:e[e.length-1]]},i.copy=function(){return Wi(e,r)},u()}function Ji(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ji(n,t,e)},u()}function Gi(n,t){function e(e){return e>=e?t[Zo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Gi(n,t)},e}function Ki(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Oi(n,t)},t.tickFormat=function(t,e){return Yi(n,t,e)},t.copy=function(){return Ki(n)},t}function Qi(n){return n.innerRadius}function no(n){return n.outerRadius}function to(n){return n.startAngle}function eo(n){return n.endAngle}function ro(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=bt(e),p=bt(r);++f<h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&&(o(),l=[]);return l.length&&o(),s.length?s.join(""):null}var e=wr,r=Sr,u=we,i=uo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=xs.get(n)||uo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function uo(n){return n.join("L")}function io(n){return uo(n)+"Z"}function oo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function ao(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function so(n,t){return n.length<4?uo(n):n[1]+ho(n.slice(1,n.length-1),go(n,t))}function lo(n,t){return n.length<3?uo(n):n[0]+ho((n.push(n[0]),n),go([n[n.length-2]].concat(n,[n[1]]),t))}function fo(n,t){return n.length<3?uo(n):n[0]+ho(n,go(n,t))}function ho(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return uo(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s<t.length;s++,c++)i=n[c],a=t[s],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var l=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+l[0]+","+l[1]}return r}function go(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function po(n){if(n.length<3)return uo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",xo(bs,o),",",xo(bs,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),Mo(c,o,a);return n.pop(),c.push("L",r),c.join("")}function vo(n){if(n.length<4)return uo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(xo(bs,i)+","+xo(bs,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),Mo(e,i,o);return e.join("")}function mo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[xo(bs,o),",",xo(bs,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),Mo(t,o,a);return t.join("")}function yo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s<=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return po(n)}function xo(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Mo(n,t,e){n.push("C",xo(Ms,t),",",xo(Ms,e),",",xo(_s,t),",",xo(_s,e),",",xo(bs,t),",",xo(bs,e))}function _o(n,t){return(t[1]-n[1])/(t[0]-n[0])}function bo(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=_o(u,i);++t<e;)r[t]=(o+(o=_o(u=i,i=n[t+1])))/2;return r[t]=o,r}function wo(n){for(var t,e,r,u,i=[],o=bo(n),a=-1,c=n.length-1;++a<c;)t=_o(n[a],n[a+1]),ua(t)<ka?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function So(n){return n.length<3?uo(n):n[0]+ho(n,wo(n))}function ko(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+ms,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Eo(n){function t(t){function c(){v.push("M",a(n(m),f),l,s(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=bt(e),_=bt(u),b=e===r?function(){return g}:bt(r),w=u===i?function(){return p}:bt(i);++y<x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=wr,r=wr,u=0,i=Sr,o=we,a=uo,c=a.key,s=a,l="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=xs.get(n)||uo).key,s=a.reverse||a,l=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function Ao(n){return n.radius}function Co(n){return[n.x,n.y]}function No(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ms;return[e*Math.cos(r),e*Math.sin(r)]}}function zo(){return 64}function Lo(){return"circle"}function To(n){var t=Math.sqrt(n/ba);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function qo(n,t){return sa(n,Cs),n.id=t,n}function Ro(n,t,e,r){var u=n.id;return P(n,"function"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Do(n){return null==n&&(n=""),function(){this.textContent=n}}function Po(n,t,e,r){var u=n.__transition__||(n.__transition__={active:0,count:0}),i=u[e];if(!i){var a=r.time;i=u[e]={tween:new o,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++u.count,Zo.timer(function(r){function o(r){return u.active>e?s():(u.active=e,i.event&&i.event.start.call(n,l,t),i.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Zo.timer(function(){return p.c=c(r||1)?we:c,1},0,a),void 0)}function c(r){if(u.active!==e)return s();for(var o=r/g,a=f(o),c=v.length;c>0;)v[--c].call(n,a);
2 return o>=1?(i.event&&i.event.end.call(n,l,t),s()):void 0}function s(){return--u.count?delete u[e]:delete n.__transition__,1}var l=n.__data__,f=i.ease,h=i.delay,g=i.duration,p=Ba,v=[];return p.t=h+a,r>=h?o(r-h):(p.c=o,void 0)},0,a)}}function Uo(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function jo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Ho(n){return n.toISOString()}function Fo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Zo.bisect(Us,u);return i==Us.length?[t.year,Fi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Us[i-1]<Us[i]/u?i-1:i]:[Fs,Fi(n,e)[2]]}return r.invert=function(t){return Oo(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Oo)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Oo(+e+1),t).length}var i=r.domain(),o=Li(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Ri(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Oo(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Oo(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Li(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Oo(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Fo(n.copy(),t,e)},ji(r,n)}function Oo(n){return new Date(n)}function Yo(n){return JSON.parse(n.responseText)}function Io(n){var t=$o.createRange();return t.selectNode($o.body),t.createContextualFragment(n.responseText)}var Zo={version:"3.4.11"};Date.now||(Date.now=function(){return+new Date});var Vo=[].slice,Xo=function(n){return Vo.call(n)},$o=document,Bo=$o.documentElement,Wo=window;try{Xo(Bo.childNodes)[0].nodeType}catch(Jo){Xo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{$o.createElement("div").style.setProperty("opacity",0,"")}catch(Go){var Ko=Wo.Element.prototype,Qo=Ko.setAttribute,na=Ko.setAttributeNS,ta=Wo.CSSStyleDeclaration.prototype,ea=ta.setProperty;Ko.setAttribute=function(n,t){Qo.call(this,n,t+"")},Ko.setAttributeNS=function(n,t,e){na.call(this,n,t,e+"")},ta.setProperty=function(n,t,e){ea.call(this,n,t+"",e)}}Zo.ascending=n,Zo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Zo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},Zo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},Zo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},Zo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Zo.mean=function(n,e){var r,u=0,i=n.length,o=-1,a=i;if(1===arguments.length)for(;++o<i;)t(r=n[o])?u+=r:--a;else for(;++o<i;)t(r=e.call(n,n[o],o))?u+=r:--a;return a?u/a:void 0},Zo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Zo.median=function(e,r){return arguments.length>1&&(e=e.map(r)),e=e.filter(t),e.length?Zo.quantile(e.sort(n),.5):void 0};var ra=e(n);Zo.bisectLeft=ra.left,Zo.bisect=Zo.bisectRight=ra.right,Zo.bisector=function(t){return e(1===t.length?function(e,r){return n(t(e),r)}:t)},Zo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Zo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Zo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Zo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,t=Zo.min(arguments,r),e=new Array(t);++n<t;)for(var u,i=-1,o=e[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return e},Zo.transpose=function(n){return Zo.zip.apply(Zo,n)},Zo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Zo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Zo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Zo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ua=Math.abs;Zo.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/e)throw new Error("infinite range");var r,i=[],o=u(ua(e)),a=-1;if(n*=o,t*=o,e*=o,0>e)for(;(r=n+e*++a)>t;)i.push(r/o);else for(;(r=n+e*++a)<t;)i.push(r/o);return i},Zo.map=function(n){var t=new o;if(n instanceof o)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},i(o,{has:a,get:function(n){return this[ia+n]},set:function(n,t){return this[ia+n]=t},remove:c,keys:s,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===oa&&n.call(this,t.substring(1),this[t])}});var ia="\x00",oa=ia.charCodeAt(0);Zo.nest=function(){function n(t,a,c){if(c>=i.length)return r?r.call(u,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=i[c++],d=new o;++g<p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e>=i.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],a=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(Zo.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return a[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},Zo.set=function(n){var t=new h;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},i(h,{has:a,add:function(n){return this[ia+n]=!0,n},remove:function(n){return n=ia+n,n in this&&delete this[n]},values:s,size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===oa&&n.call(this,t.substring(1))}}),Zo.behavior={},Zo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=g(n,t,t[e]);return n};var aa=["webkit","ms","moz","Moz","o","O"];Zo.dispatch=function(){for(var n=new d,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=m(n);return n},d.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Zo.event=null,Zo.requote=function(n){return n.replace(ca,"\\$&")};var ca=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,sa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},la=function(n,t){return t.querySelector(n)},fa=function(n,t){return t.querySelectorAll(n)},ha=Bo.matches||Bo[p(Bo,"matchesSelector")],ga=function(n,t){return ha.call(n,t)};"function"==typeof Sizzle&&(la=function(n,t){return Sizzle(n,t)[0]||null},fa=Sizzle,ga=Sizzle.matchesSelector),Zo.selection=function(){return ma};var pa=Zo.selection.prototype=[];pa.select=function(n){var t,e,r,u,i=[];n=b(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c<s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return _(i)},pa.selectAll=function(n){var t,e,r=[];n=w(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Xo(n.call(e,e.__data__,a,u))),t.parentNode=e);return _(r)};var va={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};Zo.ns={prefix:va,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),va.hasOwnProperty(e)?{space:va[e],local:n}:n}},pa.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Zo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(S(t,n[t]));return this}return this.each(S(n,t))},pa.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=A(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!E(n[u]).test(t))return!1;return!0}for(t in n)this.each(C(t,n[t]));return this}return this.each(C(n,t))},pa.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(z(e,n[e],t));return this}if(2>r)return Wo.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(z(n,t,e))},pa.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(L(t,n[t]));return this}return this.each(L(n,t))},pa.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},pa.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},pa.append=function(n){return n=T(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},pa.insert=function(n,t){return n=T(n),t=b(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},pa.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},pa.data=function(n,t){function e(n,e){var r,u,i,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new o,y=new o,x=[];for(r=-1;++r<a;)d=t.call(u=n[r],u.__data__,r),m.has(d)?v[r]=u:m.set(d,u),x.push(d);for(r=-1;++r<f;)d=t.call(e,i=e[r],r),(u=m.get(d))?(g[r]=u,u.__data__=i):y.has(d)||(p[r]=q(i)),y.set(d,i),m.remove(d);for(r=-1;++r<a;)m.has(x[r])&&(v[r]=n[r])}else{for(r=-1;++r<h;)u=n[r],i=e[r],u?(u.__data__=i,g[r]=u):p[r]=q(i);for(;f>r;++r)p[r]=q(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,u,i=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++i<a;)(u=r[i])&&(n[i]=u.__data__);return n}var c=U([]),s=_([]),l=_([]);if("function"==typeof n)for(;++i<a;)e(r=this[i],n.call(r,r.parentNode.__data__,i));else for(;++i<a;)e(r=this[i],n);return s.enter=function(){return c},s.exit=function(){return l},s},pa.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},pa.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=R(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return _(u)},pa.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},pa.sort=function(n){n=D.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},pa.each=function(n){return P(this,function(t,e,r){n.call(t,t.__data__,e,r)})},pa.call=function(n){var t=Xo(arguments);return n.apply(t[0]=this,t),this},pa.empty=function(){return!this.node()},pa.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},pa.size=function(){var n=0;return this.each(function(){++n}),n};var da=[];Zo.selection.enter=U,Zo.selection.enter.prototype=da,da.append=pa.append,da.empty=pa.empty,da.node=pa.node,da.call=pa.call,da.size=pa.size,da.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s<l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return _(o)},da.insert=function(n,t){return arguments.length<2&&(t=j(this)),pa.insert.call(this,n,t)},pa.transition=function(){for(var n,t,e=Ss||++Ns,r=[],u=ks||{time:Date.now(),ease:xu,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c<s;)(t=a[c])&&Po(t,c,e,u),n.push(t)}return qo(r,e)},pa.interrupt=function(){return this.each(H)},Zo.select=function(n){var t=["string"==typeof n?la(n,$o):n];return t.parentNode=Bo,_([t])},Zo.selectAll=function(n){var t=Xo("string"==typeof n?fa(n,$o):n);return t.parentNode=Bo,_([t])};var ma=Zo.select(Bo);pa.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(F(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(F(n,t,e))};var ya=Zo.map({mouseenter:"mouseover",mouseleave:"mouseout"});ya.forEach(function(n){"on"+n in $o&&ya.remove(n)});var xa="onselectstart"in $o?null:p(Bo.style,"userSelect"),Ma=0;Zo.mouse=function(n){return Z(n,x())};var _a=/WebKit/.test(Wo.navigator.userAgent)?-1:0;Zo.touches=function(n,t){return arguments.length<2&&(t=x().touches),t?Xo(t).map(function(t){var e=Z(n,t);return e.identifier=t.identifier,e}):[]},Zo.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",i)}function t(n,t,u,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-x[0],e=r[1]-x[1],p|=n|e,x=r,g({type:"drag",x:r[0]+s[0],y:r[1]+s[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&Zo.event.target===f),g({type:"dragend"}))}var s,l=this,f=Zo.event.target,h=l.parentNode,g=e.of(l,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=Zo.select(u()).on(i+d,a).on(o+d,c),y=I(),x=t(h,v);r?(s=r.apply(l,arguments),s=[s.x-x[0],s.y-x[1]]):s=[0,0],g({type:"dragstart"})}}var e=M(n,"drag","dragstart","dragend"),r=null,u=t(v,Zo.mouse,$,"mousemove","mouseup"),i=t(V,Zo.touch,X,"touchmove","touchend");return n.origin=function(t){return arguments.length?(r=t,n):r},Zo.rebind(n,e,"on")};var ba=Math.PI,wa=2*ba,Sa=ba/2,ka=1e-6,Ea=ka*ka,Aa=ba/180,Ca=180/ba,Na=Math.SQRT2,za=2,La=4;Zo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=Q(v),o=i/(za*h)*(e*nt(Na*t+v)-K(v));return[r+o*s,u+o*l,i*e/Q(Na*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Na*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+La*f)/(2*i*za*h),p=(c*c-i*i-La*f)/(2*c*za*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Na;return e.duration=1e3*y,e},Zo.behavior.zoom=function(){function n(n){n.on(A,s).on(Ra+".zoom",f).on("dblclick.zoom",h).on(z,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(x.range().map(function(n){return(n-S.x)/S.k}).map(x.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Zo.mouse(r),h),a(s)}function e(){f.on(C,null).on(N,null),g(l&&Zo.event.target===i),c(s)}var r=this,i=Zo.event.target,s=L.of(r,arguments),l=0,f=Zo.select(Wo).on(C,n).on(N,e),h=t(Zo.mouse(r)),g=I();H.call(r),o(s)}function l(){function n(){var n=Zo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){var t=Zo.event.target;Zo.select(t).on(M,i).on(_,f),b.push(t);for(var e=Zo.event.changedTouches,o=0,c=e.length;c>o;++o)v[e[o].identifier]=null;var s=n(),l=Date.now();if(1===s.length){if(500>l-m){var h=s[0],g=v[h.identifier];r(2*S.k),u(h,g),y(),a(p)}m=l}else if(s.length>1){var h=s[0],x=s[1],w=h[0]-x[0],k=h[1]-x[1];d=w*w+k*k}}function i(){for(var n,t,e,i,o=Zo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=d&&Math.sqrt(l/d);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}m=null,u(n,t),a(p)}function f(){if(Zo.event.touches.length){for(var t=Zo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}Zo.selectAll(b).on(x,null),w.on(A,s).on(z,l),k(),c(p)}var h,g=this,p=L.of(g,arguments),v={},d=0,x=".zoom-"+Zo.event.changedTouches[0].identifier,M="touchmove"+x,_="touchend"+x,b=[],w=Zo.select(g).on(A,null).on(z,e),k=I();H.call(g),e(),o(p)}function f(){var n=L.of(this,arguments);d?clearTimeout(d):(g=t(p=v||Zo.mouse(this)),H.call(this),o(n)),d=setTimeout(function(){d=null,c(n)},50),y(),r(Math.pow(2,.002*Ta())*S.k),u(p,g),a(n)}function h(){var n=L.of(this,arguments),e=Zo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Zo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var g,p,v,d,m,x,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=qa,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",z="touchstart.zoom",L=M(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=L.of(this,arguments),t=S;Ss?Zo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Zo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?qa:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,x=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Zo.rebind(n,L,"on")};var Ta,qa=[0,1/0],Ra="onwheel"in $o?(Ta=function(){return-Zo.event.deltaY*(Zo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in $o?(Ta=function(){return Zo.event.wheelDelta},"mousewheel"):(Ta=function(){return-Zo.event.detail},"MozMousePixelScroll");Zo.color=et,et.prototype.toString=function(){return this.rgb()+""},Zo.hsl=rt;var Da=rt.prototype=new et;Da.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,this.l/n)},Da.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,n*this.l)},Da.rgb=function(){return ut(this.h,this.s,this.l)},Zo.hcl=it;var Pa=it.prototype=new et;Pa.brighter=function(n){return new it(this.h,this.c,Math.min(100,this.l+Ua*(arguments.length?n:1)))},Pa.darker=function(n){return new it(this.h,this.c,Math.max(0,this.l-Ua*(arguments.length?n:1)))},Pa.rgb=function(){return ot(this.h,this.c,this.l).rgb()},Zo.lab=at;var Ua=18,ja=.95047,Ha=1,Fa=1.08883,Oa=at.prototype=new et;Oa.brighter=function(n){return new at(Math.min(100,this.l+Ua*(arguments.length?n:1)),this.a,this.b)},Oa.darker=function(n){return new at(Math.max(0,this.l-Ua*(arguments.length?n:1)),this.a,this.b)},Oa.rgb=function(){return ct(this.l,this.a,this.b)},Zo.rgb=gt;var Ya=gt.prototype=new et;Ya.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new gt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new gt(u,u,u)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new gt(n*this.r,n*this.g,n*this.b)},Ya.hsl=function(){return yt(this.r,this.g,this.b)},Ya.toString=function(){return"#"+dt(this.r)+dt(this.g)+dt(this.b)};var Ia=Zo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ia.forEach(function(n,t){Ia.set(n,pt(t))}),Zo.functor=bt,Zo.xhr=St(wt),Zo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=kt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++<s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++l):10===r&&(u=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;s>l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new h,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Zo.csv=Zo.dsv(",","text/csv"),Zo.tsv=Zo.dsv(" ","text/tab-separated-values"),Zo.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=x().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return Z(n,r)};var Za,Va,Xa,$a,Ba,Wa=Wo[p(Wo,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Zo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Va?Va.n=i:Za=i,Va=i,Xa||($a=clearTimeout($a),Xa=1,Wa(At))},Zo.timer.flush=function(){Ct(),Nt()},Zo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ja=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Zo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Zo.round(n,zt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),Ja[8+e/3]};var Ga=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,Ka=Zo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Zo.round(n,zt(n,t))).toFixed(Math.max(0,Math.min(20,zt(n*(1+1e-15),t))))}}),Qa=Zo.time={},nc=Date;Rt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){tc.setUTCDate.apply(this._,arguments)},setDay:function(){tc.setUTCDay.apply(this._,arguments)},setFullYear:function(){tc.setUTCFullYear.apply(this._,arguments)},setHours:function(){tc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){tc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){tc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){tc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){tc.setUTCSeconds.apply(this._,arguments)},setTime:function(){tc.setTime.apply(this._,arguments)}};var tc=Date.prototype;Qa.year=Dt(function(n){return n=Qa.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),Qa.years=Qa.year.range,Qa.years.utc=Qa.year.utc.range,Qa.day=Dt(function(n){var t=new nc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),Qa.days=Qa.day.range,Qa.days.utc=Qa.day.utc.range,Qa.dayOfYear=function(n){var t=Qa.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=Qa[n]=Dt(function(n){return(n=Qa.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});Qa[n+"s"]=e.range,Qa[n+"s"].utc=e.utc.range,Qa[n+"OfYear"]=function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)}}),Qa.week=Qa.sunday,Qa.weeks=Qa.sunday.range,Qa.weeks.utc=Qa.sunday.utc.range,Qa.weekOfYear=Qa.sundayOfYear;var ec={"-":"",_:" ",0:"0"},rc=/^\s*\d+/,uc=/^%/;Zo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Ut(n)}};var ic=Zo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Zo.format=ic.numberFormat,Zo.geo={},ue.prototype={s:0,t:0,add:function(n){ie(n,this.t,oc),ie(oc.s,this.s,this),this.s?this.t+=oc.t:this.s=oc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var oc=new ue;Zo.geo.stream=function(n,t){n&&ac.hasOwnProperty(n.type)?ac[n.type](n,t):oe(n,t)};var ac={Feature:function(n,t){oe(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)oe(e[r].geometry,t)}},cc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){ae(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ae(e[r],t,0)},Polygon:function(n,t){ce(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ce(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)oe(e[r],t)}};Zo.geo.area=function(n){return sc=0,Zo.geo.stream(n,fc),sc};var sc,lc=new ue,fc={sphere:function(){sc+=4*ba},point:v,lineStart:v,lineEnd:v,polygonStart:function(){lc.reset(),fc.lineStart=se},polygonEnd:function(){var n=2*lc;sc+=0>n?4*ba+n:n,fc.lineStart=fc.lineEnd=fc.point=v}};Zo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=le([t*Aa,e*Aa]);if(m){var u=he(m,r),i=[u[1],-u[0],0],o=he(i,u);ve(o),o=de(o);var c=t-p,s=c>0?1:-1,v=o[0]*Ca*s,d=ua(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*Ca;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*Ca;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ua(r)>180?r+(r>0?360:-360):r}else v=n,d=e;fc.point(n,e),t(n,e)}function i(){fc.lineStart()}function o(){u(v,d),fc.lineEnd(),ua(y)>ka&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,fc.polygonStart()},polygonEnd:function(){fc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0>lc?(l=-(h=180),f=-(g=90)):y>ka?g=90:-ka>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Zo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);
3 for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Zo.geo.centroid=function(n){hc=gc=pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,wc);var t=Mc,e=_c,r=bc,u=t*t+e*e+r*r;return Ea>u&&(t=mc,e=yc,r=xc,ka>gc&&(t=pc,e=vc,r=dc),u=t*t+e*e+r*r,Ea>u)?[0/0,0/0]:[Math.atan2(e,t)*Ca,G(r/Math.sqrt(u))*Ca]};var hc,gc,pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc={sphere:v,point:ye,lineStart:Me,lineEnd:_e,polygonStart:function(){wc.lineStart=be},polygonEnd:function(){wc.lineStart=Me}},Sc=Ae(we,Te,Re,[-ba,-ba/2]),kc=1e9;Zo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ue(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Zo.geo.conicEqualArea=function(){return He(Fe)}).raw=Fe,Zo.geo.albers=function(){return Zo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Zo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Zo.geo.albers(),o=Zo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Zo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+ka,f+.12*s+ka],[l-.214*s-ka,f+.234*s-ka]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+ka,f+.166*s+ka],[l-.115*s-ka,f+.234*s-ka]]).stream(c).point,n},n.scale(1070)};var Ec,Ac,Cc,Nc,zc,Lc,Tc={point:v,lineStart:v,lineEnd:v,polygonStart:function(){Ac=0,Tc.lineStart=Oe},polygonEnd:function(){Tc.lineStart=Tc.lineEnd=Tc.point=v,Ec+=ua(Ac/2)}},qc={point:Ye,lineStart:v,lineEnd:v,polygonStart:v,polygonEnd:v},Rc={point:Ve,lineStart:Xe,lineEnd:$e,polygonStart:function(){Rc.lineStart=Be},polygonEnd:function(){Rc.point=Ve,Rc.lineStart=Xe,Rc.lineEnd=$e}};Zo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Zo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Ec=0,Zo.geo.stream(n,u(Tc)),Ec},n.centroid=function(n){return pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,u(Rc)),bc?[Mc/bc,_c/bc]:xc?[mc/xc,yc/xc]:dc?[pc/dc,vc/dc]:[0/0,0/0]},n.bounds=function(n){return zc=Lc=-(Cc=Nc=1/0),Zo.geo.stream(n,u(qc)),[[Cc,Nc],[zc,Lc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Ge(n):wt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ie:new We(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Zo.geo.albersUsa()).context(null)},Zo.geo.transform=function(n){return{stream:function(t){var e=new Ke(t);for(var r in n)e[r]=n[r];return e}}},Ke.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Zo.geo.projection=nr,Zo.geo.projectionMutator=tr,(Zo.geo.equirectangular=function(){return nr(rr)}).raw=rr.invert=rr,Zo.geo.rotation=function(n){function t(t){return t=n(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t}return n=ir(n[0]%360*Aa,n[1]*Aa,n.length>2?n[2]*Aa:0),t.invert=function(t){return t=n.invert(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t},t},ur.invert=rr,Zo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ir(-n[0]*Aa,-n[1]*Aa,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Ca,n[1]*=Ca}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=sr((t=+r)*Aa,u*Aa),n):t},n.precision=function(r){return arguments.length?(e=sr(t*Aa,(u=+r)*Aa),n):u},n.angle(90)},Zo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Aa,u=n[1]*Aa,i=t[1]*Aa,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Zo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Zo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Zo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Zo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ua(n%d)>ka}).map(l)).concat(Zo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ua(n%m)>ka}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=fr(a,o,90),f=hr(r,e,y),h=fr(s,c,90),g=hr(i,u,y),n):y},n.majorExtent([[-180,-90+ka],[180,90-ka]]).minorExtent([[-180,-80-ka],[180,80+ka]])},Zo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=gr,u=pr;return n.distance=function(){return Zo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Zo.geo.interpolate=function(n,t){return vr(n[0]*Aa,n[1]*Aa,t[0]*Aa,t[1]*Aa)},Zo.geo.length=function(n){return Dc=0,Zo.geo.stream(n,Pc),Dc};var Dc,Pc={sphere:v,point:v,lineStart:dr,lineEnd:v,polygonStart:v,polygonEnd:v},Uc=mr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Zo.geo.azimuthalEqualArea=function(){return nr(Uc)}).raw=Uc;var jc=mr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},wt);(Zo.geo.azimuthalEquidistant=function(){return nr(jc)}).raw=jc,(Zo.geo.conicConformal=function(){return He(yr)}).raw=yr,(Zo.geo.conicEquidistant=function(){return He(xr)}).raw=xr;var Hc=mr(function(n){return 1/n},Math.atan);(Zo.geo.gnomonic=function(){return nr(Hc)}).raw=Hc,Mr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Sa]},(Zo.geo.mercator=function(){return _r(Mr)}).raw=Mr;var Fc=mr(function(){return 1},Math.asin);(Zo.geo.orthographic=function(){return nr(Fc)}).raw=Fc;var Oc=mr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Zo.geo.stereographic=function(){return nr(Oc)}).raw=Oc,br.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Sa]},(Zo.geo.transverseMercator=function(){var n=_r(br),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=br,Zo.geom={},Zo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=bt(e),i=bt(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(Er),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=kr(a),l=kr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t<l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=wr,r=Sr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Zo.geom.polygon=function(n){return sa(n,Yc),n};var Yc=Zo.geom.polygon.prototype=[];Yc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Yc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Yc.clip=function(n){for(var t,e,r,u,i,o,a=Nr(n),c=-1,s=this.length-Nr(this),l=this[s-1];++c<s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Ar(o,l,u)?(Ar(i,l,u)||n.push(Cr(i,o,l,u)),n.push(o)):Ar(i,l,u)&&n.push(Cr(i,o,l,u)),i=o;a&&n.push(n[0]),l=u}return n};var Ic,Zc,Vc,Xc,$c,Bc=[],Wc=[];Ur.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(Hr),t.length},Wr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Jr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=nu(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Qr(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(Qr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?nu(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,Kr(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,Qr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Kr(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,Qr(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,Kr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Qr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},Zo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return tu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x>=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/ka)*ka,y:Math.round(o(n,t)/ka)*ka,i:t}})}var r=wr,u=Sr,i=r,o=u,a=Jc;return n?t(n):(t.links=function(n){return tu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return tu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Hr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c<s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r<i.i&&r<f.i&&ru(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=bt(r=n),t):r},t.y=function(n){return arguments.length?(o=bt(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Jc:n,t):a===Jc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===Jc?null:a&&a[1]},t)};var Jc=[[-1e6,-1e6],[1e6,1e6]];Zo.geom.delaunay=function(n){return Zo.geom.voronoi().triangles(n)},Zo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(ua(c-e)+ua(l-r)<.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e>=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=ou()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=bt(a),M=bt(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.x<v&&(v=l.x),l.y<d&&(d=l.y),l.x>m&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=ou();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){au(n,k,v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=wr,c=Sr;return(o=arguments.length)?(a=uu,c=iu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Zo.interpolateRgb=cu,Zo.interpolateObject=su,Zo.interpolateNumber=lu,Zo.interpolateString=fu;var Gc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Kc=new RegExp(Gc.source,"g");Zo.interpolate=hu,Zo.interpolators=[function(n,t){var e=typeof t;return("string"===e?Ia.has(t)||/^(#|rgb\(|hsl\()/.test(t)?cu:fu:t instanceof et?cu:Array.isArray(t)?gu:"object"===e&&isNaN(t)?su:lu)(n,t)}],Zo.interpolateArray=gu;var Qc=function(){return wt},ns=Zo.map({linear:Qc,poly:Mu,quad:function(){return mu},cubic:function(){return yu},sin:function(){return _u},exp:function(){return bu},circle:function(){return wu},elastic:Su,back:ku,bounce:function(){return Eu}}),ts=Zo.map({"in":wt,out:vu,"in-out":du,"out-in":function(n){return du(vu(n))}});Zo.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ns.get(e)||Qc,r=ts.get(r)||wt,pu(r(e.apply(null,Vo.call(arguments,1))))},Zo.interpolateHcl=Au,Zo.interpolateHsl=Cu,Zo.interpolateLab=Nu,Zo.interpolateRound=zu,Zo.transform=function(n){var t=$o.createElementNS(Zo.ns.prefix.svg,"g");return(Zo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:es)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var es={a:1,b:0,c:0,d:1,e:0,f:0};Zo.interpolateTransform=Du,Zo.layout={},Zo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(ju(n[e]));return t}},Zo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Zo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(s=0,g=-1;++g<i;)s+=u[h][g];v.push(s),m.push(Zo.range(i)),n+=s}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(wa-l*i)/n,s=0,h=-1;++h<i;){for(f=s,g=-1;++g<i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+"-"+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&&t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Zo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Zo.event.x,n.py=Zo.event.y,a.resume()}var e,r,u,i,o,a={},c=Zo.dispatch("start","tick","end"),s=[1,1],l=.9,f=rs,h=us,g=-30,p=is,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Vu(t=Zo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Zo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a<s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Zo.behavior.drag().origin(wt).on("dragstart.force",Ou).on("drag.force",t).on("dragend.force",Yu)),arguments.length?(this.on("mouseover.force",Iu).on("mouseout.force",Zu).call(e),void 0):e},Zo.rebind(a,c,"on")};var rs=20,us=1,is=1/0;Zo.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(s=e.call(n,i,i.depth))&&(c=s.length)){for(var c,s,l;--c>=0;)o.push(l=s[c]),l.parent=i,l.depth=i.depth+1;r&&(i.value=0),i.children=s}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Bu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=Gu,e=Wu,r=Ju;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&($u(t,function(n){n.children&&(n.value=0)}),Bu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},Zo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s<o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Zo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Xu(e,r)},Zo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-a)/Zo.sum(o),s=Zo.range(i.length);null!=e&&s.sort(e===os?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=os,r=0,u=wa;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var os={};Zo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Zo.permute(s,f),l=Zo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m>g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=wt,e=ei,r=ri,u=ti,i=Qu,o=ni;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:as.get(t)||ei,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:cs.get(t)||ri,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var as=Zo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ui),i=n.map(ii),o=Zo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Zo.range(n.length).reverse()},"default":ei}),cs=Zo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ri});Zo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=s[i],a>=l[0]&&a<=l[1]&&(o=c[Zo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=si,u=ai;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=bt(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ci(n,t)}:bt(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Zo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Bu(a,function(n){n.r=+l(n.value)}),Bu(a,pi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;Bu(a,function(n){n.r+=f}),Bu(a,pi),Bu(a,function(n){n.r-=f})}return mi(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Zo.layout.hierarchy().sort(li),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Xu(n,e)},Zo.layout.tree=function(){function n(n,u){var l=o.call(this,n,u),f=l[0],h=t(f);if(Bu(h,e),h.parent.m=-h.z,$u(h,r),s)$u(f,i);else{var g=f,p=f,v=f;$u(f,function(n){n.x<g.x&&(g=n),n.x>p.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);$u(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return l}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){wi(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],s=u.m,l=i.m,f=o.m,h=c.m;o=_i(o),u=Mi(u),o&&u;)c=Mi(c),i=_i(i),i.a=n,r=o.z+f-u.z-s+a(o._,u._),r>0&&(bi(Si(o,n,e),n,r),s+=r,l+=r),f+=o.m,s+=u.m,h+=c.m,l+=i.m;o&&!_i(i)&&(i.t=o,i.m+=f-l),u&&!Mi(c)&&(c.t=u,c.m+=s-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=Zo.layout.hierarchy().sort(null).value(null),a=xi,c=[1,1],s=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(s=null==(c=t)?i:null,n):s?null:c},n.nodeSize=function(t){return arguments.length?(s=null==(c=t)?null:i,n):s?c:null},Xu(n,o)},Zo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;Bu(c,function(n){var t=n.children;t&&t.length?(n.x=Ei(t),n.y=ki(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ai(c),f=Ci(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return Bu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Zo.layout.hierarchy().sort(null).value(null),e=xi,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Xu(n,t)},Zo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++i<o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l>e.dx)&&(l=e.dx);++i<o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=Zo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=Ni,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ni(t):zi(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return zi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?Ni:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Xu(i,a)},Zo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Zo.random.normal.apply(Zo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Zo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Zo.scale={};var ss={floor:wt,ceil:wt};Zo.scale.linear=function(){return Ui([0,1],[0,1],hu,!1)};var ls={s:1,g:1,p:1,r:1,e:1};Zo.scale.log=function(){return Vi(Zo.scale.linear().domain([0,1]),10,!0,[1,10])};var fs=Zo.format(".0e"),hs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Zo.scale.pow=function(){return Xi(Zo.scale.linear(),1,[0,1])},Zo.scale.sqrt=function(){return Zo.scale.pow().exponent(.5)},Zo.scale.ordinal=function(){return Bi([],{t:"range",a:[[]]})},Zo.scale.category10=function(){return Zo.scale.ordinal().range(gs)},Zo.scale.category20=function(){return Zo.scale.ordinal().range(ps)},Zo.scale.category20b=function(){return Zo.scale.ordinal().range(vs)},Zo.scale.category20c=function(){return Zo.scale.ordinal().range(ds)};var gs=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(vt),ps=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(vt),vs=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(vt),ds=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(vt);Zo.scale.quantile=function(){return Wi([],[])},Zo.scale.quantize=function(){return Ji(0,1,[0,1])},Zo.scale.threshold=function(){return Gi([.5],[0,1])},Zo.scale.identity=function(){return Ki([0,1])},Zo.svg={},Zo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ms,a=u.apply(this,arguments)+ms,c=(o>a&&(c=o,o=a,a=c),a-o),s=ba>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);
4 return c>=ys?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=Qi,e=no,r=to,u=eo;return n.innerRadius=function(e){return arguments.length?(t=bt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=bt(t),n):e},n.startAngle=function(t){return arguments.length?(r=bt(t),n):r},n.endAngle=function(t){return arguments.length?(u=bt(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ms;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ms=-Sa,ys=wa-ka;Zo.svg.line=function(){return ro(wt)};var xs=Zo.map({linear:uo,"linear-closed":io,step:oo,"step-before":ao,"step-after":co,basis:po,"basis-open":vo,"basis-closed":mo,bundle:yo,cardinal:fo,"cardinal-open":so,"cardinal-closed":lo,monotone:So});xs.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Ms=[0,2/3,1/3,0],_s=[0,1/3,2/3,0],bs=[0,1/6,2/3,1/6];Zo.svg.line.radial=function(){var n=ro(ko);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},ao.reverse=co,co.reverse=ao,Zo.svg.area=function(){return Eo(wt)},Zo.svg.area.radial=function(){var n=Eo(ko);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Zo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ms,l=s.call(n,u,r)+ms;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>ba)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=gr,o=pr,a=Ao,c=to,s=eo;return n.radius=function(t){return arguments.length?(a=bt(t),n):a},n.source=function(t){return arguments.length?(i=bt(t),n):i},n.target=function(t){return arguments.length?(o=bt(t),n):o},n.startAngle=function(t){return arguments.length?(c=bt(t),n):c},n.endAngle=function(t){return arguments.length?(s=bt(t),n):s},n},Zo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=gr,e=pr,r=Co;return n.source=function(e){return arguments.length?(t=bt(e),n):t},n.target=function(t){return arguments.length?(e=bt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Zo.svg.diagonal.radial=function(){var n=Zo.svg.diagonal(),t=Co,e=n.projection;return n.projection=function(n){return arguments.length?e(No(t=n)):t},n},Zo.svg.symbol=function(){function n(n,r){return(ws.get(t.call(this,n,r))||To)(e.call(this,n,r))}var t=Lo,e=zo;return n.type=function(e){return arguments.length?(t=bt(e),n):t},n.size=function(t){return arguments.length?(e=bt(t),n):e},n};var ws=Zo.map({circle:To,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*As)),e=t*As;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Zo.svg.symbolTypes=ws.keys();var Ss,ks,Es=Math.sqrt(3),As=Math.tan(30*Aa),Cs=[],Ns=0;Cs.call=pa.call,Cs.empty=pa.empty,Cs.node=pa.node,Cs.size=pa.size,Zo.transition=function(n){return arguments.length?Ss?n.transition():n:ma.transition()},Zo.transition.prototype=Cs,Cs.select=function(n){var t,e,r,u=this.id,i=[];n=b(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s<l;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),Po(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return qo(i,u)},Cs.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=w(n);for(var c=-1,s=this.length;++c<s;)for(var l=this[c],f=-1,h=l.length;++f<h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&Po(u,g,o,i),t.push(u)}return qo(a,o)},Cs.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=R(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return qo(u,this.id)},Cs.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):P(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Cs.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Du:hu,a=Zo.ns.qualify(n);return Ro(this,"attr."+n,t,a.local?i:u)},Cs.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Zo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Cs.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Wo.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=hu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Ro(this,"style."+n,t,u)},Cs.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Wo.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Cs.text=function(n){return Ro(this,"text",n,Do)},Cs.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Cs.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Zo.ease.apply(Zo,arguments)),P(this,function(e){e.__transition__[t].ease=n}))},Cs.delay=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].delay:P(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Cs.duration=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].duration:P(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Cs.each=function(n,t){var e=this.id;if(arguments.length<2){var r=ks,u=Ss;Ss=e,P(this,function(t,r,u){ks=t.__transition__[e],n.call(t,t.__data__,r,u)}),ks=r,Ss=u}else P(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Zo.dispatch("start","end"))).on(n,t)});return this},Cs.transition=function(){for(var n,t,e,r,u=this.id,i=++Ns,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,Po(e,s,i,r)),n.push(e)}return qo(o,i)},Zo.svg.axis=function(){function n(n){n.each(function(){var n,s=Zo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):wt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",ka),d=Zo.transition(p.exit()).style("opacity",ka).remove(),m=Zo.transition(p.order()).style("opacity",1),y=Ti(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Zo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Uo,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Uo,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=jo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=jo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Zo.scale.linear(),r=zs,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Ls?t+"":zs,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var zs="bottom",Ls={top:1,right:1,bottom:1,left:1};Zo.svg.brush=function(){function n(i){i.each(function(){var i=Zo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,wt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Ts[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Zo.transition(i),h=Zo.transition(o);c&&(l=Ti(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ti(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Zo.event.keyCode&&(C||(x=null,z[0]-=l[1],z[1]-=f[1],C=2),y())}function p(){32==Zo.event.keyCode&&2==C&&(z[0]+=l[1],z[1]+=f[1],C=0,y())}function v(){var n=Zo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Zo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),z[0]=l[+(n[0]<x[0])],z[1]=f[+(n[1]<x[1])]):x=null),E&&d(n,c,0)&&(e(S),u=!0),A&&d(n,s,1)&&(r(S),u=!0),u&&(t(S),w({type:"brush",mode:C?"move":"resize"}))}function d(n,t,e){var r,u,a=Ti(t),c=a[0],s=a[1],p=z[e],v=e?f:l,d=v[1]-v[0];return C&&(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&&(p=Math.max(c,Math.min(s,2*x[e]-r))),r>p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function m(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Zo.select("body").style("cursor",null),L.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Zo.select(Zo.event.target),w=a.of(_,arguments),S=Zo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=I(),z=Zo.mouse(_),L=Zo.select(Wo).on("keydown.brush",u).on("keyup.brush",p);if(Zo.event.changedTouches?L.on("touchmove.brush",v).on("touchend.brush",m):L.on("mousemove.brush",v).on("mouseup.brush",m),S.interrupt().selectAll("*").interrupt(),C)z[0]=l[0]-z[0],z[1]=f[0]-z[1];else if(k){var T=+/w$/.test(k),q=+/^n/.test(k);M=[l[1-T]-z[0],f[1-q]-z[1]],z[0]=l[T],z[1]=f[q]}else Zo.event.altKey&&(x=z.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Zo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=M(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=qs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,Ss?Zo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=gu(l,t.x),r=gu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=qs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=qs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Zo.rebind(n,a,"on")};var Ts={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},qs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Rs=Qa.format=ic.timeFormat,Ds=Rs.utc,Ps=Ds("%Y-%m-%dT%H:%M:%S.%LZ");Rs.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Ho:Ps,Ho.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Ho.toString=Ps.toString,Qa.second=Dt(function(n){return new nc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),Qa.seconds=Qa.second.range,Qa.seconds.utc=Qa.second.utc.range,Qa.minute=Dt(function(n){return new nc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),Qa.minutes=Qa.minute.range,Qa.minutes.utc=Qa.minute.utc.range,Qa.hour=Dt(function(n){var t=n.getTimezoneOffset()/60;return new nc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),Qa.hours=Qa.hour.range,Qa.hours.utc=Qa.hour.utc.range,Qa.month=Dt(function(n){return n=Qa.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),Qa.months=Qa.month.range,Qa.months.utc=Qa.month.utc.range;var Us=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],js=[[Qa.second,1],[Qa.second,5],[Qa.second,15],[Qa.second,30],[Qa.minute,1],[Qa.minute,5],[Qa.minute,15],[Qa.minute,30],[Qa.hour,1],[Qa.hour,3],[Qa.hour,6],[Qa.hour,12],[Qa.day,1],[Qa.day,2],[Qa.week,1],[Qa.month,1],[Qa.month,3],[Qa.year,1]],Hs=Rs.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",we]]),Fs={range:function(n,t,e){return Zo.range(Math.ceil(n/e)*e,+t,e).map(Oo)},floor:wt,ceil:wt};js.year=Qa.year,Qa.scale=function(){return Fo(Zo.scale.linear(),js,Hs)};var Os=js.map(function(n){return[n[0].utc,n[1]]}),Ys=Ds.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",we]]);Os.year=Qa.year.utc,Qa.scale.utc=function(){return Fo(Zo.scale.linear(),Os,Ys)},Zo.text=St(function(n){return n.responseText}),Zo.json=function(n,t){return kt(n,"application/json",Yo,t)},Zo.html=function(n,t){return kt(n,"text/html",Io,t)},Zo.xml=St(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Zo):"object"==typeof module&&module.exports&&(module.exports=Zo),this.d3=Zo}();
+0
-5
faraday/server/www/script/d3.v3.min.js less more
0 !function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function r(n){return null===n?0/0:+n}function u(n){return!isNaN(n)}function i(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function c(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function l(){this._=Object.create(null)}function s(n){return(n+="")===pa||n[0]===va?va+n:n}function f(n){return(n+="")[0]===va?n.slice(1):n}function h(n){return s(n)in this._}function g(n){return(n=s(n))in this._&&delete this._[n]}function p(){var n=[];for(var t in this._)n.push(f(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function m(){this._=Object.create(null)}function y(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=da.length;r>e;++e){var u=da[e]+t;if(u in n)return u}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new l;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function S(){ta.event.preventDefault()}function k(){for(var n,t=ta.event;n=t.sourceEvent;)t=n;return t}function E(n){for(var t=new _,e=0,r=arguments.length;++e<r;)t[arguments[e]]=w(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=ta.event;u.target=n,ta.event=u,t[u.type].apply(e,r)}finally{ta.event=i}}},t}function A(n){return ya(n,_a),n}function N(n){return"function"==typeof n?n:function(){return Ma(n,this)}}function C(n){return"function"==typeof n?n:function(){return xa(n,this)}}function z(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ta.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function q(n){return n.trim().replace(/\s+/g," ")}function L(n){return new RegExp("(?:^|\\s+)"+ta.requote(n)+"(?:\\s+|$)","g")}function T(n){return(n+"").trim().split(/^|\s+/)}function R(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=T(n).map(D);var u=n.length;return"function"==typeof t?r:e}function D(n){var t=L(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",q(u+" "+n))):e.setAttribute("class",q(u.replace(t," ")))}}function P(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function U(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function j(n){function t(){var t=this.ownerDocument,e=this.namespaceURI;return e?t.createElementNS(e,n):t.createElement(n)}function e(){return this.ownerDocument.createElementNS(n.space,n.local)}return"function"==typeof n?n:(n=ta.ns.qualify(n)).local?e:t}function F(){var n=this.parentNode;n&&n.removeChild(this)}function H(n){return{__data__:n}}function O(n){return function(){return ba(this,n)}}function I(n){return arguments.length||(n=e),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function Y(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function Z(n){return ya(n,Sa),n}function V(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function X(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,ra(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+ta.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=$;a>0&&(n=n.slice(0,a));var l=ka.get(n);return l&&(n=l,c=B),a?t?u:r:t?b:i}function $(n,t){return function(e){var r=ta.event;ta.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ta.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Aa,u="click"+r,i=ta.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ea&&(Ea="onselectstart"in e?!1:x(e.style,"userSelect")),Ea){var o=n(e).style,a=o[Ea];o[Ea]="none"}return function(n){if(i.on(r,null),Ea&&(o[Ea]=a),n){var t=function(){i.on(u,null)};i.on(u,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var u=r.createSVGPoint();if(0>Na){var i=t(n);if(i.scrollX||i.scrollY){r=ta.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Na=!(o.f||o.e),r.remove()}}return Na?(u.x=e.pageX,u.y=e.pageY):(u.x=e.clientX,u.y=e.clientY),u=u.matrixTransform(n.getScreenCTM().inverse()),[u.x,u.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ta.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nt(n){return n>1?0:-1>n?qa:Math.acos(n)}function tt(n){return n>1?Ra:-1>n?-Ra:Math.asin(n)}function et(n){return((n=Math.exp(n))-1/n)/2}function rt(n){return((n=Math.exp(n))+1/n)/2}function ut(n){return((n=Math.exp(2*n))-1)/(n+1)}function it(n){return(n=Math.sin(n/2))*n}function ot(){}function at(n,t,e){return this instanceof at?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof at?new at(n.h,n.s,n.l):bt(""+n,_t,at):new at(n,t,e)}function ct(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new mt(u(n+120),u(n),u(n-120))}function lt(n,t,e){return this instanceof lt?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof lt?new lt(n.h,n.c,n.l):n instanceof ft?gt(n.l,n.a,n.b):gt((n=wt((n=ta.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new lt(n,t,e)}function st(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new ft(e,Math.cos(n*=Da)*t,Math.sin(n)*t)}function ft(n,t,e){return this instanceof ft?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof ft?new ft(n.l,n.a,n.b):n instanceof lt?st(n.h,n.c,n.l):wt((n=mt(n)).r,n.g,n.b):new ft(n,t,e)}function ht(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=pt(u)*Xa,r=pt(r)*$a,i=pt(i)*Ba,new mt(dt(3.2404542*u-1.5371385*r-.4985314*i),dt(-.969266*u+1.8760108*r+.041556*i),dt(.0556434*u-.2040259*r+1.0572252*i))}function gt(n,t,e){return n>0?new lt(Math.atan2(e,t)*Pa,Math.sqrt(t*t+e*e),n):new lt(0/0,0/0,n)}function pt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function vt(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function dt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mt(n,t,e){return this instanceof mt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mt?new mt(n.r,n.g,n.b):bt(""+n,mt,ct):new mt(n,t,e)}function yt(n){return new mt(n>>16,n>>8&255,255&n)}function Mt(n){return yt(n)+""}function xt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function bt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(kt(u[0]),kt(u[1]),kt(u[2]))}return(i=Ga.get(n.toLowerCase()))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function _t(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new at(r,u,c)}function wt(n,t,e){n=St(n),t=St(t),e=St(e);var r=vt((.4124564*n+.3575761*t+.1804375*e)/Xa),u=vt((.2126729*n+.7151522*t+.072175*e)/$a),i=vt((.0193339*n+.119192*t+.9503041*e)/Ba);return ft(116*u-16,500*(r-u),200*(u-i))}function St(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function kt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function Et(n){return"function"==typeof n?n:function(){return n}}function At(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Nt(t,e,n,r)}}function Nt(n,t,e,r){function u(){var n,t=c.status;if(!t&&zt(c)||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return void o.error.call(i,r)}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=ta.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,l=null;return!this.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=ta.event;ta.event=n;try{o.progress.call(i,c)}finally{ta.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(l=n,i):l},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(ra(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var s in a)c.setRequestHeader(s,a[s]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=l&&(c.responseType=l),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},ta.rebind(i,o,"on"),null==r?i:i.get(Ct(r))}function Ct(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function zt(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qt(){var n=Lt(),t=Tt()-n;t>24?(isFinite(t)&&(clearTimeout(tc),tc=setTimeout(qt,t)),nc=0):(nc=1,rc(qt))}function Lt(){var n=Date.now();for(ec=Ka;ec;)n>=ec.t&&(ec.f=ec.c(n-ec.t)),ec=ec.n;return n}function Tt(){for(var n,t=Ka,e=1/0;t;)t.f?t=n?n.n=t.n:Ka=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return Qa=n,e}function Rt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Dt(n,t){var e=Math.pow(10,3*ga(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Pt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r&&e?function(n,t){for(var u=n.length,i=[],o=0,a=r[0],c=0;u>0&&a>0&&(c+a+1>t&&(a=Math.max(1,t-c)),i.push(n.substring(u-=a,u+a)),!((c+=a+1)>t));)a=r[o=(o+1)%r.length];return i.reverse().join(e)}:y;return function(n){var e=ic.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",c=e[4]||"",l=e[5],s=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1,y=!0;switch(h&&(h=+h.substring(1)),(l||"0"===r&&"="===o)&&(l=r="0",o="="),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":y=!1;case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=oc.get(g)||Ut;var M=l&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>p){var c=ta.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=y?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!l&&f&&(x=i(x,1/0));var S=v.length+x.length+b.length+(M?0:u.length),k=s>S?new Array(S=s-S+1).join(r):"";return M&&(x=i(k+x,k.length?s-b.length:1/0)),u+=v,n=x+b,("<"===o?u+n+k:">"===o?k+u+n:"^"===o?k.substring(0,S>>=1)+u+n+k.substring(S):u+(M?n:k+n))+e}}}function Ut(n){return n+""}function jt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ft(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new cc(e-1)),1),e}function i(n,e){return t(n=new cc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{cc=jt;var r=new jt;return r._=n,o(r,t,e)}finally{cc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Ht(n);return c.floor=c,c.round=Ht(r),c.ceil=Ht(u),c.offset=Ht(i),c.range=a,n}function Ht(n){return function(t,e){try{cc=jt;var r=new jt;return r._=t,n(r,e)._}finally{cc=Date}}}function Ot(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.slice(c,a)),null!=(u=sc[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=N[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.slice(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&cc!==jt,o=new(i?jt:cc);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+(r.Z/100|0),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,l=e.length;c>a;){if(r>=l)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=C[o in sc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.slice(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,N.c.toString(),t,r)}function c(n,t,r){return e(n,N.x.toString(),t,r)}function l(n,t,r){return e(n,N.X.toString(),t,r)}function s(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{cc=jt;var t=new cc;return t._=n,r(t)}finally{cc=Date}}var r=t(n);return e.parse=function(n){try{cc=jt;var t=r.parse(n);return t&&t._}finally{cc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ae;var M=ta.map(),x=Yt(v),b=Zt(v),_=Yt(d),w=Zt(d),S=Yt(m),k=Zt(m),E=Yt(y),A=Zt(y);p.forEach(function(n,t){M.set(n.toLowerCase(),t)});var N={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return It(n.getDate(),t,2)},e:function(n,t){return It(n.getDate(),t,2)},H:function(n,t){return It(n.getHours(),t,2)},I:function(n,t){return It(n.getHours()%12||12,t,2)},j:function(n,t){return It(1+ac.dayOfYear(n),t,3)},L:function(n,t){return It(n.getMilliseconds(),t,3)},m:function(n,t){return It(n.getMonth()+1,t,2)},M:function(n,t){return It(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return It(n.getSeconds(),t,2)},U:function(n,t){return It(ac.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return It(ac.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return It(n.getFullYear()%100,t,2)},Y:function(n,t){return It(n.getFullYear()%1e4,t,4)},Z:ie,"%":function(){return"%"}},C={a:r,A:u,b:i,B:o,c:a,d:Qt,e:Qt,H:te,I:te,j:ne,L:ue,m:Kt,M:ee,p:s,S:re,U:Xt,w:Vt,W:$t,x:c,X:l,y:Wt,Y:Bt,Z:Jt,"%":oe};return t}function It(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Yt(n){return new RegExp("^(?:"+n.map(ta.requote).join("|")+")","i")}function Zt(n){for(var t=new l,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Vt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Xt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e));return r?(n.U=+r[0],e+r[0].length):-1}function $t(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e));return r?(n.W=+r[0],e+r[0].length):-1}function Bt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Wt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.y=Gt(+r[0]),e+r[0].length):-1}function Jt(n,t,e){return/^[+-]\d{4}$/.test(t=t.slice(e,e+5))?(n.Z=-t,e+5):-1}function Gt(n){return n+(n>68?1900:2e3)}function Kt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Qt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function ne(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function te(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ee(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function re(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ue(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ie(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=ga(t)/60|0,u=ga(t)%60;return e+It(r,"0",2)+It(u,"0",2)}function oe(n,t,e){hc.lastIndex=0;var r=hc.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ae(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function ce(){}function le(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function se(n,t){n&&dc.hasOwnProperty(n.type)&&dc[n.type](n,t)}function fe(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function he(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)fe(n[e],t,1);t.polygonEnd()}function ge(){function n(n,t){n*=Da,t=t*Da/2+qa/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),l=Math.sin(t),s=i*l,f=u*c+s*Math.cos(a),h=s*o*Math.sin(a);yc.add(Math.atan2(h,f)),r=n,u=c,i=l}var t,e,r,u,i;Mc.point=function(o,a){Mc.point=n,r=(t=o)*Da,u=Math.cos(a=(e=a)*Da/2+qa/4),i=Math.sin(a)},Mc.lineEnd=function(){n(t,e)}}function pe(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function ve(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function de(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function me(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ye(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function Me(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function xe(n){return[Math.atan2(n[1],n[0]),tt(n[2])]}function be(n,t){return ga(n[0]-t[0])<Ca&&ga(n[1]-t[1])<Ca}function _e(n,t){n*=Da;var e=Math.cos(t*=Da);we(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function we(n,t,e){++xc,_c+=(n-_c)/xc,wc+=(t-wc)/xc,Sc+=(e-Sc)/xc}function Se(){function n(n,u){n*=Da;var i=Math.cos(u*=Da),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),l=Math.atan2(Math.sqrt((l=e*c-r*a)*l+(l=r*o-t*c)*l+(l=t*a-e*o)*l),t*o+e*a+r*c);bc+=l,kc+=l*(t+(t=o)),Ec+=l*(e+(e=a)),Ac+=l*(r+(r=c)),we(t,e,r)}var t,e,r;qc.point=function(u,i){u*=Da;var o=Math.cos(i*=Da);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),qc.point=n,we(t,e,r)}}function ke(){qc.point=_e}function Ee(){function n(n,t){n*=Da;var e=Math.cos(t*=Da),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),l=u*c-i*a,s=i*o-r*c,f=r*a-u*o,h=Math.sqrt(l*l+s*s+f*f),g=r*o+u*a+i*c,p=h&&-nt(g)/h,v=Math.atan2(h,g);Nc+=p*l,Cc+=p*s,zc+=p*f,bc+=v,kc+=v*(r+(r=o)),Ec+=v*(u+(u=a)),Ac+=v*(i+(i=c)),we(r,u,i)}var t,e,r,u,i;qc.point=function(o,a){t=o,e=a,qc.point=n,o*=Da;var c=Math.cos(a*=Da);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),we(r,u,i)},qc.lineEnd=function(){n(t,e),qc.lineEnd=ke,qc.point=_e}}function Ae(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function Ne(){return!0}function Ce(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(be(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return void u.lineEnd()}var c=new qe(e,n,null,!0),l=new qe(e,null,c,!1);c.o=l,i.push(c),o.push(l),c=new qe(r,n,null,!1),l=new qe(r,null,c,!0),c.o=l,i.push(c),o.push(l)}}),o.sort(t),ze(i),ze(o),i.length){for(var a=0,c=e,l=o.length;l>a;++a)o[a].e=c=!c;for(var s,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;s=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,l=s.length;l>a;++a)u.point((f=s[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){s=g.p.z;for(var a=s.length-1;a>=0;--a)u.point((f=s[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,s=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ze(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function qe(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Le(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function l(){y.point=o,d.lineEnd()}function s(n,t){v.push([n,t]);var e=u(n,t);x.point(e[0],e[1])}function f(){x.lineStart(),v=[]}function h(){s(v[0][0],v[0][1]),x.lineEnd();var n,t=x.clean(),e=M.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r)if(1&t){n=e[0];var u,r=n.length-1,o=-1;if(r>0){for(b||(i.polygonStart(),b=!0),i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);i.lineEnd()}}else r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Te))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:l,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=l,g=ta.merge(g);var n=Fe(m,p);g.length?(b||(i.polygonStart(),b=!0),Ce(g,De,n,e,i)):n&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Re(),x=t(M),b=!1;return y}}function Te(n){return n.length>1}function Re(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function De(n,t){return((n=n.x)[0]<0?n[1]-Ra-Ca:Ra-n[1])-((t=t.x)[0]<0?t[1]-Ra-Ca:Ra-t[1])}function Pe(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?qa:-qa,c=ga(i-e);ga(c-qa)<Ca?(n.point(e,r=(r+o)/2>0?Ra:-Ra),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=qa&&(ga(e-u)<Ca&&(e-=u*Ca),ga(i-a)<Ca&&(i-=a*Ca),r=Ue(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function Ue(n,t,e,r){var u,i,o=Math.sin(n-e);return ga(o)>Ca?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function je(n,t,e,r){var u;if(null==n)u=e*Ra,r.point(-qa,u),r.point(0,u),r.point(qa,u),r.point(qa,0),r.point(qa,-u),r.point(0,-u),r.point(-qa,-u),r.point(-qa,0),r.point(-qa,u);else if(ga(n[0]-t[0])>Ca){var i=n[0]<t[0]?qa:-qa;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Fe(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;yc.reset();for(var a=0,c=t.length;c>a;++a){var l=t[a],s=l.length;if(s)for(var f=l[0],h=f[0],g=f[1]/2+qa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===s&&(d=0),n=l[d];var m=n[0],y=n[1]/2+qa/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=b>=0?1:-1,w=_*b,S=w>qa,k=p*M;if(yc.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),i+=S?b+_*La:b,S^h>=e^m>=e){var E=de(pe(f),pe(n));Me(E);var A=de(u,E);Me(A);var N=(S^b>=0?-1:1)*tt(A[2]);(r>N||r===N&&(E[0]||E[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=m,p=M,v=x,f=n}}return(-Ca>i||Ca>i&&0>yc)^1&o}function He(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,l,s;return{lineStart:function(){l=c=!1,s=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?qa:-qa),h):0;if(!e&&(l=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(be(e,g)||be(p,g))&&(p[0]+=Ca,p[1]+=Ca,v=t(p[0],p[1]))),v!==c)s=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(s=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&be(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return s|(l&&c)<<1}}}function r(n,t,e){var r=pe(n),u=pe(t),o=[1,0,0],a=de(r,u),c=ve(a,a),l=a[0],s=c-l*l;if(!s)return!e&&n;var f=i*c/s,h=-i*l/s,g=de(o,a),p=ye(o,f),v=ye(a,h);me(p,v);var d=g,m=ve(p,d),y=ve(d,d),M=m*m-y*(ve(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=ye(d,(-m-x)/y);if(me(b,p),b=xe(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=ga(A-qa)<Ca,C=N||Ca>A;if(!N&&k>E&&(_=k,k=E,E=_),C?N?k+E>0^b[1]<(ga(b[0]-w)<Ca?k:E):k<=b[1]&&b[1]<=E:A>qa^(w<=b[0]&&b[0]<=S)){var z=ye(d,(-m+x)/y);return me(z,p),[b,xe(z)]}}}function u(t,e){var r=o?n:qa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ga(i)>Ca,c=gr(n,6*Da);return Le(t,e,c,o?[0,-n]:[-qa,n-qa])}function Oe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,l=o.y,s=a.x,f=a.y,h=0,g=1,p=s-c,v=f-l;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-l,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-l,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:l+h*v}),1>g&&(u.b={x:c+g*p,y:l+g*v}),u}}}}}}function Ie(n,t,e,r){function u(r,u){return ga(r[0]-n)<Ca?u>0?0:3:ga(r[0]-e)<Ca?u>0?2:1:ga(r[1]-t)<Ca?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,l=a[0];c>o;++o)i=a[o],l[1]<=r?i[1]>r&&Q(l,i,n)>0&&++t:i[1]<=r&&Q(l,i,n)<0&&--t,l=i;return 0!==t}function l(i,a,c,l){var s=0,f=0;if(null==i||(s=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do l.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+c+4)%4)!==f)}else l.point(a[0],a[1])}function s(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){s(n,t)&&a.point(n,t)}function h(){C.point=p,d&&d.push(m=[]),S=!0,w=!1,b=_=0/0}function g(){v&&(p(y,M),x&&w&&A.rejoin(),v.push(A.buffer())),C.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Tc,Math.min(Tc,n)),t=Math.max(-Tc,Math.min(Tc,t));var e=s(n,t);if(d&&m.push([n,t]),S)y=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};N(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,m,y,M,x,b,_,w,S,k,E=a,A=Re(),N=Oe(n,t,e,r),C={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=ta.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),l(null,null,1,a),a.lineEnd()),u&&Ce(v,i,t,l,a),a.polygonEnd()),v=d=m=null}};return C}}function Ye(n){var t=0,e=qa/3,r=ir(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*qa/180,e=n[1]*qa/180):[t/qa*180,e/qa*180]},u}function Ze(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,tt((i-(n*n+e*e)*u*u)/(2*u))]},e}function Ve(){function n(n,t){Dc+=u*n-r*t,r=n,u=t}var t,e,r,u;Hc.point=function(i,o){Hc.point=n,t=r=i,e=u=o},Hc.lineEnd=function(){n(t,e)}}function Xe(n,t){Pc>n&&(Pc=n),n>jc&&(jc=n),Uc>t&&(Uc=t),t>Fc&&(Fc=t)}function $e(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Be(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Be(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Be(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function We(n,t){_c+=n,wc+=t,++Sc}function Je(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);kc+=o*(t+n)/2,Ec+=o*(e+r)/2,Ac+=o,We(t=n,e=r)}var t,e;Ic.point=function(r,u){Ic.point=n,We(t=r,e=u)}}function Ge(){Ic.point=We}function Ke(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);kc+=o*(r+n)/2,Ec+=o*(u+t)/2,Ac+=o,o=u*n-r*t,Nc+=o*(r+n),Cc+=o*(u+t),zc+=3*o,We(r=n,u=t)}var t,e,r,u;Ic.point=function(i,o){Ic.point=n,We(t=r=i,e=u=o)},Ic.lineEnd=function(){n(t,e)}}function Qe(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,La)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function nr(n){function t(n){return(a?r:e)(n)}function e(t){return rr(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=0/0,S.point=i,t.lineStart()}function i(e,r){var i=pe([e,r]),o=n(e,r);u(M,x,y,b,_,w,M=o[0],x=o[1],y=e,b=i[0],_=i[1],w=i[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=l,S.lineEnd=s}function l(n,t){i(f=n,h=t),g=M,p=x,v=b,d=_,m=w,S.point=i}function s(){u(M,x,y,b,_,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c
1 },polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,l,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=a+g,_=c+p,w=l+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),E=ga(ga(w)-1)<Ca||ga(r-h)<Ca?(r+h)/2:Math.atan2(_,b),A=n(E,k),N=A[0],C=A[1],z=N-t,q=C-e,L=M*z-y*q;(L*L/x>i||ga((y*z+M*q)/x-.5)>.3||o>a*g+c*p+l*v)&&(u(t,e,r,a,c,l,N,C,E,b/=S,_/=S,w,d,m),m.point(N,C),u(N,C,E,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Da),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function tr(n){var t=nr(function(t,e){return n([t*Pa,e*Pa])});return function(n){return or(t(n))}}function er(n){this.stream=n}function rr(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ur(n){return ir(function(){return n})()}function ir(n){function t(n){return n=a(n[0]*Da,n[1]*Da),[n[0]*h+c,l-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(l-n[1])/h),n&&[n[0]*Pa,n[1]*Pa]}function r(){a=Ae(o=lr(m,M,x),i);var n=i(v,d);return c=g-n[0]*h,l=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,o,a,c,l,s,f=nr(function(n,t){return n=i(n,t),[n[0]*h+c,l-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,M=0,x=0,b=Lc,_=y,w=null,S=null;return t.stream=function(n){return s&&(s.valid=!1),s=or(b(o,f(_(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Lc):He((w=+n)*Da),u()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Ie(n[0][0],n[0][1],n[1][0],n[1][1]):y,u()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Da,d=n[1]%360*Da,r()):[v*Pa,d*Pa]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Da,M=n[1]%360*Da,x=n.length>2?n[2]%360*Da:0,r()):[m*Pa,M*Pa,x*Pa]},ta.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function or(n){return rr(n,function(t,e){n.point(t*Da,e*Da)})}function ar(n,t){return[n,t]}function cr(n,t){return[n>qa?n-La:-qa>n?n+La:n,t]}function lr(n,t,e){return n?t||e?Ae(fr(n),hr(t,e)):fr(n):t||e?hr(t,e):cr}function sr(n){return function(t,e){return t+=n,[t>qa?t-La:-qa>t?t+La:t,e]}}function fr(n){var t=sr(n);return t.invert=sr(-n),t}function hr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*r+a*u;return[Math.atan2(c*i-s*o,a*r-l*u),tt(s*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*i-c*o;return[Math.atan2(c*i+l*o,a*r+s*u),tt(s*r-a*u)]},e}function gr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=pr(e,u),i=pr(e,i),(o>0?i>u:u>i)&&(u+=o*La)):(u=n+o*La,i=n-.5*c);for(var l,s=u;o>0?s>i:i>s;s-=c)a.point((l=xe([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],l[1])}}function pr(n,t){var e=pe(t);e[0]-=n,Me(e);var r=nt(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Ca)%(2*Math.PI)}function vr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function dr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function mr(n){return n.source}function yr(n){return n.target}function Mr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),l=u*Math.sin(n),s=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(it(r-t)+u*o*it(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*s,u=e*l+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Pa,Math.atan2(o,Math.sqrt(r*r+u*u))*Pa]}:function(){return[n*Pa,t*Pa]};return p.distance=h,p}function xr(){function n(n,u){var i=Math.sin(u*=Da),o=Math.cos(u),a=ga((n*=Da)-t),c=Math.cos(a);Yc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Zc.point=function(u,i){t=u*Da,e=Math.sin(i*=Da),r=Math.cos(i),Zc.point=n},Zc.lineEnd=function(){Zc.point=Zc.lineEnd=b}}function br(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function _r(n,t){function e(n,t){o>0?-Ra+Ca>t&&(t=-Ra+Ca):t>Ra-Ca&&(t=Ra-Ca);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(qa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=K(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ra]},e):Sr}function wr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ga(u)<Ca?ar:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-K(u)*Math.sqrt(n*n+e*e)]},e)}function Sr(n,t){return[n,Math.log(Math.tan(qa/4+t/2))]}function kr(n){var t,e=ur(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=qa*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function Er(n,t){return[Math.log(Math.tan(qa/4+t/2)),-n]}function Ar(n){return n[0]}function Nr(n){return n[1]}function Cr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function zr(n,t){return n[0]-t[0]||n[1]-t[1]}function qr(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Lr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],l=e[1],s=t[1]-c,f=r[1]-l,h=(a*(c-l)-f*(u-i))/(f*o-a*s);return[u+h*o,c+h*s]}function Tr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Rr(){tu(this),this.edge=this.site=this.circle=null}function Dr(n){var t=el.pop()||new Rr;return t.site=n,t}function Pr(n){Xr(n),Qc.remove(n),el.push(n),tu(n)}function Ur(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Pr(n);for(var c=i;c.circle&&ga(e-c.circle.x)<Ca&&ga(r-c.circle.cy)<Ca;)i=c.P,a.unshift(c),Pr(c),c=i;a.unshift(c),Xr(c);for(var l=o;l.circle&&ga(e-l.circle.x)<Ca&&ga(r-l.circle.cy)<Ca;)o=l.N,a.push(l),Pr(l),l=o;a.push(l),Xr(l);var s,f=a.length;for(s=1;f>s;++s)l=a[s],c=a[s-1],Kr(l.edge,c.site,l.site,u);c=a[0],l=a[f-1],l.edge=Jr(c.site,l.site,null,u),Vr(c),Vr(l)}function jr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Qc._;a;)if(r=Fr(a,o)-i,r>Ca)a=a.L;else{if(u=i-Hr(a,o),!(u>Ca)){r>-Ca?(t=a.P,e=a):u>-Ca?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Dr(n);if(Qc.insert(t,c),t||e){if(t===e)return Xr(t),e=Dr(t.site),Qc.insert(c,e),c.edge=e.edge=Jr(t.site,c.site),Vr(t),void Vr(e);if(!e)return void(c.edge=Jr(t.site,c.site));Xr(t),Xr(e);var l=t.site,s=l.x,f=l.y,h=n.x-s,g=n.y-f,p=e.site,v=p.x-s,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,M=v*v+d*d,x={x:(d*y-g*M)/m+s,y:(h*M-v*y)/m+f};Kr(e.edge,l,p,x),c.edge=Jr(l,n,null,x),e.edge=Jr(n,p,null,x),Vr(t),Vr(e)}}function Fr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,l=c-t;if(!l)return a;var s=a-r,f=1/i-1/l,h=s/l;return f?(-h+Math.sqrt(h*h-2*f*(s*s/(-2*l)-c+l/2+u-i/2)))/f+r:(r+a)/2}function Hr(n,t){var e=n.N;if(e)return Fr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Or(n){this.site=n,this.edges=[]}function Ir(n){for(var t,e,r,u,i,o,a,c,l,s,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Kc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)s=a[o].end(),r=s.x,u=s.y,l=a[++o%c].start(),t=l.x,e=l.y,(ga(r-t)>Ca||ga(u-e)>Ca)&&(a.splice(o,0,new Qr(Gr(i.site,s,ga(r-f)<Ca&&p-u>Ca?{x:f,y:ga(t-f)<Ca?e:p}:ga(u-p)<Ca&&h-r>Ca?{x:ga(e-p)<Ca?t:h,y:p}:ga(r-h)<Ca&&u-g>Ca?{x:h,y:ga(t-h)<Ca?e:g}:ga(u-g)<Ca&&r-f>Ca?{x:ga(e-g)<Ca?t:f,y:g}:null),i.site,null)),++c)}function Yr(n,t){return t.angle-n.angle}function Zr(){tu(this),this.x=this.y=this.arc=this.site=this.cy=null}function Vr(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,l=r.y-a,s=i.x-o,f=i.y-a,h=2*(c*f-l*s);if(!(h>=-za)){var g=c*c+l*l,p=s*s+f*f,v=(f*g-l*p)/h,d=(c*p-s*g)/h,f=d+a,m=rl.pop()||new Zr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,M=tl._;M;)if(m.y<M.y||m.y===M.y&&m.x<=M.x){if(!M.L){y=M.P;break}M=M.L}else{if(!M.R){y=M;break}M=M.R}tl.insert(y,m),y||(nl=m)}}}}function Xr(n){var t=n.circle;t&&(t.P||(nl=t.N),tl.remove(t),rl.push(t),tu(t),n.circle=null)}function $r(n){for(var t,e=Gc,r=Oe(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Br(t,n)||!r(t)||ga(t.a.x-t.b.x)<Ca&&ga(t.a.y-t.b.y)<Ca)&&(t.a=t.b=null,e.splice(u,1))}function Br(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],l=t[1][1],s=n.l,f=n.r,h=s.x,g=s.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=l)return}else i={x:d,y:c};e={x:d,y:l}}else{if(i){if(i.y<c)return}else i={x:d,y:l};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=l)return}else i={x:(c-u)/r,y:c};e={x:(l-u)/r,y:l}}else{if(i){if(i.y<c)return}else i={x:(l-u)/r,y:l};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Wr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Jr(n,t,e,r){var u=new Wr(n,t);return Gc.push(u),e&&Kr(u,n,t,e),r&&Kr(u,t,n,r),Kc[n.i].edges.push(new Qr(u,n,t)),Kc[t.i].edges.push(new Qr(u,t,n)),u}function Gr(n,t,e){var r=new Wr(n,null);return r.a=t,r.b=e,Gc.push(r),r}function Kr(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Qr(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function nu(){this._=null}function tu(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function eu(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function ru(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function uu(n){for(;n.L;)n=n.L;return n}function iu(n,t){var e,r,u,i=n.sort(ou).pop();for(Gc=[],Kc=new Array(n.length),Qc=new nu,tl=new nu;;)if(u=nl,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Kc[i.i]=new Or(i),jr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;Ur(u.arc)}t&&($r(t),Ir(t));var o={cells:Kc,edges:Gc};return Qc=tl=Gc=Kc=null,o}function ou(n,t){return t.y-n.y||t.x-n.x}function au(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function cu(n){return n.x}function lu(n){return n.y}function su(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function fu(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&fu(n,c[0],e,r,o,a),c[1]&&fu(n,c[1],o,r,u,a),c[2]&&fu(n,c[2],e,a,o,i),c[3]&&fu(n,c[3],o,a,u,i)}}function hu(n,t,e,r,u,i,o){var a,c=1/0;return function l(n,s,f,h,g){if(!(s>i||f>o||r>h||u>g)){if(p=n.point){var p,v=t-n.x,d=e-n.y,m=v*v+d*d;if(c>m){var y=Math.sqrt(c=m);r=t-y,u=e-y,i=t+y,o=e+y,a=p}}for(var M=n.nodes,x=.5*(s+h),b=.5*(f+g),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:l(n,s,f,x,b);break;case 1:l(n,x,f,h,b);break;case 2:l(n,s,b,x,g);break;case 3:l(n,x,b,h,g)}}}(n,r,u,i,o),a}function gu(n,t){n=ta.rgb(n),t=ta.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+xt(Math.round(e+i*n))+xt(Math.round(r+o*n))+xt(Math.round(u+a*n))}}function pu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=mu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function vu(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function du(n,t){var e,r,u,i=il.lastIndex=ol.lastIndex=0,o=-1,a=[],c=[];for(n+="",t+="";(e=il.exec(n))&&(r=ol.exec(t));)(u=r.index)>i&&(u=t.slice(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:vu(e,r)})),i=ol.lastIndex;return i<t.length&&(u=t.slice(i),a[o]?a[o]+=u:a[++o]=u),a.length<2?c[0]?(t=c[0].x,function(n){return t(n)+""}):function(){return t}:(t=c.length,function(n){for(var e,r=0;t>r;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function mu(n,t){for(var e,r=ta.interpolators.length;--r>=0&&!(e=ta.interpolators[r](n,t)););return e}function yu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(mu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function Mu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function xu(n){return function(t){return 1-n(1-t)}}function bu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function _u(n){return n*n}function wu(n){return n*n*n}function Su(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function ku(n){return function(t){return Math.pow(t,n)}}function Eu(n){return 1-Math.cos(n*Ra)}function Au(n){return Math.pow(2,10*(n-1))}function Nu(n){return 1-Math.sqrt(1-n*n)}function Cu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/La*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*La/t)}}function zu(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function qu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Lu(n,t){n=ta.hcl(n),t=ta.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return st(e+i*n,r+o*n,u+a*n)+""}}function Tu(n,t){n=ta.hsl(n),t=ta.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function Ru(n,t){n=ta.lab(n),t=ta.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ht(e+i*n,r+o*n,u+a*n)+""}}function Du(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Pu(n){var t=[n.a,n.b],e=[n.c,n.d],r=ju(t),u=Uu(t,e),i=ju(Fu(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Pa,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*Pa:0}function Uu(n,t){return n[0]*t[0]+n[1]*t[1]}function ju(n){var t=Math.sqrt(Uu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Fu(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Hu(n,t){var e,r=[],u=[],i=ta.transform(n),o=ta.transform(t),a=i.translate,c=o.translate,l=i.rotate,s=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:vu(a[0],c[0])},{i:3,x:vu(a[1],c[1])})):r.push(c[0]||c[1]?"translate("+c+")":""),l!=s?(l-s>180?s+=360:s-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:vu(l,s)})):s&&r.push(r.pop()+"rotate("+s+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:vu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:vu(g[0],p[0])},{i:e-2,x:vu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Ou(n,t){return t=(t-=n=+n)||1/t,function(e){return(e-n)/t}}function Iu(n,t){return t=(t-=n=+n)||1/t,function(e){return Math.max(0,Math.min(1,(e-n)/t))}}function Yu(n){for(var t=n.source,e=n.target,r=Vu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Zu(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Vu(n,t){if(n===t)return n;for(var e=Zu(n),r=Zu(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Xu(n){n.fixed|=2}function $u(n){n.fixed&=-7}function Bu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Wu(n){n.fixed&=-5}function Ju(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Ju(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var l=t*e[n.point.index];n.charge+=n.pointCharge=l,r+=l*n.point.x,u+=l*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Gu(n,t){return ta.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=ri,n}function Ku(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(u=n.children)&&(r=u.length))for(var r,u;--r>=0;)e.push(u[r])}function Qu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++o<u;)e.push(i[o]);for(;null!=(n=r.pop());)t(n)}function ni(n){return n.children}function ti(n){return n.value}function ei(n,t){return t.value-n.value}function ri(n){return ta.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function ui(n){return n.x}function ii(n){return n.y}function oi(n,t,e){n.y0=t,n.y=e}function ai(n){return ta.range(n.length)}function ci(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function li(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function si(n){return n.reduce(fi,0)}function fi(n,t){return n+t[1]}function hi(n,t){return gi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function gi(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function pi(n){return[ta.min(n),ta.max(n)]}function vi(n,t){return n.value-t.value}function di(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function mi(n,t){n._pack_next=t,t._pack_prev=n}function yi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Mi(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,u,i,o,a,c,l,s=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(xi),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(u=e[1],u.x=u.r,u.y=0,t(u),l>2))for(i=e[2],wi(r,u,i),t(i),di(r,i),r._pack_prev=i,di(i,u),u=r._pack_next,o=3;l>o;o++){wi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(yi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!yi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?mi(r,u=a):mi(r=c,u),o--):(di(r,i),u=i,t(i))}var m=(s+f)/2,y=(h+g)/2,M=0;for(o=0;l>o;o++)i=e[o],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(bi)}}function xi(n){n._pack_next=n._pack_prev=n}function bi(n){delete n._pack_next,delete n._pack_prev}function _i(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)_i(u[i],t,e,r)}function wi(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),l=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+l*i,e.y=n.y+c*i-l*u}else e.x=n.x+r,e.y=n.y}function Si(n,t){return n.parent==t.parent?1:2}function ki(n){var t=n.children;return t.length?t[0]:n.t}function Ei(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function Ai(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function Ni(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Ci(n,t,e){return n.a.parent===t.parent?n.a:e}function zi(n){return 1+ta.max(n,function(n){return n.y})}function qi(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Li(n){var t=n.children;return t&&t.length?Li(t[0]):n}function Ti(n){var t,e=n.children;return e&&(t=e.length)?Ti(e[t-1]):n}function Ri(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Di(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Pi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ui(n){return n.rangeExtent?n.rangeExtent():Pi(n.range())}function ji(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Fi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Hi(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ml}function Oi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=ta.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Ii(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?Oi:ji,c=r?Iu:Ou;return o=u(n,t,c,e),a=u(t,n,c,mu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Du)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Xi(n,t)},i.tickFormat=function(t,e){return $i(n,t,e)},i.nice=function(t){return Zi(n,t),u()},i.copy=function(){return Ii(n,t,e,r)},u()}function Yi(n,t){return ta.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Zi(n,t){return Fi(n,Hi(Vi(n,t)[2]))}function Vi(n,t){null==t&&(t=10);var e=Pi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Xi(n,t){return ta.range.apply(ta,Vi(n,t))}function $i(n,t,e){var r=Vi(n,t);if(e){var u=ic.exec(e);if(u.shift(),"s"===u[8]){var i=ta.formatPrefix(Math.max(ga(r[0]),ga(r[1])));return u[7]||(u[7]="."+Bi(i.scale(r[2]))),u[8]="f",e=ta.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Wi(u[8],r)),e=u.join("")}else e=",."+Bi(r[2])+"f";return ta.format(e)}function Bi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Wi(n,t){var e=Bi(t[2]);return n in yl?Math.abs(e-Bi(Math.max(ga(t[0]),ga(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Ji(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Fi(r.map(u),e?Math:xl);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Pi(r),o=[],a=n[0],c=n[1],l=Math.floor(u(a)),s=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(s-l)){if(e){for(;s>l;l++)for(var h=1;f>h;h++)o.push(i(l)*h);o.push(i(l))}else for(o.push(i(l));l++<s;)for(var h=f-1;h>0;h--)o.push(i(l)*h);for(l=0;o[l]<a;l++);for(s=o.length;o[s-1]>c;s--);o=o.slice(l,s)}return o},o.tickFormat=function(n,t){if(!arguments.length)return Ml;arguments.length<2?t=Ml:"function"!=typeof t&&(t=ta.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Ji(n.copy(),t,e,r)},Yi(o,n)}function Gi(n,t,e){function r(t){return n(u(t))}var u=Ki(t),i=Ki(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Xi(e,n)},r.tickFormat=function(n,t){return $i(e,n,t)},r.nice=function(n){return r.domain(Zi(e,n))},r.exponent=function(o){return arguments.length?(u=Ki(t=o),i=Ki(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Gi(n.copy(),t,e)},Yi(r,n)}function Ki(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Qi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return ta.range(n.length).map(function(n){return t+e*n})}var u,i,o;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new l;for(var i,o=-1,a=r.length;++o<a;)u.has(i=r[o])||u.set(i,n.push(i));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(i=n,o=0,t={t:"range",a:arguments},e):i},e.rangePoints=function(u,a){arguments.length<2&&(a=0);var c=u[0],l=u[1],s=n.length<2?(c=(c+l)/2,0):(l-c)/(n.length-1+a);return i=r(c+s*a/2,s),o=0,t={t:"rangePoints",a:arguments},e},e.rangeRoundPoints=function(u,a){arguments.length<2&&(a=0);var c=u[0],l=u[1],s=n.length<2?(c=l=Math.round((c+l)/2),0):(l-c)/(n.length-1+a)|0;return i=r(c+Math.round(s*a/2+(l-c-(n.length-1+a)*s)/2),s),o=0,t={t:"rangeRoundPoints",a:arguments},e},e.rangeBands=function(u,a,c){arguments.length<2&&(a=0),arguments.length<3&&(c=a);var l=u[1]<u[0],s=u[l-0],f=u[1-l],h=(f-s)/(n.length-a+2*c);return i=r(s+h*c,h),l&&i.reverse(),o=h*(1-a),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,a,c){arguments.length<2&&(a=0),arguments.length<3&&(c=a);var l=u[1]<u[0],s=u[l-0],f=u[1-l],h=Math.floor((f-s)/(n.length-a+2*c));return i=r(s+Math.round((f-s-(n.length-a)*h)/2),h),l&&i.reverse(),o=Math.round(h*(1-a)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Pi(t.a[0])},e.copy=function(){return Qi(n,t)},e.domain(n)}function no(n,t){function i(){var e=0,r=t.length;for(a=[];++e<r;)a[e-1]=ta.quantile(n,e/r);return o}function o(n){return isNaN(n=+n)?void 0:t[ta.bisect(a,n)]}var a;return o.domain=function(t){return arguments.length?(n=t.map(r).filter(u).sort(e),i()):n},o.range=function(n){return arguments.length?(t=n,i()):t},o.quantiles=function(){return a},o.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?a[e-1]:n[0],e<a.length?a[e]:n[n.length-1]]},o.copy=function(){return no(n,t)},i()}function to(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return to(n,t,e)},u()}function eo(n,t){function e(e){return e>=e?t[ta.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return eo(n,t)},e}function ro(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Xi(n,t)},t.tickFormat=function(t,e){return $i(n,t,e)},t.copy=function(){return ro(n)},t}function uo(){return 0}function io(n){return n.innerRadius}function oo(n){return n.outerRadius}function ao(n){return n.startAngle}function co(n){return n.endAngle}function lo(n){return n&&n.padAngle}function so(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function fo(n,t,e,r,u){var i=n[0]-t[0],o=n[1]-t[1],a=(u?r:-r)/Math.sqrt(i*i+o*o),c=a*o,l=-a*i,s=n[0]+c,f=n[1]+l,h=t[0]+c,g=t[1]+l,p=(s+h)/2,v=(f+g)/2,d=h-s,m=g-f,y=d*d+m*m,M=e-r,x=s*g-h*f,b=(0>m?-1:1)*Math.sqrt(M*M*y-x*x),_=(x*m-d*b)/y,w=(-x*d-m*b)/y,S=(x*m+d*b)/y,k=(-x*d+m*b)/y,E=_-p,A=w-v,N=S-p,C=k-v;return E*E+A*A>N*N+C*C&&(_=S,w=k),[[_-c,w-l],[_*e/M,w*e/M]]}function ho(n){function t(t){function o(){l.push("M",i(n(s),a))}for(var c,l=[],s=[],f=-1,h=t.length,g=Et(e),p=Et(r);++f<h;)u.call(this,c=t[f],f)?s.push([+g.call(this,c,f),+p.call(this,c,f)]):s.length&&(o(),s=[]);return s.length&&o(),l.length?l.join(""):null}var e=Ar,r=Nr,u=Ne,i=go,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=El.get(n)||go).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function go(n){return n.join("L")}function po(n){return go(n)+"Z"}function vo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function mo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function yo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function Mo(n,t){return n.length<4?go(n):n[1]+_o(n.slice(1,-1),wo(n,t))}function xo(n,t){return n.length<3?go(n):n[0]+_o((n.push(n[0]),n),wo([n[n.length-2]].concat(n,[n[1]]),t))}function bo(n,t){return n.length<3?go(n):n[0]+_o(n,wo(n,t))}function _o(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return go(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var l=2;l<t.length;l++,c++)i=n[c],a=t[l],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var s=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+s[0]+","+s[1]}return r}function wo(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function So(n){if(n.length<3)return go(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",No(Cl,o),",",No(Cl,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),Co(c,o,a);return n.pop(),c.push("L",r),c.join("")}function ko(n){if(n.length<4)return go(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(No(Cl,i)+","+No(Cl,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),Co(e,i,o);return e.join("")}function Eo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[No(Cl,o),",",No(Cl,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),Co(t,o,a);return t.join("")}function Ao(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,l=-1;++l<=e;)r=n[l],u=l/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return So(n)}function No(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Co(n,t,e){n.push("C",No(Al,t),",",No(Al,e),",",No(Nl,t),",",No(Nl,e),",",No(Cl,t),",",No(Cl,e))}function zo(n,t){return(t[1]-n[1])/(t[0]-n[0])}function qo(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=zo(u,i);++t<e;)r[t]=(o+(o=zo(u=i,i=n[t+1])))/2;return r[t]=o,r}function Lo(n){for(var t,e,r,u,i=[],o=qo(n),a=-1,c=n.length-1;++a<c;)t=zo(n[a],n[a+1]),ga(t)<Ca?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function To(n){return n.length<3?go(n):n[0]+_o(n,Lo(n))}function Ro(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]-Ra,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Do(n){function t(t){function c(){v.push("M",a(n(m),f),s,l(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,M=t.length,x=Et(e),b=Et(u),_=e===r?function(){return g}:Et(r),w=u===i?function(){return p}:Et(i);++y<M;)o.call(this,h=t[y],y)?(d.push([g=+x.call(this,h,y),p=+b.call(this,h,y)]),m.push([+_.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=Ar,r=Ar,u=0,i=Nr,o=Ne,a=go,c=a.key,l=a,s="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r
2 },t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=El.get(n)||go).key,l=a.reverse||a,s=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function Po(n){return n.radius}function Uo(n){return[n.x,n.y]}function jo(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]-Ra;return[e*Math.cos(r),e*Math.sin(r)]}}function Fo(){return 64}function Ho(){return"circle"}function Oo(n){var t=Math.sqrt(n/qa);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Io(n){return function(){var t,e;(t=this[n])&&(e=t[t.active])&&(--t.count?delete t[t.active]:delete this[n],t.active+=.5,e.event&&e.event.interrupt.call(this,this.__data__,e.index))}}function Yo(n,t,e){return ya(n,Pl),n.namespace=t,n.id=e,n}function Zo(n,t,e,r){var u=n.id,i=n.namespace;return Y(n,"function"==typeof e?function(n,o,a){n[i][u].tween.set(t,r(e.call(n,n.__data__,o,a)))}:(e=r(e),function(n){n[i][u].tween.set(t,e)}))}function Vo(n){return null==n&&(n=""),function(){this.textContent=n}}function Xo(n){return null==n?"__transition__":"__transition_"+n+"__"}function $o(n,t,e,r,u){var i=n[e]||(n[e]={active:0,count:0}),o=i[r];if(!o){var a=u.time;o=i[r]={tween:new l,time:a,delay:u.delay,duration:u.duration,ease:u.ease,index:t},u=null,++i.count,ta.timer(function(u){function c(e){if(i.active>r)return s();var u=i[i.active];u&&(--i.count,delete i[i.active],u.event&&u.event.interrupt.call(n,n.__data__,u.index)),i.active=r,o.event&&o.event.start.call(n,n.__data__,t),o.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&v.push(r)}),h=o.ease,f=o.duration,ta.timer(function(){return p.c=l(e||1)?Ne:l,1},0,a)}function l(e){if(i.active!==r)return 1;for(var u=e/f,a=h(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,n.__data__,t),s()):void 0}function s(){return--i.count?delete i[r]:delete n[e],1}var f,h,g=o.delay,p=ec,v=[];return p.t=g+a,u>=g?c(u-g):void(p.c=c)},0,a)}}function Bo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function Wo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function Jo(n){return n.toISOString()}function Go(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=ta.bisect(Vl,u);return i==Vl.length?[t.year,Vi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Vl[i-1]<Vl[i]/u?i-1:i]:[Bl,Vi(n,e)[2]]}return r.invert=function(t){return Ko(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Ko)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Ko(+e+1),t).length}var i=r.domain(),o=Pi(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Fi(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Ko(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Ko(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Pi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Ko(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Go(n.copy(),t,e)},Yi(r,n)}function Ko(n){return new Date(n)}function Qo(n){return JSON.parse(n.responseText)}function na(n){var t=ua.createRange();return t.selectNode(ua.body),t.createContextualFragment(n.responseText)}var ta={version:"3.5.5"},ea=[].slice,ra=function(n){return ea.call(n)},ua=this.document;if(ua)try{ra(ua.documentElement.childNodes)[0].nodeType}catch(ia){ra=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),ua)try{ua.createElement("DIV").style.setProperty("opacity",0,"")}catch(oa){var aa=this.Element.prototype,ca=aa.setAttribute,la=aa.setAttributeNS,sa=this.CSSStyleDeclaration.prototype,fa=sa.setProperty;aa.setAttribute=function(n,t){ca.call(this,n,t+"")},aa.setAttributeNS=function(n,t,e){la.call(this,n,t,e+"")},sa.setProperty=function(n,t,e){fa.call(this,n,t+"",e)}}ta.ascending=e,ta.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},ta.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i;)if(null!=(r=n[u])&&r>=r){e=r;break}for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=r;break}for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},ta.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i;)if(null!=(r=n[u])&&r>=r){e=r;break}for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=r;break}for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},ta.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o;)if(null!=(r=n[i])&&r>=r){e=u=r;break}for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=u=r;break}for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},ta.sum=function(n,t){var e,r=0,i=n.length,o=-1;if(1===arguments.length)for(;++o<i;)u(e=+n[o])&&(r+=e);else for(;++o<i;)u(e=+t.call(n,n[o],o))&&(r+=e);return r},ta.mean=function(n,t){var e,i=0,o=n.length,a=-1,c=o;if(1===arguments.length)for(;++a<o;)u(e=r(n[a]))?i+=e:--c;else for(;++a<o;)u(e=r(t.call(n,n[a],a)))?i+=e:--c;return c?i/c:void 0},ta.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},ta.median=function(n,t){var i,o=[],a=n.length,c=-1;if(1===arguments.length)for(;++c<a;)u(i=r(n[c]))&&o.push(i);else for(;++c<a;)u(i=r(t.call(n,n[c],c)))&&o.push(i);return o.length?ta.quantile(o.sort(e),.5):void 0},ta.variance=function(n,t){var e,i,o=n.length,a=0,c=0,l=-1,s=0;if(1===arguments.length)for(;++l<o;)u(e=r(n[l]))&&(i=e-a,a+=i/++s,c+=i*(e-a));else for(;++l<o;)u(e=r(t.call(n,n[l],l)))&&(i=e-a,a+=i/++s,c+=i*(e-a));return s>1?c/(s-1):void 0},ta.deviation=function(){var n=ta.variance.apply(this,arguments);return n?Math.sqrt(n):n};var ha=i(e);ta.bisectLeft=ha.left,ta.bisect=ta.bisectRight=ha.right,ta.bisector=function(n){return i(1===n.length?function(t,r){return e(n(t),r)}:n)},ta.shuffle=function(n,t,e){(i=arguments.length)<3&&(e=n.length,2>i&&(t=0));for(var r,u,i=e-t;i;)u=Math.random()*i--|0,r=n[i+t],n[i+t]=n[u+t],n[u+t]=r;return n},ta.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ta.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},ta.zip=function(){if(!(r=arguments.length))return[];for(var n=-1,t=ta.min(arguments,o),e=new Array(t);++n<t;)for(var r,u=-1,i=e[n]=new Array(r);++u<r;)i[u]=arguments[u][n];return e},ta.transpose=function(n){return ta.zip.apply(ta,n)},ta.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ta.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ta.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ta.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ga=Math.abs;ta.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,u=[],i=a(ga(e)),o=-1;if(n*=i,t*=i,e*=i,0>e)for(;(r=n+e*++o)>t;)u.push(r/i);else for(;(r=n+e*++o)<t;)u.push(r/i);return u},ta.map=function(n,t){var e=new l;if(n instanceof l)n.forEach(function(n,t){e.set(n,t)});else if(Array.isArray(n)){var r,u=-1,i=n.length;if(1===arguments.length)for(;++u<i;)e.set(u,n[u]);else for(;++u<i;)e.set(t.call(n,r=n[u],u),r)}else for(var o in n)e.set(o,n[o]);return e};var pa="__proto__",va="\x00";c(l,{has:h,get:function(n){return this._[s(n)]},set:function(n,t){return this._[s(n)]=t},remove:g,keys:p,values:function(){var n=[];for(var t in this._)n.push(this._[t]);return n},entries:function(){var n=[];for(var t in this._)n.push({key:f(t),value:this._[t]});return n},size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t),this._[t])}}),ta.nest=function(){function n(t,o,a){if(a>=i.length)return r?r.call(u,o):e?o.sort(e):o;for(var c,s,f,h,g=-1,p=o.length,v=i[a++],d=new l;++g<p;)(h=d.get(c=v(s=o[g])))?h.push(s):d.set(c,[s]);return t?(s=t(),f=function(e,r){s.set(e,n(t,r,a))}):(s={},f=function(e,r){s[e]=n(t,r,a)}),d.forEach(f),s}function t(n,e){if(e>=i.length)return n;var r=[],u=o[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],o=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(ta.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return o[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},ta.set=function(n){var t=new m;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},c(m,{has:h,add:function(n){return this._[s(n+="")]=!0,n},remove:g,values:p,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t))}}),ta.behavior={},ta.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=M(n,t,t[e]);return n};var da=["webkit","ms","moz","Moz","o","O"];ta.dispatch=function(){for(var n=new _,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=w(n);return n},_.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ta.event=null,ta.requote=function(n){return n.replace(ma,"\\$&")};var ma=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ya={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},Ma=function(n,t){return t.querySelector(n)},xa=function(n,t){return t.querySelectorAll(n)},ba=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(ba=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(Ma=function(n,t){return Sizzle(n,t)[0]||null},xa=Sizzle,ba=Sizzle.matchesSelector),ta.selection=function(){return ta.select(ua.documentElement)};var _a=ta.selection.prototype=[];_a.select=function(n){var t,e,r,u,i=[];n=N(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,l=r.length;++c<l;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return A(i)},_a.selectAll=function(n){var t,e,r=[];n=C(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=ra(n.call(e,e.__data__,a,u))),t.parentNode=e);return A(r)};var wa={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};ta.ns={prefix:wa,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.slice(0,t),n=n.slice(t+1)),wa.hasOwnProperty(e)?{space:wa[e],local:n}:n}},_a.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ta.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},_a.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!L(n[u]).test(t))return!1;return!0}for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},_a.style=function(n,e,r){var u=arguments.length;if(3>u){if("string"!=typeof n){2>u&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>u){var i=this.node();return t(i).getComputedStyle(i,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},_a.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(U(t,n[t]));return this}return this.each(U(n,t))},_a.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},_a.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},_a.append=function(n){return n=j(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},_a.insert=function(n,t){return n=j(n),t=N(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},_a.remove=function(){return this.each(F)},_a.data=function(n,t){function e(n,e){var r,u,i,o=n.length,f=e.length,h=Math.min(o,f),g=new Array(f),p=new Array(f),v=new Array(o);if(t){var d,m=new l,y=new Array(o);for(r=-1;++r<o;)m.has(d=t.call(u=n[r],u.__data__,r))?v[r]=u:m.set(d,u),y[r]=d;for(r=-1;++r<f;)(u=m.get(d=t.call(e,i=e[r],r)))?u!==!0&&(g[r]=u,u.__data__=i):p[r]=H(i),m.set(d,!0);for(r=-1;++r<o;)m.get(y[r])!==!0&&(v[r]=n[r])}else{for(r=-1;++r<h;)u=n[r],i=e[r],u?(u.__data__=i,g[r]=u):p[r]=H(i);for(;f>r;++r)p[r]=H(e[r]);for(;o>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,a.push(p),c.push(g),s.push(v)}var r,u,i=-1,o=this.length;if(!arguments.length){for(n=new Array(o=(r=this[0]).length);++i<o;)(u=r[i])&&(n[i]=u.__data__);return n}var a=Z([]),c=A([]),s=A([]);if("function"==typeof n)for(;++i<o;)e(r=this[i],n.call(r,r.parentNode.__data__,i));else for(;++i<o;)e(r=this[i],n);return c.enter=function(){return a},c.exit=function(){return s},c},_a.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},_a.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=O(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return A(u)},_a.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},_a.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},_a.each=function(n){return Y(this,function(t,e,r){n.call(t,t.__data__,e,r)})},_a.call=function(n){var t=ra(arguments);return n.apply(t[0]=this,t),this},_a.empty=function(){return!this.node()},_a.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},_a.size=function(){var n=0;return Y(this,function(){++n}),n};var Sa=[];ta.selection.enter=Z,ta.selection.enter.prototype=Sa,Sa.append=_a.append,Sa.empty=_a.empty,Sa.node=_a.node,Sa.call=_a.call,Sa.size=_a.size,Sa.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var l=-1,s=u.length;++l<s;)(i=u[l])?(t.push(r[l]=e=n.call(u.parentNode,i.__data__,l,a)),e.__data__=i.__data__):t.push(null)}return A(o)},Sa.insert=function(n,t){return arguments.length<2&&(t=V(this)),_a.insert.call(this,n,t)},ta.select=function(t){var e;return"string"==typeof t?(e=[Ma(t,ua)],e.parentNode=ua.documentElement):(e=[t],e.parentNode=n(t)),A([e])},ta.selectAll=function(n){var t;return"string"==typeof n?(t=ra(xa(n,ua)),t.parentNode=ua.documentElement):(t=n,t.parentNode=null),A([t])},_a.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var ka=ta.map({mouseenter:"mouseover",mouseleave:"mouseout"});ua&&ka.forEach(function(n){"on"+n in ua&&ka.remove(n)});var Ea,Aa=0;ta.mouse=function(n){return J(n,k())};var Na=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;ta.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return J(n,r)},ta.behavior.drag=function(){function n(){this.on("mousedown.drag",i).on("touchstart.drag",o)}function e(n,t,e,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],p|=n|e,M=r,g({type:"drag",x:r[0]+l[0],y:r[1]+l[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&ta.event.target===f),g({type:"dragend"}))}var l,s=this,f=ta.event.target,h=s.parentNode,g=r.of(s,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=ta.select(e(f)).on(i+d,a).on(o+d,c),y=W(f),M=t(h,v);u?(l=u.apply(s,arguments),l=[l.x-M[0],l.y-M[1]]):l=[0,0],g({type:"dragstart"})}}var r=E(n,"drag","dragstart","dragend"),u=null,i=e(b,ta.mouse,t,"mousemove","mouseup"),o=e(G,ta.touch,y,"touchmove","touchend");return n.origin=function(t){return arguments.length?(u=t,n):u},ta.rebind(n,r,"on")},ta.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?ra(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Ca=1e-6,za=Ca*Ca,qa=Math.PI,La=2*qa,Ta=La-Ca,Ra=qa/2,Da=qa/180,Pa=180/qa,Ua=Math.SQRT2,ja=2,Fa=4;ta.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=rt(v),o=i/(ja*h)*(e*ut(Ua*t+v)-et(v));return[r+o*l,u+o*s,i*e/rt(Ua*t+v)]}return[r+n*l,u+n*s,i*Math.exp(Ua*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],l=o-r,s=a-u,f=l*l+s*s,h=Math.sqrt(f),g=(c*c-i*i+Fa*f)/(2*i*ja*h),p=(c*c-i*i-Fa*f)/(2*c*ja*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ua;return e.duration=1e3*y,e},ta.behavior.zoom=function(){function n(n){n.on(q,f).on(Oa+".zoom",g).on("dblclick.zoom",p).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function u(n){k.k=Math.max(N[0],Math.min(N[1],n))}function i(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function o(t,e,r,o){t.__chart__={x:k.x,y:k.y,k:k.k},u(Math.pow(2,o)),i(d=e,r),t=ta.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function a(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function c(n){z++||n({type:"zoomstart"})}function l(n){a(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function s(n){--z||n({type:"zoomend"}),d=null}function f(){function n(){f=1,i(ta.mouse(u),g),l(a)}function r(){h.on(L,null).on(T,null),p(f&&ta.event.target===o),s(a)}var u=this,o=ta.event.target,a=D.of(u,arguments),f=0,h=ta.select(t(u)).on(L,n).on(T,r),g=e(ta.mouse(u)),p=W(u);Dl.call(u),c(a)}function h(){function n(){var n=ta.touches(p);return g=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=ta.event.target;ta.select(t).on(x,r).on(b,a),_.push(t);for(var e=ta.event.changedTouches,u=0,i=e.length;i>u;++u)d[e[u].identifier]=null;var c=n(),l=Date.now();if(1===c.length){if(500>l-M){var s=c[0];o(p,s,d[s.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=l}else if(c.length>1){var s=c[0],f=c[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function r(){var n,t,e,r,o=ta.touches(p);Dl.call(p);for(var a=0,c=o.length;c>a;++a,r=null)if(e=o[a],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],u(f*g)}M=null,i(n,t),l(v)}function a(){if(ta.event.touches.length){for(var t=ta.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var u in d)return void n()}ta.selectAll(_).on(y,null),w.on(q,f).on(R,h),E(),s(v)}var g,p=this,v=D.of(p,arguments),d={},m=0,y=".zoom-"+ta.event.changedTouches[0].identifier,x="touchmove"+y,b="touchend"+y,_=[],w=ta.select(p),E=W(p);t(),c(v),w.on(q,null).on(R,t)}function g(){var n=D.of(this,arguments);y?clearTimeout(y):(v=e(d=m||ta.mouse(this)),Dl.call(this),c(n)),y=setTimeout(function(){y=null,s(n)},50),S(),u(Math.pow(2,.002*Ha())*k.k),i(d,v),l(n)}function p(){var n=ta.mouse(this),t=Math.log(k.k)/Math.LN2;o(this,n,e(n),ta.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,m,y,M,x,b,_,w,k={x:0,y:0,k:1},A=[960,500],N=Ia,C=250,z=0,q="mousedown.zoom",L="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=E(n,"zoomstart","zoom","zoomend");return Oa||(Oa="onwheel"in ua?(Ha=function(){return-ta.event.deltaY*(ta.event.deltaMode?120:1)},"wheel"):"onmousewheel"in ua?(Ha=function(){return ta.event.wheelDelta},"mousewheel"):(Ha=function(){return-ta.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Tl?ta.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},c(n)}).tween("zoom:zoom",function(){var e=A[0],r=A[1],u=d?d[0]:e/2,i=d?d[1]:r/2,o=ta.interpolateZoom([(u-k.x)/k.k,(i-k.y)/k.k,e/k.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),a=e/r[2];this.__chart__=k={x:u-r[0]*a,y:i-r[1]*a,k:a},l(n)}}).each("interrupt.zoom",function(){s(n)}).each("end.zoom",function(){s(n)}):(this.__chart__=k,c(n),l(n),s(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},a(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:+t},a(),n):k.k},n.scaleExtent=function(t){return arguments.length?(N=null==t?Ia:[+t[0],+t[1]],n):N},n.center=function(t){return arguments.length?(m=t&&[+t[0],+t[1]],n):m},n.size=function(t){return arguments.length?(A=t&&[+t[0],+t[1]],n):A},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},ta.rebind(n,D,"on")};var Ha,Oa,Ia=[0,1/0];ta.color=ot,ot.prototype.toString=function(){return this.rgb()+""},ta.hsl=at;var Ya=at.prototype=new ot;Ya.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new at(this.h,this.s,this.l/n)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new at(this.h,this.s,n*this.l)},Ya.rgb=function(){return ct(this.h,this.s,this.l)},ta.hcl=lt;var Za=lt.prototype=new ot;Za.brighter=function(n){return new lt(this.h,this.c,Math.min(100,this.l+Va*(arguments.length?n:1)))},Za.darker=function(n){return new lt(this.h,this.c,Math.max(0,this.l-Va*(arguments.length?n:1)))},Za.rgb=function(){return st(this.h,this.c,this.l).rgb()},ta.lab=ft;var Va=18,Xa=.95047,$a=1,Ba=1.08883,Wa=ft.prototype=new ot;Wa.brighter=function(n){return new ft(Math.min(100,this.l+Va*(arguments.length?n:1)),this.a,this.b)},Wa.darker=function(n){return new ft(Math.max(0,this.l-Va*(arguments.length?n:1)),this.a,this.b)},Wa.rgb=function(){return ht(this.l,this.a,this.b)},ta.rgb=mt;var Ja=mt.prototype=new ot;Ja.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new mt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new mt(u,u,u)},Ja.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new mt(n*this.r,n*this.g,n*this.b)},Ja.hsl=function(){return _t(this.r,this.g,this.b)},Ja.toString=function(){return"#"+xt(this.r)+xt(this.g)+xt(this.b)};var Ga=ta.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ga.forEach(function(n,t){Ga.set(n,yt(t))}),ta.functor=Et,ta.xhr=At(y),ta.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=Nt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=l)return o;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++<l;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}s=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++s):10===r&&(u=!0),n.slice(t+1,e).replace(/""/g,'"')}for(;l>s;){var r=n.charCodeAt(s++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++a);else if(r!==c)continue;return n.slice(t,s-a)}return n.slice(t)}for(var r,u,i={},o={},a=[],l=n.length,s=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();t&&null==(h=t(h,f++))||a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new m,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},ta.csv=ta.dsv(",","text/csv"),ta.tsv=ta.dsv(" ","text/tab-separated-values");var Ka,Qa,nc,tc,ec,rc=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};ta.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Qa?Qa.n=i:Ka=i,Qa=i,nc||(tc=clearTimeout(tc),nc=1,rc(qt))},ta.timer.flush=function(){Lt(),Tt()},ta.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var uc=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Dt);ta.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=ta.round(n,Rt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),uc[8+e/3]};var ic=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,oc=ta.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ta.round(n,Rt(n,t))).toFixed(Math.max(0,Math.min(20,Rt(n*(1+1e-15),t))))}}),ac=ta.time={},cc=Date;jt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){lc.setUTCDate.apply(this._,arguments)},setDay:function(){lc.setUTCDay.apply(this._,arguments)},setFullYear:function(){lc.setUTCFullYear.apply(this._,arguments)},setHours:function(){lc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){lc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){lc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){lc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){lc.setUTCSeconds.apply(this._,arguments)},setTime:function(){lc.setTime.apply(this._,arguments)}};var lc=Date.prototype;ac.year=Ft(function(n){return n=ac.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ac.years=ac.year.range,ac.years.utc=ac.year.utc.range,ac.day=Ft(function(n){var t=new cc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ac.days=ac.day.range,ac.days.utc=ac.day.utc.range,ac.dayOfYear=function(n){var t=ac.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ac[n]=Ft(function(n){return(n=ac.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ac.year(n).getDay();return Math.floor((ac.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ac[n+"s"]=e.range,ac[n+"s"].utc=e.utc.range,ac[n+"OfYear"]=function(n){var e=ac.year(n).getDay();return Math.floor((ac.dayOfYear(n)+(e+t)%7)/7)}}),ac.week=ac.sunday,ac.weeks=ac.sunday.range,ac.weeks.utc=ac.sunday.utc.range,ac.weekOfYear=ac.sundayOfYear;var sc={"-":"",_:" ",0:"0"},fc=/^\s*\d+/,hc=/^%/;ta.locale=function(n){return{numberFormat:Pt(n),timeFormat:Ot(n)}};var gc=ta.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});ta.format=gc.numberFormat,ta.geo={},ce.prototype={s:0,t:0,add:function(n){le(n,this.t,pc),le(pc.s,this.s,this),this.s?this.t+=pc.t:this.s=pc.t
3 },reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var pc=new ce;ta.geo.stream=function(n,t){n&&vc.hasOwnProperty(n.type)?vc[n.type](n,t):se(n,t)};var vc={Feature:function(n,t){se(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)se(e[r].geometry,t)}},dc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){fe(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)fe(e[r],t,0)},Polygon:function(n,t){he(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)he(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)se(e[r],t)}};ta.geo.area=function(n){return mc=0,ta.geo.stream(n,Mc),mc};var mc,yc=new ce,Mc={sphere:function(){mc+=4*qa},point:b,lineStart:b,lineEnd:b,polygonStart:function(){yc.reset(),Mc.lineStart=ge},polygonEnd:function(){var n=2*yc;mc+=0>n?4*qa+n:n,Mc.lineStart=Mc.lineEnd=Mc.point=b}};ta.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=pe([t*Da,e*Da]);if(m){var u=de(m,r),i=[u[1],-u[0],0],o=de(i,u);Me(o),o=xe(o);var c=t-p,l=c>0?1:-1,v=o[0]*Pa*l,d=ga(c)>180;if(d^(v>l*p&&l*t>v)){var y=o[1]*Pa;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>l*p&&l*t>v)){var y=-o[1]*Pa;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?a(s,t)>a(s,h)&&(h=t):a(t,h)>a(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ga(r)>180?r+(r>0?360:-360):r}else v=n,d=e;Mc.point(n,e),t(n,e)}function i(){Mc.lineStart()}function o(){u(v,d),Mc.lineEnd(),ga(y)>Ca&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function l(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var s,f,h,g,p,v,d,m,y,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=u,b.lineStart=i,b.lineEnd=o,y=0,Mc.polygonStart()},polygonEnd:function(){Mc.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>yc?(s=-(h=180),f=-(g=90)):y>Ca?g=90:-Ca>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],ta.geo.stream(n,b);var t=M.length;if(t){M.sort(c);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],l(e[0],u)||l(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,s=e[0],h=u[1])}return M=x=null,1/0===s||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[s,f],[h,g]]}}(),ta.geo.centroid=function(n){xc=bc=_c=wc=Sc=kc=Ec=Ac=Nc=Cc=zc=0,ta.geo.stream(n,qc);var t=Nc,e=Cc,r=zc,u=t*t+e*e+r*r;return za>u&&(t=kc,e=Ec,r=Ac,Ca>bc&&(t=_c,e=wc,r=Sc),u=t*t+e*e+r*r,za>u)?[0/0,0/0]:[Math.atan2(e,t)*Pa,tt(r/Math.sqrt(u))*Pa]};var xc,bc,_c,wc,Sc,kc,Ec,Ac,Nc,Cc,zc,qc={sphere:b,point:_e,lineStart:Se,lineEnd:ke,polygonStart:function(){qc.lineStart=Ee},polygonEnd:function(){qc.lineStart=Se}},Lc=Le(Ne,Pe,je,[-qa,-qa/2]),Tc=1e9;ta.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ie(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(ta.geo.conicEqualArea=function(){return Ye(Ze)}).raw=Ze,ta.geo.albers=function(){return ta.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ta.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=ta.geo.albers(),o=ta.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=ta.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var l=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*l,f-.238*l],[s+.455*l,f+.238*l]]).stream(c).point,r=o.translate([s-.307*l,f+.201*l]).clipExtent([[s-.425*l+Ca,f+.12*l+Ca],[s-.214*l-Ca,f+.234*l-Ca]]).stream(c).point,u=a.translate([s-.205*l,f+.212*l]).clipExtent([[s-.214*l+Ca,f+.166*l+Ca],[s-.115*l-Ca,f+.234*l-Ca]]).stream(c).point,n},n.scale(1070)};var Rc,Dc,Pc,Uc,jc,Fc,Hc={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Dc=0,Hc.lineStart=Ve},polygonEnd:function(){Hc.lineStart=Hc.lineEnd=Hc.point=b,Rc+=ga(Dc/2)}},Oc={point:Xe,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Ic={point:We,lineStart:Je,lineEnd:Ge,polygonStart:function(){Ic.lineStart=Ke},polygonEnd:function(){Ic.point=We,Ic.lineStart=Je,Ic.lineEnd=Ge}};ta.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),ta.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Rc=0,ta.geo.stream(n,u(Hc)),Rc},n.centroid=function(n){return _c=wc=Sc=kc=Ec=Ac=Nc=Cc=zc=0,ta.geo.stream(n,u(Ic)),zc?[Nc/zc,Cc/zc]:Ac?[kc/Ac,Ec/Ac]:Sc?[_c/Sc,wc/Sc]:[0/0,0/0]},n.bounds=function(n){return jc=Fc=-(Pc=Uc=1/0),ta.geo.stream(n,u(Oc)),[[Pc,Uc],[jc,Fc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||tr(n):y,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new $e:new Qe(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(ta.geo.albersUsa()).context(null)},ta.geo.transform=function(n){return{stream:function(t){var e=new er(t);for(var r in n)e[r]=n[r];return e}}},er.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},ta.geo.projection=ur,ta.geo.projectionMutator=ir,(ta.geo.equirectangular=function(){return ur(ar)}).raw=ar.invert=ar,ta.geo.rotation=function(n){function t(t){return t=n(t[0]*Da,t[1]*Da),t[0]*=Pa,t[1]*=Pa,t}return n=lr(n[0]%360*Da,n[1]*Da,n.length>2?n[2]*Da:0),t.invert=function(t){return t=n.invert(t[0]*Da,t[1]*Da),t[0]*=Pa,t[1]*=Pa,t},t},cr.invert=ar,ta.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=lr(-n[0]*Da,-n[1]*Da,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Pa,n[1]*=Pa}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=gr((t=+r)*Da,u*Da),n):t},n.precision=function(r){return arguments.length?(e=gr(t*Da,(u=+r)*Da),n):u},n.angle(90)},ta.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Da,u=n[1]*Da,i=t[1]*Da,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),l=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=l*s-c*f*a)*e),c*s+l*f*a)},ta.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ta.range(Math.ceil(i/d)*d,u,d).map(h).concat(ta.range(Math.ceil(l/m)*m,c,m).map(g)).concat(ta.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ga(n%d)>Ca}).map(s)).concat(ta.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ga(n%m)>Ca}).map(f))}var e,r,u,i,o,a,c,l,s,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(l).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],l=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[i,l],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,s=vr(a,o,90),f=dr(r,e,y),h=vr(l,c,90),g=dr(i,u,y),n):y},n.majorExtent([[-180,-90+Ca],[180,90-Ca]]).minorExtent([[-180,-80-Ca],[180,80+Ca]])},ta.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=mr,u=yr;return n.distance=function(){return ta.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},ta.geo.interpolate=function(n,t){return Mr(n[0]*Da,n[1]*Da,t[0]*Da,t[1]*Da)},ta.geo.length=function(n){return Yc=0,ta.geo.stream(n,Zc),Yc};var Yc,Zc={sphere:b,point:b,lineStart:xr,lineEnd:b,polygonStart:b,polygonEnd:b},Vc=br(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ta.geo.azimuthalEqualArea=function(){return ur(Vc)}).raw=Vc;var Xc=br(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},y);(ta.geo.azimuthalEquidistant=function(){return ur(Xc)}).raw=Xc,(ta.geo.conicConformal=function(){return Ye(_r)}).raw=_r,(ta.geo.conicEquidistant=function(){return Ye(wr)}).raw=wr;var $c=br(function(n){return 1/n},Math.atan);(ta.geo.gnomonic=function(){return ur($c)}).raw=$c,Sr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ra]},(ta.geo.mercator=function(){return kr(Sr)}).raw=Sr;var Bc=br(function(){return 1},Math.asin);(ta.geo.orthographic=function(){return ur(Bc)}).raw=Bc;var Wc=br(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ta.geo.stereographic=function(){return ur(Wc)}).raw=Wc,Er.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ra]},(ta.geo.transverseMercator=function(){var n=kr(Er),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Er,ta.geom={},ta.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=Et(e),i=Et(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(zr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var l=Cr(a),s=Cr(c),f=s[0]===l[0],h=s[s.length-1]===l[l.length-1],g=[];for(t=l.length-1;t>=0;--t)g.push(n[a[l[t]][2]]);for(t=+f;t<s.length-h;++t)g.push(n[a[s[t]][2]]);return g}var e=Ar,r=Nr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},ta.geom.polygon=function(n){return ya(n,Jc),n};var Jc=ta.geom.polygon.prototype=[];Jc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Jc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Jc.clip=function(n){for(var t,e,r,u,i,o,a=Tr(n),c=-1,l=this.length-Tr(this),s=this[l-1];++c<l;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],qr(o,s,u)?(qr(i,s,u)||n.push(Lr(i,o,s,u)),n.push(o)):qr(i,s,u)&&n.push(Lr(i,o,s,u)),i=o;a&&n.push(n[0]),s=u}return n};var Gc,Kc,Qc,nl,tl,el=[],rl=[];Or.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(Yr),t.length},Qr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},nu.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=uu(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(eu(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ru(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(ru(this,e),n=e,e=n.U),e.C=!1,r.C=!0,eu(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?uu(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return void(n.C=!1);do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,eu(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,ru(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,eu(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,ru(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,eu(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,ru(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},ta.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return iu(e(n),a).cells.forEach(function(e,a){var c=e.edges,l=e.site,s=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):l.x>=r&&l.x<=i&&l.y>=u&&l.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];s.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Ca)*Ca,y:Math.round(o(n,t)/Ca)*Ca,i:t}})}var r=Ar,u=Nr,i=r,o=u,a=ul;return n?t(n):(t.links=function(n){return iu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return iu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Yr),c=-1,l=a.length,s=a[l-1].edge,f=s.l===o?s.r:s.l;++c<l;)u=s,i=f,s=a[c].edge,f=s.l===o?s.r:s.l,r<i.i&&r<f.i&&au(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=Et(r=n),t):r},t.y=function(n){return arguments.length?(o=Et(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?ul:n,t):a===ul?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===ul?null:a&&a[1]},t)};var ul=[[-1e6,-1e6],[1e6,1e6]];ta.geom.delaunay=function(n){return ta.geom.voronoi().triangles(n)},ta.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,s=n.y;if(null!=c)if(ga(c-e)+ga(s-r)<.01)l(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,l(n,f,c,s,u,i,o,a),l(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else l(n,t,e,r,u,i,o,a)}function l(n,t,e,r,u,o,a,c){var l=.5*(u+a),s=.5*(o+c),f=e>=l,h=r>=s,g=h<<1|f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=su()),f?u=l:a=l,h?o=s:c=s,i(n,t,e,r,u,o,a,c)}var s,f,h,g,p,v,d,m,y,M=Et(a),x=Et(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)s=n[g],s.x<v&&(v=s.x),s.y<d&&(d=s.y),s.x>m&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);v>b&&(v=b),d>_&&(d=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=su();if(k.add=function(n){i(k,n,+M(n,++g),+x(n,g),v,d,m,y)},k.visit=function(n){fu(n,k,v,d,m,y)},k.find=function(n){return hu(k,n[0],n[1],v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=s=null,k}var o,a=Ar,c=Nr;return(o=arguments.length)?(a=cu,c=lu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},ta.interpolateRgb=gu,ta.interpolateObject=pu,ta.interpolateNumber=vu,ta.interpolateString=du;var il=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,ol=new RegExp(il.source,"g");ta.interpolate=mu,ta.interpolators=[function(n,t){var e=typeof t;return("string"===e?Ga.has(t)||/^(#|rgb\(|hsl\()/.test(t)?gu:du:t instanceof ot?gu:Array.isArray(t)?yu:"object"===e&&isNaN(t)?pu:vu)(n,t)}],ta.interpolateArray=yu;var al=function(){return y},cl=ta.map({linear:al,poly:ku,quad:function(){return _u},cubic:function(){return wu},sin:function(){return Eu},exp:function(){return Au},circle:function(){return Nu},elastic:Cu,back:zu,bounce:function(){return qu}}),ll=ta.map({"in":y,out:xu,"in-out":bu,"out-in":function(n){return bu(xu(n))}});ta.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=cl.get(e)||al,r=ll.get(r)||y,Mu(r(e.apply(null,ea.call(arguments,1))))},ta.interpolateHcl=Lu,ta.interpolateHsl=Tu,ta.interpolateLab=Ru,ta.interpolateRound=Du,ta.transform=function(n){var t=ua.createElementNS(ta.ns.prefix.svg,"g");return(ta.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Pu(e?e.matrix:sl)})(n)},Pu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var sl={a:1,b:0,c:0,d:1,e:0,f:0};ta.interpolateTransform=Hu,ta.layout={},ta.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Yu(n[e]));return t}},ta.layout.chord=function(){function n(){var n,l,f,h,g,p={},v=[],d=ta.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(l=0,g=-1;++g<i;)l+=u[h][g];v.push(l),m.push(ta.range(i)),n+=l}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(La-s*i)/n,l=0,h=-1;++h<i;){for(f=l,g=-1;++g<i;){var y=d[h],M=m[y][g],x=u[y][M],b=l,_=l+=x*n;p[y+"-"+M]={index:y,subindex:M,startAngle:b,endAngle:_,value:x}}r[y]={index:y,startAngle:f,endAngle:l,value:(l-f)/n},l+=s}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,l={},s=0;return l.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,l):u},l.padding=function(n){return arguments.length?(s=n,e=r=null,l):s},l.sortGroups=function(n){return arguments.length?(o=n,e=r=null,l):o},l.sortSubgroups=function(n){return arguments.length?(a=n,e=null,l):a},l.sortChords=function(n){return arguments.length?(c=n,e&&t(),l):c},l.chords=function(){return e||n(),e},l.groups=function(){return r||n(),r},l},ta.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var l=t.charge/c;n.px-=i*l,n.py-=o*l}return!0}if(t.point&&c&&p>c){var l=t.pointCharge/c;n.px-=i*l,n.py-=o*l}}return!t.charge}}function t(n){n.px=ta.event.x,n.py=ta.event.y,a.resume()}var e,r,u,i,o,a={},c=ta.dispatch("start","tick","end"),l=[1,1],s=.9,f=fl,h=hl,g=-30,p=gl,v=.1,d=.64,m=[],M=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,y,x,b=m.length,_=M.length;for(e=0;_>e;++e)a=M[e],f=a.source,h=a.target,y=h.x-f.x,x=h.y-f.y,(p=y*y+x*x)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,y*=p,x*=p,h.x-=y*(d=f.weight/(h.weight+f.weight)),h.y-=x*d,f.x+=y*(d=1-d),f.y+=x*d);if((d=r*v)&&(y=l[0]/2,x=l[1]/2,e=-1,d))for(;++e<b;)a=m[e],a.x+=(y-a.x)*d,a.y+=(x-a.y)*d;if(g)for(Ju(t=ta.geom.quadtree(m),r,o),e=-1;++e<b;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<b;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*s,a.y-=(a.py-(a.py=a.y))*s);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(M=n,a):M},a.size=function(n){return arguments.length?(l=n,a):l},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(s=+n,a):s},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),ta.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=M[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,l=o.length;++a<l;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,s=M.length,p=l[0],v=l[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;s>t;++t)r=M[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;s>t;++t)u[t]=+f.call(this,M[t],t);else for(t=0;s>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;s>t;++t)i[t]=+h.call(this,M[t],t);else for(t=0;s>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=ta.behavior.drag().origin(y).on("dragstart.force",Xu).on("drag.force",t).on("dragend.force",$u)),arguments.length?void this.on("mouseover.force",Bu).on("mouseout.force",Wu).call(e):e},ta.rebind(a,c,"on")};var fl=20,hl=1,gl=1/0;ta.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(l=e.call(n,i,i.depth))&&(c=l.length)){for(var c,l,s;--c>=0;)o.push(s=l[c]),s.parent=i,s.depth=i.depth+1;r&&(i.value=0),i.children=l}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Qu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=ei,e=ni,r=ti;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(Ku(t,function(n){n.children&&(n.value=0)}),Qu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},ta.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,l=-1;for(r=t.value?r/t.value:0;++l<o;)n(a=i[l],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=ta.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Gu(e,r)},ta.layout.pie=function(){function n(o){var a,c=o.length,l=o.map(function(e,r){return+t.call(n,e,r)}),s=+("function"==typeof r?r.apply(this,arguments):r),f=("function"==typeof u?u.apply(this,arguments):u)-s,h=Math.min(Math.abs(f)/c,+("function"==typeof i?i.apply(this,arguments):i)),g=h*(0>f?-1:1),p=(f-c*g)/ta.sum(l),v=ta.range(c),d=[];return null!=e&&v.sort(e===pl?function(n,t){return l[t]-l[n]}:function(n,t){return e(o[n],o[t])}),v.forEach(function(n){d[n]={data:o[n],value:a=l[n],startAngle:s,endAngle:s+=a*p+g,padAngle:h}}),d}var t=Number,e=pl,r=0,u=La,i=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n.padAngle=function(t){return arguments.length?(i=t,n):i},n};var pl={};ta.layout.stack=function(){function n(a,c){if(!(h=a.length))return a;var l=a.map(function(e,r){return t.call(n,e,r)}),s=l.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,s,c);l=ta.permute(l,f),s=ta.permute(s,f);var h,g,p,v,d=r.call(n,s,c),m=l[0].length;for(p=0;m>p;++p)for(u.call(n,l[0][p],v=d[p],s[0][p][1]),g=1;h>g;++g)u.call(n,l[g][p],v+=s[g-1][p][1],s[g][p][1]);return a}var t=y,e=ai,r=ci,u=oi,i=ui,o=ii;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:vl.get(t)||ai,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:dl.get(t)||ci,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var vl=ta.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(li),i=n.map(si),o=ta.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,l=[],s=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],l.push(e)):(c+=i[e],s.push(e));return s.reverse().concat(l)},reverse:function(n){return ta.range(n.length).reverse()},"default":ai}),dl=ta.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,l,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];s>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ci});ta.layout.histogram=function(){function n(n,i){for(var o,a,c=[],l=n.map(e,this),s=r.call(this,l,i),f=u.call(this,s,l,i),i=-1,h=l.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=l[i],a>=s[0]&&a<=s[1]&&(o=c[ta.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=pi,u=hi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=Et(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return gi(n,t)}:Et(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ta.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],l=u[1],s=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Qu(a,function(n){n.r=+s(n.value)}),Qu(a,Mi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/l))/2;Qu(a,function(n){n.r+=f}),Qu(a,Mi),Qu(a,function(n){n.r-=f})}return _i(a,c/2,l/2,t?1:1/Math.max(2*a.r/c,2*a.r/l)),o}var t,e=ta.layout.hierarchy().sort(vi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Gu(n,e)},ta.layout.tree=function(){function n(n,u){var s=o.call(this,n,u),f=s[0],h=t(f);if(Qu(h,e),h.parent.m=-h.z,Ku(h,r),l)Ku(f,i);else{var g=f,p=f,v=f;Ku(f,function(n){n.x<g.x&&(g=n),n.x>p.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);Ku(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return s}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Ni(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],l=u.m,s=i.m,f=o.m,h=c.m;o=Ei(o),u=ki(u),o&&u;)c=ki(c),i=Ei(i),i.a=n,r=o.z+f-u.z-l+a(o._,u._),r>0&&(Ai(Ci(o,n,e),n,r),l+=r,s+=r),f+=o.m,l+=u.m,h+=c.m,s+=i.m;o&&!Ei(i)&&(i.t=o,i.m+=f-s),u&&!ki(c)&&(c.t=u,c.m+=l-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=ta.layout.hierarchy().sort(null).value(null),a=Si,c=[1,1],l=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(l=null==(c=t)?i:null,n):l?null:c},n.nodeSize=function(t){return arguments.length?(l=null==(c=t)?null:i,n):l?c:null},Gu(n,o)},ta.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],l=0;Qu(c,function(n){var t=n.children;t&&t.length?(n.x=qi(t),n.y=zi(t)):(n.x=o?l+=e(n,o):0,n.y=0,o=n)});var s=Li(c),f=Ti(c),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return Qu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=ta.layout.hierarchy().sort(null).value(null),e=Si,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Gu(n,t)},ta.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,l=f(e),s=[],h=i.slice(),p=1/0,v="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),s.area=0;(c=h.length)>0;)s.push(o=h[c-1]),s.area+=o.area,"squarify"!==g||(a=r(s,v))<=p?(h.pop(),p=a):(s.area-=s.pop().area,u(s,v,l,!1),v=Math.min(l.dx,l.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,v,l,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,l=e.y,s=t?c(n.area/t):0;if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++i<o;)u=n[i],u.x=a,u.y=l,u.dy=s,a+=u.dx=Math.min(e.x+e.dx-a,s?c(u.area/s):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=s,e.dy-=s}else{for((r||s>e.dx)&&(s=e.dx);++i<o;)u=n[i],u.x=a,u.y=l,u.dx=s,l+=u.dy=Math.min(e.y+e.dy-l,s?c(u.area/s):0);u.z=!1,u.dy+=e.y+e.dy-l,e.x+=s,e.dx-=s}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=l[0],i.dy=l[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=ta.layout.hierarchy(),c=Math.round,l=[1,1],s=null,f=Ri,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));
4 return i.size=function(n){return arguments.length?(l=n,i):l},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ri(t):Di(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Di(t,n)}if(!arguments.length)return s;var r;return f=null==(s=n)?Ri:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Gu(i,a)},ta.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=ta.random.normal.apply(ta,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=ta.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},ta.scale={};var ml={floor:y,ceil:y};ta.scale.linear=function(){return Ii([0,1],[0,1],mu,!1)};var yl={s:1,g:1,p:1,r:1,e:1};ta.scale.log=function(){return Ji(ta.scale.linear().domain([0,1]),10,!0,[1,10])};var Ml=ta.format(".0e"),xl={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};ta.scale.pow=function(){return Gi(ta.scale.linear(),1,[0,1])},ta.scale.sqrt=function(){return ta.scale.pow().exponent(.5)},ta.scale.ordinal=function(){return Qi([],{t:"range",a:[[]]})},ta.scale.category10=function(){return ta.scale.ordinal().range(bl)},ta.scale.category20=function(){return ta.scale.ordinal().range(_l)},ta.scale.category20b=function(){return ta.scale.ordinal().range(wl)},ta.scale.category20c=function(){return ta.scale.ordinal().range(Sl)};var bl=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(Mt),_l=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(Mt),wl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(Mt),Sl=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(Mt);ta.scale.quantile=function(){return no([],[])},ta.scale.quantize=function(){return to(0,1,[0,1])},ta.scale.threshold=function(){return eo([.5],[0,1])},ta.scale.identity=function(){return ro([0,1])},ta.svg={},ta.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),l=Math.max(0,+r.apply(this,arguments)),s=o.apply(this,arguments)-Ra,f=a.apply(this,arguments)-Ra,h=Math.abs(f-s),g=s>f?0:1;if(n>l&&(p=l,l=n,n=p),h>=Ta)return t(l,g)+(n?t(n,1-g):"")+"Z";var p,v,d,m,y,M,x,b,_,w,S,k,E=0,A=0,N=[];if((m=(+c.apply(this,arguments)||0)/2)&&(d=i===kl?Math.sqrt(n*n+l*l):+i.apply(this,arguments),g||(A*=-1),l&&(A=tt(d/l*Math.sin(m))),n&&(E=tt(d/n*Math.sin(m)))),l){y=l*Math.cos(s+A),M=l*Math.sin(s+A),x=l*Math.cos(f-A),b=l*Math.sin(f-A);var C=Math.abs(f-s-2*A)<=qa?0:1;if(A&&so(y,M,x,b)===g^C){var z=(s+f)/2;y=l*Math.cos(z),M=l*Math.sin(z),x=b=null}}else y=M=0;if(n){_=n*Math.cos(f-E),w=n*Math.sin(f-E),S=n*Math.cos(s+E),k=n*Math.sin(s+E);var q=Math.abs(s-f+2*E)<=qa?0:1;if(E&&so(_,w,S,k)===1-g^q){var L=(s+f)/2;_=n*Math.cos(L),w=n*Math.sin(L),S=k=null}}else _=w=0;if((p=Math.min(Math.abs(l-n)/2,+u.apply(this,arguments)))>.001){v=l>n^g?0:1;var T=null==S?[_,w]:null==x?[y,M]:Lr([y,M],[S,k],[x,b],[_,w]),R=y-T[0],D=M-T[1],P=x-T[0],U=b-T[1],j=1/Math.sin(Math.acos((R*P+D*U)/(Math.sqrt(R*R+D*D)*Math.sqrt(P*P+U*U)))/2),F=Math.sqrt(T[0]*T[0]+T[1]*T[1]);if(null!=x){var H=Math.min(p,(l-F)/(j+1)),O=fo(null==S?[_,w]:[S,k],[y,M],l,H,g),I=fo([x,b],[_,w],l,H,g);p===H?N.push("M",O[0],"A",H,",",H," 0 0,",v," ",O[1],"A",l,",",l," 0 ",1-g^so(O[1][0],O[1][1],I[1][0],I[1][1]),",",g," ",I[1],"A",H,",",H," 0 0,",v," ",I[0]):N.push("M",O[0],"A",H,",",H," 0 1,",v," ",I[0])}else N.push("M",y,",",M);if(null!=S){var Y=Math.min(p,(n-F)/(j-1)),Z=fo([y,M],[S,k],n,-Y,g),V=fo([_,w],null==x?[y,M]:[x,b],n,-Y,g);p===Y?N.push("L",V[0],"A",Y,",",Y," 0 0,",v," ",V[1],"A",n,",",n," 0 ",g^so(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-g," ",Z[1],"A",Y,",",Y," 0 0,",v," ",Z[0]):N.push("L",V[0],"A",Y,",",Y," 0 0,",v," ",Z[0])}else N.push("L",_,",",w)}else N.push("M",y,",",M),null!=x&&N.push("A",l,",",l," 0 ",C,",",g," ",x,",",b),N.push("L",_,",",w),null!=S&&N.push("A",n,",",n," 0 ",q,",",1-g," ",S,",",k);return N.push("Z"),N.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=io,r=oo,u=uo,i=kl,o=ao,a=co,c=lo;return n.innerRadius=function(t){return arguments.length?(e=Et(t),n):e},n.outerRadius=function(t){return arguments.length?(r=Et(t),n):r},n.cornerRadius=function(t){return arguments.length?(u=Et(t),n):u},n.padRadius=function(t){return arguments.length?(i=t==kl?kl:Et(t),n):i},n.startAngle=function(t){return arguments.length?(o=Et(t),n):o},n.endAngle=function(t){return arguments.length?(a=Et(t),n):a},n.padAngle=function(t){return arguments.length?(c=Et(t),n):c},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+o.apply(this,arguments)+ +a.apply(this,arguments))/2-Ra;return[Math.cos(t)*n,Math.sin(t)*n]},n};var kl="auto";ta.svg.line=function(){return ho(y)};var El=ta.map({linear:go,"linear-closed":po,step:vo,"step-before":mo,"step-after":yo,basis:So,"basis-open":ko,"basis-closed":Eo,bundle:Ao,cardinal:bo,"cardinal-open":Mo,"cardinal-closed":xo,monotone:To});El.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Al=[0,2/3,1/3,0],Nl=[0,1/3,2/3,0],Cl=[0,1/6,2/3,1/6];ta.svg.line.radial=function(){var n=ho(Ro);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},mo.reverse=yo,yo.reverse=mo,ta.svg.area=function(){return Do(y)},ta.svg.area.radial=function(){var n=Do(Ro);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ta.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),l=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+u(l.r,l.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)-Ra,s=l.call(n,u,r)-Ra;return{r:i,a0:o,a1:s,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>qa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=mr,o=yr,a=Po,c=ao,l=co;return n.radius=function(t){return arguments.length?(a=Et(t),n):a},n.source=function(t){return arguments.length?(i=Et(t),n):i},n.target=function(t){return arguments.length?(o=Et(t),n):o},n.startAngle=function(t){return arguments.length?(c=Et(t),n):c},n.endAngle=function(t){return arguments.length?(l=Et(t),n):l},n},ta.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=mr,e=yr,r=Uo;return n.source=function(e){return arguments.length?(t=Et(e),n):t},n.target=function(t){return arguments.length?(e=Et(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ta.svg.diagonal.radial=function(){var n=ta.svg.diagonal(),t=Uo,e=n.projection;return n.projection=function(n){return arguments.length?e(jo(t=n)):t},n},ta.svg.symbol=function(){function n(n,r){return(zl.get(t.call(this,n,r))||Oo)(e.call(this,n,r))}var t=Ho,e=Fo;return n.type=function(e){return arguments.length?(t=Et(e),n):t},n.size=function(t){return arguments.length?(e=Et(t),n):e},n};var zl=ta.map({circle:Oo,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Ll)),e=t*Ll;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/ql),e=t*ql/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/ql),e=t*ql/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ta.svg.symbolTypes=zl.keys();var ql=Math.sqrt(3),Ll=Math.tan(30*Da);_a.transition=function(n){for(var t,e,r=Tl||++Ul,u=Xo(n),i=[],o=Rl||{time:Date.now(),ease:Su,delay:0,duration:250},a=-1,c=this.length;++a<c;){i.push(t=[]);for(var l=this[a],s=-1,f=l.length;++s<f;)(e=l[s])&&$o(e,s,u,r,o),t.push(e)}return Yo(i,u,r)},_a.interrupt=function(n){return this.each(null==n?Dl:Io(Xo(n)))};var Tl,Rl,Dl=Io(Xo()),Pl=[],Ul=0;Pl.call=_a.call,Pl.empty=_a.empty,Pl.node=_a.node,Pl.size=_a.size,ta.transition=function(n,t){return n&&n.transition?Tl?n.transition(t):n:ta.selection().transition(n)},ta.transition.prototype=Pl,Pl.select=function(n){var t,e,r,u=this.id,i=this.namespace,o=[];n=N(n);for(var a=-1,c=this.length;++a<c;){o.push(t=[]);for(var l=this[a],s=-1,f=l.length;++s<f;)(r=l[s])&&(e=n.call(r,r.__data__,s,a))?("__data__"in r&&(e.__data__=r.__data__),$o(e,s,i,u,r[i][u]),t.push(e)):t.push(null)}return Yo(o,i,u)},Pl.selectAll=function(n){var t,e,r,u,i,o=this.id,a=this.namespace,c=[];n=C(n);for(var l=-1,s=this.length;++l<s;)for(var f=this[l],h=-1,g=f.length;++h<g;)if(r=f[h]){i=r[a][o],e=n.call(r,r.__data__,h,l),c.push(t=[]);for(var p=-1,v=e.length;++p<v;)(u=e[p])&&$o(u,p,a,o,i),t.push(u)}return Yo(c,a,o)},Pl.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=O(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Yo(u,this.namespace,this.id)},Pl.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(u){u[r][e].tween.set(n,t)})},Pl.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Hu:mu,a=ta.ns.qualify(n);return Zo(this,"attr."+n,t,a.local?i:u)},Pl.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=ta.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Pl.style=function(n,e,r){function u(){this.style.removeProperty(n)}function i(e){return null==e?u:(e+="",function(){var u,i=t(this).getComputedStyle(this,null).getPropertyValue(n);return i!==e&&(u=mu(i,e),function(t){this.style.setProperty(n,u(t),r)})})}var o=arguments.length;if(3>o){if("string"!=typeof n){2>o&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Zo(this,"style."+n,e,i)},Pl.styleTween=function(n,e,r){function u(u,i){var o=e.call(this,u,i,t(this).getComputedStyle(this,null).getPropertyValue(n));return o&&function(t){this.style.setProperty(n,o(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,u)},Pl.text=function(n){return Zo(this,"text",n,Vo)},Pl.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Pl.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=ta.ease.apply(ta,arguments)),Y(this,function(r){r[e][t].ease=n}))},Pl.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,u,i){r[e][t].delay=+n.call(r,r.__data__,u,i)}:(n=+n,function(r){r[e][t].delay=n}))},Pl.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,u,i){r[e][t].duration=Math.max(1,n.call(r,r.__data__,u,i))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Pl.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var u=Rl,i=Tl;try{Tl=e,Y(this,function(t,u,i){Rl=t[r][e],n.call(t,t.__data__,u,i)})}finally{Rl=u,Tl=i}}else Y(this,function(u){var i=u[r][e];(i.event||(i.event=ta.dispatch("start","end","interrupt"))).on(n,t)});return this},Pl.transition=function(){for(var n,t,e,r,u=this.id,i=++Ul,o=this.namespace,a=[],c=0,l=this.length;l>c;c++){a.push(n=[]);for(var t=this[c],s=0,f=t.length;f>s;s++)(e=t[s])&&(r=e[o][u],$o(e,s,o,i,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Yo(a,o,i)},ta.svg.axis=function(){function n(n){n.each(function(){var n,l=ta.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):y:t,p=l.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Ca),d=ta.transition(p.exit()).style("opacity",Ca).remove(),m=ta.transition(p.order()).style("opacity",1),M=Math.max(u,0)+o,x=Ui(f),b=l.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),ta.transition(b));v.append("line"),v.append("text");var w,S,k,E,A=v.select("line"),N=m.select("line"),C=p.select("text").text(g),z=v.select("text"),q=m.select("text"),L="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=Bo,w="x",k="y",S="x2",E="y2",C.attr("dy",0>L?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+L*i+"V0H"+x[1]+"V"+L*i)):(n=Wo,w="y",k="x",S="y2",E="x2",C.attr("dy",".32em").style("text-anchor",0>L?"end":"start"),_.attr("d","M"+L*i+","+x[0]+"H0V"+x[1]+"H"+L*i)),A.attr(E,L*u),z.attr(k,L*M),N.attr(S,0).attr(E,L*u),q.attr(w,0).attr(k,L*M),f.rangeBand){var T=f,R=T.rangeBand()/2;s=f=function(n){return T(n)+R}}else s.rangeBand?s=f:d.call(n,f,s);v.call(n,s,f),m.call(n,f,f)})}var t,e=ta.scale.linear(),r=jl,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Fl?t+"":jl,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var jl="bottom",Fl={top:1,right:1,bottom:1,left:1};ta.svg.brush=function(){function n(t){t.each(function(){var t=ta.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",i).on("touchstart.brush",i),o=t.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=t.selectAll(".resize").data(v,y);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Hl[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var c,f=ta.transition(t),h=ta.transition(o);l&&(c=Ui(l),h.attr("x",c[0]).attr("width",c[1]-c[0]),r(f)),s&&(c=Ui(s),h.attr("y",c[0]).attr("height",c[1]-c[0]),u(f)),e(f)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+f[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",f[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",f[1]-f[0])}function u(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function i(){function i(){32==ta.event.keyCode&&(C||(M=null,q[0]-=f[1],q[1]-=h[1],C=2),S())}function v(){32==ta.event.keyCode&&2==C&&(q[0]+=f[1],q[1]+=h[1],C=0,S())}function d(){var n=ta.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(ta.event.altKey?(M||(M=[(f[0]+f[1])/2,(h[0]+h[1])/2]),q[0]=f[+(n[0]<M[0])],q[1]=h[+(n[1]<M[1])]):M=null),A&&m(n,l,0)&&(r(k),t=!0),N&&m(n,s,1)&&(u(k),t=!0),t&&(e(k),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,i=Ui(t),c=i[0],l=i[1],s=q[e],v=e?h:f,d=v[1]-v[0];return C&&(c-=s,l-=d+s),r=(e?p:g)?Math.max(c,Math.min(l,n[e])):n[e],C?u=(r+=s)+d:(M&&(s=Math.max(c,Math.min(l,2*M[e]-r))),r>s?(u=r,r=s):u=s),v[0]!=r||v[1]!=u?(e?a=null:o=null,v[0]=r,v[1]=u,!0):void 0}function y(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ta.select("body").style("cursor",null),L.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=ta.select(ta.event.target),w=c.of(b,arguments),k=ta.select(b),E=_.datum(),A=!/^(n|s)$/.test(E)&&l,N=!/^(e|w)$/.test(E)&&s,C=_.classed("extent"),z=W(b),q=ta.mouse(b),L=ta.select(t(b)).on("keydown.brush",i).on("keyup.brush",v);if(ta.event.changedTouches?L.on("touchmove.brush",d).on("touchend.brush",y):L.on("mousemove.brush",d).on("mouseup.brush",y),k.interrupt().selectAll("*").interrupt(),C)q[0]=f[0]-q[0],q[1]=h[0]-q[1];else if(E){var T=+/w$/.test(E),R=+/^n/.test(E);x=[f[1-T]-q[0],h[1-R]-q[1]],q[0]=f[T],q[1]=h[R]}else ta.event.altKey&&(M=q.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),ta.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var o,a,c=E(n,"brushstart","brush","brushend"),l=null,s=null,f=[0,0],h=[0,0],g=!0,p=!0,v=Ol[0];return n.event=function(n){n.each(function(){var n=c.of(this,arguments),t={x:f,y:h,i:o,j:a},e=this.__chart__||t;this.__chart__=t,Tl?ta.select(this).transition().each("start.brush",function(){o=e.i,a=e.j,f=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=yu(f,t.x),r=yu(h,t.y);return o=a=null,function(u){f=t.x=e(u),h=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){o=t.i,a=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(l=t,v=Ol[!l<<1|!s],n):l},n.y=function(t){return arguments.length?(s=t,v=Ol[!l<<1|!s],n):s},n.clamp=function(t){return arguments.length?(l&&s?(g=!!t[0],p=!!t[1]):l?g=!!t:s&&(p=!!t),n):l&&s?[g,p]:l?g:s?p:null},n.extent=function(t){var e,r,u,i,c;return arguments.length?(l&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),o=[e,r],l.invert&&(e=l(e),r=l(r)),e>r&&(c=e,e=r,r=c),(e!=f[0]||r!=f[1])&&(f=[e,r])),s&&(u=t[0],i=t[1],l&&(u=u[1],i=i[1]),a=[u,i],s.invert&&(u=s(u),i=s(i)),u>i&&(c=u,u=i,i=c),(u!=h[0]||i!=h[1])&&(h=[u,i])),n):(l&&(o?(e=o[0],r=o[1]):(e=f[0],r=f[1],l.invert&&(e=l.invert(e),r=l.invert(r)),e>r&&(c=e,e=r,r=c))),s&&(a?(u=a[0],i=a[1]):(u=h[0],i=h[1],s.invert&&(u=s.invert(u),i=s.invert(i)),u>i&&(c=u,u=i,i=c))),l&&s?[[e,u],[r,i]]:l?[e,r]:s&&[u,i])},n.clear=function(){return n.empty()||(f=[0,0],h=[0,0],o=a=null),n},n.empty=function(){return!!l&&f[0]==f[1]||!!s&&h[0]==h[1]},ta.rebind(n,c,"on")};var Hl={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Ol=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Il=ac.format=gc.timeFormat,Yl=Il.utc,Zl=Yl("%Y-%m-%dT%H:%M:%S.%LZ");Il.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Jo:Zl,Jo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Jo.toString=Zl.toString,ac.second=Ft(function(n){return new cc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ac.seconds=ac.second.range,ac.seconds.utc=ac.second.utc.range,ac.minute=Ft(function(n){return new cc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ac.minutes=ac.minute.range,ac.minutes.utc=ac.minute.utc.range,ac.hour=Ft(function(n){var t=n.getTimezoneOffset()/60;return new cc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ac.hours=ac.hour.range,ac.hours.utc=ac.hour.utc.range,ac.month=Ft(function(n){return n=ac.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ac.months=ac.month.range,ac.months.utc=ac.month.utc.range;var Vl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Xl=[[ac.second,1],[ac.second,5],[ac.second,15],[ac.second,30],[ac.minute,1],[ac.minute,5],[ac.minute,15],[ac.minute,30],[ac.hour,1],[ac.hour,3],[ac.hour,6],[ac.hour,12],[ac.day,1],[ac.day,2],[ac.week,1],[ac.month,1],[ac.month,3],[ac.year,1]],$l=Il.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",Ne]]),Bl={range:function(n,t,e){return ta.range(Math.ceil(n/e)*e,+t,e).map(Ko)},floor:y,ceil:y};Xl.year=ac.year,ac.scale=function(){return Go(ta.scale.linear(),Xl,$l)};var Wl=Xl.map(function(n){return[n[0].utc,n[1]]}),Jl=Yl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",Ne]]);Wl.year=ac.year.utc,ac.scale.utc=function(){return Go(ta.scale.linear(),Wl,Jl)},ta.text=At(function(n){return n.responseText}),ta.json=function(n,t){return Nt(n,"application/json",Qo,t)},ta.html=function(n,t){return Nt(n,"text/html",na,t)},ta.xml=At(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(ta):"object"==typeof module&&module.exports&&(module.exports=ta),this.d3=ta}();
+0
-56
faraday/server/www/script/font.opensans.css less more
0 /* cyrillic-ext */
1 @font-face {
2 font-family: 'Open Sans';
3 font-style: normal;
4 font-weight: 400;
5 src: local('Open Sans'), local('OpenSans'), url(../fonts/opensans/K88pR3goAWT7BTt32Z01mxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
6 unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
7 }
8 /* cyrillic */
9 @font-face {
10 font-family: 'Open Sans';
11 font-style: normal;
12 font-weight: 400;
13 src: local('Open Sans'), local('OpenSans'), url(../fonts/opensans/RjgO7rYTmqiVp7vzi-Q5URJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
14 unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
15 }
16 /* greek-ext */
17 @font-face {
18 font-family: 'Open Sans';
19 font-style: normal;
20 font-weight: 400;
21 src: local('Open Sans'), local('OpenSans'), url(../fonts/opensans/LWCjsQkB6EMdfHrEVqA1KRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
22 unicode-range: U+1F00-1FFF;
23 }
24 /* greek */
25 @font-face {
26 font-family: 'Open Sans';
27 font-style: normal;
28 font-weight: 400;
29 src: local('Open Sans'), local('OpenSans'), url(../fonts/opensans/xozscpT2726on7jbcb_pAhJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
30 unicode-range: U+0370-03FF;
31 }
32 /* vietnamese */
33 @font-face {
34 font-family: 'Open Sans';
35 font-style: normal;
36 font-weight: 400;
37 src: local('Open Sans'), local('OpenSans'), url(../fonts/opensans/59ZRklaO5bWGqF5A9baEERJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
38 unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
39 }
40 /* latin-ext */
41 @font-face {
42 font-family: 'Open Sans';
43 font-style: normal;
44 font-weight: 400;
45 src: local('Open Sans'), local('OpenSans'), url(../fonts/opensans/u-WUoqrET9fUeobQW7jkRRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
46 unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
47 }
48 /* latin */
49 @font-face {
50 font-family: 'Open Sans';
51 font-style: normal;
52 font-weight: 400;
53 src: local('Open Sans'), local('OpenSans'), url(../fonts/opensans/cJZKeOuBrn4kERxqtaUH3VtXRa8TVwTICgirnJhmVJw.woff2) format('woff2');
54 unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
55 }
+0
-10346
faraday/server/www/script/jquery-1.11.2.js less more
0 /*!
1 * jQuery JavaScript Library v1.11.2
2 * http://jquery.com/
3 *
4 * Includes Sizzle.js
5 * http://sizzlejs.com/
6 *
7 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
8 * Released under the MIT license
9 * http://jquery.org/license
10 *
11 * Date: 2014-12-17T15:27Z
12 */
13
14 (function( global, factory ) {
15
16 if ( typeof module === "object" && typeof module.exports === "object" ) {
17 // For CommonJS and CommonJS-like environments where a proper window is present,
18 // execute the factory and get jQuery
19 // For environments that do not inherently posses a window with a document
20 // (such as Node.js), expose a jQuery-making factory as module.exports
21 // This accentuates the need for the creation of a real window
22 // e.g. var jQuery = require("jquery")(window);
23 // See ticket #14549 for more info
24 module.exports = global.document ?
25 factory( global, true ) :
26 function( w ) {
27 if ( !w.document ) {
28 throw new Error( "jQuery requires a window with a document" );
29 }
30 return factory( w );
31 };
32 } else {
33 factory( global );
34 }
35
36 // Pass this if window is not defined yet
37 }(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
38
39 // Can't do this because several apps including ASP.NET trace
40 // the stack via arguments.caller.callee and Firefox dies if
41 // you try to trace through "use strict" call chains. (#13335)
42 // Support: Firefox 18+
43 //
44
45 var deletedIds = [];
46
47 var slice = deletedIds.slice;
48
49 var concat = deletedIds.concat;
50
51 var push = deletedIds.push;
52
53 var indexOf = deletedIds.indexOf;
54
55 var class2type = {};
56
57 var toString = class2type.toString;
58
59 var hasOwn = class2type.hasOwnProperty;
60
61 var support = {};
62
63
64
65 var
66 version = "1.11.2",
67
68 // Define a local copy of jQuery
69 jQuery = function( selector, context ) {
70 // The jQuery object is actually just the init constructor 'enhanced'
71 // Need init if jQuery is called (just allow error to be thrown if not included)
72 return new jQuery.fn.init( selector, context );
73 },
74
75 // Support: Android<4.1, IE<9
76 // Make sure we trim BOM and NBSP
77 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
78
79 // Matches dashed string for camelizing
80 rmsPrefix = /^-ms-/,
81 rdashAlpha = /-([\da-z])/gi,
82
83 // Used by jQuery.camelCase as callback to replace()
84 fcamelCase = function( all, letter ) {
85 return letter.toUpperCase();
86 };
87
88 jQuery.fn = jQuery.prototype = {
89 // The current version of jQuery being used
90 jquery: version,
91
92 constructor: jQuery,
93
94 // Start with an empty selector
95 selector: "",
96
97 // The default length of a jQuery object is 0
98 length: 0,
99
100 toArray: function() {
101 return slice.call( this );
102 },
103
104 // Get the Nth element in the matched element set OR
105 // Get the whole matched element set as a clean array
106 get: function( num ) {
107 return num != null ?
108
109 // Return just the one element from the set
110 ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
111
112 // Return all the elements in a clean array
113 slice.call( this );
114 },
115
116 // Take an array of elements and push it onto the stack
117 // (returning the new matched element set)
118 pushStack: function( elems ) {
119
120 // Build a new jQuery matched element set
121 var ret = jQuery.merge( this.constructor(), elems );
122
123 // Add the old object onto the stack (as a reference)
124 ret.prevObject = this;
125 ret.context = this.context;
126
127 // Return the newly-formed element set
128 return ret;
129 },
130
131 // Execute a callback for every element in the matched set.
132 // (You can seed the arguments with an array of args, but this is
133 // only used internally.)
134 each: function( callback, args ) {
135 return jQuery.each( this, callback, args );
136 },
137
138 map: function( callback ) {
139 return this.pushStack( jQuery.map(this, function( elem, i ) {
140 return callback.call( elem, i, elem );
141 }));
142 },
143
144 slice: function() {
145 return this.pushStack( slice.apply( this, arguments ) );
146 },
147
148 first: function() {
149 return this.eq( 0 );
150 },
151
152 last: function() {
153 return this.eq( -1 );
154 },
155
156 eq: function( i ) {
157 var len = this.length,
158 j = +i + ( i < 0 ? len : 0 );
159 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
160 },
161
162 end: function() {
163 return this.prevObject || this.constructor(null);
164 },
165
166 // For internal use only.
167 // Behaves like an Array's method, not like a jQuery method.
168 push: push,
169 sort: deletedIds.sort,
170 splice: deletedIds.splice
171 };
172
173 jQuery.extend = jQuery.fn.extend = function() {
174 var src, copyIsArray, copy, name, options, clone,
175 target = arguments[0] || {},
176 i = 1,
177 length = arguments.length,
178 deep = false;
179
180 // Handle a deep copy situation
181 if ( typeof target === "boolean" ) {
182 deep = target;
183
184 // skip the boolean and the target
185 target = arguments[ i ] || {};
186 i++;
187 }
188
189 // Handle case when target is a string or something (possible in deep copy)
190 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
191 target = {};
192 }
193
194 // extend jQuery itself if only one argument is passed
195 if ( i === length ) {
196 target = this;
197 i--;
198 }
199
200 for ( ; i < length; i++ ) {
201 // Only deal with non-null/undefined values
202 if ( (options = arguments[ i ]) != null ) {
203 // Extend the base object
204 for ( name in options ) {
205 src = target[ name ];
206 copy = options[ name ];
207
208 // Prevent never-ending loop
209 if ( target === copy ) {
210 continue;
211 }
212
213 // Recurse if we're merging plain objects or arrays
214 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
215 if ( copyIsArray ) {
216 copyIsArray = false;
217 clone = src && jQuery.isArray(src) ? src : [];
218
219 } else {
220 clone = src && jQuery.isPlainObject(src) ? src : {};
221 }
222
223 // Never move original objects, clone them
224 target[ name ] = jQuery.extend( deep, clone, copy );
225
226 // Don't bring in undefined values
227 } else if ( copy !== undefined ) {
228 target[ name ] = copy;
229 }
230 }
231 }
232 }
233
234 // Return the modified object
235 return target;
236 };
237
238 jQuery.extend({
239 // Unique for each copy of jQuery on the page
240 expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
241
242 // Assume jQuery is ready without the ready module
243 isReady: true,
244
245 error: function( msg ) {
246 throw new Error( msg );
247 },
248
249 noop: function() {},
250
251 // See test/unit/core.js for details concerning isFunction.
252 // Since version 1.3, DOM methods and functions like alert
253 // aren't supported. They return false on IE (#2968).
254 isFunction: function( obj ) {
255 return jQuery.type(obj) === "function";
256 },
257
258 isArray: Array.isArray || function( obj ) {
259 return jQuery.type(obj) === "array";
260 },
261
262 isWindow: function( obj ) {
263 /* jshint eqeqeq: false */
264 return obj != null && obj == obj.window;
265 },
266
267 isNumeric: function( obj ) {
268 // parseFloat NaNs numeric-cast false positives (null|true|false|"")
269 // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
270 // subtraction forces infinities to NaN
271 // adding 1 corrects loss of precision from parseFloat (#15100)
272 return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
273 },
274
275 isEmptyObject: function( obj ) {
276 var name;
277 for ( name in obj ) {
278 return false;
279 }
280 return true;
281 },
282
283 isPlainObject: function( obj ) {
284 var key;
285
286 // Must be an Object.
287 // Because of IE, we also have to check the presence of the constructor property.
288 // Make sure that DOM nodes and window objects don't pass through, as well
289 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
290 return false;
291 }
292
293 try {
294 // Not own constructor property must be Object
295 if ( obj.constructor &&
296 !hasOwn.call(obj, "constructor") &&
297 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
298 return false;
299 }
300 } catch ( e ) {
301 // IE8,9 Will throw exceptions on certain host objects #9897
302 return false;
303 }
304
305 // Support: IE<9
306 // Handle iteration over inherited properties before own properties.
307 if ( support.ownLast ) {
308 for ( key in obj ) {
309 return hasOwn.call( obj, key );
310 }
311 }
312
313 // Own properties are enumerated firstly, so to speed up,
314 // if last one is own, then all properties are own.
315 for ( key in obj ) {}
316
317 return key === undefined || hasOwn.call( obj, key );
318 },
319
320 type: function( obj ) {
321 if ( obj == null ) {
322 return obj + "";
323 }
324 return typeof obj === "object" || typeof obj === "function" ?
325 class2type[ toString.call(obj) ] || "object" :
326 typeof obj;
327 },
328
329 // Evaluates a script in a global context
330 // Workarounds based on findings by Jim Driscoll
331 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
332 globalEval: function( data ) {
333 if ( data && jQuery.trim( data ) ) {
334 // We use execScript on Internet Explorer
335 // We use an anonymous function so that context is window
336 // rather than jQuery in Firefox
337 ( window.execScript || function( data ) {
338 window[ "eval" ].call( window, data );
339 } )( data );
340 }
341 },
342
343 // Convert dashed to camelCase; used by the css and data modules
344 // Microsoft forgot to hump their vendor prefix (#9572)
345 camelCase: function( string ) {
346 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
347 },
348
349 nodeName: function( elem, name ) {
350 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
351 },
352
353 // args is for internal usage only
354 each: function( obj, callback, args ) {
355 var value,
356 i = 0,
357 length = obj.length,
358 isArray = isArraylike( obj );
359
360 if ( args ) {
361 if ( isArray ) {
362 for ( ; i < length; i++ ) {
363 value = callback.apply( obj[ i ], args );
364
365 if ( value === false ) {
366 break;
367 }
368 }
369 } else {
370 for ( i in obj ) {
371 value = callback.apply( obj[ i ], args );
372
373 if ( value === false ) {
374 break;
375 }
376 }
377 }
378
379 // A special, fast, case for the most common use of each
380 } else {
381 if ( isArray ) {
382 for ( ; i < length; i++ ) {
383 value = callback.call( obj[ i ], i, obj[ i ] );
384
385 if ( value === false ) {
386 break;
387 }
388 }
389 } else {
390 for ( i in obj ) {
391 value = callback.call( obj[ i ], i, obj[ i ] );
392
393 if ( value === false ) {
394 break;
395 }
396 }
397 }
398 }
399
400 return obj;
401 },
402
403 // Support: Android<4.1, IE<9
404 trim: function( text ) {
405 return text == null ?
406 "" :
407 ( text + "" ).replace( rtrim, "" );
408 },
409
410 // results is for internal usage only
411 makeArray: function( arr, results ) {
412 var ret = results || [];
413
414 if ( arr != null ) {
415 if ( isArraylike( Object(arr) ) ) {
416 jQuery.merge( ret,
417 typeof arr === "string" ?
418 [ arr ] : arr
419 );
420 } else {
421 push.call( ret, arr );
422 }
423 }
424
425 return ret;
426 },
427
428 inArray: function( elem, arr, i ) {
429 var len;
430
431 if ( arr ) {
432 if ( indexOf ) {
433 return indexOf.call( arr, elem, i );
434 }
435
436 len = arr.length;
437 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
438
439 for ( ; i < len; i++ ) {
440 // Skip accessing in sparse arrays
441 if ( i in arr && arr[ i ] === elem ) {
442 return i;
443 }
444 }
445 }
446
447 return -1;
448 },
449
450 merge: function( first, second ) {
451 var len = +second.length,
452 j = 0,
453 i = first.length;
454
455 while ( j < len ) {
456 first[ i++ ] = second[ j++ ];
457 }
458
459 // Support: IE<9
460 // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
461 if ( len !== len ) {
462 while ( second[j] !== undefined ) {
463 first[ i++ ] = second[ j++ ];
464 }
465 }
466
467 first.length = i;
468
469 return first;
470 },
471
472 grep: function( elems, callback, invert ) {
473 var callbackInverse,
474 matches = [],
475 i = 0,
476 length = elems.length,
477 callbackExpect = !invert;
478
479 // Go through the array, only saving the items
480 // that pass the validator function
481 for ( ; i < length; i++ ) {
482 callbackInverse = !callback( elems[ i ], i );
483 if ( callbackInverse !== callbackExpect ) {
484 matches.push( elems[ i ] );
485 }
486 }
487
488 return matches;
489 },
490
491 // arg is for internal usage only
492 map: function( elems, callback, arg ) {
493 var value,
494 i = 0,
495 length = elems.length,
496 isArray = isArraylike( elems ),
497 ret = [];
498
499 // Go through the array, translating each of the items to their new values
500 if ( isArray ) {
501 for ( ; i < length; i++ ) {
502 value = callback( elems[ i ], i, arg );
503
504 if ( value != null ) {
505 ret.push( value );
506 }
507 }
508
509 // Go through every key on the object,
510 } else {
511 for ( i in elems ) {
512 value = callback( elems[ i ], i, arg );
513
514 if ( value != null ) {
515 ret.push( value );
516 }
517 }
518 }
519
520 // Flatten any nested arrays
521 return concat.apply( [], ret );
522 },
523
524 // A global GUID counter for objects
525 guid: 1,
526
527 // Bind a function to a context, optionally partially applying any
528 // arguments.
529 proxy: function( fn, context ) {
530 var args, proxy, tmp;
531
532 if ( typeof context === "string" ) {
533 tmp = fn[ context ];
534 context = fn;
535 fn = tmp;
536 }
537
538 // Quick check to determine if target is callable, in the spec
539 // this throws a TypeError, but we will just return undefined.
540 if ( !jQuery.isFunction( fn ) ) {
541 return undefined;
542 }
543
544 // Simulated bind
545 args = slice.call( arguments, 2 );
546 proxy = function() {
547 return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
548 };
549
550 // Set the guid of unique handler to the same of original handler, so it can be removed
551 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
552
553 return proxy;
554 },
555
556 now: function() {
557 return +( new Date() );
558 },
559
560 // jQuery.support is not used in Core but other projects attach their
561 // properties to it so it needs to exist.
562 support: support
563 });
564
565 // Populate the class2type map
566 jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
567 class2type[ "[object " + name + "]" ] = name.toLowerCase();
568 });
569
570 function isArraylike( obj ) {
571 var length = obj.length,
572 type = jQuery.type( obj );
573
574 if ( type === "function" || jQuery.isWindow( obj ) ) {
575 return false;
576 }
577
578 if ( obj.nodeType === 1 && length ) {
579 return true;
580 }
581
582 return type === "array" || length === 0 ||
583 typeof length === "number" && length > 0 && ( length - 1 ) in obj;
584 }
585 var Sizzle =
586 /*!
587 * Sizzle CSS Selector Engine v2.2.0-pre
588 * http://sizzlejs.com/
589 *
590 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
591 * Released under the MIT license
592 * http://jquery.org/license
593 *
594 * Date: 2014-12-16
595 */
596 (function( window ) {
597
598 var i,
599 support,
600 Expr,
601 getText,
602 isXML,
603 tokenize,
604 compile,
605 select,
606 outermostContext,
607 sortInput,
608 hasDuplicate,
609
610 // Local document vars
611 setDocument,
612 document,
613 docElem,
614 documentIsHTML,
615 rbuggyQSA,
616 rbuggyMatches,
617 matches,
618 contains,
619
620 // Instance-specific data
621 expando = "sizzle" + 1 * new Date(),
622 preferredDoc = window.document,
623 dirruns = 0,
624 done = 0,
625 classCache = createCache(),
626 tokenCache = createCache(),
627 compilerCache = createCache(),
628 sortOrder = function( a, b ) {
629 if ( a === b ) {
630 hasDuplicate = true;
631 }
632 return 0;
633 },
634
635 // General-purpose constants
636 MAX_NEGATIVE = 1 << 31,
637
638 // Instance methods
639 hasOwn = ({}).hasOwnProperty,
640 arr = [],
641 pop = arr.pop,
642 push_native = arr.push,
643 push = arr.push,
644 slice = arr.slice,
645 // Use a stripped-down indexOf as it's faster than native
646 // http://jsperf.com/thor-indexof-vs-for/5
647 indexOf = function( list, elem ) {
648 var i = 0,
649 len = list.length;
650 for ( ; i < len; i++ ) {
651 if ( list[i] === elem ) {
652 return i;
653 }
654 }
655 return -1;
656 },
657
658 booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
659
660 // Regular expressions
661
662 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
663 whitespace = "[\\x20\\t\\r\\n\\f]",
664 // http://www.w3.org/TR/css3-syntax/#characters
665 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
666
667 // Loosely modeled on CSS identifier characters
668 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
669 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
670 identifier = characterEncoding.replace( "w", "w#" ),
671
672 // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
673 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
674 // Operator (capture 2)
675 "*([*^$|!~]?=)" + whitespace +
676 // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
677 "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
678 "*\\]",
679
680 pseudos = ":(" + characterEncoding + ")(?:\\((" +
681 // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
682 // 1. quoted (capture 3; capture 4 or capture 5)
683 "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
684 // 2. simple (capture 6)
685 "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
686 // 3. anything else (capture 2)
687 ".*" +
688 ")\\)|)",
689
690 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
691 rwhitespace = new RegExp( whitespace + "+", "g" ),
692 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
693
694 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
695 rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
696
697 rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
698
699 rpseudo = new RegExp( pseudos ),
700 ridentifier = new RegExp( "^" + identifier + "$" ),
701
702 matchExpr = {
703 "ID": new RegExp( "^#(" + characterEncoding + ")" ),
704 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
705 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
706 "ATTR": new RegExp( "^" + attributes ),
707 "PSEUDO": new RegExp( "^" + pseudos ),
708 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
709 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
710 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
711 "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
712 // For use in libraries implementing .is()
713 // We use this for POS matching in `select`
714 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
715 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
716 },
717
718 rinputs = /^(?:input|select|textarea|button)$/i,
719 rheader = /^h\d$/i,
720
721 rnative = /^[^{]+\{\s*\[native \w/,
722
723 // Easily-parseable/retrievable ID or TAG or CLASS selectors
724 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
725
726 rsibling = /[+~]/,
727 rescape = /'|\\/g,
728
729 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
730 runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
731 funescape = function( _, escaped, escapedWhitespace ) {
732 var high = "0x" + escaped - 0x10000;
733 // NaN means non-codepoint
734 // Support: Firefox<24
735 // Workaround erroneous numeric interpretation of +"0x"
736 return high !== high || escapedWhitespace ?
737 escaped :
738 high < 0 ?
739 // BMP codepoint
740 String.fromCharCode( high + 0x10000 ) :
741 // Supplemental Plane codepoint (surrogate pair)
742 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
743 },
744
745 // Used for iframes
746 // See setDocument()
747 // Removing the function wrapper causes a "Permission Denied"
748 // error in IE
749 unloadHandler = function() {
750 setDocument();
751 };
752
753 // Optimize for push.apply( _, NodeList )
754 try {
755 push.apply(
756 (arr = slice.call( preferredDoc.childNodes )),
757 preferredDoc.childNodes
758 );
759 // Support: Android<4.0
760 // Detect silently failing push.apply
761 arr[ preferredDoc.childNodes.length ].nodeType;
762 } catch ( e ) {
763 push = { apply: arr.length ?
764
765 // Leverage slice if possible
766 function( target, els ) {
767 push_native.apply( target, slice.call(els) );
768 } :
769
770 // Support: IE<9
771 // Otherwise append directly
772 function( target, els ) {
773 var j = target.length,
774 i = 0;
775 // Can't trust NodeList.length
776 while ( (target[j++] = els[i++]) ) {}
777 target.length = j - 1;
778 }
779 };
780 }
781
782 function Sizzle( selector, context, results, seed ) {
783 var match, elem, m, nodeType,
784 // QSA vars
785 i, groups, old, nid, newContext, newSelector;
786
787 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
788 setDocument( context );
789 }
790
791 context = context || document;
792 results = results || [];
793 nodeType = context.nodeType;
794
795 if ( typeof selector !== "string" || !selector ||
796 nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
797
798 return results;
799 }
800
801 if ( !seed && documentIsHTML ) {
802
803 // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
804 if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
805 // Speed-up: Sizzle("#ID")
806 if ( (m = match[1]) ) {
807 if ( nodeType === 9 ) {
808 elem = context.getElementById( m );
809 // Check parentNode to catch when Blackberry 4.6 returns
810 // nodes that are no longer in the document (jQuery #6963)
811 if ( elem && elem.parentNode ) {
812 // Handle the case where IE, Opera, and Webkit return items
813 // by name instead of ID
814 if ( elem.id === m ) {
815 results.push( elem );
816 return results;
817 }
818 } else {
819 return results;
820 }
821 } else {
822 // Context is not a document
823 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
824 contains( context, elem ) && elem.id === m ) {
825 results.push( elem );
826 return results;
827 }
828 }
829
830 // Speed-up: Sizzle("TAG")
831 } else if ( match[2] ) {
832 push.apply( results, context.getElementsByTagName( selector ) );
833 return results;
834
835 // Speed-up: Sizzle(".CLASS")
836 } else if ( (m = match[3]) && support.getElementsByClassName ) {
837 push.apply( results, context.getElementsByClassName( m ) );
838 return results;
839 }
840 }
841
842 // QSA path
843 if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
844 nid = old = expando;
845 newContext = context;
846 newSelector = nodeType !== 1 && selector;
847
848 // qSA works strangely on Element-rooted queries
849 // We can work around this by specifying an extra ID on the root
850 // and working up from there (Thanks to Andrew Dupont for the technique)
851 // IE 8 doesn't work on object elements
852 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
853 groups = tokenize( selector );
854
855 if ( (old = context.getAttribute("id")) ) {
856 nid = old.replace( rescape, "\\$&" );
857 } else {
858 context.setAttribute( "id", nid );
859 }
860 nid = "[id='" + nid + "'] ";
861
862 i = groups.length;
863 while ( i-- ) {
864 groups[i] = nid + toSelector( groups[i] );
865 }
866 newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
867 newSelector = groups.join(",");
868 }
869
870 if ( newSelector ) {
871 try {
872 push.apply( results,
873 newContext.querySelectorAll( newSelector )
874 );
875 return results;
876 } catch(qsaError) {
877 } finally {
878 if ( !old ) {
879 context.removeAttribute("id");
880 }
881 }
882 }
883 }
884 }
885
886 // All others
887 return select( selector.replace( rtrim, "$1" ), context, results, seed );
888 }
889
890 /**
891 * Create key-value caches of limited size
892 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
893 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
894 * deleting the oldest entry
895 */
896 function createCache() {
897 var keys = [];
898
899 function cache( key, value ) {
900 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
901 if ( keys.push( key + " " ) > Expr.cacheLength ) {
902 // Only keep the most recent entries
903 delete cache[ keys.shift() ];
904 }
905 return (cache[ key + " " ] = value);
906 }
907 return cache;
908 }
909
910 /**
911 * Mark a function for special use by Sizzle
912 * @param {Function} fn The function to mark
913 */
914 function markFunction( fn ) {
915 fn[ expando ] = true;
916 return fn;
917 }
918
919 /**
920 * Support testing using an element
921 * @param {Function} fn Passed the created div and expects a boolean result
922 */
923 function assert( fn ) {
924 var div = document.createElement("div");
925
926 try {
927 return !!fn( div );
928 } catch (e) {
929 return false;
930 } finally {
931 // Remove from its parent by default
932 if ( div.parentNode ) {
933 div.parentNode.removeChild( div );
934 }
935 // release memory in IE
936 div = null;
937 }
938 }
939
940 /**
941 * Adds the same handler for all of the specified attrs
942 * @param {String} attrs Pipe-separated list of attributes
943 * @param {Function} handler The method that will be applied
944 */
945 function addHandle( attrs, handler ) {
946 var arr = attrs.split("|"),
947 i = attrs.length;
948
949 while ( i-- ) {
950 Expr.attrHandle[ arr[i] ] = handler;
951 }
952 }
953
954 /**
955 * Checks document order of two siblings
956 * @param {Element} a
957 * @param {Element} b
958 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
959 */
960 function siblingCheck( a, b ) {
961 var cur = b && a,
962 diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
963 ( ~b.sourceIndex || MAX_NEGATIVE ) -
964 ( ~a.sourceIndex || MAX_NEGATIVE );
965
966 // Use IE sourceIndex if available on both nodes
967 if ( diff ) {
968 return diff;
969 }
970
971 // Check if b follows a
972 if ( cur ) {
973 while ( (cur = cur.nextSibling) ) {
974 if ( cur === b ) {
975 return -1;
976 }
977 }
978 }
979
980 return a ? 1 : -1;
981 }
982
983 /**
984 * Returns a function to use in pseudos for input types
985 * @param {String} type
986 */
987 function createInputPseudo( type ) {
988 return function( elem ) {
989 var name = elem.nodeName.toLowerCase();
990 return name === "input" && elem.type === type;
991 };
992 }
993
994 /**
995 * Returns a function to use in pseudos for buttons
996 * @param {String} type
997 */
998 function createButtonPseudo( type ) {
999 return function( elem ) {
1000 var name = elem.nodeName.toLowerCase();
1001 return (name === "input" || name === "button") && elem.type === type;
1002 };
1003 }
1004
1005 /**
1006 * Returns a function to use in pseudos for positionals
1007 * @param {Function} fn
1008 */
1009 function createPositionalPseudo( fn ) {
1010 return markFunction(function( argument ) {
1011 argument = +argument;
1012 return markFunction(function( seed, matches ) {
1013 var j,
1014 matchIndexes = fn( [], seed.length, argument ),
1015 i = matchIndexes.length;
1016
1017 // Match elements found at the specified indexes
1018 while ( i-- ) {
1019 if ( seed[ (j = matchIndexes[i]) ] ) {
1020 seed[j] = !(matches[j] = seed[j]);
1021 }
1022 }
1023 });
1024 });
1025 }
1026
1027 /**
1028 * Checks a node for validity as a Sizzle context
1029 * @param {Element|Object=} context
1030 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
1031 */
1032 function testContext( context ) {
1033 return context && typeof context.getElementsByTagName !== "undefined" && context;
1034 }
1035
1036 // Expose support vars for convenience
1037 support = Sizzle.support = {};
1038
1039 /**
1040 * Detects XML nodes
1041 * @param {Element|Object} elem An element or a document
1042 * @returns {Boolean} True iff elem is a non-HTML XML node
1043 */
1044 isXML = Sizzle.isXML = function( elem ) {
1045 // documentElement is verified for cases where it doesn't yet exist
1046 // (such as loading iframes in IE - #4833)
1047 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1048 return documentElement ? documentElement.nodeName !== "HTML" : false;
1049 };
1050
1051 /**
1052 * Sets document-related variables once based on the current document
1053 * @param {Element|Object} [doc] An element or document object to use to set the document
1054 * @returns {Object} Returns the current document
1055 */
1056 setDocument = Sizzle.setDocument = function( node ) {
1057 var hasCompare, parent,
1058 doc = node ? node.ownerDocument || node : preferredDoc;
1059
1060 // If no document and documentElement is available, return
1061 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1062 return document;
1063 }
1064
1065 // Set our document
1066 document = doc;
1067 docElem = doc.documentElement;
1068 parent = doc.defaultView;
1069
1070 // Support: IE>8
1071 // If iframe document is assigned to "document" variable and if iframe has been reloaded,
1072 // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
1073 // IE6-8 do not support the defaultView property so parent will be undefined
1074 if ( parent && parent !== parent.top ) {
1075 // IE11 does not have attachEvent, so all must suffer
1076 if ( parent.addEventListener ) {
1077 parent.addEventListener( "unload", unloadHandler, false );
1078 } else if ( parent.attachEvent ) {
1079 parent.attachEvent( "onunload", unloadHandler );
1080 }
1081 }
1082
1083 /* Support tests
1084 ---------------------------------------------------------------------- */
1085 documentIsHTML = !isXML( doc );
1086
1087 /* Attributes
1088 ---------------------------------------------------------------------- */
1089
1090 // Support: IE<8
1091 // Verify that getAttribute really returns attributes and not properties
1092 // (excepting IE8 booleans)
1093 support.attributes = assert(function( div ) {
1094 div.className = "i";
1095 return !div.getAttribute("className");
1096 });
1097
1098 /* getElement(s)By*
1099 ---------------------------------------------------------------------- */
1100
1101 // Check if getElementsByTagName("*") returns only elements
1102 support.getElementsByTagName = assert(function( div ) {
1103 div.appendChild( doc.createComment("") );
1104 return !div.getElementsByTagName("*").length;
1105 });
1106
1107 // Support: IE<9
1108 support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
1109
1110 // Support: IE<10
1111 // Check if getElementById returns elements by name
1112 // The broken getElementById methods don't pick up programatically-set names,
1113 // so use a roundabout getElementsByName test
1114 support.getById = assert(function( div ) {
1115 docElem.appendChild( div ).id = expando;
1116 return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
1117 });
1118
1119 // ID find and filter
1120 if ( support.getById ) {
1121 Expr.find["ID"] = function( id, context ) {
1122 if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
1123 var m = context.getElementById( id );
1124 // Check parentNode to catch when Blackberry 4.6 returns
1125 // nodes that are no longer in the document #6963
1126 return m && m.parentNode ? [ m ] : [];
1127 }
1128 };
1129 Expr.filter["ID"] = function( id ) {
1130 var attrId = id.replace( runescape, funescape );
1131 return function( elem ) {
1132 return elem.getAttribute("id") === attrId;
1133 };
1134 };
1135 } else {
1136 // Support: IE6/7
1137 // getElementById is not reliable as a find shortcut
1138 delete Expr.find["ID"];
1139
1140 Expr.filter["ID"] = function( id ) {
1141 var attrId = id.replace( runescape, funescape );
1142 return function( elem ) {
1143 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
1144 return node && node.value === attrId;
1145 };
1146 };
1147 }
1148
1149 // Tag
1150 Expr.find["TAG"] = support.getElementsByTagName ?
1151 function( tag, context ) {
1152 if ( typeof context.getElementsByTagName !== "undefined" ) {
1153 return context.getElementsByTagName( tag );
1154
1155 // DocumentFragment nodes don't have gEBTN
1156 } else if ( support.qsa ) {
1157 return context.querySelectorAll( tag );
1158 }
1159 } :
1160
1161 function( tag, context ) {
1162 var elem,
1163 tmp = [],
1164 i = 0,
1165 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
1166 results = context.getElementsByTagName( tag );
1167
1168 // Filter out possible comments
1169 if ( tag === "*" ) {
1170 while ( (elem = results[i++]) ) {
1171 if ( elem.nodeType === 1 ) {
1172 tmp.push( elem );
1173 }
1174 }
1175
1176 return tmp;
1177 }
1178 return results;
1179 };
1180
1181 // Class
1182 Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1183 if ( documentIsHTML ) {
1184 return context.getElementsByClassName( className );
1185 }
1186 };
1187
1188 /* QSA/matchesSelector
1189 ---------------------------------------------------------------------- */
1190
1191 // QSA and matchesSelector support
1192
1193 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1194 rbuggyMatches = [];
1195
1196 // qSa(:focus) reports false when true (Chrome 21)
1197 // We allow this because of a bug in IE8/9 that throws an error
1198 // whenever `document.activeElement` is accessed on an iframe
1199 // So, we allow :focus to pass through QSA all the time to avoid the IE error
1200 // See http://bugs.jquery.com/ticket/13378
1201 rbuggyQSA = [];
1202
1203 if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
1204 // Build QSA regex
1205 // Regex strategy adopted from Diego Perini
1206 assert(function( div ) {
1207 // Select is set to empty string on purpose
1208 // This is to test IE's treatment of not explicitly
1209 // setting a boolean content attribute,
1210 // since its presence should be enough
1211 // http://bugs.jquery.com/ticket/12359
1212 docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
1213 "<select id='" + expando + "-\f]' msallowcapture=''>" +
1214 "<option selected=''></option></select>";
1215
1216 // Support: IE8, Opera 11-12.16
1217 // Nothing should be selected when empty strings follow ^= or $= or *=
1218 // The test attribute must be unknown in Opera but "safe" for WinRT
1219 // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
1220 if ( div.querySelectorAll("[msallowcapture^='']").length ) {
1221 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1222 }
1223
1224 // Support: IE8
1225 // Boolean attributes and "value" are not treated correctly
1226 if ( !div.querySelectorAll("[selected]").length ) {
1227 rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1228 }
1229
1230 // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
1231 if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
1232 rbuggyQSA.push("~=");
1233 }
1234
1235 // Webkit/Opera - :checked should return selected option elements
1236 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1237 // IE8 throws error here and will not see later tests
1238 if ( !div.querySelectorAll(":checked").length ) {
1239 rbuggyQSA.push(":checked");
1240 }
1241
1242 // Support: Safari 8+, iOS 8+
1243 // https://bugs.webkit.org/show_bug.cgi?id=136851
1244 // In-page `selector#id sibing-combinator selector` fails
1245 if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
1246 rbuggyQSA.push(".#.+[+~]");
1247 }
1248 });
1249
1250 assert(function( div ) {
1251 // Support: Windows 8 Native Apps
1252 // The type and name attributes are restricted during .innerHTML assignment
1253 var input = doc.createElement("input");
1254 input.setAttribute( "type", "hidden" );
1255 div.appendChild( input ).setAttribute( "name", "D" );
1256
1257 // Support: IE8
1258 // Enforce case-sensitivity of name attribute
1259 if ( div.querySelectorAll("[name=d]").length ) {
1260 rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
1261 }
1262
1263 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1264 // IE8 throws error here and will not see later tests
1265 if ( !div.querySelectorAll(":enabled").length ) {
1266 rbuggyQSA.push( ":enabled", ":disabled" );
1267 }
1268
1269 // Opera 10-11 does not throw on post-comma invalid pseudos
1270 div.querySelectorAll("*,:x");
1271 rbuggyQSA.push(",.*:");
1272 });
1273 }
1274
1275 if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
1276 docElem.webkitMatchesSelector ||
1277 docElem.mozMatchesSelector ||
1278 docElem.oMatchesSelector ||
1279 docElem.msMatchesSelector) )) ) {
1280
1281 assert(function( div ) {
1282 // Check to see if it's possible to do matchesSelector
1283 // on a disconnected node (IE 9)
1284 support.disconnectedMatch = matches.call( div, "div" );
1285
1286 // This should fail with an exception
1287 // Gecko does not error, returns false instead
1288 matches.call( div, "[s!='']:x" );
1289 rbuggyMatches.push( "!=", pseudos );
1290 });
1291 }
1292
1293 rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1294 rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1295
1296 /* Contains
1297 ---------------------------------------------------------------------- */
1298 hasCompare = rnative.test( docElem.compareDocumentPosition );
1299
1300 // Element contains another
1301 // Purposefully does not implement inclusive descendent
1302 // As in, an element does not contain itself
1303 contains = hasCompare || rnative.test( docElem.contains ) ?
1304 function( a, b ) {
1305 var adown = a.nodeType === 9 ? a.documentElement : a,
1306 bup = b && b.parentNode;
1307 return a === bup || !!( bup && bup.nodeType === 1 && (
1308 adown.contains ?
1309 adown.contains( bup ) :
1310 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1311 ));
1312 } :
1313 function( a, b ) {
1314 if ( b ) {
1315 while ( (b = b.parentNode) ) {
1316 if ( b === a ) {
1317 return true;
1318 }
1319 }
1320 }
1321 return false;
1322 };
1323
1324 /* Sorting
1325 ---------------------------------------------------------------------- */
1326
1327 // Document order sorting
1328 sortOrder = hasCompare ?
1329 function( a, b ) {
1330
1331 // Flag for duplicate removal
1332 if ( a === b ) {
1333 hasDuplicate = true;
1334 return 0;
1335 }
1336
1337 // Sort on method existence if only one input has compareDocumentPosition
1338 var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
1339 if ( compare ) {
1340 return compare;
1341 }
1342
1343 // Calculate position if both inputs belong to the same document
1344 compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
1345 a.compareDocumentPosition( b ) :
1346
1347 // Otherwise we know they are disconnected
1348 1;
1349
1350 // Disconnected nodes
1351 if ( compare & 1 ||
1352 (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1353
1354 // Choose the first element that is related to our preferred document
1355 if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
1356 return -1;
1357 }
1358 if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
1359 return 1;
1360 }
1361
1362 // Maintain original order
1363 return sortInput ?
1364 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1365 0;
1366 }
1367
1368 return compare & 4 ? -1 : 1;
1369 } :
1370 function( a, b ) {
1371 // Exit early if the nodes are identical
1372 if ( a === b ) {
1373 hasDuplicate = true;
1374 return 0;
1375 }
1376
1377 var cur,
1378 i = 0,
1379 aup = a.parentNode,
1380 bup = b.parentNode,
1381 ap = [ a ],
1382 bp = [ b ];
1383
1384 // Parentless nodes are either documents or disconnected
1385 if ( !aup || !bup ) {
1386 return a === doc ? -1 :
1387 b === doc ? 1 :
1388 aup ? -1 :
1389 bup ? 1 :
1390 sortInput ?
1391 ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
1392 0;
1393
1394 // If the nodes are siblings, we can do a quick check
1395 } else if ( aup === bup ) {
1396 return siblingCheck( a, b );
1397 }
1398
1399 // Otherwise we need full lists of their ancestors for comparison
1400 cur = a;
1401 while ( (cur = cur.parentNode) ) {
1402 ap.unshift( cur );
1403 }
1404 cur = b;
1405 while ( (cur = cur.parentNode) ) {
1406 bp.unshift( cur );
1407 }
1408
1409 // Walk down the tree looking for a discrepancy
1410 while ( ap[i] === bp[i] ) {
1411 i++;
1412 }
1413
1414 return i ?
1415 // Do a sibling check if the nodes have a common ancestor
1416 siblingCheck( ap[i], bp[i] ) :
1417
1418 // Otherwise nodes in our document sort first
1419 ap[i] === preferredDoc ? -1 :
1420 bp[i] === preferredDoc ? 1 :
1421 0;
1422 };
1423
1424 return doc;
1425 };
1426
1427 Sizzle.matches = function( expr, elements ) {
1428 return Sizzle( expr, null, null, elements );
1429 };
1430
1431 Sizzle.matchesSelector = function( elem, expr ) {
1432 // Set document vars if needed
1433 if ( ( elem.ownerDocument || elem ) !== document ) {
1434 setDocument( elem );
1435 }
1436
1437 // Make sure that attribute selectors are quoted
1438 expr = expr.replace( rattributeQuotes, "='$1']" );
1439
1440 if ( support.matchesSelector && documentIsHTML &&
1441 ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1442 ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1443
1444 try {
1445 var ret = matches.call( elem, expr );
1446
1447 // IE 9's matchesSelector returns false on disconnected nodes
1448 if ( ret || support.disconnectedMatch ||
1449 // As well, disconnected nodes are said to be in a document
1450 // fragment in IE 9
1451 elem.document && elem.document.nodeType !== 11 ) {
1452 return ret;
1453 }
1454 } catch (e) {}
1455 }
1456
1457 return Sizzle( expr, document, null, [ elem ] ).length > 0;
1458 };
1459
1460 Sizzle.contains = function( context, elem ) {
1461 // Set document vars if needed
1462 if ( ( context.ownerDocument || context ) !== document ) {
1463 setDocument( context );
1464 }
1465 return contains( context, elem );
1466 };
1467
1468 Sizzle.attr = function( elem, name ) {
1469 // Set document vars if needed
1470 if ( ( elem.ownerDocument || elem ) !== document ) {
1471 setDocument( elem );
1472 }
1473
1474 var fn = Expr.attrHandle[ name.toLowerCase() ],
1475 // Don't get fooled by Object.prototype properties (jQuery #13807)
1476 val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1477 fn( elem, name, !documentIsHTML ) :
1478 undefined;
1479
1480 return val !== undefined ?
1481 val :
1482 support.attributes || !documentIsHTML ?
1483 elem.getAttribute( name ) :
1484 (val = elem.getAttributeNode(name)) && val.specified ?
1485 val.value :
1486 null;
1487 };
1488
1489 Sizzle.error = function( msg ) {
1490 throw new Error( "Syntax error, unrecognized expression: " + msg );
1491 };
1492
1493 /**
1494 * Document sorting and removing duplicates
1495 * @param {ArrayLike} results
1496 */
1497 Sizzle.uniqueSort = function( results ) {
1498 var elem,
1499 duplicates = [],
1500 j = 0,
1501 i = 0;
1502
1503 // Unless we *know* we can detect duplicates, assume their presence
1504 hasDuplicate = !support.detectDuplicates;
1505 sortInput = !support.sortStable && results.slice( 0 );
1506 results.sort( sortOrder );
1507
1508 if ( hasDuplicate ) {
1509 while ( (elem = results[i++]) ) {
1510 if ( elem === results[ i ] ) {
1511 j = duplicates.push( i );
1512 }
1513 }
1514 while ( j-- ) {
1515 results.splice( duplicates[ j ], 1 );
1516 }
1517 }
1518
1519 // Clear input after sorting to release objects
1520 // See https://github.com/jquery/sizzle/pull/225
1521 sortInput = null;
1522
1523 return results;
1524 };
1525
1526 /**
1527 * Utility function for retrieving the text value of an array of DOM nodes
1528 * @param {Array|Element} elem
1529 */
1530 getText = Sizzle.getText = function( elem ) {
1531 var node,
1532 ret = "",
1533 i = 0,
1534 nodeType = elem.nodeType;
1535
1536 if ( !nodeType ) {
1537 // If no nodeType, this is expected to be an array
1538 while ( (node = elem[i++]) ) {
1539 // Do not traverse comment nodes
1540 ret += getText( node );
1541 }
1542 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1543 // Use textContent for elements
1544 // innerText usage removed for consistency of new lines (jQuery #11153)
1545 if ( typeof elem.textContent === "string" ) {
1546 return elem.textContent;
1547 } else {
1548 // Traverse its children
1549 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1550 ret += getText( elem );
1551 }
1552 }
1553 } else if ( nodeType === 3 || nodeType === 4 ) {
1554 return elem.nodeValue;
1555 }
1556 // Do not include comment or processing instruction nodes
1557
1558 return ret;
1559 };
1560
1561 Expr = Sizzle.selectors = {
1562
1563 // Can be adjusted by the user
1564 cacheLength: 50,
1565
1566 createPseudo: markFunction,
1567
1568 match: matchExpr,
1569
1570 attrHandle: {},
1571
1572 find: {},
1573
1574 relative: {
1575 ">": { dir: "parentNode", first: true },
1576 " ": { dir: "parentNode" },
1577 "+": { dir: "previousSibling", first: true },
1578 "~": { dir: "previousSibling" }
1579 },
1580
1581 preFilter: {
1582 "ATTR": function( match ) {
1583 match[1] = match[1].replace( runescape, funescape );
1584
1585 // Move the given value to match[3] whether quoted or unquoted
1586 match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
1587
1588 if ( match[2] === "~=" ) {
1589 match[3] = " " + match[3] + " ";
1590 }
1591
1592 return match.slice( 0, 4 );
1593 },
1594
1595 "CHILD": function( match ) {
1596 /* matches from matchExpr["CHILD"]
1597 1 type (only|nth|...)
1598 2 what (child|of-type)
1599 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1600 4 xn-component of xn+y argument ([+-]?\d*n|)
1601 5 sign of xn-component
1602 6 x of xn-component
1603 7 sign of y-component
1604 8 y of y-component
1605 */
1606 match[1] = match[1].toLowerCase();
1607
1608 if ( match[1].slice( 0, 3 ) === "nth" ) {
1609 // nth-* requires argument
1610 if ( !match[3] ) {
1611 Sizzle.error( match[0] );
1612 }
1613
1614 // numeric x and y parameters for Expr.filter.CHILD
1615 // remember that false/true cast respectively to 0/1
1616 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1617 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1618
1619 // other types prohibit arguments
1620 } else if ( match[3] ) {
1621 Sizzle.error( match[0] );
1622 }
1623
1624 return match;
1625 },
1626
1627 "PSEUDO": function( match ) {
1628 var excess,
1629 unquoted = !match[6] && match[2];
1630
1631 if ( matchExpr["CHILD"].test( match[0] ) ) {
1632 return null;
1633 }
1634
1635 // Accept quoted arguments as-is
1636 if ( match[3] ) {
1637 match[2] = match[4] || match[5] || "";
1638
1639 // Strip excess characters from unquoted arguments
1640 } else if ( unquoted && rpseudo.test( unquoted ) &&
1641 // Get excess from tokenize (recursively)
1642 (excess = tokenize( unquoted, true )) &&
1643 // advance to the next closing parenthesis
1644 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
1645
1646 // excess is a negative index
1647 match[0] = match[0].slice( 0, excess );
1648 match[2] = unquoted.slice( 0, excess );
1649 }
1650
1651 // Return only captures needed by the pseudo filter method (type and argument)
1652 return match.slice( 0, 3 );
1653 }
1654 },
1655
1656 filter: {
1657
1658 "TAG": function( nodeNameSelector ) {
1659 var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
1660 return nodeNameSelector === "*" ?
1661 function() { return true; } :
1662 function( elem ) {
1663 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
1664 };
1665 },
1666
1667 "CLASS": function( className ) {
1668 var pattern = classCache[ className + " " ];
1669
1670 return pattern ||
1671 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
1672 classCache( className, function( elem ) {
1673 return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
1674 });
1675 },
1676
1677 "ATTR": function( name, operator, check ) {
1678 return function( elem ) {
1679 var result = Sizzle.attr( elem, name );
1680
1681 if ( result == null ) {
1682 return operator === "!=";
1683 }
1684 if ( !operator ) {
1685 return true;
1686 }
1687
1688 result += "";
1689
1690 return operator === "=" ? result === check :
1691 operator === "!=" ? result !== check :
1692 operator === "^=" ? check && result.indexOf( check ) === 0 :
1693 operator === "*=" ? check && result.indexOf( check ) > -1 :
1694 operator === "$=" ? check && result.slice( -check.length ) === check :
1695 operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
1696 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
1697 false;
1698 };
1699 },
1700
1701 "CHILD": function( type, what, argument, first, last ) {
1702 var simple = type.slice( 0, 3 ) !== "nth",
1703 forward = type.slice( -4 ) !== "last",
1704 ofType = what === "of-type";
1705
1706 return first === 1 && last === 0 ?
1707
1708 // Shortcut for :nth-*(n)
1709 function( elem ) {
1710 return !!elem.parentNode;
1711 } :
1712
1713 function( elem, context, xml ) {
1714 var cache, outerCache, node, diff, nodeIndex, start,
1715 dir = simple !== forward ? "nextSibling" : "previousSibling",
1716 parent = elem.parentNode,
1717 name = ofType && elem.nodeName.toLowerCase(),
1718 useCache = !xml && !ofType;
1719
1720 if ( parent ) {
1721
1722 // :(first|last|only)-(child|of-type)
1723 if ( simple ) {
1724 while ( dir ) {
1725 node = elem;
1726 while ( (node = node[ dir ]) ) {
1727 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
1728 return false;
1729 }
1730 }
1731 // Reverse direction for :only-* (if we haven't yet done so)
1732 start = dir = type === "only" && !start && "nextSibling";
1733 }
1734 return true;
1735 }
1736
1737 start = [ forward ? parent.firstChild : parent.lastChild ];
1738
1739 // non-xml :nth-child(...) stores cache data on `parent`
1740 if ( forward && useCache ) {
1741 // Seek `elem` from a previously-cached index
1742 outerCache = parent[ expando ] || (parent[ expando ] = {});
1743 cache = outerCache[ type ] || [];
1744 nodeIndex = cache[0] === dirruns && cache[1];
1745 diff = cache[0] === dirruns && cache[2];
1746 node = nodeIndex && parent.childNodes[ nodeIndex ];
1747
1748 while ( (node = ++nodeIndex && node && node[ dir ] ||
1749
1750 // Fallback to seeking `elem` from the start
1751 (diff = nodeIndex = 0) || start.pop()) ) {
1752
1753 // When found, cache indexes on `parent` and break
1754 if ( node.nodeType === 1 && ++diff && node === elem ) {
1755 outerCache[ type ] = [ dirruns, nodeIndex, diff ];
1756 break;
1757 }
1758 }
1759
1760 // Use previously-cached element index if available
1761 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
1762 diff = cache[1];
1763
1764 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
1765 } else {
1766 // Use the same loop as above to seek `elem` from the start
1767 while ( (node = ++nodeIndex && node && node[ dir ] ||
1768 (diff = nodeIndex = 0) || start.pop()) ) {
1769
1770 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
1771 // Cache the index of each encountered element
1772 if ( useCache ) {
1773 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
1774 }
1775
1776 if ( node === elem ) {
1777 break;
1778 }
1779 }
1780 }
1781 }
1782
1783 // Incorporate the offset, then check against cycle size
1784 diff -= last;
1785 return diff === first || ( diff % first === 0 && diff / first >= 0 );
1786 }
1787 };
1788 },
1789
1790 "PSEUDO": function( pseudo, argument ) {
1791 // pseudo-class names are case-insensitive
1792 // http://www.w3.org/TR/selectors/#pseudo-classes
1793 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
1794 // Remember that setFilters inherits from pseudos
1795 var args,
1796 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
1797 Sizzle.error( "unsupported pseudo: " + pseudo );
1798
1799 // The user may use createPseudo to indicate that
1800 // arguments are needed to create the filter function
1801 // just as Sizzle does
1802 if ( fn[ expando ] ) {
1803 return fn( argument );
1804 }
1805
1806 // But maintain support for old signatures
1807 if ( fn.length > 1 ) {
1808 args = [ pseudo, pseudo, "", argument ];
1809 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
1810 markFunction(function( seed, matches ) {
1811 var idx,
1812 matched = fn( seed, argument ),
1813 i = matched.length;
1814 while ( i-- ) {
1815 idx = indexOf( seed, matched[i] );
1816 seed[ idx ] = !( matches[ idx ] = matched[i] );
1817 }
1818 }) :
1819 function( elem ) {
1820 return fn( elem, 0, args );
1821 };
1822 }
1823
1824 return fn;
1825 }
1826 },
1827
1828 pseudos: {
1829 // Potentially complex pseudos
1830 "not": markFunction(function( selector ) {
1831 // Trim the selector passed to compile
1832 // to avoid treating leading and trailing
1833 // spaces as combinators
1834 var input = [],
1835 results = [],
1836 matcher = compile( selector.replace( rtrim, "$1" ) );
1837
1838 return matcher[ expando ] ?
1839 markFunction(function( seed, matches, context, xml ) {
1840 var elem,
1841 unmatched = matcher( seed, null, xml, [] ),
1842 i = seed.length;
1843
1844 // Match elements unmatched by `matcher`
1845 while ( i-- ) {
1846 if ( (elem = unmatched[i]) ) {
1847 seed[i] = !(matches[i] = elem);
1848 }
1849 }
1850 }) :
1851 function( elem, context, xml ) {
1852 input[0] = elem;
1853 matcher( input, null, xml, results );
1854 // Don't keep the element (issue #299)
1855 input[0] = null;
1856 return !results.pop();
1857 };
1858 }),
1859
1860 "has": markFunction(function( selector ) {
1861 return function( elem ) {
1862 return Sizzle( selector, elem ).length > 0;
1863 };
1864 }),
1865
1866 "contains": markFunction(function( text ) {
1867 text = text.replace( runescape, funescape );
1868 return function( elem ) {
1869 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
1870 };
1871 }),
1872
1873 // "Whether an element is represented by a :lang() selector
1874 // is based solely on the element's language value
1875 // being equal to the identifier C,
1876 // or beginning with the identifier C immediately followed by "-".
1877 // The matching of C against the element's language value is performed case-insensitively.
1878 // The identifier C does not have to be a valid language name."
1879 // http://www.w3.org/TR/selectors/#lang-pseudo
1880 "lang": markFunction( function( lang ) {
1881 // lang value must be a valid identifier
1882 if ( !ridentifier.test(lang || "") ) {
1883 Sizzle.error( "unsupported lang: " + lang );
1884 }
1885 lang = lang.replace( runescape, funescape ).toLowerCase();
1886 return function( elem ) {
1887 var elemLang;
1888 do {
1889 if ( (elemLang = documentIsHTML ?
1890 elem.lang :
1891 elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
1892
1893 elemLang = elemLang.toLowerCase();
1894 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
1895 }
1896 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
1897 return false;
1898 };
1899 }),
1900
1901 // Miscellaneous
1902 "target": function( elem ) {
1903 var hash = window.location && window.location.hash;
1904 return hash && hash.slice( 1 ) === elem.id;
1905 },
1906
1907 "root": function( elem ) {
1908 return elem === docElem;
1909 },
1910
1911 "focus": function( elem ) {
1912 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
1913 },
1914
1915 // Boolean properties
1916 "enabled": function( elem ) {
1917 return elem.disabled === false;
1918 },
1919
1920 "disabled": function( elem ) {
1921 return elem.disabled === true;
1922 },
1923
1924 "checked": function( elem ) {
1925 // In CSS3, :checked should return both checked and selected elements
1926 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1927 var nodeName = elem.nodeName.toLowerCase();
1928 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
1929 },
1930
1931 "selected": function( elem ) {
1932 // Accessing this property makes selected-by-default
1933 // options in Safari work properly
1934 if ( elem.parentNode ) {
1935 elem.parentNode.selectedIndex;
1936 }
1937
1938 return elem.selected === true;
1939 },
1940
1941 // Contents
1942 "empty": function( elem ) {
1943 // http://www.w3.org/TR/selectors/#empty-pseudo
1944 // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
1945 // but not by others (comment: 8; processing instruction: 7; etc.)
1946 // nodeType < 6 works because attributes (2) do not appear as children
1947 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1948 if ( elem.nodeType < 6 ) {
1949 return false;
1950 }
1951 }
1952 return true;
1953 },
1954
1955 "parent": function( elem ) {
1956 return !Expr.pseudos["empty"]( elem );
1957 },
1958
1959 // Element/input types
1960 "header": function( elem ) {
1961 return rheader.test( elem.nodeName );
1962 },
1963
1964 "input": function( elem ) {
1965 return rinputs.test( elem.nodeName );
1966 },
1967
1968 "button": function( elem ) {
1969 var name = elem.nodeName.toLowerCase();
1970 return name === "input" && elem.type === "button" || name === "button";
1971 },
1972
1973 "text": function( elem ) {
1974 var attr;
1975 return elem.nodeName.toLowerCase() === "input" &&
1976 elem.type === "text" &&
1977
1978 // Support: IE<8
1979 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
1980 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
1981 },
1982
1983 // Position-in-collection
1984 "first": createPositionalPseudo(function() {
1985 return [ 0 ];
1986 }),
1987
1988 "last": createPositionalPseudo(function( matchIndexes, length ) {
1989 return [ length - 1 ];
1990 }),
1991
1992 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
1993 return [ argument < 0 ? argument + length : argument ];
1994 }),
1995
1996 "even": createPositionalPseudo(function( matchIndexes, length ) {
1997 var i = 0;
1998 for ( ; i < length; i += 2 ) {
1999 matchIndexes.push( i );
2000 }
2001 return matchIndexes;
2002 }),
2003
2004 "odd": createPositionalPseudo(function( matchIndexes, length ) {
2005 var i = 1;
2006 for ( ; i < length; i += 2 ) {
2007 matchIndexes.push( i );
2008 }
2009 return matchIndexes;
2010 }),
2011
2012 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2013 var i = argument < 0 ? argument + length : argument;
2014 for ( ; --i >= 0; ) {
2015 matchIndexes.push( i );
2016 }
2017 return matchIndexes;
2018 }),
2019
2020 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2021 var i = argument < 0 ? argument + length : argument;
2022 for ( ; ++i < length; ) {
2023 matchIndexes.push( i );
2024 }
2025 return matchIndexes;
2026 })
2027 }
2028 };
2029
2030 Expr.pseudos["nth"] = Expr.pseudos["eq"];
2031
2032 // Add button/input type pseudos
2033 for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2034 Expr.pseudos[ i ] = createInputPseudo( i );
2035 }
2036 for ( i in { submit: true, reset: true } ) {
2037 Expr.pseudos[ i ] = createButtonPseudo( i );
2038 }
2039
2040 // Easy API for creating new setFilters
2041 function setFilters() {}
2042 setFilters.prototype = Expr.filters = Expr.pseudos;
2043 Expr.setFilters = new setFilters();
2044
2045 tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
2046 var matched, match, tokens, type,
2047 soFar, groups, preFilters,
2048 cached = tokenCache[ selector + " " ];
2049
2050 if ( cached ) {
2051 return parseOnly ? 0 : cached.slice( 0 );
2052 }
2053
2054 soFar = selector;
2055 groups = [];
2056 preFilters = Expr.preFilter;
2057
2058 while ( soFar ) {
2059
2060 // Comma and first run
2061 if ( !matched || (match = rcomma.exec( soFar )) ) {
2062 if ( match ) {
2063 // Don't consume trailing commas as valid
2064 soFar = soFar.slice( match[0].length ) || soFar;
2065 }
2066 groups.push( (tokens = []) );
2067 }
2068
2069 matched = false;
2070
2071 // Combinators
2072 if ( (match = rcombinators.exec( soFar )) ) {
2073 matched = match.shift();
2074 tokens.push({
2075 value: matched,
2076 // Cast descendant combinators to space
2077 type: match[0].replace( rtrim, " " )
2078 });
2079 soFar = soFar.slice( matched.length );
2080 }
2081
2082 // Filters
2083 for ( type in Expr.filter ) {
2084 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2085 (match = preFilters[ type ]( match ))) ) {
2086 matched = match.shift();
2087 tokens.push({
2088 value: matched,
2089 type: type,
2090 matches: match
2091 });
2092 soFar = soFar.slice( matched.length );
2093 }
2094 }
2095
2096 if ( !matched ) {
2097 break;
2098 }
2099 }
2100
2101 // Return the length of the invalid excess
2102 // if we're just parsing
2103 // Otherwise, throw an error or return tokens
2104 return parseOnly ?
2105 soFar.length :
2106 soFar ?
2107 Sizzle.error( selector ) :
2108 // Cache the tokens
2109 tokenCache( selector, groups ).slice( 0 );
2110 };
2111
2112 function toSelector( tokens ) {
2113 var i = 0,
2114 len = tokens.length,
2115 selector = "";
2116 for ( ; i < len; i++ ) {
2117 selector += tokens[i].value;
2118 }
2119 return selector;
2120 }
2121
2122 function addCombinator( matcher, combinator, base ) {
2123 var dir = combinator.dir,
2124 checkNonElements = base && dir === "parentNode",
2125 doneName = done++;
2126
2127 return combinator.first ?
2128 // Check against closest ancestor/preceding element
2129 function( elem, context, xml ) {
2130 while ( (elem = elem[ dir ]) ) {
2131 if ( elem.nodeType === 1 || checkNonElements ) {
2132 return matcher( elem, context, xml );
2133 }
2134 }
2135 } :
2136
2137 // Check against all ancestor/preceding elements
2138 function( elem, context, xml ) {
2139 var oldCache, outerCache,
2140 newCache = [ dirruns, doneName ];
2141
2142 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
2143 if ( xml ) {
2144 while ( (elem = elem[ dir ]) ) {
2145 if ( elem.nodeType === 1 || checkNonElements ) {
2146 if ( matcher( elem, context, xml ) ) {
2147 return true;
2148 }
2149 }
2150 }
2151 } else {
2152 while ( (elem = elem[ dir ]) ) {
2153 if ( elem.nodeType === 1 || checkNonElements ) {
2154 outerCache = elem[ expando ] || (elem[ expando ] = {});
2155 if ( (oldCache = outerCache[ dir ]) &&
2156 oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
2157
2158 // Assign to newCache so results back-propagate to previous elements
2159 return (newCache[ 2 ] = oldCache[ 2 ]);
2160 } else {
2161 // Reuse newcache so results back-propagate to previous elements
2162 outerCache[ dir ] = newCache;
2163
2164 // A match means we're done; a fail means we have to keep checking
2165 if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
2166 return true;
2167 }
2168 }
2169 }
2170 }
2171 }
2172 };
2173 }
2174
2175 function elementMatcher( matchers ) {
2176 return matchers.length > 1 ?
2177 function( elem, context, xml ) {
2178 var i = matchers.length;
2179 while ( i-- ) {
2180 if ( !matchers[i]( elem, context, xml ) ) {
2181 return false;
2182 }
2183 }
2184 return true;
2185 } :
2186 matchers[0];
2187 }
2188
2189 function multipleContexts( selector, contexts, results ) {
2190 var i = 0,
2191 len = contexts.length;
2192 for ( ; i < len; i++ ) {
2193 Sizzle( selector, contexts[i], results );
2194 }
2195 return results;
2196 }
2197
2198 function condense( unmatched, map, filter, context, xml ) {
2199 var elem,
2200 newUnmatched = [],
2201 i = 0,
2202 len = unmatched.length,
2203 mapped = map != null;
2204
2205 for ( ; i < len; i++ ) {
2206 if ( (elem = unmatched[i]) ) {
2207 if ( !filter || filter( elem, context, xml ) ) {
2208 newUnmatched.push( elem );
2209 if ( mapped ) {
2210 map.push( i );
2211 }
2212 }
2213 }
2214 }
2215
2216 return newUnmatched;
2217 }
2218
2219 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2220 if ( postFilter && !postFilter[ expando ] ) {
2221 postFilter = setMatcher( postFilter );
2222 }
2223 if ( postFinder && !postFinder[ expando ] ) {
2224 postFinder = setMatcher( postFinder, postSelector );
2225 }
2226 return markFunction(function( seed, results, context, xml ) {
2227 var temp, i, elem,
2228 preMap = [],
2229 postMap = [],
2230 preexisting = results.length,
2231
2232 // Get initial elements from seed or context
2233 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2234
2235 // Prefilter to get matcher input, preserving a map for seed-results synchronization
2236 matcherIn = preFilter && ( seed || !selector ) ?
2237 condense( elems, preMap, preFilter, context, xml ) :
2238 elems,
2239
2240 matcherOut = matcher ?
2241 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2242 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2243
2244 // ...intermediate processing is necessary
2245 [] :
2246
2247 // ...otherwise use results directly
2248 results :
2249 matcherIn;
2250
2251 // Find primary matches
2252 if ( matcher ) {
2253 matcher( matcherIn, matcherOut, context, xml );
2254 }
2255
2256 // Apply postFilter
2257 if ( postFilter ) {
2258 temp = condense( matcherOut, postMap );
2259 postFilter( temp, [], context, xml );
2260
2261 // Un-match failing elements by moving them back to matcherIn
2262 i = temp.length;
2263 while ( i-- ) {
2264 if ( (elem = temp[i]) ) {
2265 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2266 }
2267 }
2268 }
2269
2270 if ( seed ) {
2271 if ( postFinder || preFilter ) {
2272 if ( postFinder ) {
2273 // Get the final matcherOut by condensing this intermediate into postFinder contexts
2274 temp = [];
2275 i = matcherOut.length;
2276 while ( i-- ) {
2277 if ( (elem = matcherOut[i]) ) {
2278 // Restore matcherIn since elem is not yet a final match
2279 temp.push( (matcherIn[i] = elem) );
2280 }
2281 }
2282 postFinder( null, (matcherOut = []), temp, xml );
2283 }
2284
2285 // Move matched elements from seed to results to keep them synchronized
2286 i = matcherOut.length;
2287 while ( i-- ) {
2288 if ( (elem = matcherOut[i]) &&
2289 (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
2290
2291 seed[temp] = !(results[temp] = elem);
2292 }
2293 }
2294 }
2295
2296 // Add elements to results, through postFinder if defined
2297 } else {
2298 matcherOut = condense(
2299 matcherOut === results ?
2300 matcherOut.splice( preexisting, matcherOut.length ) :
2301 matcherOut
2302 );
2303 if ( postFinder ) {
2304 postFinder( null, results, matcherOut, xml );
2305 } else {
2306 push.apply( results, matcherOut );
2307 }
2308 }
2309 });
2310 }
2311
2312 function matcherFromTokens( tokens ) {
2313 var checkContext, matcher, j,
2314 len = tokens.length,
2315 leadingRelative = Expr.relative[ tokens[0].type ],
2316 implicitRelative = leadingRelative || Expr.relative[" "],
2317 i = leadingRelative ? 1 : 0,
2318
2319 // The foundational matcher ensures that elements are reachable from top-level context(s)
2320 matchContext = addCombinator( function( elem ) {
2321 return elem === checkContext;
2322 }, implicitRelative, true ),
2323 matchAnyContext = addCombinator( function( elem ) {
2324 return indexOf( checkContext, elem ) > -1;
2325 }, implicitRelative, true ),
2326 matchers = [ function( elem, context, xml ) {
2327 var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2328 (checkContext = context).nodeType ?
2329 matchContext( elem, context, xml ) :
2330 matchAnyContext( elem, context, xml ) );
2331 // Avoid hanging onto element (issue #299)
2332 checkContext = null;
2333 return ret;
2334 } ];
2335
2336 for ( ; i < len; i++ ) {
2337 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2338 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2339 } else {
2340 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2341
2342 // Return special upon seeing a positional matcher
2343 if ( matcher[ expando ] ) {
2344 // Find the next relative operator (if any) for proper handling
2345 j = ++i;
2346 for ( ; j < len; j++ ) {
2347 if ( Expr.relative[ tokens[j].type ] ) {
2348 break;
2349 }
2350 }
2351 return setMatcher(
2352 i > 1 && elementMatcher( matchers ),
2353 i > 1 && toSelector(
2354 // If the preceding token was a descendant combinator, insert an implicit any-element `*`
2355 tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2356 ).replace( rtrim, "$1" ),
2357 matcher,
2358 i < j && matcherFromTokens( tokens.slice( i, j ) ),
2359 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2360 j < len && toSelector( tokens )
2361 );
2362 }
2363 matchers.push( matcher );
2364 }
2365 }
2366
2367 return elementMatcher( matchers );
2368 }
2369
2370 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2371 var bySet = setMatchers.length > 0,
2372 byElement = elementMatchers.length > 0,
2373 superMatcher = function( seed, context, xml, results, outermost ) {
2374 var elem, j, matcher,
2375 matchedCount = 0,
2376 i = "0",
2377 unmatched = seed && [],
2378 setMatched = [],
2379 contextBackup = outermostContext,
2380 // We must always have either seed elements or outermost context
2381 elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
2382 // Use integer dirruns iff this is the outermost matcher
2383 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
2384 len = elems.length;
2385
2386 if ( outermost ) {
2387 outermostContext = context !== document && context;
2388 }
2389
2390 // Add elements passing elementMatchers directly to results
2391 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
2392 // Support: IE<9, Safari
2393 // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
2394 for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
2395 if ( byElement && elem ) {
2396 j = 0;
2397 while ( (matcher = elementMatchers[j++]) ) {
2398 if ( matcher( elem, context, xml ) ) {
2399 results.push( elem );
2400 break;
2401 }
2402 }
2403 if ( outermost ) {
2404 dirruns = dirrunsUnique;
2405 }
2406 }
2407
2408 // Track unmatched elements for set filters
2409 if ( bySet ) {
2410 // They will have gone through all possible matchers
2411 if ( (elem = !matcher && elem) ) {
2412 matchedCount--;
2413 }
2414
2415 // Lengthen the array for every element, matched or not
2416 if ( seed ) {
2417 unmatched.push( elem );
2418 }
2419 }
2420 }
2421
2422 // Apply set filters to unmatched elements
2423 matchedCount += i;
2424 if ( bySet && i !== matchedCount ) {
2425 j = 0;
2426 while ( (matcher = setMatchers[j++]) ) {
2427 matcher( unmatched, setMatched, context, xml );
2428 }
2429
2430 if ( seed ) {
2431 // Reintegrate element matches to eliminate the need for sorting
2432 if ( matchedCount > 0 ) {
2433 while ( i-- ) {
2434 if ( !(unmatched[i] || setMatched[i]) ) {
2435 setMatched[i] = pop.call( results );
2436 }
2437 }
2438 }
2439
2440 // Discard index placeholder values to get only actual matches
2441 setMatched = condense( setMatched );
2442 }
2443
2444 // Add matches to results
2445 push.apply( results, setMatched );
2446
2447 // Seedless set matches succeeding multiple successful matchers stipulate sorting
2448 if ( outermost && !seed && setMatched.length > 0 &&
2449 ( matchedCount + setMatchers.length ) > 1 ) {
2450
2451 Sizzle.uniqueSort( results );
2452 }
2453 }
2454
2455 // Override manipulation of globals by nested matchers
2456 if ( outermost ) {
2457 dirruns = dirrunsUnique;
2458 outermostContext = contextBackup;
2459 }
2460
2461 return unmatched;
2462 };
2463
2464 return bySet ?
2465 markFunction( superMatcher ) :
2466 superMatcher;
2467 }
2468
2469 compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
2470 var i,
2471 setMatchers = [],
2472 elementMatchers = [],
2473 cached = compilerCache[ selector + " " ];
2474
2475 if ( !cached ) {
2476 // Generate a function of recursive functions that can be used to check each element
2477 if ( !match ) {
2478 match = tokenize( selector );
2479 }
2480 i = match.length;
2481 while ( i-- ) {
2482 cached = matcherFromTokens( match[i] );
2483 if ( cached[ expando ] ) {
2484 setMatchers.push( cached );
2485 } else {
2486 elementMatchers.push( cached );
2487 }
2488 }
2489
2490 // Cache the compiled function
2491 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2492
2493 // Save selector and tokenization
2494 cached.selector = selector;
2495 }
2496 return cached;
2497 };
2498
2499 /**
2500 * A low-level selection function that works with Sizzle's compiled
2501 * selector functions
2502 * @param {String|Function} selector A selector or a pre-compiled
2503 * selector function built with Sizzle.compile
2504 * @param {Element} context
2505 * @param {Array} [results]
2506 * @param {Array} [seed] A set of elements to match against
2507 */
2508 select = Sizzle.select = function( selector, context, results, seed ) {
2509 var i, tokens, token, type, find,
2510 compiled = typeof selector === "function" && selector,
2511 match = !seed && tokenize( (selector = compiled.selector || selector) );
2512
2513 results = results || [];
2514
2515 // Try to minimize operations if there is no seed and only one group
2516 if ( match.length === 1 ) {
2517
2518 // Take a shortcut and set the context if the root selector is an ID
2519 tokens = match[0] = match[0].slice( 0 );
2520 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2521 support.getById && context.nodeType === 9 && documentIsHTML &&
2522 Expr.relative[ tokens[1].type ] ) {
2523
2524 context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2525 if ( !context ) {
2526 return results;
2527
2528 // Precompiled matchers will still verify ancestry, so step up a level
2529 } else if ( compiled ) {
2530 context = context.parentNode;
2531 }
2532
2533 selector = selector.slice( tokens.shift().value.length );
2534 }
2535
2536 // Fetch a seed set for right-to-left matching
2537 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2538 while ( i-- ) {
2539 token = tokens[i];
2540
2541 // Abort if we hit a combinator
2542 if ( Expr.relative[ (type = token.type) ] ) {
2543 break;
2544 }
2545 if ( (find = Expr.find[ type ]) ) {
2546 // Search, expanding context for leading sibling combinators
2547 if ( (seed = find(
2548 token.matches[0].replace( runescape, funescape ),
2549 rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
2550 )) ) {
2551
2552 // If seed is empty or no tokens remain, we can return early
2553 tokens.splice( i, 1 );
2554 selector = seed.length && toSelector( tokens );
2555 if ( !selector ) {
2556 push.apply( results, seed );
2557 return results;
2558 }
2559
2560 break;
2561 }
2562 }
2563 }
2564 }
2565
2566 // Compile and execute a filtering function if one is not provided
2567 // Provide `match` to avoid retokenization if we modified the selector above
2568 ( compiled || compile( selector, match ) )(
2569 seed,
2570 context,
2571 !documentIsHTML,
2572 results,
2573 rsibling.test( selector ) && testContext( context.parentNode ) || context
2574 );
2575 return results;
2576 };
2577
2578 // One-time assignments
2579
2580 // Sort stability
2581 support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2582
2583 // Support: Chrome 14-35+
2584 // Always assume duplicates if they aren't passed to the comparison function
2585 support.detectDuplicates = !!hasDuplicate;
2586
2587 // Initialize against the default document
2588 setDocument();
2589
2590 // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2591 // Detached nodes confoundingly follow *each other*
2592 support.sortDetached = assert(function( div1 ) {
2593 // Should return 1, but returns 4 (following)
2594 return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2595 });
2596
2597 // Support: IE<8
2598 // Prevent attribute/property "interpolation"
2599 // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2600 if ( !assert(function( div ) {
2601 div.innerHTML = "<a href='#'></a>";
2602 return div.firstChild.getAttribute("href") === "#" ;
2603 }) ) {
2604 addHandle( "type|href|height|width", function( elem, name, isXML ) {
2605 if ( !isXML ) {
2606 return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2607 }
2608 });
2609 }
2610
2611 // Support: IE<9
2612 // Use defaultValue in place of getAttribute("value")
2613 if ( !support.attributes || !assert(function( div ) {
2614 div.innerHTML = "<input/>";
2615 div.firstChild.setAttribute( "value", "" );
2616 return div.firstChild.getAttribute( "value" ) === "";
2617 }) ) {
2618 addHandle( "value", function( elem, name, isXML ) {
2619 if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2620 return elem.defaultValue;
2621 }
2622 });
2623 }
2624
2625 // Support: IE<9
2626 // Use getAttributeNode to fetch booleans when getAttribute lies
2627 if ( !assert(function( div ) {
2628 return div.getAttribute("disabled") == null;
2629 }) ) {
2630 addHandle( booleans, function( elem, name, isXML ) {
2631 var val;
2632 if ( !isXML ) {
2633 return elem[ name ] === true ? name.toLowerCase() :
2634 (val = elem.getAttributeNode( name )) && val.specified ?
2635 val.value :
2636 null;
2637 }
2638 });
2639 }
2640
2641 return Sizzle;
2642
2643 })( window );
2644
2645
2646
2647 jQuery.find = Sizzle;
2648 jQuery.expr = Sizzle.selectors;
2649 jQuery.expr[":"] = jQuery.expr.pseudos;
2650 jQuery.unique = Sizzle.uniqueSort;
2651 jQuery.text = Sizzle.getText;
2652 jQuery.isXMLDoc = Sizzle.isXML;
2653 jQuery.contains = Sizzle.contains;
2654
2655
2656
2657 var rneedsContext = jQuery.expr.match.needsContext;
2658
2659 var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
2660
2661
2662
2663 var risSimple = /^.[^:#\[\.,]*$/;
2664
2665 // Implement the identical functionality for filter and not
2666 function winnow( elements, qualifier, not ) {
2667 if ( jQuery.isFunction( qualifier ) ) {
2668 return jQuery.grep( elements, function( elem, i ) {
2669 /* jshint -W018 */
2670 return !!qualifier.call( elem, i, elem ) !== not;
2671 });
2672
2673 }
2674
2675 if ( qualifier.nodeType ) {
2676 return jQuery.grep( elements, function( elem ) {
2677 return ( elem === qualifier ) !== not;
2678 });
2679
2680 }
2681
2682 if ( typeof qualifier === "string" ) {
2683 if ( risSimple.test( qualifier ) ) {
2684 return jQuery.filter( qualifier, elements, not );
2685 }
2686
2687 qualifier = jQuery.filter( qualifier, elements );
2688 }
2689
2690 return jQuery.grep( elements, function( elem ) {
2691 return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
2692 });
2693 }
2694
2695 jQuery.filter = function( expr, elems, not ) {
2696 var elem = elems[ 0 ];
2697
2698 if ( not ) {
2699 expr = ":not(" + expr + ")";
2700 }
2701
2702 return elems.length === 1 && elem.nodeType === 1 ?
2703 jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
2704 jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
2705 return elem.nodeType === 1;
2706 }));
2707 };
2708
2709 jQuery.fn.extend({
2710 find: function( selector ) {
2711 var i,
2712 ret = [],
2713 self = this,
2714 len = self.length;
2715
2716 if ( typeof selector !== "string" ) {
2717 return this.pushStack( jQuery( selector ).filter(function() {
2718 for ( i = 0; i < len; i++ ) {
2719 if ( jQuery.contains( self[ i ], this ) ) {
2720 return true;
2721 }
2722 }
2723 }) );
2724 }
2725
2726 for ( i = 0; i < len; i++ ) {
2727 jQuery.find( selector, self[ i ], ret );
2728 }
2729
2730 // Needed because $( selector, context ) becomes $( context ).find( selector )
2731 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
2732 ret.selector = this.selector ? this.selector + " " + selector : selector;
2733 return ret;
2734 },
2735 filter: function( selector ) {
2736 return this.pushStack( winnow(this, selector || [], false) );
2737 },
2738 not: function( selector ) {
2739 return this.pushStack( winnow(this, selector || [], true) );
2740 },
2741 is: function( selector ) {
2742 return !!winnow(
2743 this,
2744
2745 // If this is a positional/relative selector, check membership in the returned set
2746 // so $("p:first").is("p:last") won't return true for a doc with two "p".
2747 typeof selector === "string" && rneedsContext.test( selector ) ?
2748 jQuery( selector ) :
2749 selector || [],
2750 false
2751 ).length;
2752 }
2753 });
2754
2755
2756 // Initialize a jQuery object
2757
2758
2759 // A central reference to the root jQuery(document)
2760 var rootjQuery,
2761
2762 // Use the correct document accordingly with window argument (sandbox)
2763 document = window.document,
2764
2765 // A simple way to check for HTML strings
2766 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
2767 // Strict HTML recognition (#11290: must start with <)
2768 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
2769
2770 init = jQuery.fn.init = function( selector, context ) {
2771 var match, elem;
2772
2773 // HANDLE: $(""), $(null), $(undefined), $(false)
2774 if ( !selector ) {
2775 return this;
2776 }
2777
2778 // Handle HTML strings
2779 if ( typeof selector === "string" ) {
2780 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
2781 // Assume that strings that start and end with <> are HTML and skip the regex check
2782 match = [ null, selector, null ];
2783
2784 } else {
2785 match = rquickExpr.exec( selector );
2786 }
2787
2788 // Match html or make sure no context is specified for #id
2789 if ( match && (match[1] || !context) ) {
2790
2791 // HANDLE: $(html) -> $(array)
2792 if ( match[1] ) {
2793 context = context instanceof jQuery ? context[0] : context;
2794
2795 // scripts is true for back-compat
2796 // Intentionally let the error be thrown if parseHTML is not present
2797 jQuery.merge( this, jQuery.parseHTML(
2798 match[1],
2799 context && context.nodeType ? context.ownerDocument || context : document,
2800 true
2801 ) );
2802
2803 // HANDLE: $(html, props)
2804 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
2805 for ( match in context ) {
2806 // Properties of context are called as methods if possible
2807 if ( jQuery.isFunction( this[ match ] ) ) {
2808 this[ match ]( context[ match ] );
2809
2810 // ...and otherwise set as attributes
2811 } else {
2812 this.attr( match, context[ match ] );
2813 }
2814 }
2815 }
2816
2817 return this;
2818
2819 // HANDLE: $(#id)
2820 } else {
2821 elem = document.getElementById( match[2] );
2822
2823 // Check parentNode to catch when Blackberry 4.6 returns
2824 // nodes that are no longer in the document #6963
2825 if ( elem && elem.parentNode ) {
2826 // Handle the case where IE and Opera return items
2827 // by name instead of ID
2828 if ( elem.id !== match[2] ) {
2829 return rootjQuery.find( selector );
2830 }
2831
2832 // Otherwise, we inject the element directly into the jQuery object
2833 this.length = 1;
2834 this[0] = elem;
2835 }
2836
2837 this.context = document;
2838 this.selector = selector;
2839 return this;
2840 }
2841
2842 // HANDLE: $(expr, $(...))
2843 } else if ( !context || context.jquery ) {
2844 return ( context || rootjQuery ).find( selector );
2845
2846 // HANDLE: $(expr, context)
2847 // (which is just equivalent to: $(context).find(expr)
2848 } else {
2849 return this.constructor( context ).find( selector );
2850 }
2851
2852 // HANDLE: $(DOMElement)
2853 } else if ( selector.nodeType ) {
2854 this.context = this[0] = selector;
2855 this.length = 1;
2856 return this;
2857
2858 // HANDLE: $(function)
2859 // Shortcut for document ready
2860 } else if ( jQuery.isFunction( selector ) ) {
2861 return typeof rootjQuery.ready !== "undefined" ?
2862 rootjQuery.ready( selector ) :
2863 // Execute immediately if ready is not present
2864 selector( jQuery );
2865 }
2866
2867 if ( selector.selector !== undefined ) {
2868 this.selector = selector.selector;
2869 this.context = selector.context;
2870 }
2871
2872 return jQuery.makeArray( selector, this );
2873 };
2874
2875 // Give the init function the jQuery prototype for later instantiation
2876 init.prototype = jQuery.fn;
2877
2878 // Initialize central reference
2879 rootjQuery = jQuery( document );
2880
2881
2882 var rparentsprev = /^(?:parents|prev(?:Until|All))/,
2883 // methods guaranteed to produce a unique set when starting from a unique set
2884 guaranteedUnique = {
2885 children: true,
2886 contents: true,
2887 next: true,
2888 prev: true
2889 };
2890
2891 jQuery.extend({
2892 dir: function( elem, dir, until ) {
2893 var matched = [],
2894 cur = elem[ dir ];
2895
2896 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
2897 if ( cur.nodeType === 1 ) {
2898 matched.push( cur );
2899 }
2900 cur = cur[dir];
2901 }
2902 return matched;
2903 },
2904
2905 sibling: function( n, elem ) {
2906 var r = [];
2907
2908 for ( ; n; n = n.nextSibling ) {
2909 if ( n.nodeType === 1 && n !== elem ) {
2910 r.push( n );
2911 }
2912 }
2913
2914 return r;
2915 }
2916 });
2917
2918 jQuery.fn.extend({
2919 has: function( target ) {
2920 var i,
2921 targets = jQuery( target, this ),
2922 len = targets.length;
2923
2924 return this.filter(function() {
2925 for ( i = 0; i < len; i++ ) {
2926 if ( jQuery.contains( this, targets[i] ) ) {
2927 return true;
2928 }
2929 }
2930 });
2931 },
2932
2933 closest: function( selectors, context ) {
2934 var cur,
2935 i = 0,
2936 l = this.length,
2937 matched = [],
2938 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
2939 jQuery( selectors, context || this.context ) :
2940 0;
2941
2942 for ( ; i < l; i++ ) {
2943 for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
2944 // Always skip document fragments
2945 if ( cur.nodeType < 11 && (pos ?
2946 pos.index(cur) > -1 :
2947
2948 // Don't pass non-elements to Sizzle
2949 cur.nodeType === 1 &&
2950 jQuery.find.matchesSelector(cur, selectors)) ) {
2951
2952 matched.push( cur );
2953 break;
2954 }
2955 }
2956 }
2957
2958 return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
2959 },
2960
2961 // Determine the position of an element within
2962 // the matched set of elements
2963 index: function( elem ) {
2964
2965 // No argument, return index in parent
2966 if ( !elem ) {
2967 return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
2968 }
2969
2970 // index in selector
2971 if ( typeof elem === "string" ) {
2972 return jQuery.inArray( this[0], jQuery( elem ) );
2973 }
2974
2975 // Locate the position of the desired element
2976 return jQuery.inArray(
2977 // If it receives a jQuery object, the first element is used
2978 elem.jquery ? elem[0] : elem, this );
2979 },
2980
2981 add: function( selector, context ) {
2982 return this.pushStack(
2983 jQuery.unique(
2984 jQuery.merge( this.get(), jQuery( selector, context ) )
2985 )
2986 );
2987 },
2988
2989 addBack: function( selector ) {
2990 return this.add( selector == null ?
2991 this.prevObject : this.prevObject.filter(selector)
2992 );
2993 }
2994 });
2995
2996 function sibling( cur, dir ) {
2997 do {
2998 cur = cur[ dir ];
2999 } while ( cur && cur.nodeType !== 1 );
3000
3001 return cur;
3002 }
3003
3004 jQuery.each({
3005 parent: function( elem ) {
3006 var parent = elem.parentNode;
3007 return parent && parent.nodeType !== 11 ? parent : null;
3008 },
3009 parents: function( elem ) {
3010 return jQuery.dir( elem, "parentNode" );
3011 },
3012 parentsUntil: function( elem, i, until ) {
3013 return jQuery.dir( elem, "parentNode", until );
3014 },
3015 next: function( elem ) {
3016 return sibling( elem, "nextSibling" );
3017 },
3018 prev: function( elem ) {
3019 return sibling( elem, "previousSibling" );
3020 },
3021 nextAll: function( elem ) {
3022 return jQuery.dir( elem, "nextSibling" );
3023 },
3024 prevAll: function( elem ) {
3025 return jQuery.dir( elem, "previousSibling" );
3026 },
3027 nextUntil: function( elem, i, until ) {
3028 return jQuery.dir( elem, "nextSibling", until );
3029 },
3030 prevUntil: function( elem, i, until ) {
3031 return jQuery.dir( elem, "previousSibling", until );
3032 },
3033 siblings: function( elem ) {
3034 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
3035 },
3036 children: function( elem ) {
3037 return jQuery.sibling( elem.firstChild );
3038 },
3039 contents: function( elem ) {
3040 return jQuery.nodeName( elem, "iframe" ) ?
3041 elem.contentDocument || elem.contentWindow.document :
3042 jQuery.merge( [], elem.childNodes );
3043 }
3044 }, function( name, fn ) {
3045 jQuery.fn[ name ] = function( until, selector ) {
3046 var ret = jQuery.map( this, fn, until );
3047
3048 if ( name.slice( -5 ) !== "Until" ) {
3049 selector = until;
3050 }
3051
3052 if ( selector && typeof selector === "string" ) {
3053 ret = jQuery.filter( selector, ret );
3054 }
3055
3056 if ( this.length > 1 ) {
3057 // Remove duplicates
3058 if ( !guaranteedUnique[ name ] ) {
3059 ret = jQuery.unique( ret );
3060 }
3061
3062 // Reverse order for parents* and prev-derivatives
3063 if ( rparentsprev.test( name ) ) {
3064 ret = ret.reverse();
3065 }
3066 }
3067
3068 return this.pushStack( ret );
3069 };
3070 });
3071 var rnotwhite = (/\S+/g);
3072
3073
3074
3075 // String to Object options format cache
3076 var optionsCache = {};
3077
3078 // Convert String-formatted options into Object-formatted ones and store in cache
3079 function createOptions( options ) {
3080 var object = optionsCache[ options ] = {};
3081 jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
3082 object[ flag ] = true;
3083 });
3084 return object;
3085 }
3086
3087 /*
3088 * Create a callback list using the following parameters:
3089 *
3090 * options: an optional list of space-separated options that will change how
3091 * the callback list behaves or a more traditional option object
3092 *
3093 * By default a callback list will act like an event callback list and can be
3094 * "fired" multiple times.
3095 *
3096 * Possible options:
3097 *
3098 * once: will ensure the callback list can only be fired once (like a Deferred)
3099 *
3100 * memory: will keep track of previous values and will call any callback added
3101 * after the list has been fired right away with the latest "memorized"
3102 * values (like a Deferred)
3103 *
3104 * unique: will ensure a callback can only be added once (no duplicate in the list)
3105 *
3106 * stopOnFalse: interrupt callings when a callback returns false
3107 *
3108 */
3109 jQuery.Callbacks = function( options ) {
3110
3111 // Convert options from String-formatted to Object-formatted if needed
3112 // (we check in cache first)
3113 options = typeof options === "string" ?
3114 ( optionsCache[ options ] || createOptions( options ) ) :
3115 jQuery.extend( {}, options );
3116
3117 var // Flag to know if list is currently firing
3118 firing,
3119 // Last fire value (for non-forgettable lists)
3120 memory,
3121 // Flag to know if list was already fired
3122 fired,
3123 // End of the loop when firing
3124 firingLength,
3125 // Index of currently firing callback (modified by remove if needed)
3126 firingIndex,
3127 // First callback to fire (used internally by add and fireWith)
3128 firingStart,
3129 // Actual callback list
3130 list = [],
3131 // Stack of fire calls for repeatable lists
3132 stack = !options.once && [],
3133 // Fire callbacks
3134 fire = function( data ) {
3135 memory = options.memory && data;
3136 fired = true;
3137 firingIndex = firingStart || 0;
3138 firingStart = 0;
3139 firingLength = list.length;
3140 firing = true;
3141 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
3142 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
3143 memory = false; // To prevent further calls using add
3144 break;
3145 }
3146 }
3147 firing = false;
3148 if ( list ) {
3149 if ( stack ) {
3150 if ( stack.length ) {
3151 fire( stack.shift() );
3152 }
3153 } else if ( memory ) {
3154 list = [];
3155 } else {
3156 self.disable();
3157 }
3158 }
3159 },
3160 // Actual Callbacks object
3161 self = {
3162 // Add a callback or a collection of callbacks to the list
3163 add: function() {
3164 if ( list ) {
3165 // First, we save the current length
3166 var start = list.length;
3167 (function add( args ) {
3168 jQuery.each( args, function( _, arg ) {
3169 var type = jQuery.type( arg );
3170 if ( type === "function" ) {
3171 if ( !options.unique || !self.has( arg ) ) {
3172 list.push( arg );
3173 }
3174 } else if ( arg && arg.length && type !== "string" ) {
3175 // Inspect recursively
3176 add( arg );
3177 }
3178 });
3179 })( arguments );
3180 // Do we need to add the callbacks to the
3181 // current firing batch?
3182 if ( firing ) {
3183 firingLength = list.length;
3184 // With memory, if we're not firing then
3185 // we should call right away
3186 } else if ( memory ) {
3187 firingStart = start;
3188 fire( memory );
3189 }
3190 }
3191 return this;
3192 },
3193 // Remove a callback from the list
3194 remove: function() {
3195 if ( list ) {
3196 jQuery.each( arguments, function( _, arg ) {
3197 var index;
3198 while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3199 list.splice( index, 1 );
3200 // Handle firing indexes
3201 if ( firing ) {
3202 if ( index <= firingLength ) {
3203 firingLength--;
3204 }
3205 if ( index <= firingIndex ) {
3206 firingIndex--;
3207 }
3208 }
3209 }
3210 });
3211 }
3212 return this;
3213 },
3214 // Check if a given callback is in the list.
3215 // If no argument is given, return whether or not list has callbacks attached.
3216 has: function( fn ) {
3217 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
3218 },
3219 // Remove all callbacks from the list
3220 empty: function() {
3221 list = [];
3222 firingLength = 0;
3223 return this;
3224 },
3225 // Have the list do nothing anymore
3226 disable: function() {
3227 list = stack = memory = undefined;
3228 return this;
3229 },
3230 // Is it disabled?
3231 disabled: function() {
3232 return !list;
3233 },
3234 // Lock the list in its current state
3235 lock: function() {
3236 stack = undefined;
3237 if ( !memory ) {
3238 self.disable();
3239 }
3240 return this;
3241 },
3242 // Is it locked?
3243 locked: function() {
3244 return !stack;
3245 },
3246 // Call all callbacks with the given context and arguments
3247 fireWith: function( context, args ) {
3248 if ( list && ( !fired || stack ) ) {
3249 args = args || [];
3250 args = [ context, args.slice ? args.slice() : args ];
3251 if ( firing ) {
3252 stack.push( args );
3253 } else {
3254 fire( args );
3255 }
3256 }
3257 return this;
3258 },
3259 // Call all the callbacks with the given arguments
3260 fire: function() {
3261 self.fireWith( this, arguments );
3262 return this;
3263 },
3264 // To know if the callbacks have already been called at least once
3265 fired: function() {
3266 return !!fired;
3267 }
3268 };
3269
3270 return self;
3271 };
3272
3273
3274 jQuery.extend({
3275
3276 Deferred: function( func ) {
3277 var tuples = [
3278 // action, add listener, listener list, final state
3279 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
3280 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
3281 [ "notify", "progress", jQuery.Callbacks("memory") ]
3282 ],
3283 state = "pending",
3284 promise = {
3285 state: function() {
3286 return state;
3287 },
3288 always: function() {
3289 deferred.done( arguments ).fail( arguments );
3290 return this;
3291 },
3292 then: function( /* fnDone, fnFail, fnProgress */ ) {
3293 var fns = arguments;
3294 return jQuery.Deferred(function( newDefer ) {
3295 jQuery.each( tuples, function( i, tuple ) {
3296 var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3297 // deferred[ done | fail | progress ] for forwarding actions to newDefer
3298 deferred[ tuple[1] ](function() {
3299 var returned = fn && fn.apply( this, arguments );
3300 if ( returned && jQuery.isFunction( returned.promise ) ) {
3301 returned.promise()
3302 .done( newDefer.resolve )
3303 .fail( newDefer.reject )
3304 .progress( newDefer.notify );
3305 } else {
3306 newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
3307 }
3308 });
3309 });
3310 fns = null;
3311 }).promise();
3312 },
3313 // Get a promise for this deferred
3314 // If obj is provided, the promise aspect is added to the object
3315 promise: function( obj ) {
3316 return obj != null ? jQuery.extend( obj, promise ) : promise;
3317 }
3318 },
3319 deferred = {};
3320
3321 // Keep pipe for back-compat
3322 promise.pipe = promise.then;
3323
3324 // Add list-specific methods
3325 jQuery.each( tuples, function( i, tuple ) {
3326 var list = tuple[ 2 ],
3327 stateString = tuple[ 3 ];
3328
3329 // promise[ done | fail | progress ] = list.add
3330 promise[ tuple[1] ] = list.add;
3331
3332 // Handle state
3333 if ( stateString ) {
3334 list.add(function() {
3335 // state = [ resolved | rejected ]
3336 state = stateString;
3337
3338 // [ reject_list | resolve_list ].disable; progress_list.lock
3339 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3340 }
3341
3342 // deferred[ resolve | reject | notify ]
3343 deferred[ tuple[0] ] = function() {
3344 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
3345 return this;
3346 };
3347 deferred[ tuple[0] + "With" ] = list.fireWith;
3348 });
3349
3350 // Make the deferred a promise
3351 promise.promise( deferred );
3352
3353 // Call given func if any
3354 if ( func ) {
3355 func.call( deferred, deferred );
3356 }
3357
3358 // All done!
3359 return deferred;
3360 },
3361
3362 // Deferred helper
3363 when: function( subordinate /* , ..., subordinateN */ ) {
3364 var i = 0,
3365 resolveValues = slice.call( arguments ),
3366 length = resolveValues.length,
3367
3368 // the count of uncompleted subordinates
3369 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3370
3371 // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
3372 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3373
3374 // Update function for both resolve and progress values
3375 updateFunc = function( i, contexts, values ) {
3376 return function( value ) {
3377 contexts[ i ] = this;
3378 values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
3379 if ( values === progressValues ) {
3380 deferred.notifyWith( contexts, values );
3381
3382 } else if ( !(--remaining) ) {
3383 deferred.resolveWith( contexts, values );
3384 }
3385 };
3386 },
3387
3388 progressValues, progressContexts, resolveContexts;
3389
3390 // add listeners to Deferred subordinates; treat others as resolved
3391 if ( length > 1 ) {
3392 progressValues = new Array( length );
3393 progressContexts = new Array( length );
3394 resolveContexts = new Array( length );
3395 for ( ; i < length; i++ ) {
3396 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3397 resolveValues[ i ].promise()
3398 .done( updateFunc( i, resolveContexts, resolveValues ) )
3399 .fail( deferred.reject )
3400 .progress( updateFunc( i, progressContexts, progressValues ) );
3401 } else {
3402 --remaining;
3403 }
3404 }
3405 }
3406
3407 // if we're not waiting on anything, resolve the master
3408 if ( !remaining ) {
3409 deferred.resolveWith( resolveContexts, resolveValues );
3410 }
3411
3412 return deferred.promise();
3413 }
3414 });
3415
3416
3417 // The deferred used on DOM ready
3418 var readyList;
3419
3420 jQuery.fn.ready = function( fn ) {
3421 // Add the callback
3422 jQuery.ready.promise().done( fn );
3423
3424 return this;
3425 };
3426
3427 jQuery.extend({
3428 // Is the DOM ready to be used? Set to true once it occurs.
3429 isReady: false,
3430
3431 // A counter to track how many items to wait for before
3432 // the ready event fires. See #6781
3433 readyWait: 1,
3434
3435 // Hold (or release) the ready event
3436 holdReady: function( hold ) {
3437 if ( hold ) {
3438 jQuery.readyWait++;
3439 } else {
3440 jQuery.ready( true );
3441 }
3442 },
3443
3444 // Handle when the DOM is ready
3445 ready: function( wait ) {
3446
3447 // Abort if there are pending holds or we're already ready
3448 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
3449 return;
3450 }
3451
3452 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
3453 if ( !document.body ) {
3454 return setTimeout( jQuery.ready );
3455 }
3456
3457 // Remember that the DOM is ready
3458 jQuery.isReady = true;
3459
3460 // If a normal DOM Ready event fired, decrement, and wait if need be
3461 if ( wait !== true && --jQuery.readyWait > 0 ) {
3462 return;
3463 }
3464
3465 // If there are functions bound, to execute
3466 readyList.resolveWith( document, [ jQuery ] );
3467
3468 // Trigger any bound ready events
3469 if ( jQuery.fn.triggerHandler ) {
3470 jQuery( document ).triggerHandler( "ready" );
3471 jQuery( document ).off( "ready" );
3472 }
3473 }
3474 });
3475
3476 /**
3477 * Clean-up method for dom ready events
3478 */
3479 function detach() {
3480 if ( document.addEventListener ) {
3481 document.removeEventListener( "DOMContentLoaded", completed, false );
3482 window.removeEventListener( "load", completed, false );
3483
3484 } else {
3485 document.detachEvent( "onreadystatechange", completed );
3486 window.detachEvent( "onload", completed );
3487 }
3488 }
3489
3490 /**
3491 * The ready event handler and self cleanup method
3492 */
3493 function completed() {
3494 // readyState === "complete" is good enough for us to call the dom ready in oldIE
3495 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
3496 detach();
3497 jQuery.ready();
3498 }
3499 }
3500
3501 jQuery.ready.promise = function( obj ) {
3502 if ( !readyList ) {
3503
3504 readyList = jQuery.Deferred();
3505
3506 // Catch cases where $(document).ready() is called after the browser event has already occurred.
3507 // we once tried to use readyState "interactive" here, but it caused issues like the one
3508 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
3509 if ( document.readyState === "complete" ) {
3510 // Handle it asynchronously to allow scripts the opportunity to delay ready
3511 setTimeout( jQuery.ready );
3512
3513 // Standards-based browsers support DOMContentLoaded
3514 } else if ( document.addEventListener ) {
3515 // Use the handy event callback
3516 document.addEventListener( "DOMContentLoaded", completed, false );
3517
3518 // A fallback to window.onload, that will always work
3519 window.addEventListener( "load", completed, false );
3520
3521 // If IE event model is used
3522 } else {
3523 // Ensure firing before onload, maybe late but safe also for iframes
3524 document.attachEvent( "onreadystatechange", completed );
3525
3526 // A fallback to window.onload, that will always work
3527 window.attachEvent( "onload", completed );
3528
3529 // If IE and not a frame
3530 // continually check to see if the document is ready
3531 var top = false;
3532
3533 try {
3534 top = window.frameElement == null && document.documentElement;
3535 } catch(e) {}
3536
3537 if ( top && top.doScroll ) {
3538 (function doScrollCheck() {
3539 if ( !jQuery.isReady ) {
3540
3541 try {
3542 // Use the trick by Diego Perini
3543 // http://javascript.nwbox.com/IEContentLoaded/
3544 top.doScroll("left");
3545 } catch(e) {
3546 return setTimeout( doScrollCheck, 50 );
3547 }
3548
3549 // detach all dom ready events
3550 detach();
3551
3552 // and execute any waiting functions
3553 jQuery.ready();
3554 }
3555 })();
3556 }
3557 }
3558 }
3559 return readyList.promise( obj );
3560 };
3561
3562
3563 var strundefined = typeof undefined;
3564
3565
3566
3567 // Support: IE<9
3568 // Iteration over object's inherited properties before its own
3569 var i;
3570 for ( i in jQuery( support ) ) {
3571 break;
3572 }
3573 support.ownLast = i !== "0";
3574
3575 // Note: most support tests are defined in their respective modules.
3576 // false until the test is run
3577 support.inlineBlockNeedsLayout = false;
3578
3579 // Execute ASAP in case we need to set body.style.zoom
3580 jQuery(function() {
3581 // Minified: var a,b,c,d
3582 var val, div, body, container;
3583
3584 body = document.getElementsByTagName( "body" )[ 0 ];
3585 if ( !body || !body.style ) {
3586 // Return for frameset docs that don't have a body
3587 return;
3588 }
3589
3590 // Setup
3591 div = document.createElement( "div" );
3592 container = document.createElement( "div" );
3593 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
3594 body.appendChild( container ).appendChild( div );
3595
3596 if ( typeof div.style.zoom !== strundefined ) {
3597 // Support: IE<8
3598 // Check if natively block-level elements act like inline-block
3599 // elements when setting their display to 'inline' and giving
3600 // them layout
3601 div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
3602
3603 support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
3604 if ( val ) {
3605 // Prevent IE 6 from affecting layout for positioned elements #11048
3606 // Prevent IE from shrinking the body in IE 7 mode #12869
3607 // Support: IE<8
3608 body.style.zoom = 1;
3609 }
3610 }
3611
3612 body.removeChild( container );
3613 });
3614
3615
3616
3617
3618 (function() {
3619 var div = document.createElement( "div" );
3620
3621 // Execute the test only if not already executed in another module.
3622 if (support.deleteExpando == null) {
3623 // Support: IE<9
3624 support.deleteExpando = true;
3625 try {
3626 delete div.test;
3627 } catch( e ) {
3628 support.deleteExpando = false;
3629 }
3630 }
3631
3632 // Null elements to avoid leaks in IE.
3633 div = null;
3634 })();
3635
3636
3637 /**
3638 * Determines whether an object can have data
3639 */
3640 jQuery.acceptData = function( elem ) {
3641 var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
3642 nodeType = +elem.nodeType || 1;
3643
3644 // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
3645 return nodeType !== 1 && nodeType !== 9 ?
3646 false :
3647
3648 // Nodes accept data unless otherwise specified; rejection can be conditional
3649 !noData || noData !== true && elem.getAttribute("classid") === noData;
3650 };
3651
3652
3653 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
3654 rmultiDash = /([A-Z])/g;
3655
3656 function dataAttr( elem, key, data ) {
3657 // If nothing was found internally, try to fetch any
3658 // data from the HTML5 data-* attribute
3659 if ( data === undefined && elem.nodeType === 1 ) {
3660
3661 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
3662
3663 data = elem.getAttribute( name );
3664
3665 if ( typeof data === "string" ) {
3666 try {
3667 data = data === "true" ? true :
3668 data === "false" ? false :
3669 data === "null" ? null :
3670 // Only convert to a number if it doesn't change the string
3671 +data + "" === data ? +data :
3672 rbrace.test( data ) ? jQuery.parseJSON( data ) :
3673 data;
3674 } catch( e ) {}
3675
3676 // Make sure we set the data so it isn't changed later
3677 jQuery.data( elem, key, data );
3678
3679 } else {
3680 data = undefined;
3681 }
3682 }
3683
3684 return data;
3685 }
3686
3687 // checks a cache object for emptiness
3688 function isEmptyDataObject( obj ) {
3689 var name;
3690 for ( name in obj ) {
3691
3692 // if the public data object is empty, the private is still empty
3693 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
3694 continue;
3695 }
3696 if ( name !== "toJSON" ) {
3697 return false;
3698 }
3699 }
3700
3701 return true;
3702 }
3703
3704 function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
3705 if ( !jQuery.acceptData( elem ) ) {
3706 return;
3707 }
3708
3709 var ret, thisCache,
3710 internalKey = jQuery.expando,
3711
3712 // We have to handle DOM nodes and JS objects differently because IE6-7
3713 // can't GC object references properly across the DOM-JS boundary
3714 isNode = elem.nodeType,
3715
3716 // Only DOM nodes need the global jQuery cache; JS object data is
3717 // attached directly to the object so GC can occur automatically
3718 cache = isNode ? jQuery.cache : elem,
3719
3720 // Only defining an ID for JS objects if its cache already exists allows
3721 // the code to shortcut on the same path as a DOM node with no cache
3722 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
3723
3724 // Avoid doing any more work than we need to when trying to get data on an
3725 // object that has no data at all
3726 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
3727 return;
3728 }
3729
3730 if ( !id ) {
3731 // Only DOM nodes need a new unique ID for each element since their data
3732 // ends up in the global cache
3733 if ( isNode ) {
3734 id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
3735 } else {
3736 id = internalKey;
3737 }
3738 }
3739
3740 if ( !cache[ id ] ) {
3741 // Avoid exposing jQuery metadata on plain JS objects when the object
3742 // is serialized using JSON.stringify
3743 cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
3744 }
3745
3746 // An object can be passed to jQuery.data instead of a key/value pair; this gets
3747 // shallow copied over onto the existing cache
3748 if ( typeof name === "object" || typeof name === "function" ) {
3749 if ( pvt ) {
3750 cache[ id ] = jQuery.extend( cache[ id ], name );
3751 } else {
3752 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
3753 }
3754 }
3755
3756 thisCache = cache[ id ];
3757
3758 // jQuery data() is stored in a separate object inside the object's internal data
3759 // cache in order to avoid key collisions between internal data and user-defined
3760 // data.
3761 if ( !pvt ) {
3762 if ( !thisCache.data ) {
3763 thisCache.data = {};
3764 }
3765
3766 thisCache = thisCache.data;
3767 }
3768
3769 if ( data !== undefined ) {
3770 thisCache[ jQuery.camelCase( name ) ] = data;
3771 }
3772
3773 // Check for both converted-to-camel and non-converted data property names
3774 // If a data property was specified
3775 if ( typeof name === "string" ) {
3776
3777 // First Try to find as-is property data
3778 ret = thisCache[ name ];
3779
3780 // Test for null|undefined property data
3781 if ( ret == null ) {
3782
3783 // Try to find the camelCased property
3784 ret = thisCache[ jQuery.camelCase( name ) ];
3785 }
3786 } else {
3787 ret = thisCache;
3788 }
3789
3790 return ret;
3791 }
3792
3793 function internalRemoveData( elem, name, pvt ) {
3794 if ( !jQuery.acceptData( elem ) ) {
3795 return;
3796 }
3797
3798 var thisCache, i,
3799 isNode = elem.nodeType,
3800
3801 // See jQuery.data for more information
3802 cache = isNode ? jQuery.cache : elem,
3803 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
3804
3805 // If there is already no cache entry for this object, there is no
3806 // purpose in continuing
3807 if ( !cache[ id ] ) {
3808 return;
3809 }
3810
3811 if ( name ) {
3812
3813 thisCache = pvt ? cache[ id ] : cache[ id ].data;
3814
3815 if ( thisCache ) {
3816
3817 // Support array or space separated string names for data keys
3818 if ( !jQuery.isArray( name ) ) {
3819
3820 // try the string as a key before any manipulation
3821 if ( name in thisCache ) {
3822 name = [ name ];
3823 } else {
3824
3825 // split the camel cased version by spaces unless a key with the spaces exists
3826 name = jQuery.camelCase( name );
3827 if ( name in thisCache ) {
3828 name = [ name ];
3829 } else {
3830 name = name.split(" ");
3831 }
3832 }
3833 } else {
3834 // If "name" is an array of keys...
3835 // When data is initially created, via ("key", "val") signature,
3836 // keys will be converted to camelCase.
3837 // Since there is no way to tell _how_ a key was added, remove
3838 // both plain key and camelCase key. #12786
3839 // This will only penalize the array argument path.
3840 name = name.concat( jQuery.map( name, jQuery.camelCase ) );
3841 }
3842
3843 i = name.length;
3844 while ( i-- ) {
3845 delete thisCache[ name[i] ];
3846 }
3847
3848 // If there is no data left in the cache, we want to continue
3849 // and let the cache object itself get destroyed
3850 if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
3851 return;
3852 }
3853 }
3854 }
3855
3856 // See jQuery.data for more information
3857 if ( !pvt ) {
3858 delete cache[ id ].data;
3859
3860 // Don't destroy the parent cache unless the internal data object
3861 // had been the only thing left in it
3862 if ( !isEmptyDataObject( cache[ id ] ) ) {
3863 return;
3864 }
3865 }
3866
3867 // Destroy the cache
3868 if ( isNode ) {
3869 jQuery.cleanData( [ elem ], true );
3870
3871 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
3872 /* jshint eqeqeq: false */
3873 } else if ( support.deleteExpando || cache != cache.window ) {
3874 /* jshint eqeqeq: true */
3875 delete cache[ id ];
3876
3877 // When all else fails, null
3878 } else {
3879 cache[ id ] = null;
3880 }
3881 }
3882
3883 jQuery.extend({
3884 cache: {},
3885
3886 // The following elements (space-suffixed to avoid Object.prototype collisions)
3887 // throw uncatchable exceptions if you attempt to set expando properties
3888 noData: {
3889 "applet ": true,
3890 "embed ": true,
3891 // ...but Flash objects (which have this classid) *can* handle expandos
3892 "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
3893 },
3894
3895 hasData: function( elem ) {
3896 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
3897 return !!elem && !isEmptyDataObject( elem );
3898 },
3899
3900 data: function( elem, name, data ) {
3901 return internalData( elem, name, data );
3902 },
3903
3904 removeData: function( elem, name ) {
3905 return internalRemoveData( elem, name );
3906 },
3907
3908 // For internal use only.
3909 _data: function( elem, name, data ) {
3910 return internalData( elem, name, data, true );
3911 },
3912
3913 _removeData: function( elem, name ) {
3914 return internalRemoveData( elem, name, true );
3915 }
3916 });
3917
3918 jQuery.fn.extend({
3919 data: function( key, value ) {
3920 var i, name, data,
3921 elem = this[0],
3922 attrs = elem && elem.attributes;
3923
3924 // Special expections of .data basically thwart jQuery.access,
3925 // so implement the relevant behavior ourselves
3926
3927 // Gets all values
3928 if ( key === undefined ) {
3929 if ( this.length ) {
3930 data = jQuery.data( elem );
3931
3932 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
3933 i = attrs.length;
3934 while ( i-- ) {
3935
3936 // Support: IE11+
3937 // The attrs elements can be null (#14894)
3938 if ( attrs[ i ] ) {
3939 name = attrs[ i ].name;
3940 if ( name.indexOf( "data-" ) === 0 ) {
3941 name = jQuery.camelCase( name.slice(5) );
3942 dataAttr( elem, name, data[ name ] );
3943 }
3944 }
3945 }
3946 jQuery._data( elem, "parsedAttrs", true );
3947 }
3948 }
3949
3950 return data;
3951 }
3952
3953 // Sets multiple values
3954 if ( typeof key === "object" ) {
3955 return this.each(function() {
3956 jQuery.data( this, key );
3957 });
3958 }
3959
3960 return arguments.length > 1 ?
3961
3962 // Sets one value
3963 this.each(function() {
3964 jQuery.data( this, key, value );
3965 }) :
3966
3967 // Gets one value
3968 // Try to fetch any internally stored data first
3969 elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
3970 },
3971
3972 removeData: function( key ) {
3973 return this.each(function() {
3974 jQuery.removeData( this, key );
3975 });
3976 }
3977 });
3978
3979
3980 jQuery.extend({
3981 queue: function( elem, type, data ) {
3982 var queue;
3983
3984 if ( elem ) {
3985 type = ( type || "fx" ) + "queue";
3986 queue = jQuery._data( elem, type );
3987
3988 // Speed up dequeue by getting out quickly if this is just a lookup
3989 if ( data ) {
3990 if ( !queue || jQuery.isArray(data) ) {
3991 queue = jQuery._data( elem, type, jQuery.makeArray(data) );
3992 } else {
3993 queue.push( data );
3994 }
3995 }
3996 return queue || [];
3997 }
3998 },
3999
4000 dequeue: function( elem, type ) {
4001 type = type || "fx";
4002
4003 var queue = jQuery.queue( elem, type ),
4004 startLength = queue.length,
4005 fn = queue.shift(),
4006 hooks = jQuery._queueHooks( elem, type ),
4007 next = function() {
4008 jQuery.dequeue( elem, type );
4009 };
4010
4011 // If the fx queue is dequeued, always remove the progress sentinel
4012 if ( fn === "inprogress" ) {
4013 fn = queue.shift();
4014 startLength--;
4015 }
4016
4017 if ( fn ) {
4018
4019 // Add a progress sentinel to prevent the fx queue from being
4020 // automatically dequeued
4021 if ( type === "fx" ) {
4022 queue.unshift( "inprogress" );
4023 }
4024
4025 // clear up the last queue stop function
4026 delete hooks.stop;
4027 fn.call( elem, next, hooks );
4028 }
4029
4030 if ( !startLength && hooks ) {
4031 hooks.empty.fire();
4032 }
4033 },
4034
4035 // not intended for public consumption - generates a queueHooks object, or returns the current one
4036 _queueHooks: function( elem, type ) {
4037 var key = type + "queueHooks";
4038 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
4039 empty: jQuery.Callbacks("once memory").add(function() {
4040 jQuery._removeData( elem, type + "queue" );
4041 jQuery._removeData( elem, key );
4042 })
4043 });
4044 }
4045 });
4046
4047 jQuery.fn.extend({
4048 queue: function( type, data ) {
4049 var setter = 2;
4050
4051 if ( typeof type !== "string" ) {
4052 data = type;
4053 type = "fx";
4054 setter--;
4055 }
4056
4057 if ( arguments.length < setter ) {
4058 return jQuery.queue( this[0], type );
4059 }
4060
4061 return data === undefined ?
4062 this :
4063 this.each(function() {
4064 var queue = jQuery.queue( this, type, data );
4065
4066 // ensure a hooks for this queue
4067 jQuery._queueHooks( this, type );
4068
4069 if ( type === "fx" && queue[0] !== "inprogress" ) {
4070 jQuery.dequeue( this, type );
4071 }
4072 });
4073 },
4074 dequeue: function( type ) {
4075 return this.each(function() {
4076 jQuery.dequeue( this, type );
4077 });
4078 },
4079 clearQueue: function( type ) {
4080 return this.queue( type || "fx", [] );
4081 },
4082 // Get a promise resolved when queues of a certain type
4083 // are emptied (fx is the type by default)
4084 promise: function( type, obj ) {
4085 var tmp,
4086 count = 1,
4087 defer = jQuery.Deferred(),
4088 elements = this,
4089 i = this.length,
4090 resolve = function() {
4091 if ( !( --count ) ) {
4092 defer.resolveWith( elements, [ elements ] );
4093 }
4094 };
4095
4096 if ( typeof type !== "string" ) {
4097 obj = type;
4098 type = undefined;
4099 }
4100 type = type || "fx";
4101
4102 while ( i-- ) {
4103 tmp = jQuery._data( elements[ i ], type + "queueHooks" );
4104 if ( tmp && tmp.empty ) {
4105 count++;
4106 tmp.empty.add( resolve );
4107 }
4108 }
4109 resolve();
4110 return defer.promise( obj );
4111 }
4112 });
4113 var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
4114
4115 var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
4116
4117 var isHidden = function( elem, el ) {
4118 // isHidden might be called from jQuery#filter function;
4119 // in that case, element will be second argument
4120 elem = el || elem;
4121 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
4122 };
4123
4124
4125
4126 // Multifunctional method to get and set values of a collection
4127 // The value/s can optionally be executed if it's a function
4128 var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
4129 var i = 0,
4130 length = elems.length,
4131 bulk = key == null;
4132
4133 // Sets many values
4134 if ( jQuery.type( key ) === "object" ) {
4135 chainable = true;
4136 for ( i in key ) {
4137 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
4138 }
4139
4140 // Sets one value
4141 } else if ( value !== undefined ) {
4142 chainable = true;
4143
4144 if ( !jQuery.isFunction( value ) ) {
4145 raw = true;
4146 }
4147
4148 if ( bulk ) {
4149 // Bulk operations run against the entire set
4150 if ( raw ) {
4151 fn.call( elems, value );
4152 fn = null;
4153
4154 // ...except when executing function values
4155 } else {
4156 bulk = fn;
4157 fn = function( elem, key, value ) {
4158 return bulk.call( jQuery( elem ), value );
4159 };
4160 }
4161 }
4162
4163 if ( fn ) {
4164 for ( ; i < length; i++ ) {
4165 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
4166 }
4167 }
4168 }
4169
4170 return chainable ?
4171 elems :
4172
4173 // Gets
4174 bulk ?
4175 fn.call( elems ) :
4176 length ? fn( elems[0], key ) : emptyGet;
4177 };
4178 var rcheckableType = (/^(?:checkbox|radio)$/i);
4179
4180
4181
4182 (function() {
4183 // Minified: var a,b,c
4184 var input = document.createElement( "input" ),
4185 div = document.createElement( "div" ),
4186 fragment = document.createDocumentFragment();
4187
4188 // Setup
4189 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
4190
4191 // IE strips leading whitespace when .innerHTML is used
4192 support.leadingWhitespace = div.firstChild.nodeType === 3;
4193
4194 // Make sure that tbody elements aren't automatically inserted
4195 // IE will insert them into empty tables
4196 support.tbody = !div.getElementsByTagName( "tbody" ).length;
4197
4198 // Make sure that link elements get serialized correctly by innerHTML
4199 // This requires a wrapper element in IE
4200 support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
4201
4202 // Makes sure cloning an html5 element does not cause problems
4203 // Where outerHTML is undefined, this still works
4204 support.html5Clone =
4205 document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
4206
4207 // Check if a disconnected checkbox will retain its checked
4208 // value of true after appended to the DOM (IE6/7)
4209 input.type = "checkbox";
4210 input.checked = true;
4211 fragment.appendChild( input );
4212 support.appendChecked = input.checked;
4213
4214 // Make sure textarea (and checkbox) defaultValue is properly cloned
4215 // Support: IE6-IE11+
4216 div.innerHTML = "<textarea>x</textarea>";
4217 support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
4218
4219 // #11217 - WebKit loses check when the name is after the checked attribute
4220 fragment.appendChild( div );
4221 div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
4222
4223 // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
4224 // old WebKit doesn't clone checked state correctly in fragments
4225 support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
4226
4227 // Support: IE<9
4228 // Opera does not clone events (and typeof div.attachEvent === undefined).
4229 // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
4230 support.noCloneEvent = true;
4231 if ( div.attachEvent ) {
4232 div.attachEvent( "onclick", function() {
4233 support.noCloneEvent = false;
4234 });
4235
4236 div.cloneNode( true ).click();
4237 }
4238
4239 // Execute the test only if not already executed in another module.
4240 if (support.deleteExpando == null) {
4241 // Support: IE<9
4242 support.deleteExpando = true;
4243 try {
4244 delete div.test;
4245 } catch( e ) {
4246 support.deleteExpando = false;
4247 }
4248 }
4249 })();
4250
4251
4252 (function() {
4253 var i, eventName,
4254 div = document.createElement( "div" );
4255
4256 // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
4257 for ( i in { submit: true, change: true, focusin: true }) {
4258 eventName = "on" + i;
4259
4260 if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
4261 // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
4262 div.setAttribute( eventName, "t" );
4263 support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
4264 }
4265 }
4266
4267 // Null elements to avoid leaks in IE.
4268 div = null;
4269 })();
4270
4271
4272 var rformElems = /^(?:input|select|textarea)$/i,
4273 rkeyEvent = /^key/,
4274 rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
4275 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
4276 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
4277
4278 function returnTrue() {
4279 return true;
4280 }
4281
4282 function returnFalse() {
4283 return false;
4284 }
4285
4286 function safeActiveElement() {
4287 try {
4288 return document.activeElement;
4289 } catch ( err ) { }
4290 }
4291
4292 /*
4293 * Helper functions for managing events -- not part of the public interface.
4294 * Props to Dean Edwards' addEvent library for many of the ideas.
4295 */
4296 jQuery.event = {
4297
4298 global: {},
4299
4300 add: function( elem, types, handler, data, selector ) {
4301 var tmp, events, t, handleObjIn,
4302 special, eventHandle, handleObj,
4303 handlers, type, namespaces, origType,
4304 elemData = jQuery._data( elem );
4305
4306 // Don't attach events to noData or text/comment nodes (but allow plain objects)
4307 if ( !elemData ) {
4308 return;
4309 }
4310
4311 // Caller can pass in an object of custom data in lieu of the handler
4312 if ( handler.handler ) {
4313 handleObjIn = handler;
4314 handler = handleObjIn.handler;
4315 selector = handleObjIn.selector;
4316 }
4317
4318 // Make sure that the handler has a unique ID, used to find/remove it later
4319 if ( !handler.guid ) {
4320 handler.guid = jQuery.guid++;
4321 }
4322
4323 // Init the element's event structure and main handler, if this is the first
4324 if ( !(events = elemData.events) ) {
4325 events = elemData.events = {};
4326 }
4327 if ( !(eventHandle = elemData.handle) ) {
4328 eventHandle = elemData.handle = function( e ) {
4329 // Discard the second event of a jQuery.event.trigger() and
4330 // when an event is called after a page has unloaded
4331 return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
4332 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
4333 undefined;
4334 };
4335 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
4336 eventHandle.elem = elem;
4337 }
4338
4339 // Handle multiple events separated by a space
4340 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4341 t = types.length;
4342 while ( t-- ) {
4343 tmp = rtypenamespace.exec( types[t] ) || [];
4344 type = origType = tmp[1];
4345 namespaces = ( tmp[2] || "" ).split( "." ).sort();
4346
4347 // There *must* be a type, no attaching namespace-only handlers
4348 if ( !type ) {
4349 continue;
4350 }
4351
4352 // If event changes its type, use the special event handlers for the changed type
4353 special = jQuery.event.special[ type ] || {};
4354
4355 // If selector defined, determine special event api type, otherwise given type
4356 type = ( selector ? special.delegateType : special.bindType ) || type;
4357
4358 // Update special based on newly reset type
4359 special = jQuery.event.special[ type ] || {};
4360
4361 // handleObj is passed to all event handlers
4362 handleObj = jQuery.extend({
4363 type: type,
4364 origType: origType,
4365 data: data,
4366 handler: handler,
4367 guid: handler.guid,
4368 selector: selector,
4369 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4370 namespace: namespaces.join(".")
4371 }, handleObjIn );
4372
4373 // Init the event handler queue if we're the first
4374 if ( !(handlers = events[ type ]) ) {
4375 handlers = events[ type ] = [];
4376 handlers.delegateCount = 0;
4377
4378 // Only use addEventListener/attachEvent if the special events handler returns false
4379 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4380 // Bind the global event handler to the element
4381 if ( elem.addEventListener ) {
4382 elem.addEventListener( type, eventHandle, false );
4383
4384 } else if ( elem.attachEvent ) {
4385 elem.attachEvent( "on" + type, eventHandle );
4386 }
4387 }
4388 }
4389
4390 if ( special.add ) {
4391 special.add.call( elem, handleObj );
4392
4393 if ( !handleObj.handler.guid ) {
4394 handleObj.handler.guid = handler.guid;
4395 }
4396 }
4397
4398 // Add to the element's handler list, delegates in front
4399 if ( selector ) {
4400 handlers.splice( handlers.delegateCount++, 0, handleObj );
4401 } else {
4402 handlers.push( handleObj );
4403 }
4404
4405 // Keep track of which events have ever been used, for event optimization
4406 jQuery.event.global[ type ] = true;
4407 }
4408
4409 // Nullify elem to prevent memory leaks in IE
4410 elem = null;
4411 },
4412
4413 // Detach an event or set of events from an element
4414 remove: function( elem, types, handler, selector, mappedTypes ) {
4415 var j, handleObj, tmp,
4416 origCount, t, events,
4417 special, handlers, type,
4418 namespaces, origType,
4419 elemData = jQuery.hasData( elem ) && jQuery._data( elem );
4420
4421 if ( !elemData || !(events = elemData.events) ) {
4422 return;
4423 }
4424
4425 // Once for each type.namespace in types; type may be omitted
4426 types = ( types || "" ).match( rnotwhite ) || [ "" ];
4427 t = types.length;
4428 while ( t-- ) {
4429 tmp = rtypenamespace.exec( types[t] ) || [];
4430 type = origType = tmp[1];
4431 namespaces = ( tmp[2] || "" ).split( "." ).sort();
4432
4433 // Unbind all events (on this namespace, if provided) for the element
4434 if ( !type ) {
4435 for ( type in events ) {
4436 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4437 }
4438 continue;
4439 }
4440
4441 special = jQuery.event.special[ type ] || {};
4442 type = ( selector ? special.delegateType : special.bindType ) || type;
4443 handlers = events[ type ] || [];
4444 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
4445
4446 // Remove matching events
4447 origCount = j = handlers.length;
4448 while ( j-- ) {
4449 handleObj = handlers[ j ];
4450
4451 if ( ( mappedTypes || origType === handleObj.origType ) &&
4452 ( !handler || handler.guid === handleObj.guid ) &&
4453 ( !tmp || tmp.test( handleObj.namespace ) ) &&
4454 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
4455 handlers.splice( j, 1 );
4456
4457 if ( handleObj.selector ) {
4458 handlers.delegateCount--;
4459 }
4460 if ( special.remove ) {
4461 special.remove.call( elem, handleObj );
4462 }
4463 }
4464 }
4465
4466 // Remove generic event handler if we removed something and no more handlers exist
4467 // (avoids potential for endless recursion during removal of special event handlers)
4468 if ( origCount && !handlers.length ) {
4469 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
4470 jQuery.removeEvent( elem, type, elemData.handle );
4471 }
4472
4473 delete events[ type ];
4474 }
4475 }
4476
4477 // Remove the expando if it's no longer used
4478 if ( jQuery.isEmptyObject( events ) ) {
4479 delete elemData.handle;
4480
4481 // removeData also checks for emptiness and clears the expando if empty
4482 // so use it instead of delete
4483 jQuery._removeData( elem, "events" );
4484 }
4485 },
4486
4487 trigger: function( event, data, elem, onlyHandlers ) {
4488 var handle, ontype, cur,
4489 bubbleType, special, tmp, i,
4490 eventPath = [ elem || document ],
4491 type = hasOwn.call( event, "type" ) ? event.type : event,
4492 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
4493
4494 cur = tmp = elem = elem || document;
4495
4496 // Don't do events on text and comment nodes
4497 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
4498 return;
4499 }
4500
4501 // focus/blur morphs to focusin/out; ensure we're not firing them right now
4502 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
4503 return;
4504 }
4505
4506 if ( type.indexOf(".") >= 0 ) {
4507 // Namespaced trigger; create a regexp to match event type in handle()
4508 namespaces = type.split(".");
4509 type = namespaces.shift();
4510 namespaces.sort();
4511 }
4512 ontype = type.indexOf(":") < 0 && "on" + type;
4513
4514 // Caller can pass in a jQuery.Event object, Object, or just an event type string
4515 event = event[ jQuery.expando ] ?
4516 event :
4517 new jQuery.Event( type, typeof event === "object" && event );
4518
4519 // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
4520 event.isTrigger = onlyHandlers ? 2 : 3;
4521 event.namespace = namespaces.join(".");
4522 event.namespace_re = event.namespace ?
4523 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
4524 null;
4525
4526 // Clean up the event in case it is being reused
4527 event.result = undefined;
4528 if ( !event.target ) {
4529 event.target = elem;
4530 }
4531
4532 // Clone any incoming data and prepend the event, creating the handler arg list
4533 data = data == null ?
4534 [ event ] :
4535 jQuery.makeArray( data, [ event ] );
4536
4537 // Allow special events to draw outside the lines
4538 special = jQuery.event.special[ type ] || {};
4539 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
4540 return;
4541 }
4542
4543 // Determine event propagation path in advance, per W3C events spec (#9951)
4544 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
4545 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
4546
4547 bubbleType = special.delegateType || type;
4548 if ( !rfocusMorph.test( bubbleType + type ) ) {
4549 cur = cur.parentNode;
4550 }
4551 for ( ; cur; cur = cur.parentNode ) {
4552 eventPath.push( cur );
4553 tmp = cur;
4554 }
4555
4556 // Only add window if we got to document (e.g., not plain obj or detached DOM)
4557 if ( tmp === (elem.ownerDocument || document) ) {
4558 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
4559 }
4560 }
4561
4562 // Fire handlers on the event path
4563 i = 0;
4564 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
4565
4566 event.type = i > 1 ?
4567 bubbleType :
4568 special.bindType || type;
4569
4570 // jQuery handler
4571 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
4572 if ( handle ) {
4573 handle.apply( cur, data );
4574 }
4575
4576 // Native handler
4577 handle = ontype && cur[ ontype ];
4578 if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
4579 event.result = handle.apply( cur, data );
4580 if ( event.result === false ) {
4581 event.preventDefault();
4582 }
4583 }
4584 }
4585 event.type = type;
4586
4587 // If nobody prevented the default action, do it now
4588 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
4589
4590 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
4591 jQuery.acceptData( elem ) ) {
4592
4593 // Call a native DOM method on the target with the same name name as the event.
4594 // Can't use an .isFunction() check here because IE6/7 fails that test.
4595 // Don't do default actions on window, that's where global variables be (#6170)
4596 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
4597
4598 // Don't re-trigger an onFOO event when we call its FOO() method
4599 tmp = elem[ ontype ];
4600
4601 if ( tmp ) {
4602 elem[ ontype ] = null;
4603 }
4604
4605 // Prevent re-triggering of the same event, since we already bubbled it above
4606 jQuery.event.triggered = type;
4607 try {
4608 elem[ type ]();
4609 } catch ( e ) {
4610 // IE<9 dies on focus/blur to hidden element (#1486,#12518)
4611 // only reproducible on winXP IE8 native, not IE9 in IE8 mode
4612 }
4613 jQuery.event.triggered = undefined;
4614
4615 if ( tmp ) {
4616 elem[ ontype ] = tmp;
4617 }
4618 }
4619 }
4620 }
4621
4622 return event.result;
4623 },
4624
4625 dispatch: function( event ) {
4626
4627 // Make a writable jQuery.Event from the native event object
4628 event = jQuery.event.fix( event );
4629
4630 var i, ret, handleObj, matched, j,
4631 handlerQueue = [],
4632 args = slice.call( arguments ),
4633 handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
4634 special = jQuery.event.special[ event.type ] || {};
4635
4636 // Use the fix-ed jQuery.Event rather than the (read-only) native event
4637 args[0] = event;
4638 event.delegateTarget = this;
4639
4640 // Call the preDispatch hook for the mapped type, and let it bail if desired
4641 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
4642 return;
4643 }
4644
4645 // Determine handlers
4646 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
4647
4648 // Run delegates first; they may want to stop propagation beneath us
4649 i = 0;
4650 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
4651 event.currentTarget = matched.elem;
4652
4653 j = 0;
4654 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
4655
4656 // Triggered event must either 1) have no namespace, or
4657 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
4658 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
4659
4660 event.handleObj = handleObj;
4661 event.data = handleObj.data;
4662
4663 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
4664 .apply( matched.elem, args );
4665
4666 if ( ret !== undefined ) {
4667 if ( (event.result = ret) === false ) {
4668 event.preventDefault();
4669 event.stopPropagation();
4670 }
4671 }
4672 }
4673 }
4674 }
4675
4676 // Call the postDispatch hook for the mapped type
4677 if ( special.postDispatch ) {
4678 special.postDispatch.call( this, event );
4679 }
4680
4681 return event.result;
4682 },
4683
4684 handlers: function( event, handlers ) {
4685 var sel, handleObj, matches, i,
4686 handlerQueue = [],
4687 delegateCount = handlers.delegateCount,
4688 cur = event.target;
4689
4690 // Find delegate handlers
4691 // Black-hole SVG <use> instance trees (#13180)
4692 // Avoid non-left-click bubbling in Firefox (#3861)
4693 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
4694
4695 /* jshint eqeqeq: false */
4696 for ( ; cur != this; cur = cur.parentNode || this ) {
4697 /* jshint eqeqeq: true */
4698
4699 // Don't check non-elements (#13208)
4700 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
4701 if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
4702 matches = [];
4703 for ( i = 0; i < delegateCount; i++ ) {
4704 handleObj = handlers[ i ];
4705
4706 // Don't conflict with Object.prototype properties (#13203)
4707 sel = handleObj.selector + " ";
4708
4709 if ( matches[ sel ] === undefined ) {
4710 matches[ sel ] = handleObj.needsContext ?
4711 jQuery( sel, this ).index( cur ) >= 0 :
4712 jQuery.find( sel, this, null, [ cur ] ).length;
4713 }
4714 if ( matches[ sel ] ) {
4715 matches.push( handleObj );
4716 }
4717 }
4718 if ( matches.length ) {
4719 handlerQueue.push({ elem: cur, handlers: matches });
4720 }
4721 }
4722 }
4723 }
4724
4725 // Add the remaining (directly-bound) handlers
4726 if ( delegateCount < handlers.length ) {
4727 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
4728 }
4729
4730 return handlerQueue;
4731 },
4732
4733 fix: function( event ) {
4734 if ( event[ jQuery.expando ] ) {
4735 return event;
4736 }
4737
4738 // Create a writable copy of the event object and normalize some properties
4739 var i, prop, copy,
4740 type = event.type,
4741 originalEvent = event,
4742 fixHook = this.fixHooks[ type ];
4743
4744 if ( !fixHook ) {
4745 this.fixHooks[ type ] = fixHook =
4746 rmouseEvent.test( type ) ? this.mouseHooks :
4747 rkeyEvent.test( type ) ? this.keyHooks :
4748 {};
4749 }
4750 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
4751
4752 event = new jQuery.Event( originalEvent );
4753
4754 i = copy.length;
4755 while ( i-- ) {
4756 prop = copy[ i ];
4757 event[ prop ] = originalEvent[ prop ];
4758 }
4759
4760 // Support: IE<9
4761 // Fix target property (#1925)
4762 if ( !event.target ) {
4763 event.target = originalEvent.srcElement || document;
4764 }
4765
4766 // Support: Chrome 23+, Safari?
4767 // Target should not be a text node (#504, #13143)
4768 if ( event.target.nodeType === 3 ) {
4769 event.target = event.target.parentNode;
4770 }
4771
4772 // Support: IE<9
4773 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
4774 event.metaKey = !!event.metaKey;
4775
4776 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
4777 },
4778
4779 // Includes some event props shared by KeyEvent and MouseEvent
4780 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
4781
4782 fixHooks: {},
4783
4784 keyHooks: {
4785 props: "char charCode key keyCode".split(" "),
4786 filter: function( event, original ) {
4787
4788 // Add which for key events
4789 if ( event.which == null ) {
4790 event.which = original.charCode != null ? original.charCode : original.keyCode;
4791 }
4792
4793 return event;
4794 }
4795 },
4796
4797 mouseHooks: {
4798 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
4799 filter: function( event, original ) {
4800 var body, eventDoc, doc,
4801 button = original.button,
4802 fromElement = original.fromElement;
4803
4804 // Calculate pageX/Y if missing and clientX/Y available
4805 if ( event.pageX == null && original.clientX != null ) {
4806 eventDoc = event.target.ownerDocument || document;
4807 doc = eventDoc.documentElement;
4808 body = eventDoc.body;
4809
4810 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
4811 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
4812 }
4813
4814 // Add relatedTarget, if necessary
4815 if ( !event.relatedTarget && fromElement ) {
4816 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
4817 }
4818
4819 // Add which for click: 1 === left; 2 === middle; 3 === right
4820 // Note: button is not normalized, so don't use it
4821 if ( !event.which && button !== undefined ) {
4822 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
4823 }
4824
4825 return event;
4826 }
4827 },
4828
4829 special: {
4830 load: {
4831 // Prevent triggered image.load events from bubbling to window.load
4832 noBubble: true
4833 },
4834 focus: {
4835 // Fire native event if possible so blur/focus sequence is correct
4836 trigger: function() {
4837 if ( this !== safeActiveElement() && this.focus ) {
4838 try {
4839 this.focus();
4840 return false;
4841 } catch ( e ) {
4842 // Support: IE<9
4843 // If we error on focus to hidden element (#1486, #12518),
4844 // let .trigger() run the handlers
4845 }
4846 }
4847 },
4848 delegateType: "focusin"
4849 },
4850 blur: {
4851 trigger: function() {
4852 if ( this === safeActiveElement() && this.blur ) {
4853 this.blur();
4854 return false;
4855 }
4856 },
4857 delegateType: "focusout"
4858 },
4859 click: {
4860 // For checkbox, fire native event so checked state will be right
4861 trigger: function() {
4862 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
4863 this.click();
4864 return false;
4865 }
4866 },
4867
4868 // For cross-browser consistency, don't fire native .click() on links
4869 _default: function( event ) {
4870 return jQuery.nodeName( event.target, "a" );
4871 }
4872 },
4873
4874 beforeunload: {
4875 postDispatch: function( event ) {
4876
4877 // Support: Firefox 20+
4878 // Firefox doesn't alert if the returnValue field is not set.
4879 if ( event.result !== undefined && event.originalEvent ) {
4880 event.originalEvent.returnValue = event.result;
4881 }
4882 }
4883 }
4884 },
4885
4886 simulate: function( type, elem, event, bubble ) {
4887 // Piggyback on a donor event to simulate a different one.
4888 // Fake originalEvent to avoid donor's stopPropagation, but if the
4889 // simulated event prevents default then we do the same on the donor.
4890 var e = jQuery.extend(
4891 new jQuery.Event(),
4892 event,
4893 {
4894 type: type,
4895 isSimulated: true,
4896 originalEvent: {}
4897 }
4898 );
4899 if ( bubble ) {
4900 jQuery.event.trigger( e, null, elem );
4901 } else {
4902 jQuery.event.dispatch.call( elem, e );
4903 }
4904 if ( e.isDefaultPrevented() ) {
4905 event.preventDefault();
4906 }
4907 }
4908 };
4909
4910 jQuery.removeEvent = document.removeEventListener ?
4911 function( elem, type, handle ) {
4912 if ( elem.removeEventListener ) {
4913 elem.removeEventListener( type, handle, false );
4914 }
4915 } :
4916 function( elem, type, handle ) {
4917 var name = "on" + type;
4918
4919 if ( elem.detachEvent ) {
4920
4921 // #8545, #7054, preventing memory leaks for custom events in IE6-8
4922 // detachEvent needed property on element, by name of that event, to properly expose it to GC
4923 if ( typeof elem[ name ] === strundefined ) {
4924 elem[ name ] = null;
4925 }
4926
4927 elem.detachEvent( name, handle );
4928 }
4929 };
4930
4931 jQuery.Event = function( src, props ) {
4932 // Allow instantiation without the 'new' keyword
4933 if ( !(this instanceof jQuery.Event) ) {
4934 return new jQuery.Event( src, props );
4935 }
4936
4937 // Event object
4938 if ( src && src.type ) {
4939 this.originalEvent = src;
4940 this.type = src.type;
4941
4942 // Events bubbling up the document may have been marked as prevented
4943 // by a handler lower down the tree; reflect the correct value.
4944 this.isDefaultPrevented = src.defaultPrevented ||
4945 src.defaultPrevented === undefined &&
4946 // Support: IE < 9, Android < 4.0
4947 src.returnValue === false ?
4948 returnTrue :
4949 returnFalse;
4950
4951 // Event type
4952 } else {
4953 this.type = src;
4954 }
4955
4956 // Put explicitly provided properties onto the event object
4957 if ( props ) {
4958 jQuery.extend( this, props );
4959 }
4960
4961 // Create a timestamp if incoming event doesn't have one
4962 this.timeStamp = src && src.timeStamp || jQuery.now();
4963
4964 // Mark it as fixed
4965 this[ jQuery.expando ] = true;
4966 };
4967
4968 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
4969 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
4970 jQuery.Event.prototype = {
4971 isDefaultPrevented: returnFalse,
4972 isPropagationStopped: returnFalse,
4973 isImmediatePropagationStopped: returnFalse,
4974
4975 preventDefault: function() {
4976 var e = this.originalEvent;
4977
4978 this.isDefaultPrevented = returnTrue;
4979 if ( !e ) {
4980 return;
4981 }
4982
4983 // If preventDefault exists, run it on the original event
4984 if ( e.preventDefault ) {
4985 e.preventDefault();
4986
4987 // Support: IE
4988 // Otherwise set the returnValue property of the original event to false
4989 } else {
4990 e.returnValue = false;
4991 }
4992 },
4993 stopPropagation: function() {
4994 var e = this.originalEvent;
4995
4996 this.isPropagationStopped = returnTrue;
4997 if ( !e ) {
4998 return;
4999 }
5000 // If stopPropagation exists, run it on the original event
5001 if ( e.stopPropagation ) {
5002 e.stopPropagation();
5003 }
5004
5005 // Support: IE
5006 // Set the cancelBubble property of the original event to true
5007 e.cancelBubble = true;
5008 },
5009 stopImmediatePropagation: function() {
5010 var e = this.originalEvent;
5011
5012 this.isImmediatePropagationStopped = returnTrue;
5013
5014 if ( e && e.stopImmediatePropagation ) {
5015 e.stopImmediatePropagation();
5016 }
5017
5018 this.stopPropagation();
5019 }
5020 };
5021
5022 // Create mouseenter/leave events using mouseover/out and event-time checks
5023 jQuery.each({
5024 mouseenter: "mouseover",
5025 mouseleave: "mouseout",
5026 pointerenter: "pointerover",
5027 pointerleave: "pointerout"
5028 }, function( orig, fix ) {
5029 jQuery.event.special[ orig ] = {
5030 delegateType: fix,
5031 bindType: fix,
5032
5033 handle: function( event ) {
5034 var ret,
5035 target = this,
5036 related = event.relatedTarget,
5037 handleObj = event.handleObj;
5038
5039 // For mousenter/leave call the handler if related is outside the target.
5040 // NB: No relatedTarget if the mouse left/entered the browser window
5041 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
5042 event.type = handleObj.origType;
5043 ret = handleObj.handler.apply( this, arguments );
5044 event.type = fix;
5045 }
5046 return ret;
5047 }
5048 };
5049 });
5050
5051 // IE submit delegation
5052 if ( !support.submitBubbles ) {
5053
5054 jQuery.event.special.submit = {
5055 setup: function() {
5056 // Only need this for delegated form submit events
5057 if ( jQuery.nodeName( this, "form" ) ) {
5058 return false;
5059 }
5060
5061 // Lazy-add a submit handler when a descendant form may potentially be submitted
5062 jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
5063 // Node name check avoids a VML-related crash in IE (#9807)
5064 var elem = e.target,
5065 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
5066 if ( form && !jQuery._data( form, "submitBubbles" ) ) {
5067 jQuery.event.add( form, "submit._submit", function( event ) {
5068 event._submit_bubble = true;
5069 });
5070 jQuery._data( form, "submitBubbles", true );
5071 }
5072 });
5073 // return undefined since we don't need an event listener
5074 },
5075
5076 postDispatch: function( event ) {
5077 // If form was submitted by the user, bubble the event up the tree
5078 if ( event._submit_bubble ) {
5079 delete event._submit_bubble;
5080 if ( this.parentNode && !event.isTrigger ) {
5081 jQuery.event.simulate( "submit", this.parentNode, event, true );
5082 }
5083 }
5084 },
5085
5086 teardown: function() {
5087 // Only need this for delegated form submit events
5088 if ( jQuery.nodeName( this, "form" ) ) {
5089 return false;
5090 }
5091
5092 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
5093 jQuery.event.remove( this, "._submit" );
5094 }
5095 };
5096 }
5097
5098 // IE change delegation and checkbox/radio fix
5099 if ( !support.changeBubbles ) {
5100
5101 jQuery.event.special.change = {
5102
5103 setup: function() {
5104
5105 if ( rformElems.test( this.nodeName ) ) {
5106 // IE doesn't fire change on a check/radio until blur; trigger it on click
5107 // after a propertychange. Eat the blur-change in special.change.handle.
5108 // This still fires onchange a second time for check/radio after blur.
5109 if ( this.type === "checkbox" || this.type === "radio" ) {
5110 jQuery.event.add( this, "propertychange._change", function( event ) {
5111 if ( event.originalEvent.propertyName === "checked" ) {
5112 this._just_changed = true;
5113 }
5114 });
5115 jQuery.event.add( this, "click._change", function( event ) {
5116 if ( this._just_changed && !event.isTrigger ) {
5117 this._just_changed = false;
5118 }
5119 // Allow triggered, simulated change events (#11500)
5120 jQuery.event.simulate( "change", this, event, true );
5121 });
5122 }
5123 return false;
5124 }
5125 // Delegated event; lazy-add a change handler on descendant inputs
5126 jQuery.event.add( this, "beforeactivate._change", function( e ) {
5127 var elem = e.target;
5128
5129 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
5130 jQuery.event.add( elem, "change._change", function( event ) {
5131 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
5132 jQuery.event.simulate( "change", this.parentNode, event, true );
5133 }
5134 });
5135 jQuery._data( elem, "changeBubbles", true );
5136 }
5137 });
5138 },
5139
5140 handle: function( event ) {
5141 var elem = event.target;
5142
5143 // Swallow native change events from checkbox/radio, we already triggered them above
5144 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
5145 return event.handleObj.handler.apply( this, arguments );
5146 }
5147 },
5148
5149 teardown: function() {
5150 jQuery.event.remove( this, "._change" );
5151
5152 return !rformElems.test( this.nodeName );
5153 }
5154 };
5155 }
5156
5157 // Create "bubbling" focus and blur events
5158 if ( !support.focusinBubbles ) {
5159 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
5160
5161 // Attach a single capturing handler on the document while someone wants focusin/focusout
5162 var handler = function( event ) {
5163 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
5164 };
5165
5166 jQuery.event.special[ fix ] = {
5167 setup: function() {
5168 var doc = this.ownerDocument || this,
5169 attaches = jQuery._data( doc, fix );
5170
5171 if ( !attaches ) {
5172 doc.addEventListener( orig, handler, true );
5173 }
5174 jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
5175 },
5176 teardown: function() {
5177 var doc = this.ownerDocument || this,
5178 attaches = jQuery._data( doc, fix ) - 1;
5179
5180 if ( !attaches ) {
5181 doc.removeEventListener( orig, handler, true );
5182 jQuery._removeData( doc, fix );
5183 } else {
5184 jQuery._data( doc, fix, attaches );
5185 }
5186 }
5187 };
5188 });
5189 }
5190
5191 jQuery.fn.extend({
5192
5193 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
5194 var type, origFn;
5195
5196 // Types can be a map of types/handlers
5197 if ( typeof types === "object" ) {
5198 // ( types-Object, selector, data )
5199 if ( typeof selector !== "string" ) {
5200 // ( types-Object, data )
5201 data = data || selector;
5202 selector = undefined;
5203 }
5204 for ( type in types ) {
5205 this.on( type, selector, data, types[ type ], one );
5206 }
5207 return this;
5208 }
5209
5210 if ( data == null && fn == null ) {
5211 // ( types, fn )
5212 fn = selector;
5213 data = selector = undefined;
5214 } else if ( fn == null ) {
5215 if ( typeof selector === "string" ) {
5216 // ( types, selector, fn )
5217 fn = data;
5218 data = undefined;
5219 } else {
5220 // ( types, data, fn )
5221 fn = data;
5222 data = selector;
5223 selector = undefined;
5224 }
5225 }
5226 if ( fn === false ) {
5227 fn = returnFalse;
5228 } else if ( !fn ) {
5229 return this;
5230 }
5231
5232 if ( one === 1 ) {
5233 origFn = fn;
5234 fn = function( event ) {
5235 // Can use an empty set, since event contains the info
5236 jQuery().off( event );
5237 return origFn.apply( this, arguments );
5238 };
5239 // Use same guid so caller can remove using origFn
5240 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
5241 }
5242 return this.each( function() {
5243 jQuery.event.add( this, types, fn, data, selector );
5244 });
5245 },
5246 one: function( types, selector, data, fn ) {
5247 return this.on( types, selector, data, fn, 1 );
5248 },
5249 off: function( types, selector, fn ) {
5250 var handleObj, type;
5251 if ( types && types.preventDefault && types.handleObj ) {
5252 // ( event ) dispatched jQuery.Event
5253 handleObj = types.handleObj;
5254 jQuery( types.delegateTarget ).off(
5255 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
5256 handleObj.selector,
5257 handleObj.handler
5258 );
5259 return this;
5260 }
5261 if ( typeof types === "object" ) {
5262 // ( types-object [, selector] )
5263 for ( type in types ) {
5264 this.off( type, selector, types[ type ] );
5265 }
5266 return this;
5267 }
5268 if ( selector === false || typeof selector === "function" ) {
5269 // ( types [, fn] )
5270 fn = selector;
5271 selector = undefined;
5272 }
5273 if ( fn === false ) {
5274 fn = returnFalse;
5275 }
5276 return this.each(function() {
5277 jQuery.event.remove( this, types, fn, selector );
5278 });
5279 },
5280
5281 trigger: function( type, data ) {
5282 return this.each(function() {
5283 jQuery.event.trigger( type, data, this );
5284 });
5285 },
5286 triggerHandler: function( type, data ) {
5287 var elem = this[0];
5288 if ( elem ) {
5289 return jQuery.event.trigger( type, data, elem, true );
5290 }
5291 }
5292 });
5293
5294
5295 function createSafeFragment( document ) {
5296 var list = nodeNames.split( "|" ),
5297 safeFrag = document.createDocumentFragment();
5298
5299 if ( safeFrag.createElement ) {
5300 while ( list.length ) {
5301 safeFrag.createElement(
5302 list.pop()
5303 );
5304 }
5305 }
5306 return safeFrag;
5307 }
5308
5309 var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5310 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5311 rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5312 rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5313 rleadingWhitespace = /^\s+/,
5314 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5315 rtagName = /<([\w:]+)/,
5316 rtbody = /<tbody/i,
5317 rhtml = /<|&#?\w+;/,
5318 rnoInnerhtml = /<(?:script|style|link)/i,
5319 // checked="checked" or checked
5320 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5321 rscriptType = /^$|\/(?:java|ecma)script/i,
5322 rscriptTypeMasked = /^true\/(.*)/,
5323 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5324
5325 // We have to close these tags to support XHTML (#13200)
5326 wrapMap = {
5327 option: [ 1, "<select multiple='multiple'>", "</select>" ],
5328 legend: [ 1, "<fieldset>", "</fieldset>" ],
5329 area: [ 1, "<map>", "</map>" ],
5330 param: [ 1, "<object>", "</object>" ],
5331 thead: [ 1, "<table>", "</table>" ],
5332 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5333 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5334 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5335
5336 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5337 // unless wrapped in a div with non-breaking characters in front of it.
5338 _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
5339 },
5340 safeFragment = createSafeFragment( document ),
5341 fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5342
5343 wrapMap.optgroup = wrapMap.option;
5344 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5345 wrapMap.th = wrapMap.td;
5346
5347 function getAll( context, tag ) {
5348 var elems, elem,
5349 i = 0,
5350 found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
5351 typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
5352 undefined;
5353
5354 if ( !found ) {
5355 for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
5356 if ( !tag || jQuery.nodeName( elem, tag ) ) {
5357 found.push( elem );
5358 } else {
5359 jQuery.merge( found, getAll( elem, tag ) );
5360 }
5361 }
5362 }
5363
5364 return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
5365 jQuery.merge( [ context ], found ) :
5366 found;
5367 }
5368
5369 // Used in buildFragment, fixes the defaultChecked property
5370 function fixDefaultChecked( elem ) {
5371 if ( rcheckableType.test( elem.type ) ) {
5372 elem.defaultChecked = elem.checked;
5373 }
5374 }
5375
5376 // Support: IE<8
5377 // Manipulating tables requires a tbody
5378 function manipulationTarget( elem, content ) {
5379 return jQuery.nodeName( elem, "table" ) &&
5380 jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
5381
5382 elem.getElementsByTagName("tbody")[0] ||
5383 elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
5384 elem;
5385 }
5386
5387 // Replace/restore the type attribute of script elements for safe DOM manipulation
5388 function disableScript( elem ) {
5389 elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
5390 return elem;
5391 }
5392 function restoreScript( elem ) {
5393 var match = rscriptTypeMasked.exec( elem.type );
5394 if ( match ) {
5395 elem.type = match[1];
5396 } else {
5397 elem.removeAttribute("type");
5398 }
5399 return elem;
5400 }
5401
5402 // Mark scripts as having already been evaluated
5403 function setGlobalEval( elems, refElements ) {
5404 var elem,
5405 i = 0;
5406 for ( ; (elem = elems[i]) != null; i++ ) {
5407 jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
5408 }
5409 }
5410
5411 function cloneCopyEvent( src, dest ) {
5412
5413 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
5414 return;
5415 }
5416
5417 var type, i, l,
5418 oldData = jQuery._data( src ),
5419 curData = jQuery._data( dest, oldData ),
5420 events = oldData.events;
5421
5422 if ( events ) {
5423 delete curData.handle;
5424 curData.events = {};
5425
5426 for ( type in events ) {
5427 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
5428 jQuery.event.add( dest, type, events[ type ][ i ] );
5429 }
5430 }
5431 }
5432
5433 // make the cloned public data object a copy from the original
5434 if ( curData.data ) {
5435 curData.data = jQuery.extend( {}, curData.data );
5436 }
5437 }
5438
5439 function fixCloneNodeIssues( src, dest ) {
5440 var nodeName, e, data;
5441
5442 // We do not need to do anything for non-Elements
5443 if ( dest.nodeType !== 1 ) {
5444 return;
5445 }
5446
5447 nodeName = dest.nodeName.toLowerCase();
5448
5449 // IE6-8 copies events bound via attachEvent when using cloneNode.
5450 if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
5451 data = jQuery._data( dest );
5452
5453 for ( e in data.events ) {
5454 jQuery.removeEvent( dest, e, data.handle );
5455 }
5456
5457 // Event data gets referenced instead of copied if the expando gets copied too
5458 dest.removeAttribute( jQuery.expando );
5459 }
5460
5461 // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
5462 if ( nodeName === "script" && dest.text !== src.text ) {
5463 disableScript( dest ).text = src.text;
5464 restoreScript( dest );
5465
5466 // IE6-10 improperly clones children of object elements using classid.
5467 // IE10 throws NoModificationAllowedError if parent is null, #12132.
5468 } else if ( nodeName === "object" ) {
5469 if ( dest.parentNode ) {
5470 dest.outerHTML = src.outerHTML;
5471 }
5472
5473 // This path appears unavoidable for IE9. When cloning an object
5474 // element in IE9, the outerHTML strategy above is not sufficient.
5475 // If the src has innerHTML and the destination does not,
5476 // copy the src.innerHTML into the dest.innerHTML. #10324
5477 if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
5478 dest.innerHTML = src.innerHTML;
5479 }
5480
5481 } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
5482 // IE6-8 fails to persist the checked state of a cloned checkbox
5483 // or radio button. Worse, IE6-7 fail to give the cloned element
5484 // a checked appearance if the defaultChecked value isn't also set
5485
5486 dest.defaultChecked = dest.checked = src.checked;
5487
5488 // IE6-7 get confused and end up setting the value of a cloned
5489 // checkbox/radio button to an empty string instead of "on"
5490 if ( dest.value !== src.value ) {
5491 dest.value = src.value;
5492 }
5493
5494 // IE6-8 fails to return the selected option to the default selected
5495 // state when cloning options
5496 } else if ( nodeName === "option" ) {
5497 dest.defaultSelected = dest.selected = src.defaultSelected;
5498
5499 // IE6-8 fails to set the defaultValue to the correct value when
5500 // cloning other types of input fields
5501 } else if ( nodeName === "input" || nodeName === "textarea" ) {
5502 dest.defaultValue = src.defaultValue;
5503 }
5504 }
5505
5506 jQuery.extend({
5507 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
5508 var destElements, node, clone, i, srcElements,
5509 inPage = jQuery.contains( elem.ownerDocument, elem );
5510
5511 if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
5512 clone = elem.cloneNode( true );
5513
5514 // IE<=8 does not properly clone detached, unknown element nodes
5515 } else {
5516 fragmentDiv.innerHTML = elem.outerHTML;
5517 fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
5518 }
5519
5520 if ( (!support.noCloneEvent || !support.noCloneChecked) &&
5521 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
5522
5523 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
5524 destElements = getAll( clone );
5525 srcElements = getAll( elem );
5526
5527 // Fix all IE cloning issues
5528 for ( i = 0; (node = srcElements[i]) != null; ++i ) {
5529 // Ensure that the destination node is not null; Fixes #9587
5530 if ( destElements[i] ) {
5531 fixCloneNodeIssues( node, destElements[i] );
5532 }
5533 }
5534 }
5535
5536 // Copy the events from the original to the clone
5537 if ( dataAndEvents ) {
5538 if ( deepDataAndEvents ) {
5539 srcElements = srcElements || getAll( elem );
5540 destElements = destElements || getAll( clone );
5541
5542 for ( i = 0; (node = srcElements[i]) != null; i++ ) {
5543 cloneCopyEvent( node, destElements[i] );
5544 }
5545 } else {
5546 cloneCopyEvent( elem, clone );
5547 }
5548 }
5549
5550 // Preserve script evaluation history
5551 destElements = getAll( clone, "script" );
5552 if ( destElements.length > 0 ) {
5553 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
5554 }
5555
5556 destElements = srcElements = node = null;
5557
5558 // Return the cloned set
5559 return clone;
5560 },
5561
5562 buildFragment: function( elems, context, scripts, selection ) {
5563 var j, elem, contains,
5564 tmp, tag, tbody, wrap,
5565 l = elems.length,
5566
5567 // Ensure a safe fragment
5568 safe = createSafeFragment( context ),
5569
5570 nodes = [],
5571 i = 0;
5572
5573 for ( ; i < l; i++ ) {
5574 elem = elems[ i ];
5575
5576 if ( elem || elem === 0 ) {
5577
5578 // Add nodes directly
5579 if ( jQuery.type( elem ) === "object" ) {
5580 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
5581
5582 // Convert non-html into a text node
5583 } else if ( !rhtml.test( elem ) ) {
5584 nodes.push( context.createTextNode( elem ) );
5585
5586 // Convert html into DOM nodes
5587 } else {
5588 tmp = tmp || safe.appendChild( context.createElement("div") );
5589
5590 // Deserialize a standard representation
5591 tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
5592 wrap = wrapMap[ tag ] || wrapMap._default;
5593
5594 tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
5595
5596 // Descend through wrappers to the right content
5597 j = wrap[0];
5598 while ( j-- ) {
5599 tmp = tmp.lastChild;
5600 }
5601
5602 // Manually add leading whitespace removed by IE
5603 if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
5604 nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
5605 }
5606
5607 // Remove IE's autoinserted <tbody> from table fragments
5608 if ( !support.tbody ) {
5609
5610 // String was a <table>, *may* have spurious <tbody>
5611 elem = tag === "table" && !rtbody.test( elem ) ?
5612 tmp.firstChild :
5613
5614 // String was a bare <thead> or <tfoot>
5615 wrap[1] === "<table>" && !rtbody.test( elem ) ?
5616 tmp :
5617 0;
5618
5619 j = elem && elem.childNodes.length;
5620 while ( j-- ) {
5621 if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
5622 elem.removeChild( tbody );
5623 }
5624 }
5625 }
5626
5627 jQuery.merge( nodes, tmp.childNodes );
5628
5629 // Fix #12392 for WebKit and IE > 9
5630 tmp.textContent = "";
5631
5632 // Fix #12392 for oldIE
5633 while ( tmp.firstChild ) {
5634 tmp.removeChild( tmp.firstChild );
5635 }
5636
5637 // Remember the top-level container for proper cleanup
5638 tmp = safe.lastChild;
5639 }
5640 }
5641 }
5642
5643 // Fix #11356: Clear elements from fragment
5644 if ( tmp ) {
5645 safe.removeChild( tmp );
5646 }
5647
5648 // Reset defaultChecked for any radios and checkboxes
5649 // about to be appended to the DOM in IE 6/7 (#8060)
5650 if ( !support.appendChecked ) {
5651 jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
5652 }
5653
5654 i = 0;
5655 while ( (elem = nodes[ i++ ]) ) {
5656
5657 // #4087 - If origin and destination elements are the same, and this is
5658 // that element, do not do anything
5659 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
5660 continue;
5661 }
5662
5663 contains = jQuery.contains( elem.ownerDocument, elem );
5664
5665 // Append to fragment
5666 tmp = getAll( safe.appendChild( elem ), "script" );
5667
5668 // Preserve script evaluation history
5669 if ( contains ) {
5670 setGlobalEval( tmp );
5671 }
5672
5673 // Capture executables
5674 if ( scripts ) {
5675 j = 0;
5676 while ( (elem = tmp[ j++ ]) ) {
5677 if ( rscriptType.test( elem.type || "" ) ) {
5678 scripts.push( elem );
5679 }
5680 }
5681 }
5682 }
5683
5684 tmp = null;
5685
5686 return safe;
5687 },
5688
5689 cleanData: function( elems, /* internal */ acceptData ) {
5690 var elem, type, id, data,
5691 i = 0,
5692 internalKey = jQuery.expando,
5693 cache = jQuery.cache,
5694 deleteExpando = support.deleteExpando,
5695 special = jQuery.event.special;
5696
5697 for ( ; (elem = elems[i]) != null; i++ ) {
5698 if ( acceptData || jQuery.acceptData( elem ) ) {
5699
5700 id = elem[ internalKey ];
5701 data = id && cache[ id ];
5702
5703 if ( data ) {
5704 if ( data.events ) {
5705 for ( type in data.events ) {
5706 if ( special[ type ] ) {
5707 jQuery.event.remove( elem, type );
5708
5709 // This is a shortcut to avoid jQuery.event.remove's overhead
5710 } else {
5711 jQuery.removeEvent( elem, type, data.handle );
5712 }
5713 }
5714 }
5715
5716 // Remove cache only if it was not already removed by jQuery.event.remove
5717 if ( cache[ id ] ) {
5718
5719 delete cache[ id ];
5720
5721 // IE does not allow us to delete expando properties from nodes,
5722 // nor does it have a removeAttribute function on Document nodes;
5723 // we must handle all of these cases
5724 if ( deleteExpando ) {
5725 delete elem[ internalKey ];
5726
5727 } else if ( typeof elem.removeAttribute !== strundefined ) {
5728 elem.removeAttribute( internalKey );
5729
5730 } else {
5731 elem[ internalKey ] = null;
5732 }
5733
5734 deletedIds.push( id );
5735 }
5736 }
5737 }
5738 }
5739 }
5740 });
5741
5742 jQuery.fn.extend({
5743 text: function( value ) {
5744 return access( this, function( value ) {
5745 return value === undefined ?
5746 jQuery.text( this ) :
5747 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5748 }, null, value, arguments.length );
5749 },
5750
5751 append: function() {
5752 return this.domManip( arguments, function( elem ) {
5753 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5754 var target = manipulationTarget( this, elem );
5755 target.appendChild( elem );
5756 }
5757 });
5758 },
5759
5760 prepend: function() {
5761 return this.domManip( arguments, function( elem ) {
5762 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5763 var target = manipulationTarget( this, elem );
5764 target.insertBefore( elem, target.firstChild );
5765 }
5766 });
5767 },
5768
5769 before: function() {
5770 return this.domManip( arguments, function( elem ) {
5771 if ( this.parentNode ) {
5772 this.parentNode.insertBefore( elem, this );
5773 }
5774 });
5775 },
5776
5777 after: function() {
5778 return this.domManip( arguments, function( elem ) {
5779 if ( this.parentNode ) {
5780 this.parentNode.insertBefore( elem, this.nextSibling );
5781 }
5782 });
5783 },
5784
5785 remove: function( selector, keepData /* Internal Use Only */ ) {
5786 var elem,
5787 elems = selector ? jQuery.filter( selector, this ) : this,
5788 i = 0;
5789
5790 for ( ; (elem = elems[i]) != null; i++ ) {
5791
5792 if ( !keepData && elem.nodeType === 1 ) {
5793 jQuery.cleanData( getAll( elem ) );
5794 }
5795
5796 if ( elem.parentNode ) {
5797 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
5798 setGlobalEval( getAll( elem, "script" ) );
5799 }
5800 elem.parentNode.removeChild( elem );
5801 }
5802 }
5803
5804 return this;
5805 },
5806
5807 empty: function() {
5808 var elem,
5809 i = 0;
5810
5811 for ( ; (elem = this[i]) != null; i++ ) {
5812 // Remove element nodes and prevent memory leaks
5813 if ( elem.nodeType === 1 ) {
5814 jQuery.cleanData( getAll( elem, false ) );
5815 }
5816
5817 // Remove any remaining nodes
5818 while ( elem.firstChild ) {
5819 elem.removeChild( elem.firstChild );
5820 }
5821
5822 // If this is a select, ensure that it displays empty (#12336)
5823 // Support: IE<9
5824 if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
5825 elem.options.length = 0;
5826 }
5827 }
5828
5829 return this;
5830 },
5831
5832 clone: function( dataAndEvents, deepDataAndEvents ) {
5833 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5834 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5835
5836 return this.map(function() {
5837 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5838 });
5839 },
5840
5841 html: function( value ) {
5842 return access( this, function( value ) {
5843 var elem = this[ 0 ] || {},
5844 i = 0,
5845 l = this.length;
5846
5847 if ( value === undefined ) {
5848 return elem.nodeType === 1 ?
5849 elem.innerHTML.replace( rinlinejQuery, "" ) :
5850 undefined;
5851 }
5852
5853 // See if we can take a shortcut and just use innerHTML
5854 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5855 ( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
5856 ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
5857 !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
5858
5859 value = value.replace( rxhtmlTag, "<$1></$2>" );
5860
5861 try {
5862 for (; i < l; i++ ) {
5863 // Remove element nodes and prevent memory leaks
5864 elem = this[i] || {};
5865 if ( elem.nodeType === 1 ) {
5866 jQuery.cleanData( getAll( elem, false ) );
5867 elem.innerHTML = value;
5868 }
5869 }
5870
5871 elem = 0;
5872
5873 // If using innerHTML throws an exception, use the fallback method
5874 } catch(e) {}
5875 }
5876
5877 if ( elem ) {
5878 this.empty().append( value );
5879 }
5880 }, null, value, arguments.length );
5881 },
5882
5883 replaceWith: function() {
5884 var arg = arguments[ 0 ];
5885
5886 // Make the changes, replacing each context element with the new content
5887 this.domManip( arguments, function( elem ) {
5888 arg = this.parentNode;
5889
5890 jQuery.cleanData( getAll( this ) );
5891
5892 if ( arg ) {
5893 arg.replaceChild( elem, this );
5894 }
5895 });
5896
5897 // Force removal if there was no new content (e.g., from empty arguments)
5898 return arg && (arg.length || arg.nodeType) ? this : this.remove();
5899 },
5900
5901 detach: function( selector ) {
5902 return this.remove( selector, true );
5903 },
5904
5905 domManip: function( args, callback ) {
5906
5907 // Flatten any nested arrays
5908 args = concat.apply( [], args );
5909
5910 var first, node, hasScripts,
5911 scripts, doc, fragment,
5912 i = 0,
5913 l = this.length,
5914 set = this,
5915 iNoClone = l - 1,
5916 value = args[0],
5917 isFunction = jQuery.isFunction( value );
5918
5919 // We can't cloneNode fragments that contain checked, in WebKit
5920 if ( isFunction ||
5921 ( l > 1 && typeof value === "string" &&
5922 !support.checkClone && rchecked.test( value ) ) ) {
5923 return this.each(function( index ) {
5924 var self = set.eq( index );
5925 if ( isFunction ) {
5926 args[0] = value.call( this, index, self.html() );
5927 }
5928 self.domManip( args, callback );
5929 });
5930 }
5931
5932 if ( l ) {
5933 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
5934 first = fragment.firstChild;
5935
5936 if ( fragment.childNodes.length === 1 ) {
5937 fragment = first;
5938 }
5939
5940 if ( first ) {
5941 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
5942 hasScripts = scripts.length;
5943
5944 // Use the original fragment for the last item instead of the first because it can end up
5945 // being emptied incorrectly in certain situations (#8070).
5946 for ( ; i < l; i++ ) {
5947 node = fragment;
5948
5949 if ( i !== iNoClone ) {
5950 node = jQuery.clone( node, true, true );
5951
5952 // Keep references to cloned scripts for later restoration
5953 if ( hasScripts ) {
5954 jQuery.merge( scripts, getAll( node, "script" ) );
5955 }
5956 }
5957
5958 callback.call( this[i], node, i );
5959 }
5960
5961 if ( hasScripts ) {
5962 doc = scripts[ scripts.length - 1 ].ownerDocument;
5963
5964 // Reenable scripts
5965 jQuery.map( scripts, restoreScript );
5966
5967 // Evaluate executable scripts on first document insertion
5968 for ( i = 0; i < hasScripts; i++ ) {
5969 node = scripts[ i ];
5970 if ( rscriptType.test( node.type || "" ) &&
5971 !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
5972
5973 if ( node.src ) {
5974 // Optional AJAX dependency, but won't run scripts if not present
5975 if ( jQuery._evalUrl ) {
5976 jQuery._evalUrl( node.src );
5977 }
5978 } else {
5979 jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
5980 }
5981 }
5982 }
5983 }
5984
5985 // Fix #11809: Avoid leaking memory
5986 fragment = first = null;
5987 }
5988 }
5989
5990 return this;
5991 }
5992 });
5993
5994 jQuery.each({
5995 appendTo: "append",
5996 prependTo: "prepend",
5997 insertBefore: "before",
5998 insertAfter: "after",
5999 replaceAll: "replaceWith"
6000 }, function( name, original ) {
6001 jQuery.fn[ name ] = function( selector ) {
6002 var elems,
6003 i = 0,
6004 ret = [],
6005 insert = jQuery( selector ),
6006 last = insert.length - 1;
6007
6008 for ( ; i <= last; i++ ) {
6009 elems = i === last ? this : this.clone(true);
6010 jQuery( insert[i] )[ original ]( elems );
6011
6012 // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6013 push.apply( ret, elems.get() );
6014 }
6015
6016 return this.pushStack( ret );
6017 };
6018 });
6019
6020
6021 var iframe,
6022 elemdisplay = {};
6023
6024 /**
6025 * Retrieve the actual display of a element
6026 * @param {String} name nodeName of the element
6027 * @param {Object} doc Document object
6028 */
6029 // Called only from within defaultDisplay
6030 function actualDisplay( name, doc ) {
6031 var style,
6032 elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
6033
6034 // getDefaultComputedStyle might be reliably used only on attached element
6035 display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
6036
6037 // Use of this method is a temporary fix (more like optmization) until something better comes along,
6038 // since it was removed from specification and supported only in FF
6039 style.display : jQuery.css( elem[ 0 ], "display" );
6040
6041 // We don't have any data stored on the element,
6042 // so use "detach" method as fast way to get rid of the element
6043 elem.detach();
6044
6045 return display;
6046 }
6047
6048 /**
6049 * Try to determine the default display value of an element
6050 * @param {String} nodeName
6051 */
6052 function defaultDisplay( nodeName ) {
6053 var doc = document,
6054 display = elemdisplay[ nodeName ];
6055
6056 if ( !display ) {
6057 display = actualDisplay( nodeName, doc );
6058
6059 // If the simple way fails, read from inside an iframe
6060 if ( display === "none" || !display ) {
6061
6062 // Use the already-created iframe if possible
6063 iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
6064
6065 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
6066 doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
6067
6068 // Support: IE
6069 doc.write();
6070 doc.close();
6071
6072 display = actualDisplay( nodeName, doc );
6073 iframe.detach();
6074 }
6075
6076 // Store the correct default display
6077 elemdisplay[ nodeName ] = display;
6078 }
6079
6080 return display;
6081 }
6082
6083
6084 (function() {
6085 var shrinkWrapBlocksVal;
6086
6087 support.shrinkWrapBlocks = function() {
6088 if ( shrinkWrapBlocksVal != null ) {
6089 return shrinkWrapBlocksVal;
6090 }
6091
6092 // Will be changed later if needed.
6093 shrinkWrapBlocksVal = false;
6094
6095 // Minified: var b,c,d
6096 var div, body, container;
6097
6098 body = document.getElementsByTagName( "body" )[ 0 ];
6099 if ( !body || !body.style ) {
6100 // Test fired too early or in an unsupported environment, exit.
6101 return;
6102 }
6103
6104 // Setup
6105 div = document.createElement( "div" );
6106 container = document.createElement( "div" );
6107 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
6108 body.appendChild( container ).appendChild( div );
6109
6110 // Support: IE6
6111 // Check if elements with layout shrink-wrap their children
6112 if ( typeof div.style.zoom !== strundefined ) {
6113 // Reset CSS: box-sizing; display; margin; border
6114 div.style.cssText =
6115 // Support: Firefox<29, Android 2.3
6116 // Vendor-prefix box-sizing
6117 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
6118 "box-sizing:content-box;display:block;margin:0;border:0;" +
6119 "padding:1px;width:1px;zoom:1";
6120 div.appendChild( document.createElement( "div" ) ).style.width = "5px";
6121 shrinkWrapBlocksVal = div.offsetWidth !== 3;
6122 }
6123
6124 body.removeChild( container );
6125
6126 return shrinkWrapBlocksVal;
6127 };
6128
6129 })();
6130 var rmargin = (/^margin/);
6131
6132 var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
6133
6134
6135
6136 var getStyles, curCSS,
6137 rposition = /^(top|right|bottom|left)$/;
6138
6139 if ( window.getComputedStyle ) {
6140 getStyles = function( elem ) {
6141 // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
6142 // IE throws on elements created in popups
6143 // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
6144 if ( elem.ownerDocument.defaultView.opener ) {
6145 return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
6146 }
6147
6148 return window.getComputedStyle( elem, null );
6149 };
6150
6151 curCSS = function( elem, name, computed ) {
6152 var width, minWidth, maxWidth, ret,
6153 style = elem.style;
6154
6155 computed = computed || getStyles( elem );
6156
6157 // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6158 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
6159
6160 if ( computed ) {
6161
6162 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6163 ret = jQuery.style( elem, name );
6164 }
6165
6166 // A tribute to the "awesome hack by Dean Edwards"
6167 // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6168 // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6169 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6170 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6171
6172 // Remember the original values
6173 width = style.width;
6174 minWidth = style.minWidth;
6175 maxWidth = style.maxWidth;
6176
6177 // Put in the new values to get a computed value out
6178 style.minWidth = style.maxWidth = style.width = ret;
6179 ret = computed.width;
6180
6181 // Revert the changed values
6182 style.width = width;
6183 style.minWidth = minWidth;
6184 style.maxWidth = maxWidth;
6185 }
6186 }
6187
6188 // Support: IE
6189 // IE returns zIndex value as an integer.
6190 return ret === undefined ?
6191 ret :
6192 ret + "";
6193 };
6194 } else if ( document.documentElement.currentStyle ) {
6195 getStyles = function( elem ) {
6196 return elem.currentStyle;
6197 };
6198
6199 curCSS = function( elem, name, computed ) {
6200 var left, rs, rsLeft, ret,
6201 style = elem.style;
6202
6203 computed = computed || getStyles( elem );
6204 ret = computed ? computed[ name ] : undefined;
6205
6206 // Avoid setting ret to empty string here
6207 // so we don't default to auto
6208 if ( ret == null && style && style[ name ] ) {
6209 ret = style[ name ];
6210 }
6211
6212 // From the awesome hack by Dean Edwards
6213 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6214
6215 // If we're not dealing with a regular pixel number
6216 // but a number that has a weird ending, we need to convert it to pixels
6217 // but not position css attributes, as those are proportional to the parent element instead
6218 // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
6219 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
6220
6221 // Remember the original values
6222 left = style.left;
6223 rs = elem.runtimeStyle;
6224 rsLeft = rs && rs.left;
6225
6226 // Put in the new values to get a computed value out
6227 if ( rsLeft ) {
6228 rs.left = elem.currentStyle.left;
6229 }
6230 style.left = name === "fontSize" ? "1em" : ret;
6231 ret = style.pixelLeft + "px";
6232
6233 // Revert the changed values
6234 style.left = left;
6235 if ( rsLeft ) {
6236 rs.left = rsLeft;
6237 }
6238 }
6239
6240 // Support: IE
6241 // IE returns zIndex value as an integer.
6242 return ret === undefined ?
6243 ret :
6244 ret + "" || "auto";
6245 };
6246 }
6247
6248
6249
6250
6251 function addGetHookIf( conditionFn, hookFn ) {
6252 // Define the hook, we'll check on the first run if it's really needed.
6253 return {
6254 get: function() {
6255 var condition = conditionFn();
6256
6257 if ( condition == null ) {
6258 // The test was not ready at this point; screw the hook this time
6259 // but check again when needed next time.
6260 return;
6261 }
6262
6263 if ( condition ) {
6264 // Hook not needed (or it's not possible to use it due to missing dependency),
6265 // remove it.
6266 // Since there are no other hooks for marginRight, remove the whole object.
6267 delete this.get;
6268 return;
6269 }
6270
6271 // Hook needed; redefine it so that the support test is not executed again.
6272
6273 return (this.get = hookFn).apply( this, arguments );
6274 }
6275 };
6276 }
6277
6278
6279 (function() {
6280 // Minified: var b,c,d,e,f,g, h,i
6281 var div, style, a, pixelPositionVal, boxSizingReliableVal,
6282 reliableHiddenOffsetsVal, reliableMarginRightVal;
6283
6284 // Setup
6285 div = document.createElement( "div" );
6286 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
6287 a = div.getElementsByTagName( "a" )[ 0 ];
6288 style = a && a.style;
6289
6290 // Finish early in limited (non-browser) environments
6291 if ( !style ) {
6292 return;
6293 }
6294
6295 style.cssText = "float:left;opacity:.5";
6296
6297 // Support: IE<9
6298 // Make sure that element opacity exists (as opposed to filter)
6299 support.opacity = style.opacity === "0.5";
6300
6301 // Verify style float existence
6302 // (IE uses styleFloat instead of cssFloat)
6303 support.cssFloat = !!style.cssFloat;
6304
6305 div.style.backgroundClip = "content-box";
6306 div.cloneNode( true ).style.backgroundClip = "";
6307 support.clearCloneStyle = div.style.backgroundClip === "content-box";
6308
6309 // Support: Firefox<29, Android 2.3
6310 // Vendor-prefix box-sizing
6311 support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
6312 style.WebkitBoxSizing === "";
6313
6314 jQuery.extend(support, {
6315 reliableHiddenOffsets: function() {
6316 if ( reliableHiddenOffsetsVal == null ) {
6317 computeStyleTests();
6318 }
6319 return reliableHiddenOffsetsVal;
6320 },
6321
6322 boxSizingReliable: function() {
6323 if ( boxSizingReliableVal == null ) {
6324 computeStyleTests();
6325 }
6326 return boxSizingReliableVal;
6327 },
6328
6329 pixelPosition: function() {
6330 if ( pixelPositionVal == null ) {
6331 computeStyleTests();
6332 }
6333 return pixelPositionVal;
6334 },
6335
6336 // Support: Android 2.3
6337 reliableMarginRight: function() {
6338 if ( reliableMarginRightVal == null ) {
6339 computeStyleTests();
6340 }
6341 return reliableMarginRightVal;
6342 }
6343 });
6344
6345 function computeStyleTests() {
6346 // Minified: var b,c,d,j
6347 var div, body, container, contents;
6348
6349 body = document.getElementsByTagName( "body" )[ 0 ];
6350 if ( !body || !body.style ) {
6351 // Test fired too early or in an unsupported environment, exit.
6352 return;
6353 }
6354
6355 // Setup
6356 div = document.createElement( "div" );
6357 container = document.createElement( "div" );
6358 container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
6359 body.appendChild( container ).appendChild( div );
6360
6361 div.style.cssText =
6362 // Support: Firefox<29, Android 2.3
6363 // Vendor-prefix box-sizing
6364 "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
6365 "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
6366 "border:1px;padding:1px;width:4px;position:absolute";
6367
6368 // Support: IE<9
6369 // Assume reasonable values in the absence of getComputedStyle
6370 pixelPositionVal = boxSizingReliableVal = false;
6371 reliableMarginRightVal = true;
6372
6373 // Check for getComputedStyle so that this code is not run in IE<9.
6374 if ( window.getComputedStyle ) {
6375 pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
6376 boxSizingReliableVal =
6377 ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
6378
6379 // Support: Android 2.3
6380 // Div with explicit width and no margin-right incorrectly
6381 // gets computed margin-right based on width of container (#3333)
6382 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6383 contents = div.appendChild( document.createElement( "div" ) );
6384
6385 // Reset CSS: box-sizing; display; margin; border; padding
6386 contents.style.cssText = div.style.cssText =
6387 // Support: Firefox<29, Android 2.3
6388 // Vendor-prefix box-sizing
6389 "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
6390 "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
6391 contents.style.marginRight = contents.style.width = "0";
6392 div.style.width = "1px";
6393
6394 reliableMarginRightVal =
6395 !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
6396
6397 div.removeChild( contents );
6398 }
6399
6400 // Support: IE8
6401 // Check if table cells still have offsetWidth/Height when they are set
6402 // to display:none and there are still other visible table cells in a
6403 // table row; if so, offsetWidth/Height are not reliable for use when
6404 // determining if an element has been hidden directly using
6405 // display:none (it is still safe to use offsets if a parent element is
6406 // hidden; don safety goggles and see bug #4512 for more information).
6407 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
6408 contents = div.getElementsByTagName( "td" );
6409 contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
6410 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
6411 if ( reliableHiddenOffsetsVal ) {
6412 contents[ 0 ].style.display = "";
6413 contents[ 1 ].style.display = "none";
6414 reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
6415 }
6416
6417 body.removeChild( container );
6418 }
6419
6420 })();
6421
6422
6423 // A method for quickly swapping in/out CSS properties to get correct calculations.
6424 jQuery.swap = function( elem, options, callback, args ) {
6425 var ret, name,
6426 old = {};
6427
6428 // Remember the old values, and insert the new ones
6429 for ( name in options ) {
6430 old[ name ] = elem.style[ name ];
6431 elem.style[ name ] = options[ name ];
6432 }
6433
6434 ret = callback.apply( elem, args || [] );
6435
6436 // Revert the old values
6437 for ( name in options ) {
6438 elem.style[ name ] = old[ name ];
6439 }
6440
6441 return ret;
6442 };
6443
6444
6445 var
6446 ralpha = /alpha\([^)]*\)/i,
6447 ropacity = /opacity\s*=\s*([^)]*)/,
6448
6449 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6450 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6451 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6452 rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
6453 rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
6454
6455 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6456 cssNormalTransform = {
6457 letterSpacing: "0",
6458 fontWeight: "400"
6459 },
6460
6461 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6462
6463
6464 // return a css property mapped to a potentially vendor prefixed property
6465 function vendorPropName( style, name ) {
6466
6467 // shortcut for names that are not vendor prefixed
6468 if ( name in style ) {
6469 return name;
6470 }
6471
6472 // check for vendor prefixed names
6473 var capName = name.charAt(0).toUpperCase() + name.slice(1),
6474 origName = name,
6475 i = cssPrefixes.length;
6476
6477 while ( i-- ) {
6478 name = cssPrefixes[ i ] + capName;
6479 if ( name in style ) {
6480 return name;
6481 }
6482 }
6483
6484 return origName;
6485 }
6486
6487 function showHide( elements, show ) {
6488 var display, elem, hidden,
6489 values = [],
6490 index = 0,
6491 length = elements.length;
6492
6493 for ( ; index < length; index++ ) {
6494 elem = elements[ index ];
6495 if ( !elem.style ) {
6496 continue;
6497 }
6498
6499 values[ index ] = jQuery._data( elem, "olddisplay" );
6500 display = elem.style.display;
6501 if ( show ) {
6502 // Reset the inline display of this element to learn if it is
6503 // being hidden by cascaded rules or not
6504 if ( !values[ index ] && display === "none" ) {
6505 elem.style.display = "";
6506 }
6507
6508 // Set elements which have been overridden with display: none
6509 // in a stylesheet to whatever the default browser style is
6510 // for such an element
6511 if ( elem.style.display === "" && isHidden( elem ) ) {
6512 values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
6513 }
6514 } else {
6515 hidden = isHidden( elem );
6516
6517 if ( display && display !== "none" || !hidden ) {
6518 jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6519 }
6520 }
6521 }
6522
6523 // Set the display of most of the elements in a second loop
6524 // to avoid the constant reflow
6525 for ( index = 0; index < length; index++ ) {
6526 elem = elements[ index ];
6527 if ( !elem.style ) {
6528 continue;
6529 }
6530 if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6531 elem.style.display = show ? values[ index ] || "" : "none";
6532 }
6533 }
6534
6535 return elements;
6536 }
6537
6538 function setPositiveNumber( elem, value, subtract ) {
6539 var matches = rnumsplit.exec( value );
6540 return matches ?
6541 // Guard against undefined "subtract", e.g., when used as in cssHooks
6542 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
6543 value;
6544 }
6545
6546 function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
6547 var i = extra === ( isBorderBox ? "border" : "content" ) ?
6548 // If we already have the right measurement, avoid augmentation
6549 4 :
6550 // Otherwise initialize for horizontal or vertical properties
6551 name === "width" ? 1 : 0,
6552
6553 val = 0;
6554
6555 for ( ; i < 4; i += 2 ) {
6556 // both box models exclude margin, so add it if we want it
6557 if ( extra === "margin" ) {
6558 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
6559 }
6560
6561 if ( isBorderBox ) {
6562 // border-box includes padding, so remove it if we want content
6563 if ( extra === "content" ) {
6564 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6565 }
6566
6567 // at this point, extra isn't border nor margin, so remove border
6568 if ( extra !== "margin" ) {
6569 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6570 }
6571 } else {
6572 // at this point, extra isn't content, so add padding
6573 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
6574
6575 // at this point, extra isn't content nor padding, so add border
6576 if ( extra !== "padding" ) {
6577 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
6578 }
6579 }
6580 }
6581
6582 return val;
6583 }
6584
6585 function getWidthOrHeight( elem, name, extra ) {
6586
6587 // Start with offset property, which is equivalent to the border-box value
6588 var valueIsBorderBox = true,
6589 val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
6590 styles = getStyles( elem ),
6591 isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
6592
6593 // some non-html elements return undefined for offsetWidth, so check for null/undefined
6594 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
6595 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
6596 if ( val <= 0 || val == null ) {
6597 // Fall back to computed then uncomputed css if necessary
6598 val = curCSS( elem, name, styles );
6599 if ( val < 0 || val == null ) {
6600 val = elem.style[ name ];
6601 }
6602
6603 // Computed unit is not pixels. Stop here and return.
6604 if ( rnumnonpx.test(val) ) {
6605 return val;
6606 }
6607
6608 // we need the check for style in case a browser which returns unreliable values
6609 // for getComputedStyle silently falls back to the reliable elem.style
6610 valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
6611
6612 // Normalize "", auto, and prepare for extra
6613 val = parseFloat( val ) || 0;
6614 }
6615
6616 // use the active box-sizing model to add/subtract irrelevant styles
6617 return ( val +
6618 augmentWidthOrHeight(
6619 elem,
6620 name,
6621 extra || ( isBorderBox ? "border" : "content" ),
6622 valueIsBorderBox,
6623 styles
6624 )
6625 ) + "px";
6626 }
6627
6628 jQuery.extend({
6629 // Add in style property hooks for overriding the default
6630 // behavior of getting and setting a style property
6631 cssHooks: {
6632 opacity: {
6633 get: function( elem, computed ) {
6634 if ( computed ) {
6635 // We should always get a number back from opacity
6636 var ret = curCSS( elem, "opacity" );
6637 return ret === "" ? "1" : ret;
6638 }
6639 }
6640 }
6641 },
6642
6643 // Don't automatically add "px" to these possibly-unitless properties
6644 cssNumber: {
6645 "columnCount": true,
6646 "fillOpacity": true,
6647 "flexGrow": true,
6648 "flexShrink": true,
6649 "fontWeight": true,
6650 "lineHeight": true,
6651 "opacity": true,
6652 "order": true,
6653 "orphans": true,
6654 "widows": true,
6655 "zIndex": true,
6656 "zoom": true
6657 },
6658
6659 // Add in properties whose names you wish to fix before
6660 // setting or getting the value
6661 cssProps: {
6662 // normalize float css property
6663 "float": support.cssFloat ? "cssFloat" : "styleFloat"
6664 },
6665
6666 // Get and set the style property on a DOM Node
6667 style: function( elem, name, value, extra ) {
6668 // Don't set styles on text and comment nodes
6669 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6670 return;
6671 }
6672
6673 // Make sure that we're working with the right name
6674 var ret, type, hooks,
6675 origName = jQuery.camelCase( name ),
6676 style = elem.style;
6677
6678 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6679
6680 // gets hook for the prefixed version
6681 // followed by the unprefixed version
6682 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6683
6684 // Check if we're setting a value
6685 if ( value !== undefined ) {
6686 type = typeof value;
6687
6688 // convert relative number strings (+= or -=) to relative numbers. #7345
6689 if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6690 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6691 // Fixes bug #9237
6692 type = "number";
6693 }
6694
6695 // Make sure that null and NaN values aren't set. See: #7116
6696 if ( value == null || value !== value ) {
6697 return;
6698 }
6699
6700 // If a number was passed in, add 'px' to the (except for certain CSS properties)
6701 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6702 value += "px";
6703 }
6704
6705 // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
6706 // but it would mean to define eight (for every problematic property) identical functions
6707 if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
6708 style[ name ] = "inherit";
6709 }
6710
6711 // If a hook was provided, use that value, otherwise just set the specified value
6712 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6713
6714 // Support: IE
6715 // Swallow errors from 'invalid' CSS values (#5509)
6716 try {
6717 style[ name ] = value;
6718 } catch(e) {}
6719 }
6720
6721 } else {
6722 // If a hook was provided get the non-computed value from there
6723 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6724 return ret;
6725 }
6726
6727 // Otherwise just get the value from the style object
6728 return style[ name ];
6729 }
6730 },
6731
6732 css: function( elem, name, extra, styles ) {
6733 var num, val, hooks,
6734 origName = jQuery.camelCase( name );
6735
6736 // Make sure that we're working with the right name
6737 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6738
6739 // gets hook for the prefixed version
6740 // followed by the unprefixed version
6741 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6742
6743 // If a hook was provided get the computed value from there
6744 if ( hooks && "get" in hooks ) {
6745 val = hooks.get( elem, true, extra );
6746 }
6747
6748 // Otherwise, if a way to get the computed value exists, use that
6749 if ( val === undefined ) {
6750 val = curCSS( elem, name, styles );
6751 }
6752
6753 //convert "normal" to computed value
6754 if ( val === "normal" && name in cssNormalTransform ) {
6755 val = cssNormalTransform[ name ];
6756 }
6757
6758 // Return, converting to number if forced or a qualifier was provided and val looks numeric
6759 if ( extra === "" || extra ) {
6760 num = parseFloat( val );
6761 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6762 }
6763 return val;
6764 }
6765 });
6766
6767 jQuery.each([ "height", "width" ], function( i, name ) {
6768 jQuery.cssHooks[ name ] = {
6769 get: function( elem, computed, extra ) {
6770 if ( computed ) {
6771 // certain elements can have dimension info if we invisibly show them
6772 // however, it must have a current display style that would benefit from this
6773 return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
6774 jQuery.swap( elem, cssShow, function() {
6775 return getWidthOrHeight( elem, name, extra );
6776 }) :
6777 getWidthOrHeight( elem, name, extra );
6778 }
6779 },
6780
6781 set: function( elem, value, extra ) {
6782 var styles = extra && getStyles( elem );
6783 return setPositiveNumber( elem, value, extra ?
6784 augmentWidthOrHeight(
6785 elem,
6786 name,
6787 extra,
6788 support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
6789 styles
6790 ) : 0
6791 );
6792 }
6793 };
6794 });
6795
6796 if ( !support.opacity ) {
6797 jQuery.cssHooks.opacity = {
6798 get: function( elem, computed ) {
6799 // IE uses filters for opacity
6800 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
6801 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
6802 computed ? "1" : "";
6803 },
6804
6805 set: function( elem, value ) {
6806 var style = elem.style,
6807 currentStyle = elem.currentStyle,
6808 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
6809 filter = currentStyle && currentStyle.filter || style.filter || "";
6810
6811 // IE has trouble with opacity if it does not have layout
6812 // Force it by setting the zoom level
6813 style.zoom = 1;
6814
6815 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
6816 // if value === "", then remove inline opacity #12685
6817 if ( ( value >= 1 || value === "" ) &&
6818 jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
6819 style.removeAttribute ) {
6820
6821 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
6822 // if "filter:" is present at all, clearType is disabled, we want to avoid this
6823 // style.removeAttribute is IE Only, but so apparently is this code path...
6824 style.removeAttribute( "filter" );
6825
6826 // if there is no filter style applied in a css rule or unset inline opacity, we are done
6827 if ( value === "" || currentStyle && !currentStyle.filter ) {
6828 return;
6829 }
6830 }
6831
6832 // otherwise, set new filter values
6833 style.filter = ralpha.test( filter ) ?
6834 filter.replace( ralpha, opacity ) :
6835 filter + " " + opacity;
6836 }
6837 };
6838 }
6839
6840 jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
6841 function( elem, computed ) {
6842 if ( computed ) {
6843 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
6844 // Work around by temporarily setting element display to inline-block
6845 return jQuery.swap( elem, { "display": "inline-block" },
6846 curCSS, [ elem, "marginRight" ] );
6847 }
6848 }
6849 );
6850
6851 // These hooks are used by animate to expand properties
6852 jQuery.each({
6853 margin: "",
6854 padding: "",
6855 border: "Width"
6856 }, function( prefix, suffix ) {
6857 jQuery.cssHooks[ prefix + suffix ] = {
6858 expand: function( value ) {
6859 var i = 0,
6860 expanded = {},
6861
6862 // assumes a single number if not a string
6863 parts = typeof value === "string" ? value.split(" ") : [ value ];
6864
6865 for ( ; i < 4; i++ ) {
6866 expanded[ prefix + cssExpand[ i ] + suffix ] =
6867 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
6868 }
6869
6870 return expanded;
6871 }
6872 };
6873
6874 if ( !rmargin.test( prefix ) ) {
6875 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
6876 }
6877 });
6878
6879 jQuery.fn.extend({
6880 css: function( name, value ) {
6881 return access( this, function( elem, name, value ) {
6882 var styles, len,
6883 map = {},
6884 i = 0;
6885
6886 if ( jQuery.isArray( name ) ) {
6887 styles = getStyles( elem );
6888 len = name.length;
6889
6890 for ( ; i < len; i++ ) {
6891 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6892 }
6893
6894 return map;
6895 }
6896
6897 return value !== undefined ?
6898 jQuery.style( elem, name, value ) :
6899 jQuery.css( elem, name );
6900 }, name, value, arguments.length > 1 );
6901 },
6902 show: function() {
6903 return showHide( this, true );
6904 },
6905 hide: function() {
6906 return showHide( this );
6907 },
6908 toggle: function( state ) {
6909 if ( typeof state === "boolean" ) {
6910 return state ? this.show() : this.hide();
6911 }
6912
6913 return this.each(function() {
6914 if ( isHidden( this ) ) {
6915 jQuery( this ).show();
6916 } else {
6917 jQuery( this ).hide();
6918 }
6919 });
6920 }
6921 });
6922
6923
6924 function Tween( elem, options, prop, end, easing ) {
6925 return new Tween.prototype.init( elem, options, prop, end, easing );
6926 }
6927 jQuery.Tween = Tween;
6928
6929 Tween.prototype = {
6930 constructor: Tween,
6931 init: function( elem, options, prop, end, easing, unit ) {
6932 this.elem = elem;
6933 this.prop = prop;
6934 this.easing = easing || "swing";
6935 this.options = options;
6936 this.start = this.now = this.cur();
6937 this.end = end;
6938 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
6939 },
6940 cur: function() {
6941 var hooks = Tween.propHooks[ this.prop ];
6942
6943 return hooks && hooks.get ?
6944 hooks.get( this ) :
6945 Tween.propHooks._default.get( this );
6946 },
6947 run: function( percent ) {
6948 var eased,
6949 hooks = Tween.propHooks[ this.prop ];
6950
6951 if ( this.options.duration ) {
6952 this.pos = eased = jQuery.easing[ this.easing ](
6953 percent, this.options.duration * percent, 0, 1, this.options.duration
6954 );
6955 } else {
6956 this.pos = eased = percent;
6957 }
6958 this.now = ( this.end - this.start ) * eased + this.start;
6959
6960 if ( this.options.step ) {
6961 this.options.step.call( this.elem, this.now, this );
6962 }
6963
6964 if ( hooks && hooks.set ) {
6965 hooks.set( this );
6966 } else {
6967 Tween.propHooks._default.set( this );
6968 }
6969 return this;
6970 }
6971 };
6972
6973 Tween.prototype.init.prototype = Tween.prototype;
6974
6975 Tween.propHooks = {
6976 _default: {
6977 get: function( tween ) {
6978 var result;
6979
6980 if ( tween.elem[ tween.prop ] != null &&
6981 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
6982 return tween.elem[ tween.prop ];
6983 }
6984
6985 // passing an empty string as a 3rd parameter to .css will automatically
6986 // attempt a parseFloat and fallback to a string if the parse fails
6987 // so, simple values such as "10px" are parsed to Float.
6988 // complex values such as "rotate(1rad)" are returned as is.
6989 result = jQuery.css( tween.elem, tween.prop, "" );
6990 // Empty strings, null, undefined and "auto" are converted to 0.
6991 return !result || result === "auto" ? 0 : result;
6992 },
6993 set: function( tween ) {
6994 // use step hook for back compat - use cssHook if its there - use .style if its
6995 // available and use plain properties where available
6996 if ( jQuery.fx.step[ tween.prop ] ) {
6997 jQuery.fx.step[ tween.prop ]( tween );
6998 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
6999 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
7000 } else {
7001 tween.elem[ tween.prop ] = tween.now;
7002 }
7003 }
7004 }
7005 };
7006
7007 // Support: IE <=9
7008 // Panic based approach to setting things on disconnected nodes
7009
7010 Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
7011 set: function( tween ) {
7012 if ( tween.elem.nodeType && tween.elem.parentNode ) {
7013 tween.elem[ tween.prop ] = tween.now;
7014 }
7015 }
7016 };
7017
7018 jQuery.easing = {
7019 linear: function( p ) {
7020 return p;
7021 },
7022 swing: function( p ) {
7023 return 0.5 - Math.cos( p * Math.PI ) / 2;
7024 }
7025 };
7026
7027 jQuery.fx = Tween.prototype.init;
7028
7029 // Back Compat <1.8 extension point
7030 jQuery.fx.step = {};
7031
7032
7033
7034
7035 var
7036 fxNow, timerId,
7037 rfxtypes = /^(?:toggle|show|hide)$/,
7038 rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
7039 rrun = /queueHooks$/,
7040 animationPrefilters = [ defaultPrefilter ],
7041 tweeners = {
7042 "*": [ function( prop, value ) {
7043 var tween = this.createTween( prop, value ),
7044 target = tween.cur(),
7045 parts = rfxnum.exec( value ),
7046 unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
7047
7048 // Starting value computation is required for potential unit mismatches
7049 start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
7050 rfxnum.exec( jQuery.css( tween.elem, prop ) ),
7051 scale = 1,
7052 maxIterations = 20;
7053
7054 if ( start && start[ 3 ] !== unit ) {
7055 // Trust units reported by jQuery.css
7056 unit = unit || start[ 3 ];
7057
7058 // Make sure we update the tween properties later on
7059 parts = parts || [];
7060
7061 // Iteratively approximate from a nonzero starting point
7062 start = +target || 1;
7063
7064 do {
7065 // If previous iteration zeroed out, double until we get *something*
7066 // Use a string for doubling factor so we don't accidentally see scale as unchanged below
7067 scale = scale || ".5";
7068
7069 // Adjust and apply
7070 start = start / scale;
7071 jQuery.style( tween.elem, prop, start + unit );
7072
7073 // Update scale, tolerating zero or NaN from tween.cur()
7074 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
7075 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
7076 }
7077
7078 // Update tween properties
7079 if ( parts ) {
7080 start = tween.start = +start || +target || 0;
7081 tween.unit = unit;
7082 // If a +=/-= token was provided, we're doing a relative animation
7083 tween.end = parts[ 1 ] ?
7084 start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
7085 +parts[ 2 ];
7086 }
7087
7088 return tween;
7089 } ]
7090 };
7091
7092 // Animations created synchronously will run synchronously
7093 function createFxNow() {
7094 setTimeout(function() {
7095 fxNow = undefined;
7096 });
7097 return ( fxNow = jQuery.now() );
7098 }
7099
7100 // Generate parameters to create a standard animation
7101 function genFx( type, includeWidth ) {
7102 var which,
7103 attrs = { height: type },
7104 i = 0;
7105
7106 // if we include width, step value is 1 to do all cssExpand values,
7107 // if we don't include width, step value is 2 to skip over Left and Right
7108 includeWidth = includeWidth ? 1 : 0;
7109 for ( ; i < 4 ; i += 2 - includeWidth ) {
7110 which = cssExpand[ i ];
7111 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
7112 }
7113
7114 if ( includeWidth ) {
7115 attrs.opacity = attrs.width = type;
7116 }
7117
7118 return attrs;
7119 }
7120
7121 function createTween( value, prop, animation ) {
7122 var tween,
7123 collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
7124 index = 0,
7125 length = collection.length;
7126 for ( ; index < length; index++ ) {
7127 if ( (tween = collection[ index ].call( animation, prop, value )) ) {
7128
7129 // we're done with this property
7130 return tween;
7131 }
7132 }
7133 }
7134
7135 function defaultPrefilter( elem, props, opts ) {
7136 /* jshint validthis: true */
7137 var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
7138 anim = this,
7139 orig = {},
7140 style = elem.style,
7141 hidden = elem.nodeType && isHidden( elem ),
7142 dataShow = jQuery._data( elem, "fxshow" );
7143
7144 // handle queue: false promises
7145 if ( !opts.queue ) {
7146 hooks = jQuery._queueHooks( elem, "fx" );
7147 if ( hooks.unqueued == null ) {
7148 hooks.unqueued = 0;
7149 oldfire = hooks.empty.fire;
7150 hooks.empty.fire = function() {
7151 if ( !hooks.unqueued ) {
7152 oldfire();
7153 }
7154 };
7155 }
7156 hooks.unqueued++;
7157
7158 anim.always(function() {
7159 // doing this makes sure that the complete handler will be called
7160 // before this completes
7161 anim.always(function() {
7162 hooks.unqueued--;
7163 if ( !jQuery.queue( elem, "fx" ).length ) {
7164 hooks.empty.fire();
7165 }
7166 });
7167 });
7168 }
7169
7170 // height/width overflow pass
7171 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
7172 // Make sure that nothing sneaks out
7173 // Record all 3 overflow attributes because IE does not
7174 // change the overflow attribute when overflowX and
7175 // overflowY are set to the same value
7176 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
7177
7178 // Set display property to inline-block for height/width
7179 // animations on inline elements that are having width/height animated
7180 display = jQuery.css( elem, "display" );
7181
7182 // Test default display if display is currently "none"
7183 checkDisplay = display === "none" ?
7184 jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
7185
7186 if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
7187
7188 // inline-level elements accept inline-block;
7189 // block-level elements need to be inline with layout
7190 if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
7191 style.display = "inline-block";
7192 } else {
7193 style.zoom = 1;
7194 }
7195 }
7196 }
7197
7198 if ( opts.overflow ) {
7199 style.overflow = "hidden";
7200 if ( !support.shrinkWrapBlocks() ) {
7201 anim.always(function() {
7202 style.overflow = opts.overflow[ 0 ];
7203 style.overflowX = opts.overflow[ 1 ];
7204 style.overflowY = opts.overflow[ 2 ];
7205 });
7206 }
7207 }
7208
7209 // show/hide pass
7210 for ( prop in props ) {
7211 value = props[ prop ];
7212 if ( rfxtypes.exec( value ) ) {
7213 delete props[ prop ];
7214 toggle = toggle || value === "toggle";
7215 if ( value === ( hidden ? "hide" : "show" ) ) {
7216
7217 // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
7218 if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
7219 hidden = true;
7220 } else {
7221 continue;
7222 }
7223 }
7224 orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
7225
7226 // Any non-fx value stops us from restoring the original display value
7227 } else {
7228 display = undefined;
7229 }
7230 }
7231
7232 if ( !jQuery.isEmptyObject( orig ) ) {
7233 if ( dataShow ) {
7234 if ( "hidden" in dataShow ) {
7235 hidden = dataShow.hidden;
7236 }
7237 } else {
7238 dataShow = jQuery._data( elem, "fxshow", {} );
7239 }
7240
7241 // store state if its toggle - enables .stop().toggle() to "reverse"
7242 if ( toggle ) {
7243 dataShow.hidden = !hidden;
7244 }
7245 if ( hidden ) {
7246 jQuery( elem ).show();
7247 } else {
7248 anim.done(function() {
7249 jQuery( elem ).hide();
7250 });
7251 }
7252 anim.done(function() {
7253 var prop;
7254 jQuery._removeData( elem, "fxshow" );
7255 for ( prop in orig ) {
7256 jQuery.style( elem, prop, orig[ prop ] );
7257 }
7258 });
7259 for ( prop in orig ) {
7260 tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
7261
7262 if ( !( prop in dataShow ) ) {
7263 dataShow[ prop ] = tween.start;
7264 if ( hidden ) {
7265 tween.end = tween.start;
7266 tween.start = prop === "width" || prop === "height" ? 1 : 0;
7267 }
7268 }
7269 }
7270
7271 // If this is a noop like .hide().hide(), restore an overwritten display value
7272 } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
7273 style.display = display;
7274 }
7275 }
7276
7277 function propFilter( props, specialEasing ) {
7278 var index, name, easing, value, hooks;
7279
7280 // camelCase, specialEasing and expand cssHook pass
7281 for ( index in props ) {
7282 name = jQuery.camelCase( index );
7283 easing = specialEasing[ name ];
7284 value = props[ index ];
7285 if ( jQuery.isArray( value ) ) {
7286 easing = value[ 1 ];
7287 value = props[ index ] = value[ 0 ];
7288 }
7289
7290 if ( index !== name ) {
7291 props[ name ] = value;
7292 delete props[ index ];
7293 }
7294
7295 hooks = jQuery.cssHooks[ name ];
7296 if ( hooks && "expand" in hooks ) {
7297 value = hooks.expand( value );
7298 delete props[ name ];
7299
7300 // not quite $.extend, this wont overwrite keys already present.
7301 // also - reusing 'index' from above because we have the correct "name"
7302 for ( index in value ) {
7303 if ( !( index in props ) ) {
7304 props[ index ] = value[ index ];
7305 specialEasing[ index ] = easing;
7306 }
7307 }
7308 } else {
7309 specialEasing[ name ] = easing;
7310 }
7311 }
7312 }
7313
7314 function Animation( elem, properties, options ) {
7315 var result,
7316 stopped,
7317 index = 0,
7318 length = animationPrefilters.length,
7319 deferred = jQuery.Deferred().always( function() {
7320 // don't match elem in the :animated selector
7321 delete tick.elem;
7322 }),
7323 tick = function() {
7324 if ( stopped ) {
7325 return false;
7326 }
7327 var currentTime = fxNow || createFxNow(),
7328 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
7329 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
7330 temp = remaining / animation.duration || 0,
7331 percent = 1 - temp,
7332 index = 0,
7333 length = animation.tweens.length;
7334
7335 for ( ; index < length ; index++ ) {
7336 animation.tweens[ index ].run( percent );
7337 }
7338
7339 deferred.notifyWith( elem, [ animation, percent, remaining ]);
7340
7341 if ( percent < 1 && length ) {
7342 return remaining;
7343 } else {
7344 deferred.resolveWith( elem, [ animation ] );
7345 return false;
7346 }
7347 },
7348 animation = deferred.promise({
7349 elem: elem,
7350 props: jQuery.extend( {}, properties ),
7351 opts: jQuery.extend( true, { specialEasing: {} }, options ),
7352 originalProperties: properties,
7353 originalOptions: options,
7354 startTime: fxNow || createFxNow(),
7355 duration: options.duration,
7356 tweens: [],
7357 createTween: function( prop, end ) {
7358 var tween = jQuery.Tween( elem, animation.opts, prop, end,
7359 animation.opts.specialEasing[ prop ] || animation.opts.easing );
7360 animation.tweens.push( tween );
7361 return tween;
7362 },
7363 stop: function( gotoEnd ) {
7364 var index = 0,
7365 // if we are going to the end, we want to run all the tweens
7366 // otherwise we skip this part
7367 length = gotoEnd ? animation.tweens.length : 0;
7368 if ( stopped ) {
7369 return this;
7370 }
7371 stopped = true;
7372 for ( ; index < length ; index++ ) {
7373 animation.tweens[ index ].run( 1 );
7374 }
7375
7376 // resolve when we played the last frame
7377 // otherwise, reject
7378 if ( gotoEnd ) {
7379 deferred.resolveWith( elem, [ animation, gotoEnd ] );
7380 } else {
7381 deferred.rejectWith( elem, [ animation, gotoEnd ] );
7382 }
7383 return this;
7384 }
7385 }),
7386 props = animation.props;
7387
7388 propFilter( props, animation.opts.specialEasing );
7389
7390 for ( ; index < length ; index++ ) {
7391 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
7392 if ( result ) {
7393 return result;
7394 }
7395 }
7396
7397 jQuery.map( props, createTween, animation );
7398
7399 if ( jQuery.isFunction( animation.opts.start ) ) {
7400 animation.opts.start.call( elem, animation );
7401 }
7402
7403 jQuery.fx.timer(
7404 jQuery.extend( tick, {
7405 elem: elem,
7406 anim: animation,
7407 queue: animation.opts.queue
7408 })
7409 );
7410
7411 // attach callbacks from options
7412 return animation.progress( animation.opts.progress )
7413 .done( animation.opts.done, animation.opts.complete )
7414 .fail( animation.opts.fail )
7415 .always( animation.opts.always );
7416 }
7417
7418 jQuery.Animation = jQuery.extend( Animation, {
7419 tweener: function( props, callback ) {
7420 if ( jQuery.isFunction( props ) ) {
7421 callback = props;
7422 props = [ "*" ];
7423 } else {
7424 props = props.split(" ");
7425 }
7426
7427 var prop,
7428 index = 0,
7429 length = props.length;
7430
7431 for ( ; index < length ; index++ ) {
7432 prop = props[ index ];
7433 tweeners[ prop ] = tweeners[ prop ] || [];
7434 tweeners[ prop ].unshift( callback );
7435 }
7436 },
7437
7438 prefilter: function( callback, prepend ) {
7439 if ( prepend ) {
7440 animationPrefilters.unshift( callback );
7441 } else {
7442 animationPrefilters.push( callback );
7443 }
7444 }
7445 });
7446
7447 jQuery.speed = function( speed, easing, fn ) {
7448 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
7449 complete: fn || !fn && easing ||
7450 jQuery.isFunction( speed ) && speed,
7451 duration: speed,
7452 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
7453 };
7454
7455 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
7456 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
7457
7458 // normalize opt.queue - true/undefined/null -> "fx"
7459 if ( opt.queue == null || opt.queue === true ) {
7460 opt.queue = "fx";
7461 }
7462
7463 // Queueing
7464 opt.old = opt.complete;
7465
7466 opt.complete = function() {
7467 if ( jQuery.isFunction( opt.old ) ) {
7468 opt.old.call( this );
7469 }
7470
7471 if ( opt.queue ) {
7472 jQuery.dequeue( this, opt.queue );
7473 }
7474 };
7475
7476 return opt;
7477 };
7478
7479 jQuery.fn.extend({
7480 fadeTo: function( speed, to, easing, callback ) {
7481
7482 // show any hidden elements after setting opacity to 0
7483 return this.filter( isHidden ).css( "opacity", 0 ).show()
7484
7485 // animate to the value specified
7486 .end().animate({ opacity: to }, speed, easing, callback );
7487 },
7488 animate: function( prop, speed, easing, callback ) {
7489 var empty = jQuery.isEmptyObject( prop ),
7490 optall = jQuery.speed( speed, easing, callback ),
7491 doAnimation = function() {
7492 // Operate on a copy of prop so per-property easing won't be lost
7493 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
7494
7495 // Empty animations, or finishing resolves immediately
7496 if ( empty || jQuery._data( this, "finish" ) ) {
7497 anim.stop( true );
7498 }
7499 };
7500 doAnimation.finish = doAnimation;
7501
7502 return empty || optall.queue === false ?
7503 this.each( doAnimation ) :
7504 this.queue( optall.queue, doAnimation );
7505 },
7506 stop: function( type, clearQueue, gotoEnd ) {
7507 var stopQueue = function( hooks ) {
7508 var stop = hooks.stop;
7509 delete hooks.stop;
7510 stop( gotoEnd );
7511 };
7512
7513 if ( typeof type !== "string" ) {
7514 gotoEnd = clearQueue;
7515 clearQueue = type;
7516 type = undefined;
7517 }
7518 if ( clearQueue && type !== false ) {
7519 this.queue( type || "fx", [] );
7520 }
7521
7522 return this.each(function() {
7523 var dequeue = true,
7524 index = type != null && type + "queueHooks",
7525 timers = jQuery.timers,
7526 data = jQuery._data( this );
7527
7528 if ( index ) {
7529 if ( data[ index ] && data[ index ].stop ) {
7530 stopQueue( data[ index ] );
7531 }
7532 } else {
7533 for ( index in data ) {
7534 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
7535 stopQueue( data[ index ] );
7536 }
7537 }
7538 }
7539
7540 for ( index = timers.length; index--; ) {
7541 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
7542 timers[ index ].anim.stop( gotoEnd );
7543 dequeue = false;
7544 timers.splice( index, 1 );
7545 }
7546 }
7547
7548 // start the next in the queue if the last step wasn't forced
7549 // timers currently will call their complete callbacks, which will dequeue
7550 // but only if they were gotoEnd
7551 if ( dequeue || !gotoEnd ) {
7552 jQuery.dequeue( this, type );
7553 }
7554 });
7555 },
7556 finish: function( type ) {
7557 if ( type !== false ) {
7558 type = type || "fx";
7559 }
7560 return this.each(function() {
7561 var index,
7562 data = jQuery._data( this ),
7563 queue = data[ type + "queue" ],
7564 hooks = data[ type + "queueHooks" ],
7565 timers = jQuery.timers,
7566 length = queue ? queue.length : 0;
7567
7568 // enable finishing flag on private data
7569 data.finish = true;
7570
7571 // empty the queue first
7572 jQuery.queue( this, type, [] );
7573
7574 if ( hooks && hooks.stop ) {
7575 hooks.stop.call( this, true );
7576 }
7577
7578 // look for any active animations, and finish them
7579 for ( index = timers.length; index--; ) {
7580 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
7581 timers[ index ].anim.stop( true );
7582 timers.splice( index, 1 );
7583 }
7584 }
7585
7586 // look for any animations in the old queue and finish them
7587 for ( index = 0; index < length; index++ ) {
7588 if ( queue[ index ] && queue[ index ].finish ) {
7589 queue[ index ].finish.call( this );
7590 }
7591 }
7592
7593 // turn off finishing flag
7594 delete data.finish;
7595 });
7596 }
7597 });
7598
7599 jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
7600 var cssFn = jQuery.fn[ name ];
7601 jQuery.fn[ name ] = function( speed, easing, callback ) {
7602 return speed == null || typeof speed === "boolean" ?
7603 cssFn.apply( this, arguments ) :
7604 this.animate( genFx( name, true ), speed, easing, callback );
7605 };
7606 });
7607
7608 // Generate shortcuts for custom animations
7609 jQuery.each({
7610 slideDown: genFx("show"),
7611 slideUp: genFx("hide"),
7612 slideToggle: genFx("toggle"),
7613 fadeIn: { opacity: "show" },
7614 fadeOut: { opacity: "hide" },
7615 fadeToggle: { opacity: "toggle" }
7616 }, function( name, props ) {
7617 jQuery.fn[ name ] = function( speed, easing, callback ) {
7618 return this.animate( props, speed, easing, callback );
7619 };
7620 });
7621
7622 jQuery.timers = [];
7623 jQuery.fx.tick = function() {
7624 var timer,
7625 timers = jQuery.timers,
7626 i = 0;
7627
7628 fxNow = jQuery.now();
7629
7630 for ( ; i < timers.length; i++ ) {
7631 timer = timers[ i ];
7632 // Checks the timer has not already been removed
7633 if ( !timer() && timers[ i ] === timer ) {
7634 timers.splice( i--, 1 );
7635 }
7636 }
7637
7638 if ( !timers.length ) {
7639 jQuery.fx.stop();
7640 }
7641 fxNow = undefined;
7642 };
7643
7644 jQuery.fx.timer = function( timer ) {
7645 jQuery.timers.push( timer );
7646 if ( timer() ) {
7647 jQuery.fx.start();
7648 } else {
7649 jQuery.timers.pop();
7650 }
7651 };
7652
7653 jQuery.fx.interval = 13;
7654
7655 jQuery.fx.start = function() {
7656 if ( !timerId ) {
7657 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
7658 }
7659 };
7660
7661 jQuery.fx.stop = function() {
7662 clearInterval( timerId );
7663 timerId = null;
7664 };
7665
7666 jQuery.fx.speeds = {
7667 slow: 600,
7668 fast: 200,
7669 // Default speed
7670 _default: 400
7671 };
7672
7673
7674 // Based off of the plugin by Clint Helfers, with permission.
7675 // http://blindsignals.com/index.php/2009/07/jquery-delay/
7676 jQuery.fn.delay = function( time, type ) {
7677 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
7678 type = type || "fx";
7679
7680 return this.queue( type, function( next, hooks ) {
7681 var timeout = setTimeout( next, time );
7682 hooks.stop = function() {
7683 clearTimeout( timeout );
7684 };
7685 });
7686 };
7687
7688
7689 (function() {
7690 // Minified: var a,b,c,d,e
7691 var input, div, select, a, opt;
7692
7693 // Setup
7694 div = document.createElement( "div" );
7695 div.setAttribute( "className", "t" );
7696 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
7697 a = div.getElementsByTagName("a")[ 0 ];
7698
7699 // First batch of tests.
7700 select = document.createElement("select");
7701 opt = select.appendChild( document.createElement("option") );
7702 input = div.getElementsByTagName("input")[ 0 ];
7703
7704 a.style.cssText = "top:1px";
7705
7706 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
7707 support.getSetAttribute = div.className !== "t";
7708
7709 // Get the style information from getAttribute
7710 // (IE uses .cssText instead)
7711 support.style = /top/.test( a.getAttribute("style") );
7712
7713 // Make sure that URLs aren't manipulated
7714 // (IE normalizes it by default)
7715 support.hrefNormalized = a.getAttribute("href") === "/a";
7716
7717 // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
7718 support.checkOn = !!input.value;
7719
7720 // Make sure that a selected-by-default option has a working selected property.
7721 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
7722 support.optSelected = opt.selected;
7723
7724 // Tests for enctype support on a form (#6743)
7725 support.enctype = !!document.createElement("form").enctype;
7726
7727 // Make sure that the options inside disabled selects aren't marked as disabled
7728 // (WebKit marks them as disabled)
7729 select.disabled = true;
7730 support.optDisabled = !opt.disabled;
7731
7732 // Support: IE8 only
7733 // Check if we can trust getAttribute("value")
7734 input = document.createElement( "input" );
7735 input.setAttribute( "value", "" );
7736 support.input = input.getAttribute( "value" ) === "";
7737
7738 // Check if an input maintains its value after becoming a radio
7739 input.value = "t";
7740 input.setAttribute( "type", "radio" );
7741 support.radioValue = input.value === "t";
7742 })();
7743
7744
7745 var rreturn = /\r/g;
7746
7747 jQuery.fn.extend({
7748 val: function( value ) {
7749 var hooks, ret, isFunction,
7750 elem = this[0];
7751
7752 if ( !arguments.length ) {
7753 if ( elem ) {
7754 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
7755
7756 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
7757 return ret;
7758 }
7759
7760 ret = elem.value;
7761
7762 return typeof ret === "string" ?
7763 // handle most common string cases
7764 ret.replace(rreturn, "") :
7765 // handle cases where value is null/undef or number
7766 ret == null ? "" : ret;
7767 }
7768
7769 return;
7770 }
7771
7772 isFunction = jQuery.isFunction( value );
7773
7774 return this.each(function( i ) {
7775 var val;
7776
7777 if ( this.nodeType !== 1 ) {
7778 return;
7779 }
7780
7781 if ( isFunction ) {
7782 val = value.call( this, i, jQuery( this ).val() );
7783 } else {
7784 val = value;
7785 }
7786
7787 // Treat null/undefined as ""; convert numbers to string
7788 if ( val == null ) {
7789 val = "";
7790 } else if ( typeof val === "number" ) {
7791 val += "";
7792 } else if ( jQuery.isArray( val ) ) {
7793 val = jQuery.map( val, function( value ) {
7794 return value == null ? "" : value + "";
7795 });
7796 }
7797
7798 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
7799
7800 // If set returns undefined, fall back to normal setting
7801 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
7802 this.value = val;
7803 }
7804 });
7805 }
7806 });
7807
7808 jQuery.extend({
7809 valHooks: {
7810 option: {
7811 get: function( elem ) {
7812 var val = jQuery.find.attr( elem, "value" );
7813 return val != null ?
7814 val :
7815 // Support: IE10-11+
7816 // option.text throws exceptions (#14686, #14858)
7817 jQuery.trim( jQuery.text( elem ) );
7818 }
7819 },
7820 select: {
7821 get: function( elem ) {
7822 var value, option,
7823 options = elem.options,
7824 index = elem.selectedIndex,
7825 one = elem.type === "select-one" || index < 0,
7826 values = one ? null : [],
7827 max = one ? index + 1 : options.length,
7828 i = index < 0 ?
7829 max :
7830 one ? index : 0;
7831
7832 // Loop through all the selected options
7833 for ( ; i < max; i++ ) {
7834 option = options[ i ];
7835
7836 // oldIE doesn't update selected after form reset (#2551)
7837 if ( ( option.selected || i === index ) &&
7838 // Don't return options that are disabled or in a disabled optgroup
7839 ( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
7840 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
7841
7842 // Get the specific value for the option
7843 value = jQuery( option ).val();
7844
7845 // We don't need an array for one selects
7846 if ( one ) {
7847 return value;
7848 }
7849
7850 // Multi-Selects return an array
7851 values.push( value );
7852 }
7853 }
7854
7855 return values;
7856 },
7857
7858 set: function( elem, value ) {
7859 var optionSet, option,
7860 options = elem.options,
7861 values = jQuery.makeArray( value ),
7862 i = options.length;
7863
7864 while ( i-- ) {
7865 option = options[ i ];
7866
7867 if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
7868
7869 // Support: IE6
7870 // When new option element is added to select box we need to
7871 // force reflow of newly added node in order to workaround delay
7872 // of initialization properties
7873 try {
7874 option.selected = optionSet = true;
7875
7876 } catch ( _ ) {
7877
7878 // Will be executed only in IE6
7879 option.scrollHeight;
7880 }
7881
7882 } else {
7883 option.selected = false;
7884 }
7885 }
7886
7887 // Force browsers to behave consistently when non-matching value is set
7888 if ( !optionSet ) {
7889 elem.selectedIndex = -1;
7890 }
7891
7892 return options;
7893 }
7894 }
7895 }
7896 });
7897
7898 // Radios and checkboxes getter/setter
7899 jQuery.each([ "radio", "checkbox" ], function() {
7900 jQuery.valHooks[ this ] = {
7901 set: function( elem, value ) {
7902 if ( jQuery.isArray( value ) ) {
7903 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
7904 }
7905 }
7906 };
7907 if ( !support.checkOn ) {
7908 jQuery.valHooks[ this ].get = function( elem ) {
7909 // Support: Webkit
7910 // "" is returned instead of "on" if a value isn't specified
7911 return elem.getAttribute("value") === null ? "on" : elem.value;
7912 };
7913 }
7914 });
7915
7916
7917
7918
7919 var nodeHook, boolHook,
7920 attrHandle = jQuery.expr.attrHandle,
7921 ruseDefault = /^(?:checked|selected)$/i,
7922 getSetAttribute = support.getSetAttribute,
7923 getSetInput = support.input;
7924
7925 jQuery.fn.extend({
7926 attr: function( name, value ) {
7927 return access( this, jQuery.attr, name, value, arguments.length > 1 );
7928 },
7929
7930 removeAttr: function( name ) {
7931 return this.each(function() {
7932 jQuery.removeAttr( this, name );
7933 });
7934 }
7935 });
7936
7937 jQuery.extend({
7938 attr: function( elem, name, value ) {
7939 var hooks, ret,
7940 nType = elem.nodeType;
7941
7942 // don't get/set attributes on text, comment and attribute nodes
7943 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
7944 return;
7945 }
7946
7947 // Fallback to prop when attributes are not supported
7948 if ( typeof elem.getAttribute === strundefined ) {
7949 return jQuery.prop( elem, name, value );
7950 }
7951
7952 // All attributes are lowercase
7953 // Grab necessary hook if one is defined
7954 if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
7955 name = name.toLowerCase();
7956 hooks = jQuery.attrHooks[ name ] ||
7957 ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
7958 }
7959
7960 if ( value !== undefined ) {
7961
7962 if ( value === null ) {
7963 jQuery.removeAttr( elem, name );
7964
7965 } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
7966 return ret;
7967
7968 } else {
7969 elem.setAttribute( name, value + "" );
7970 return value;
7971 }
7972
7973 } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
7974 return ret;
7975
7976 } else {
7977 ret = jQuery.find.attr( elem, name );
7978
7979 // Non-existent attributes return null, we normalize to undefined
7980 return ret == null ?
7981 undefined :
7982 ret;
7983 }
7984 },
7985
7986 removeAttr: function( elem, value ) {
7987 var name, propName,
7988 i = 0,
7989 attrNames = value && value.match( rnotwhite );
7990
7991 if ( attrNames && elem.nodeType === 1 ) {
7992 while ( (name = attrNames[i++]) ) {
7993 propName = jQuery.propFix[ name ] || name;
7994
7995 // Boolean attributes get special treatment (#10870)
7996 if ( jQuery.expr.match.bool.test( name ) ) {
7997 // Set corresponding property to false
7998 if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
7999 elem[ propName ] = false;
8000 // Support: IE<9
8001 // Also clear defaultChecked/defaultSelected (if appropriate)
8002 } else {
8003 elem[ jQuery.camelCase( "default-" + name ) ] =
8004 elem[ propName ] = false;
8005 }
8006
8007 // See #9699 for explanation of this approach (setting first, then removal)
8008 } else {
8009 jQuery.attr( elem, name, "" );
8010 }
8011
8012 elem.removeAttribute( getSetAttribute ? name : propName );
8013 }
8014 }
8015 },
8016
8017 attrHooks: {
8018 type: {
8019 set: function( elem, value ) {
8020 if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
8021 // Setting the type on a radio button after the value resets the value in IE6-9
8022 // Reset value to default in case type is set after value during creation
8023 var val = elem.value;
8024 elem.setAttribute( "type", value );
8025 if ( val ) {
8026 elem.value = val;
8027 }
8028 return value;
8029 }
8030 }
8031 }
8032 }
8033 });
8034
8035 // Hook for boolean attributes
8036 boolHook = {
8037 set: function( elem, value, name ) {
8038 if ( value === false ) {
8039 // Remove boolean attributes when set to false
8040 jQuery.removeAttr( elem, name );
8041 } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
8042 // IE<8 needs the *property* name
8043 elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
8044
8045 // Use defaultChecked and defaultSelected for oldIE
8046 } else {
8047 elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
8048 }
8049
8050 return name;
8051 }
8052 };
8053
8054 // Retrieve booleans specially
8055 jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
8056
8057 var getter = attrHandle[ name ] || jQuery.find.attr;
8058
8059 attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
8060 function( elem, name, isXML ) {
8061 var ret, handle;
8062 if ( !isXML ) {
8063 // Avoid an infinite loop by temporarily removing this function from the getter
8064 handle = attrHandle[ name ];
8065 attrHandle[ name ] = ret;
8066 ret = getter( elem, name, isXML ) != null ?
8067 name.toLowerCase() :
8068 null;
8069 attrHandle[ name ] = handle;
8070 }
8071 return ret;
8072 } :
8073 function( elem, name, isXML ) {
8074 if ( !isXML ) {
8075 return elem[ jQuery.camelCase( "default-" + name ) ] ?
8076 name.toLowerCase() :
8077 null;
8078 }
8079 };
8080 });
8081
8082 // fix oldIE attroperties
8083 if ( !getSetInput || !getSetAttribute ) {
8084 jQuery.attrHooks.value = {
8085 set: function( elem, value, name ) {
8086 if ( jQuery.nodeName( elem, "input" ) ) {
8087 // Does not return so that setAttribute is also used
8088 elem.defaultValue = value;
8089 } else {
8090 // Use nodeHook if defined (#1954); otherwise setAttribute is fine
8091 return nodeHook && nodeHook.set( elem, value, name );
8092 }
8093 }
8094 };
8095 }
8096
8097 // IE6/7 do not support getting/setting some attributes with get/setAttribute
8098 if ( !getSetAttribute ) {
8099
8100 // Use this for any attribute in IE6/7
8101 // This fixes almost every IE6/7 issue
8102 nodeHook = {
8103 set: function( elem, value, name ) {
8104 // Set the existing or create a new attribute node
8105 var ret = elem.getAttributeNode( name );
8106 if ( !ret ) {
8107 elem.setAttributeNode(
8108 (ret = elem.ownerDocument.createAttribute( name ))
8109 );
8110 }
8111
8112 ret.value = value += "";
8113
8114 // Break association with cloned elements by also using setAttribute (#9646)
8115 if ( name === "value" || value === elem.getAttribute( name ) ) {
8116 return value;
8117 }
8118 }
8119 };
8120
8121 // Some attributes are constructed with empty-string values when not defined
8122 attrHandle.id = attrHandle.name = attrHandle.coords =
8123 function( elem, name, isXML ) {
8124 var ret;
8125 if ( !isXML ) {
8126 return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
8127 ret.value :
8128 null;
8129 }
8130 };
8131
8132 // Fixing value retrieval on a button requires this module
8133 jQuery.valHooks.button = {
8134 get: function( elem, name ) {
8135 var ret = elem.getAttributeNode( name );
8136 if ( ret && ret.specified ) {
8137 return ret.value;
8138 }
8139 },
8140 set: nodeHook.set
8141 };
8142
8143 // Set contenteditable to false on removals(#10429)
8144 // Setting to empty string throws an error as an invalid value
8145 jQuery.attrHooks.contenteditable = {
8146 set: function( elem, value, name ) {
8147 nodeHook.set( elem, value === "" ? false : value, name );
8148 }
8149 };
8150
8151 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
8152 // This is for removals
8153 jQuery.each([ "width", "height" ], function( i, name ) {
8154 jQuery.attrHooks[ name ] = {
8155 set: function( elem, value ) {
8156 if ( value === "" ) {
8157 elem.setAttribute( name, "auto" );
8158 return value;
8159 }
8160 }
8161 };
8162 });
8163 }
8164
8165 if ( !support.style ) {
8166 jQuery.attrHooks.style = {
8167 get: function( elem ) {
8168 // Return undefined in the case of empty string
8169 // Note: IE uppercases css property names, but if we were to .toLowerCase()
8170 // .cssText, that would destroy case senstitivity in URL's, like in "background"
8171 return elem.style.cssText || undefined;
8172 },
8173 set: function( elem, value ) {
8174 return ( elem.style.cssText = value + "" );
8175 }
8176 };
8177 }
8178
8179
8180
8181
8182 var rfocusable = /^(?:input|select|textarea|button|object)$/i,
8183 rclickable = /^(?:a|area)$/i;
8184
8185 jQuery.fn.extend({
8186 prop: function( name, value ) {
8187 return access( this, jQuery.prop, name, value, arguments.length > 1 );
8188 },
8189
8190 removeProp: function( name ) {
8191 name = jQuery.propFix[ name ] || name;
8192 return this.each(function() {
8193 // try/catch handles cases where IE balks (such as removing a property on window)
8194 try {
8195 this[ name ] = undefined;
8196 delete this[ name ];
8197 } catch( e ) {}
8198 });
8199 }
8200 });
8201
8202 jQuery.extend({
8203 propFix: {
8204 "for": "htmlFor",
8205 "class": "className"
8206 },
8207
8208 prop: function( elem, name, value ) {
8209 var ret, hooks, notxml,
8210 nType = elem.nodeType;
8211
8212 // don't get/set properties on text, comment and attribute nodes
8213 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
8214 return;
8215 }
8216
8217 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
8218
8219 if ( notxml ) {
8220 // Fix name and attach hooks
8221 name = jQuery.propFix[ name ] || name;
8222 hooks = jQuery.propHooks[ name ];
8223 }
8224
8225 if ( value !== undefined ) {
8226 return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
8227 ret :
8228 ( elem[ name ] = value );
8229
8230 } else {
8231 return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
8232 ret :
8233 elem[ name ];
8234 }
8235 },
8236
8237 propHooks: {
8238 tabIndex: {
8239 get: function( elem ) {
8240 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
8241 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
8242 // Use proper attribute retrieval(#12072)
8243 var tabindex = jQuery.find.attr( elem, "tabindex" );
8244
8245 return tabindex ?
8246 parseInt( tabindex, 10 ) :
8247 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
8248 0 :
8249 -1;
8250 }
8251 }
8252 }
8253 });
8254
8255 // Some attributes require a special call on IE
8256 // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
8257 if ( !support.hrefNormalized ) {
8258 // href/src property should get the full normalized URL (#10299/#12915)
8259 jQuery.each([ "href", "src" ], function( i, name ) {
8260 jQuery.propHooks[ name ] = {
8261 get: function( elem ) {
8262 return elem.getAttribute( name, 4 );
8263 }
8264 };
8265 });
8266 }
8267
8268 // Support: Safari, IE9+
8269 // mis-reports the default selected property of an option
8270 // Accessing the parent's selectedIndex property fixes it
8271 if ( !support.optSelected ) {
8272 jQuery.propHooks.selected = {
8273 get: function( elem ) {
8274 var parent = elem.parentNode;
8275
8276 if ( parent ) {
8277 parent.selectedIndex;
8278
8279 // Make sure that it also works with optgroups, see #5701
8280 if ( parent.parentNode ) {
8281 parent.parentNode.selectedIndex;
8282 }
8283 }
8284 return null;
8285 }
8286 };
8287 }
8288
8289 jQuery.each([
8290 "tabIndex",
8291 "readOnly",
8292 "maxLength",
8293 "cellSpacing",
8294 "cellPadding",
8295 "rowSpan",
8296 "colSpan",
8297 "useMap",
8298 "frameBorder",
8299 "contentEditable"
8300 ], function() {
8301 jQuery.propFix[ this.toLowerCase() ] = this;
8302 });
8303
8304 // IE6/7 call enctype encoding
8305 if ( !support.enctype ) {
8306 jQuery.propFix.enctype = "encoding";
8307 }
8308
8309
8310
8311
8312 var rclass = /[\t\r\n\f]/g;
8313
8314 jQuery.fn.extend({
8315 addClass: function( value ) {
8316 var classes, elem, cur, clazz, j, finalValue,
8317 i = 0,
8318 len = this.length,
8319 proceed = typeof value === "string" && value;
8320
8321 if ( jQuery.isFunction( value ) ) {
8322 return this.each(function( j ) {
8323 jQuery( this ).addClass( value.call( this, j, this.className ) );
8324 });
8325 }
8326
8327 if ( proceed ) {
8328 // The disjunction here is for better compressibility (see removeClass)
8329 classes = ( value || "" ).match( rnotwhite ) || [];
8330
8331 for ( ; i < len; i++ ) {
8332 elem = this[ i ];
8333 cur = elem.nodeType === 1 && ( elem.className ?
8334 ( " " + elem.className + " " ).replace( rclass, " " ) :
8335 " "
8336 );
8337
8338 if ( cur ) {
8339 j = 0;
8340 while ( (clazz = classes[j++]) ) {
8341 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
8342 cur += clazz + " ";
8343 }
8344 }
8345
8346 // only assign if different to avoid unneeded rendering.
8347 finalValue = jQuery.trim( cur );
8348 if ( elem.className !== finalValue ) {
8349 elem.className = finalValue;
8350 }
8351 }
8352 }
8353 }
8354
8355 return this;
8356 },
8357
8358 removeClass: function( value ) {
8359 var classes, elem, cur, clazz, j, finalValue,
8360 i = 0,
8361 len = this.length,
8362 proceed = arguments.length === 0 || typeof value === "string" && value;
8363
8364 if ( jQuery.isFunction( value ) ) {
8365 return this.each(function( j ) {
8366 jQuery( this ).removeClass( value.call( this, j, this.className ) );
8367 });
8368 }
8369 if ( proceed ) {
8370 classes = ( value || "" ).match( rnotwhite ) || [];
8371
8372 for ( ; i < len; i++ ) {
8373 elem = this[ i ];
8374 // This expression is here for better compressibility (see addClass)
8375 cur = elem.nodeType === 1 && ( elem.className ?
8376 ( " " + elem.className + " " ).replace( rclass, " " ) :
8377 ""
8378 );
8379
8380 if ( cur ) {
8381 j = 0;
8382 while ( (clazz = classes[j++]) ) {
8383 // Remove *all* instances
8384 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
8385 cur = cur.replace( " " + clazz + " ", " " );
8386 }
8387 }
8388
8389 // only assign if different to avoid unneeded rendering.
8390 finalValue = value ? jQuery.trim( cur ) : "";
8391 if ( elem.className !== finalValue ) {
8392 elem.className = finalValue;
8393 }
8394 }
8395 }
8396 }
8397
8398 return this;
8399 },
8400
8401 toggleClass: function( value, stateVal ) {
8402 var type = typeof value;
8403
8404 if ( typeof stateVal === "boolean" && type === "string" ) {
8405 return stateVal ? this.addClass( value ) : this.removeClass( value );
8406 }
8407
8408 if ( jQuery.isFunction( value ) ) {
8409 return this.each(function( i ) {
8410 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
8411 });
8412 }
8413
8414 return this.each(function() {
8415 if ( type === "string" ) {
8416 // toggle individual class names
8417 var className,
8418 i = 0,
8419 self = jQuery( this ),
8420 classNames = value.match( rnotwhite ) || [];
8421
8422 while ( (className = classNames[ i++ ]) ) {
8423 // check each className given, space separated list
8424 if ( self.hasClass( className ) ) {
8425 self.removeClass( className );
8426 } else {
8427 self.addClass( className );
8428 }
8429 }
8430
8431 // Toggle whole class name
8432 } else if ( type === strundefined || type === "boolean" ) {
8433 if ( this.className ) {
8434 // store className if set
8435 jQuery._data( this, "__className__", this.className );
8436 }
8437
8438 // If the element has a class name or if we're passed "false",
8439 // then remove the whole classname (if there was one, the above saved it).
8440 // Otherwise bring back whatever was previously saved (if anything),
8441 // falling back to the empty string if nothing was stored.
8442 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
8443 }
8444 });
8445 },
8446
8447 hasClass: function( selector ) {
8448 var className = " " + selector + " ",
8449 i = 0,
8450 l = this.length;
8451 for ( ; i < l; i++ ) {
8452 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
8453 return true;
8454 }
8455 }
8456
8457 return false;
8458 }
8459 });
8460
8461
8462
8463
8464 // Return jQuery for attributes-only inclusion
8465
8466
8467 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
8468 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
8469 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
8470
8471 // Handle event binding
8472 jQuery.fn[ name ] = function( data, fn ) {
8473 return arguments.length > 0 ?
8474 this.on( name, null, data, fn ) :
8475 this.trigger( name );
8476 };
8477 });
8478
8479 jQuery.fn.extend({
8480 hover: function( fnOver, fnOut ) {
8481 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
8482 },
8483
8484 bind: function( types, data, fn ) {
8485 return this.on( types, null, data, fn );
8486 },
8487 unbind: function( types, fn ) {
8488 return this.off( types, null, fn );
8489 },
8490
8491 delegate: function( selector, types, data, fn ) {
8492 return this.on( types, selector, data, fn );
8493 },
8494 undelegate: function( selector, types, fn ) {
8495 // ( namespace ) or ( selector, types [, fn] )
8496 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
8497 }
8498 });
8499
8500
8501 var nonce = jQuery.now();
8502
8503 var rquery = (/\?/);
8504
8505
8506
8507 var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
8508
8509 jQuery.parseJSON = function( data ) {
8510 // Attempt to parse using the native JSON parser first
8511 if ( window.JSON && window.JSON.parse ) {
8512 // Support: Android 2.3
8513 // Workaround failure to string-cast null input
8514 return window.JSON.parse( data + "" );
8515 }
8516
8517 var requireNonComma,
8518 depth = null,
8519 str = jQuery.trim( data + "" );
8520
8521 // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
8522 // after removing valid tokens
8523 return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
8524
8525 // Force termination if we see a misplaced comma
8526 if ( requireNonComma && comma ) {
8527 depth = 0;
8528 }
8529
8530 // Perform no more replacements after returning to outermost depth
8531 if ( depth === 0 ) {
8532 return token;
8533 }
8534
8535 // Commas must not follow "[", "{", or ","
8536 requireNonComma = open || comma;
8537
8538 // Determine new depth
8539 // array/object open ("[" or "{"): depth += true - false (increment)
8540 // array/object close ("]" or "}"): depth += false - true (decrement)
8541 // other cases ("," or primitive): depth += true - true (numeric cast)
8542 depth += !close - !open;
8543
8544 // Remove this token
8545 return "";
8546 }) ) ?
8547 ( Function( "return " + str ) )() :
8548 jQuery.error( "Invalid JSON: " + data );
8549 };
8550
8551
8552 // Cross-browser xml parsing
8553 jQuery.parseXML = function( data ) {
8554 var xml, tmp;
8555 if ( !data || typeof data !== "string" ) {
8556 return null;
8557 }
8558 try {
8559 if ( window.DOMParser ) { // Standard
8560 tmp = new DOMParser();
8561 xml = tmp.parseFromString( data, "text/xml" );
8562 } else { // IE
8563 xml = new ActiveXObject( "Microsoft.XMLDOM" );
8564 xml.async = "false";
8565 xml.loadXML( data );
8566 }
8567 } catch( e ) {
8568 xml = undefined;
8569 }
8570 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
8571 jQuery.error( "Invalid XML: " + data );
8572 }
8573 return xml;
8574 };
8575
8576
8577 var
8578 // Document location
8579 ajaxLocParts,
8580 ajaxLocation,
8581
8582 rhash = /#.*$/,
8583 rts = /([?&])_=[^&]*/,
8584 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
8585 // #7653, #8125, #8152: local protocol detection
8586 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
8587 rnoContent = /^(?:GET|HEAD)$/,
8588 rprotocol = /^\/\//,
8589 rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
8590
8591 /* Prefilters
8592 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
8593 * 2) These are called:
8594 * - BEFORE asking for a transport
8595 * - AFTER param serialization (s.data is a string if s.processData is true)
8596 * 3) key is the dataType
8597 * 4) the catchall symbol "*" can be used
8598 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
8599 */
8600 prefilters = {},
8601
8602 /* Transports bindings
8603 * 1) key is the dataType
8604 * 2) the catchall symbol "*" can be used
8605 * 3) selection will start with transport dataType and THEN go to "*" if needed
8606 */
8607 transports = {},
8608
8609 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
8610 allTypes = "*/".concat("*");
8611
8612 // #8138, IE may throw an exception when accessing
8613 // a field from window.location if document.domain has been set
8614 try {
8615 ajaxLocation = location.href;
8616 } catch( e ) {
8617 // Use the href attribute of an A element
8618 // since IE will modify it given document.location
8619 ajaxLocation = document.createElement( "a" );
8620 ajaxLocation.href = "";
8621 ajaxLocation = ajaxLocation.href;
8622 }
8623
8624 // Segment location into parts
8625 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
8626
8627 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
8628 function addToPrefiltersOrTransports( structure ) {
8629
8630 // dataTypeExpression is optional and defaults to "*"
8631 return function( dataTypeExpression, func ) {
8632
8633 if ( typeof dataTypeExpression !== "string" ) {
8634 func = dataTypeExpression;
8635 dataTypeExpression = "*";
8636 }
8637
8638 var dataType,
8639 i = 0,
8640 dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
8641
8642 if ( jQuery.isFunction( func ) ) {
8643 // For each dataType in the dataTypeExpression
8644 while ( (dataType = dataTypes[i++]) ) {
8645 // Prepend if requested
8646 if ( dataType.charAt( 0 ) === "+" ) {
8647 dataType = dataType.slice( 1 ) || "*";
8648 (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
8649
8650 // Otherwise append
8651 } else {
8652 (structure[ dataType ] = structure[ dataType ] || []).push( func );
8653 }
8654 }
8655 }
8656 };
8657 }
8658
8659 // Base inspection function for prefilters and transports
8660 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
8661
8662 var inspected = {},
8663 seekingTransport = ( structure === transports );
8664
8665 function inspect( dataType ) {
8666 var selected;
8667 inspected[ dataType ] = true;
8668 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
8669 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
8670 if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
8671 options.dataTypes.unshift( dataTypeOrTransport );
8672 inspect( dataTypeOrTransport );
8673 return false;
8674 } else if ( seekingTransport ) {
8675 return !( selected = dataTypeOrTransport );
8676 }
8677 });
8678 return selected;
8679 }
8680
8681 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
8682 }
8683
8684 // A special extend for ajax options
8685 // that takes "flat" options (not to be deep extended)
8686 // Fixes #9887
8687 function ajaxExtend( target, src ) {
8688 var deep, key,
8689 flatOptions = jQuery.ajaxSettings.flatOptions || {};
8690
8691 for ( key in src ) {
8692 if ( src[ key ] !== undefined ) {
8693 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
8694 }
8695 }
8696 if ( deep ) {
8697 jQuery.extend( true, target, deep );
8698 }
8699
8700 return target;
8701 }
8702
8703 /* Handles responses to an ajax request:
8704 * - finds the right dataType (mediates between content-type and expected dataType)
8705 * - returns the corresponding response
8706 */
8707 function ajaxHandleResponses( s, jqXHR, responses ) {
8708 var firstDataType, ct, finalDataType, type,
8709 contents = s.contents,
8710 dataTypes = s.dataTypes;
8711
8712 // Remove auto dataType and get content-type in the process
8713 while ( dataTypes[ 0 ] === "*" ) {
8714 dataTypes.shift();
8715 if ( ct === undefined ) {
8716 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8717 }
8718 }
8719
8720 // Check if we're dealing with a known content-type
8721 if ( ct ) {
8722 for ( type in contents ) {
8723 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8724 dataTypes.unshift( type );
8725 break;
8726 }
8727 }
8728 }
8729
8730 // Check to see if we have a response for the expected dataType
8731 if ( dataTypes[ 0 ] in responses ) {
8732 finalDataType = dataTypes[ 0 ];
8733 } else {
8734 // Try convertible dataTypes
8735 for ( type in responses ) {
8736 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8737 finalDataType = type;
8738 break;
8739 }
8740 if ( !firstDataType ) {
8741 firstDataType = type;
8742 }
8743 }
8744 // Or just use first one
8745 finalDataType = finalDataType || firstDataType;
8746 }
8747
8748 // If we found a dataType
8749 // We add the dataType to the list if needed
8750 // and return the corresponding response
8751 if ( finalDataType ) {
8752 if ( finalDataType !== dataTypes[ 0 ] ) {
8753 dataTypes.unshift( finalDataType );
8754 }
8755 return responses[ finalDataType ];
8756 }
8757 }
8758
8759 /* Chain conversions given the request and the original response
8760 * Also sets the responseXXX fields on the jqXHR instance
8761 */
8762 function ajaxConvert( s, response, jqXHR, isSuccess ) {
8763 var conv2, current, conv, tmp, prev,
8764 converters = {},
8765 // Work with a copy of dataTypes in case we need to modify it for conversion
8766 dataTypes = s.dataTypes.slice();
8767
8768 // Create converters map with lowercased keys
8769 if ( dataTypes[ 1 ] ) {
8770 for ( conv in s.converters ) {
8771 converters[ conv.toLowerCase() ] = s.converters[ conv ];
8772 }
8773 }
8774
8775 current = dataTypes.shift();
8776
8777 // Convert to each sequential dataType
8778 while ( current ) {
8779
8780 if ( s.responseFields[ current ] ) {
8781 jqXHR[ s.responseFields[ current ] ] = response;
8782 }
8783
8784 // Apply the dataFilter if provided
8785 if ( !prev && isSuccess && s.dataFilter ) {
8786 response = s.dataFilter( response, s.dataType );
8787 }
8788
8789 prev = current;
8790 current = dataTypes.shift();
8791
8792 if ( current ) {
8793
8794 // There's only work to do if current dataType is non-auto
8795 if ( current === "*" ) {
8796
8797 current = prev;
8798
8799 // Convert response if prev dataType is non-auto and differs from current
8800 } else if ( prev !== "*" && prev !== current ) {
8801
8802 // Seek a direct converter
8803 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8804
8805 // If none found, seek a pair
8806 if ( !conv ) {
8807 for ( conv2 in converters ) {
8808
8809 // If conv2 outputs current
8810 tmp = conv2.split( " " );
8811 if ( tmp[ 1 ] === current ) {
8812
8813 // If prev can be converted to accepted input
8814 conv = converters[ prev + " " + tmp[ 0 ] ] ||
8815 converters[ "* " + tmp[ 0 ] ];
8816 if ( conv ) {
8817 // Condense equivalence converters
8818 if ( conv === true ) {
8819 conv = converters[ conv2 ];
8820
8821 // Otherwise, insert the intermediate dataType
8822 } else if ( converters[ conv2 ] !== true ) {
8823 current = tmp[ 0 ];
8824 dataTypes.unshift( tmp[ 1 ] );
8825 }
8826 break;
8827 }
8828 }
8829 }
8830 }
8831
8832 // Apply converter (if not an equivalence)
8833 if ( conv !== true ) {
8834
8835 // Unless errors are allowed to bubble, catch and return them
8836 if ( conv && s[ "throws" ] ) {
8837 response = conv( response );
8838 } else {
8839 try {
8840 response = conv( response );
8841 } catch ( e ) {
8842 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8843 }
8844 }
8845 }
8846 }
8847 }
8848 }
8849
8850 return { state: "success", data: response };
8851 }
8852
8853 jQuery.extend({
8854
8855 // Counter for holding the number of active queries
8856 active: 0,
8857
8858 // Last-Modified header cache for next request
8859 lastModified: {},
8860 etag: {},
8861
8862 ajaxSettings: {
8863 url: ajaxLocation,
8864 type: "GET",
8865 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
8866 global: true,
8867 processData: true,
8868 async: true,
8869 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
8870 /*
8871 timeout: 0,
8872 data: null,
8873 dataType: null,
8874 username: null,
8875 password: null,
8876 cache: null,
8877 throws: false,
8878 traditional: false,
8879 headers: {},
8880 */
8881
8882 accepts: {
8883 "*": allTypes,
8884 text: "text/plain",
8885 html: "text/html",
8886 xml: "application/xml, text/xml",
8887 json: "application/json, text/javascript"
8888 },
8889
8890 contents: {
8891 xml: /xml/,
8892 html: /html/,
8893 json: /json/
8894 },
8895
8896 responseFields: {
8897 xml: "responseXML",
8898 text: "responseText",
8899 json: "responseJSON"
8900 },
8901
8902 // Data converters
8903 // Keys separate source (or catchall "*") and destination types with a single space
8904 converters: {
8905
8906 // Convert anything to text
8907 "* text": String,
8908
8909 // Text to html (true = no transformation)
8910 "text html": true,
8911
8912 // Evaluate text as a json expression
8913 "text json": jQuery.parseJSON,
8914
8915 // Parse text as xml
8916 "text xml": jQuery.parseXML
8917 },
8918
8919 // For options that shouldn't be deep extended:
8920 // you can add your own custom options here if
8921 // and when you create one that shouldn't be
8922 // deep extended (see ajaxExtend)
8923 flatOptions: {
8924 url: true,
8925 context: true
8926 }
8927 },
8928
8929 // Creates a full fledged settings object into target
8930 // with both ajaxSettings and settings fields.
8931 // If target is omitted, writes into ajaxSettings.
8932 ajaxSetup: function( target, settings ) {
8933 return settings ?
8934
8935 // Building a settings object
8936 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
8937
8938 // Extending ajaxSettings
8939 ajaxExtend( jQuery.ajaxSettings, target );
8940 },
8941
8942 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
8943 ajaxTransport: addToPrefiltersOrTransports( transports ),
8944
8945 // Main method
8946 ajax: function( url, options ) {
8947
8948 // If url is an object, simulate pre-1.5 signature
8949 if ( typeof url === "object" ) {
8950 options = url;
8951 url = undefined;
8952 }
8953
8954 // Force options to be an object
8955 options = options || {};
8956
8957 var // Cross-domain detection vars
8958 parts,
8959 // Loop variable
8960 i,
8961 // URL without anti-cache param
8962 cacheURL,
8963 // Response headers as string
8964 responseHeadersString,
8965 // timeout handle
8966 timeoutTimer,
8967
8968 // To know if global events are to be dispatched
8969 fireGlobals,
8970
8971 transport,
8972 // Response headers
8973 responseHeaders,
8974 // Create the final options object
8975 s = jQuery.ajaxSetup( {}, options ),
8976 // Callbacks context
8977 callbackContext = s.context || s,
8978 // Context for global events is callbackContext if it is a DOM node or jQuery collection
8979 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
8980 jQuery( callbackContext ) :
8981 jQuery.event,
8982 // Deferreds
8983 deferred = jQuery.Deferred(),
8984 completeDeferred = jQuery.Callbacks("once memory"),
8985 // Status-dependent callbacks
8986 statusCode = s.statusCode || {},
8987 // Headers (they are sent all at once)
8988 requestHeaders = {},
8989 requestHeadersNames = {},
8990 // The jqXHR state
8991 state = 0,
8992 // Default abort message
8993 strAbort = "canceled",
8994 // Fake xhr
8995 jqXHR = {
8996 readyState: 0,
8997
8998 // Builds headers hashtable if needed
8999 getResponseHeader: function( key ) {
9000 var match;
9001 if ( state === 2 ) {
9002 if ( !responseHeaders ) {
9003 responseHeaders = {};
9004 while ( (match = rheaders.exec( responseHeadersString )) ) {
9005 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
9006 }
9007 }
9008 match = responseHeaders[ key.toLowerCase() ];
9009 }
9010 return match == null ? null : match;
9011 },
9012
9013 // Raw string
9014 getAllResponseHeaders: function() {
9015 return state === 2 ? responseHeadersString : null;
9016 },
9017
9018 // Caches the header
9019 setRequestHeader: function( name, value ) {
9020 var lname = name.toLowerCase();
9021 if ( !state ) {
9022 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
9023 requestHeaders[ name ] = value;
9024 }
9025 return this;
9026 },
9027
9028 // Overrides response content-type header
9029 overrideMimeType: function( type ) {
9030 if ( !state ) {
9031 s.mimeType = type;
9032 }
9033 return this;
9034 },
9035
9036 // Status-dependent callbacks
9037 statusCode: function( map ) {
9038 var code;
9039 if ( map ) {
9040 if ( state < 2 ) {
9041 for ( code in map ) {
9042 // Lazy-add the new callback in a way that preserves old ones
9043 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
9044 }
9045 } else {
9046 // Execute the appropriate callbacks
9047 jqXHR.always( map[ jqXHR.status ] );
9048 }
9049 }
9050 return this;
9051 },
9052
9053 // Cancel the request
9054 abort: function( statusText ) {
9055 var finalText = statusText || strAbort;
9056 if ( transport ) {
9057 transport.abort( finalText );
9058 }
9059 done( 0, finalText );
9060 return this;
9061 }
9062 };
9063
9064 // Attach deferreds
9065 deferred.promise( jqXHR ).complete = completeDeferred.add;
9066 jqXHR.success = jqXHR.done;
9067 jqXHR.error = jqXHR.fail;
9068
9069 // Remove hash character (#7531: and string promotion)
9070 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
9071 // Handle falsy url in the settings object (#10093: consistency with old signature)
9072 // We also use the url parameter if available
9073 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
9074
9075 // Alias method option to type as per ticket #12004
9076 s.type = options.method || options.type || s.method || s.type;
9077
9078 // Extract dataTypes list
9079 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
9080
9081 // A cross-domain request is in order when we have a protocol:host:port mismatch
9082 if ( s.crossDomain == null ) {
9083 parts = rurl.exec( s.url.toLowerCase() );
9084 s.crossDomain = !!( parts &&
9085 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
9086 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
9087 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
9088 );
9089 }
9090
9091 // Convert data if not already a string
9092 if ( s.data && s.processData && typeof s.data !== "string" ) {
9093 s.data = jQuery.param( s.data, s.traditional );
9094 }
9095
9096 // Apply prefilters
9097 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
9098
9099 // If request was aborted inside a prefilter, stop there
9100 if ( state === 2 ) {
9101 return jqXHR;
9102 }
9103
9104 // We can fire global events as of now if asked to
9105 // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
9106 fireGlobals = jQuery.event && s.global;
9107
9108 // Watch for a new set of requests
9109 if ( fireGlobals && jQuery.active++ === 0 ) {
9110 jQuery.event.trigger("ajaxStart");
9111 }
9112
9113 // Uppercase the type
9114 s.type = s.type.toUpperCase();
9115
9116 // Determine if request has content
9117 s.hasContent = !rnoContent.test( s.type );
9118
9119 // Save the URL in case we're toying with the If-Modified-Since
9120 // and/or If-None-Match header later on
9121 cacheURL = s.url;
9122
9123 // More options handling for requests with no content
9124 if ( !s.hasContent ) {
9125
9126 // If data is available, append data to url
9127 if ( s.data ) {
9128 cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
9129 // #9682: remove data so that it's not used in an eventual retry
9130 delete s.data;
9131 }
9132
9133 // Add anti-cache in url if needed
9134 if ( s.cache === false ) {
9135 s.url = rts.test( cacheURL ) ?
9136
9137 // If there is already a '_' parameter, set its value
9138 cacheURL.replace( rts, "$1_=" + nonce++ ) :
9139
9140 // Otherwise add one to the end
9141 cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
9142 }
9143 }
9144
9145 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9146 if ( s.ifModified ) {
9147 if ( jQuery.lastModified[ cacheURL ] ) {
9148 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
9149 }
9150 if ( jQuery.etag[ cacheURL ] ) {
9151 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
9152 }
9153 }
9154
9155 // Set the correct header, if data is being sent
9156 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
9157 jqXHR.setRequestHeader( "Content-Type", s.contentType );
9158 }
9159
9160 // Set the Accepts header for the server, depending on the dataType
9161 jqXHR.setRequestHeader(
9162 "Accept",
9163 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
9164 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
9165 s.accepts[ "*" ]
9166 );
9167
9168 // Check for headers option
9169 for ( i in s.headers ) {
9170 jqXHR.setRequestHeader( i, s.headers[ i ] );
9171 }
9172
9173 // Allow custom headers/mimetypes and early abort
9174 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
9175 // Abort if not done already and return
9176 return jqXHR.abort();
9177 }
9178
9179 // aborting is no longer a cancellation
9180 strAbort = "abort";
9181
9182 // Install callbacks on deferreds
9183 for ( i in { success: 1, error: 1, complete: 1 } ) {
9184 jqXHR[ i ]( s[ i ] );
9185 }
9186
9187 // Get transport
9188 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
9189
9190 // If no transport, we auto-abort
9191 if ( !transport ) {
9192 done( -1, "No Transport" );
9193 } else {
9194 jqXHR.readyState = 1;
9195
9196 // Send global event
9197 if ( fireGlobals ) {
9198 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
9199 }
9200 // Timeout
9201 if ( s.async && s.timeout > 0 ) {
9202 timeoutTimer = setTimeout(function() {
9203 jqXHR.abort("timeout");
9204 }, s.timeout );
9205 }
9206
9207 try {
9208 state = 1;
9209 transport.send( requestHeaders, done );
9210 } catch ( e ) {
9211 // Propagate exception as error if not done
9212 if ( state < 2 ) {
9213 done( -1, e );
9214 // Simply rethrow otherwise
9215 } else {
9216 throw e;
9217 }
9218 }
9219 }
9220
9221 // Callback for when everything is done
9222 function done( status, nativeStatusText, responses, headers ) {
9223 var isSuccess, success, error, response, modified,
9224 statusText = nativeStatusText;
9225
9226 // Called once
9227 if ( state === 2 ) {
9228 return;
9229 }
9230
9231 // State is "done" now
9232 state = 2;
9233
9234 // Clear timeout if it exists
9235 if ( timeoutTimer ) {
9236 clearTimeout( timeoutTimer );
9237 }
9238
9239 // Dereference transport for early garbage collection
9240 // (no matter how long the jqXHR object will be used)
9241 transport = undefined;
9242
9243 // Cache response headers
9244 responseHeadersString = headers || "";
9245
9246 // Set readyState
9247 jqXHR.readyState = status > 0 ? 4 : 0;
9248
9249 // Determine if successful
9250 isSuccess = status >= 200 && status < 300 || status === 304;
9251
9252 // Get response data
9253 if ( responses ) {
9254 response = ajaxHandleResponses( s, jqXHR, responses );
9255 }
9256
9257 // Convert no matter what (that way responseXXX fields are always set)
9258 response = ajaxConvert( s, response, jqXHR, isSuccess );
9259
9260 // If successful, handle type chaining
9261 if ( isSuccess ) {
9262
9263 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
9264 if ( s.ifModified ) {
9265 modified = jqXHR.getResponseHeader("Last-Modified");
9266 if ( modified ) {
9267 jQuery.lastModified[ cacheURL ] = modified;
9268 }
9269 modified = jqXHR.getResponseHeader("etag");
9270 if ( modified ) {
9271 jQuery.etag[ cacheURL ] = modified;
9272 }
9273 }
9274
9275 // if no content
9276 if ( status === 204 || s.type === "HEAD" ) {
9277 statusText = "nocontent";
9278
9279 // if not modified
9280 } else if ( status === 304 ) {
9281 statusText = "notmodified";
9282
9283 // If we have data, let's convert it
9284 } else {
9285 statusText = response.state;
9286 success = response.data;
9287 error = response.error;
9288 isSuccess = !error;
9289 }
9290 } else {
9291 // We extract error from statusText
9292 // then normalize statusText and status for non-aborts
9293 error = statusText;
9294 if ( status || !statusText ) {
9295 statusText = "error";
9296 if ( status < 0 ) {
9297 status = 0;
9298 }
9299 }
9300 }
9301
9302 // Set data for the fake xhr object
9303 jqXHR.status = status;
9304 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
9305
9306 // Success/Error
9307 if ( isSuccess ) {
9308 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
9309 } else {
9310 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
9311 }
9312
9313 // Status-dependent callbacks
9314 jqXHR.statusCode( statusCode );
9315 statusCode = undefined;
9316
9317 if ( fireGlobals ) {
9318 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
9319 [ jqXHR, s, isSuccess ? success : error ] );
9320 }
9321
9322 // Complete
9323 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
9324
9325 if ( fireGlobals ) {
9326 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
9327 // Handle the global AJAX counter
9328 if ( !( --jQuery.active ) ) {
9329 jQuery.event.trigger("ajaxStop");
9330 }
9331 }
9332 }
9333
9334 return jqXHR;
9335 },
9336
9337 getJSON: function( url, data, callback ) {
9338 return jQuery.get( url, data, callback, "json" );
9339 },
9340
9341 getScript: function( url, callback ) {
9342 return jQuery.get( url, undefined, callback, "script" );
9343 }
9344 });
9345
9346 jQuery.each( [ "get", "post" ], function( i, method ) {
9347 jQuery[ method ] = function( url, data, callback, type ) {
9348 // shift arguments if data argument was omitted
9349 if ( jQuery.isFunction( data ) ) {
9350 type = type || callback;
9351 callback = data;
9352 data = undefined;
9353 }
9354
9355 return jQuery.ajax({
9356 url: url,
9357 type: method,
9358 dataType: type,
9359 data: data,
9360 success: callback
9361 });
9362 };
9363 });
9364
9365
9366 jQuery._evalUrl = function( url ) {
9367 return jQuery.ajax({
9368 url: url,
9369 type: "GET",
9370 dataType: "script",
9371 async: false,
9372 global: false,
9373 "throws": true
9374 });
9375 };
9376
9377
9378 jQuery.fn.extend({
9379 wrapAll: function( html ) {
9380 if ( jQuery.isFunction( html ) ) {
9381 return this.each(function(i) {
9382 jQuery(this).wrapAll( html.call(this, i) );
9383 });
9384 }
9385
9386 if ( this[0] ) {
9387 // The elements to wrap the target around
9388 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
9389
9390 if ( this[0].parentNode ) {
9391 wrap.insertBefore( this[0] );
9392 }
9393
9394 wrap.map(function() {
9395 var elem = this;
9396
9397 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
9398 elem = elem.firstChild;
9399 }
9400
9401 return elem;
9402 }).append( this );
9403 }
9404
9405 return this;
9406 },
9407
9408 wrapInner: function( html ) {
9409 if ( jQuery.isFunction( html ) ) {
9410 return this.each(function(i) {
9411 jQuery(this).wrapInner( html.call(this, i) );
9412 });
9413 }
9414
9415 return this.each(function() {
9416 var self = jQuery( this ),
9417 contents = self.contents();
9418
9419 if ( contents.length ) {
9420 contents.wrapAll( html );
9421
9422 } else {
9423 self.append( html );
9424 }
9425 });
9426 },
9427
9428 wrap: function( html ) {
9429 var isFunction = jQuery.isFunction( html );
9430
9431 return this.each(function(i) {
9432 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
9433 });
9434 },
9435
9436 unwrap: function() {
9437 return this.parent().each(function() {
9438 if ( !jQuery.nodeName( this, "body" ) ) {
9439 jQuery( this ).replaceWith( this.childNodes );
9440 }
9441 }).end();
9442 }
9443 });
9444
9445
9446 jQuery.expr.filters.hidden = function( elem ) {
9447 // Support: Opera <= 12.12
9448 // Opera reports offsetWidths and offsetHeights less than zero on some elements
9449 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
9450 (!support.reliableHiddenOffsets() &&
9451 ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
9452 };
9453
9454 jQuery.expr.filters.visible = function( elem ) {
9455 return !jQuery.expr.filters.hidden( elem );
9456 };
9457
9458
9459
9460
9461 var r20 = /%20/g,
9462 rbracket = /\[\]$/,
9463 rCRLF = /\r?\n/g,
9464 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
9465 rsubmittable = /^(?:input|select|textarea|keygen)/i;
9466
9467 function buildParams( prefix, obj, traditional, add ) {
9468 var name;
9469
9470 if ( jQuery.isArray( obj ) ) {
9471 // Serialize array item.
9472 jQuery.each( obj, function( i, v ) {
9473 if ( traditional || rbracket.test( prefix ) ) {
9474 // Treat each array item as a scalar.
9475 add( prefix, v );
9476
9477 } else {
9478 // Item is non-scalar (array or object), encode its numeric index.
9479 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
9480 }
9481 });
9482
9483 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
9484 // Serialize object item.
9485 for ( name in obj ) {
9486 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
9487 }
9488
9489 } else {
9490 // Serialize scalar item.
9491 add( prefix, obj );
9492 }
9493 }
9494
9495 // Serialize an array of form elements or a set of
9496 // key/values into a query string
9497 jQuery.param = function( a, traditional ) {
9498 var prefix,
9499 s = [],
9500 add = function( key, value ) {
9501 // If value is a function, invoke it and return its value
9502 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
9503 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
9504 };
9505
9506 // Set traditional to true for jQuery <= 1.3.2 behavior.
9507 if ( traditional === undefined ) {
9508 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
9509 }
9510
9511 // If an array was passed in, assume that it is an array of form elements.
9512 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
9513 // Serialize the form elements
9514 jQuery.each( a, function() {
9515 add( this.name, this.value );
9516 });
9517
9518 } else {
9519 // If traditional, encode the "old" way (the way 1.3.2 or older
9520 // did it), otherwise encode params recursively.
9521 for ( prefix in a ) {
9522 buildParams( prefix, a[ prefix ], traditional, add );
9523 }
9524 }
9525
9526 // Return the resulting serialization
9527 return s.join( "&" ).replace( r20, "+" );
9528 };
9529
9530 jQuery.fn.extend({
9531 serialize: function() {
9532 return jQuery.param( this.serializeArray() );
9533 },
9534 serializeArray: function() {
9535 return this.map(function() {
9536 // Can add propHook for "elements" to filter or add form elements
9537 var elements = jQuery.prop( this, "elements" );
9538 return elements ? jQuery.makeArray( elements ) : this;
9539 })
9540 .filter(function() {
9541 var type = this.type;
9542 // Use .is(":disabled") so that fieldset[disabled] works
9543 return this.name && !jQuery( this ).is( ":disabled" ) &&
9544 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
9545 ( this.checked || !rcheckableType.test( type ) );
9546 })
9547 .map(function( i, elem ) {
9548 var val = jQuery( this ).val();
9549
9550 return val == null ?
9551 null :
9552 jQuery.isArray( val ) ?
9553 jQuery.map( val, function( val ) {
9554 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9555 }) :
9556 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
9557 }).get();
9558 }
9559 });
9560
9561
9562 // Create the request object
9563 // (This is still attached to ajaxSettings for backward compatibility)
9564 jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
9565 // Support: IE6+
9566 function() {
9567
9568 // XHR cannot access local files, always use ActiveX for that case
9569 return !this.isLocal &&
9570
9571 // Support: IE7-8
9572 // oldIE XHR does not support non-RFC2616 methods (#13240)
9573 // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
9574 // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
9575 // Although this check for six methods instead of eight
9576 // since IE also does not support "trace" and "connect"
9577 /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
9578
9579 createStandardXHR() || createActiveXHR();
9580 } :
9581 // For all other browsers, use the standard XMLHttpRequest object
9582 createStandardXHR;
9583
9584 var xhrId = 0,
9585 xhrCallbacks = {},
9586 xhrSupported = jQuery.ajaxSettings.xhr();
9587
9588 // Support: IE<10
9589 // Open requests must be manually aborted on unload (#5280)
9590 // See https://support.microsoft.com/kb/2856746 for more info
9591 if ( window.attachEvent ) {
9592 window.attachEvent( "onunload", function() {
9593 for ( var key in xhrCallbacks ) {
9594 xhrCallbacks[ key ]( undefined, true );
9595 }
9596 });
9597 }
9598
9599 // Determine support properties
9600 support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
9601 xhrSupported = support.ajax = !!xhrSupported;
9602
9603 // Create transport if the browser can provide an xhr
9604 if ( xhrSupported ) {
9605
9606 jQuery.ajaxTransport(function( options ) {
9607 // Cross domain only allowed if supported through XMLHttpRequest
9608 if ( !options.crossDomain || support.cors ) {
9609
9610 var callback;
9611
9612 return {
9613 send: function( headers, complete ) {
9614 var i,
9615 xhr = options.xhr(),
9616 id = ++xhrId;
9617
9618 // Open the socket
9619 xhr.open( options.type, options.url, options.async, options.username, options.password );
9620
9621 // Apply custom fields if provided
9622 if ( options.xhrFields ) {
9623 for ( i in options.xhrFields ) {
9624 xhr[ i ] = options.xhrFields[ i ];
9625 }
9626 }
9627
9628 // Override mime type if needed
9629 if ( options.mimeType && xhr.overrideMimeType ) {
9630 xhr.overrideMimeType( options.mimeType );
9631 }
9632
9633 // X-Requested-With header
9634 // For cross-domain requests, seeing as conditions for a preflight are
9635 // akin to a jigsaw puzzle, we simply never set it to be sure.
9636 // (it can always be set on a per-request basis or even using ajaxSetup)
9637 // For same-domain requests, won't change header if already provided.
9638 if ( !options.crossDomain && !headers["X-Requested-With"] ) {
9639 headers["X-Requested-With"] = "XMLHttpRequest";
9640 }
9641
9642 // Set headers
9643 for ( i in headers ) {
9644 // Support: IE<9
9645 // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
9646 // request header to a null-value.
9647 //
9648 // To keep consistent with other XHR implementations, cast the value
9649 // to string and ignore `undefined`.
9650 if ( headers[ i ] !== undefined ) {
9651 xhr.setRequestHeader( i, headers[ i ] + "" );
9652 }
9653 }
9654
9655 // Do send the request
9656 // This may raise an exception which is actually
9657 // handled in jQuery.ajax (so no try/catch here)
9658 xhr.send( ( options.hasContent && options.data ) || null );
9659
9660 // Listener
9661 callback = function( _, isAbort ) {
9662 var status, statusText, responses;
9663
9664 // Was never called and is aborted or complete
9665 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
9666 // Clean up
9667 delete xhrCallbacks[ id ];
9668 callback = undefined;
9669 xhr.onreadystatechange = jQuery.noop;
9670
9671 // Abort manually if needed
9672 if ( isAbort ) {
9673 if ( xhr.readyState !== 4 ) {
9674 xhr.abort();
9675 }
9676 } else {
9677 responses = {};
9678 status = xhr.status;
9679
9680 // Support: IE<10
9681 // Accessing binary-data responseText throws an exception
9682 // (#11426)
9683 if ( typeof xhr.responseText === "string" ) {
9684 responses.text = xhr.responseText;
9685 }
9686
9687 // Firefox throws an exception when accessing
9688 // statusText for faulty cross-domain requests
9689 try {
9690 statusText = xhr.statusText;
9691 } catch( e ) {
9692 // We normalize with Webkit giving an empty statusText
9693 statusText = "";
9694 }
9695
9696 // Filter status for non standard behaviors
9697
9698 // If the request is local and we have data: assume a success
9699 // (success with no data won't get notified, that's the best we
9700 // can do given current implementations)
9701 if ( !status && options.isLocal && !options.crossDomain ) {
9702 status = responses.text ? 200 : 404;
9703 // IE - #1450: sometimes returns 1223 when it should be 204
9704 } else if ( status === 1223 ) {
9705 status = 204;
9706 }
9707 }
9708 }
9709
9710 // Call complete if needed
9711 if ( responses ) {
9712 complete( status, statusText, responses, xhr.getAllResponseHeaders() );
9713 }
9714 };
9715
9716 if ( !options.async ) {
9717 // if we're in sync mode we fire the callback
9718 callback();
9719 } else if ( xhr.readyState === 4 ) {
9720 // (IE6 & IE7) if it's in cache and has been
9721 // retrieved directly we need to fire the callback
9722 setTimeout( callback );
9723 } else {
9724 // Add to the list of active xhr callbacks
9725 xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
9726 }
9727 },
9728
9729 abort: function() {
9730 if ( callback ) {
9731 callback( undefined, true );
9732 }
9733 }
9734 };
9735 }
9736 });
9737 }
9738
9739 // Functions to create xhrs
9740 function createStandardXHR() {
9741 try {
9742 return new window.XMLHttpRequest();
9743 } catch( e ) {}
9744 }
9745
9746 function createActiveXHR() {
9747 try {
9748 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
9749 } catch( e ) {}
9750 }
9751
9752
9753
9754
9755 // Install script dataType
9756 jQuery.ajaxSetup({
9757 accepts: {
9758 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
9759 },
9760 contents: {
9761 script: /(?:java|ecma)script/
9762 },
9763 converters: {
9764 "text script": function( text ) {
9765 jQuery.globalEval( text );
9766 return text;
9767 }
9768 }
9769 });
9770
9771 // Handle cache's special case and global
9772 jQuery.ajaxPrefilter( "script", function( s ) {
9773 if ( s.cache === undefined ) {
9774 s.cache = false;
9775 }
9776 if ( s.crossDomain ) {
9777 s.type = "GET";
9778 s.global = false;
9779 }
9780 });
9781
9782 // Bind script tag hack transport
9783 jQuery.ajaxTransport( "script", function(s) {
9784
9785 // This transport only deals with cross domain requests
9786 if ( s.crossDomain ) {
9787
9788 var script,
9789 head = document.head || jQuery("head")[0] || document.documentElement;
9790
9791 return {
9792
9793 send: function( _, callback ) {
9794
9795 script = document.createElement("script");
9796
9797 script.async = true;
9798
9799 if ( s.scriptCharset ) {
9800 script.charset = s.scriptCharset;
9801 }
9802
9803 script.src = s.url;
9804
9805 // Attach handlers for all browsers
9806 script.onload = script.onreadystatechange = function( _, isAbort ) {
9807
9808 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
9809
9810 // Handle memory leak in IE
9811 script.onload = script.onreadystatechange = null;
9812
9813 // Remove the script
9814 if ( script.parentNode ) {
9815 script.parentNode.removeChild( script );
9816 }
9817
9818 // Dereference the script
9819 script = null;
9820
9821 // Callback if not abort
9822 if ( !isAbort ) {
9823 callback( 200, "success" );
9824 }
9825 }
9826 };
9827
9828 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
9829 // Use native DOM manipulation to avoid our domManip AJAX trickery
9830 head.insertBefore( script, head.firstChild );
9831 },
9832
9833 abort: function() {
9834 if ( script ) {
9835 script.onload( undefined, true );
9836 }
9837 }
9838 };
9839 }
9840 });
9841
9842
9843
9844
9845 var oldCallbacks = [],
9846 rjsonp = /(=)\?(?=&|$)|\?\?/;
9847
9848 // Default jsonp settings
9849 jQuery.ajaxSetup({
9850 jsonp: "callback",
9851 jsonpCallback: function() {
9852 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
9853 this[ callback ] = true;
9854 return callback;
9855 }
9856 });
9857
9858 // Detect, normalize options and install callbacks for jsonp requests
9859 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
9860
9861 var callbackName, overwritten, responseContainer,
9862 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
9863 "url" :
9864 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
9865 );
9866
9867 // Handle iff the expected data type is "jsonp" or we have a parameter to set
9868 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
9869
9870 // Get callback name, remembering preexisting value associated with it
9871 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
9872 s.jsonpCallback() :
9873 s.jsonpCallback;
9874
9875 // Insert callback into url or form data
9876 if ( jsonProp ) {
9877 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
9878 } else if ( s.jsonp !== false ) {
9879 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
9880 }
9881
9882 // Use data converter to retrieve json after script execution
9883 s.converters["script json"] = function() {
9884 if ( !responseContainer ) {
9885 jQuery.error( callbackName + " was not called" );
9886 }
9887 return responseContainer[ 0 ];
9888 };
9889
9890 // force json dataType
9891 s.dataTypes[ 0 ] = "json";
9892
9893 // Install callback
9894 overwritten = window[ callbackName ];
9895 window[ callbackName ] = function() {
9896 responseContainer = arguments;
9897 };
9898
9899 // Clean-up function (fires after converters)
9900 jqXHR.always(function() {
9901 // Restore preexisting value
9902 window[ callbackName ] = overwritten;
9903
9904 // Save back as free
9905 if ( s[ callbackName ] ) {
9906 // make sure that re-using the options doesn't screw things around
9907 s.jsonpCallback = originalSettings.jsonpCallback;
9908
9909 // save the callback name for future use
9910 oldCallbacks.push( callbackName );
9911 }
9912
9913 // Call if it was a function and we have a response
9914 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
9915 overwritten( responseContainer[ 0 ] );
9916 }
9917
9918 responseContainer = overwritten = undefined;
9919 });
9920
9921 // Delegate to script
9922 return "script";
9923 }
9924 });
9925
9926
9927
9928
9929 // data: string of html
9930 // context (optional): If specified, the fragment will be created in this context, defaults to document
9931 // keepScripts (optional): If true, will include scripts passed in the html string
9932 jQuery.parseHTML = function( data, context, keepScripts ) {
9933 if ( !data || typeof data !== "string" ) {
9934 return null;
9935 }
9936 if ( typeof context === "boolean" ) {
9937 keepScripts = context;
9938 context = false;
9939 }
9940 context = context || document;
9941
9942 var parsed = rsingleTag.exec( data ),
9943 scripts = !keepScripts && [];
9944
9945 // Single tag
9946 if ( parsed ) {
9947 return [ context.createElement( parsed[1] ) ];
9948 }
9949
9950 parsed = jQuery.buildFragment( [ data ], context, scripts );
9951
9952 if ( scripts && scripts.length ) {
9953 jQuery( scripts ).remove();
9954 }
9955
9956 return jQuery.merge( [], parsed.childNodes );
9957 };
9958
9959
9960 // Keep a copy of the old load method
9961 var _load = jQuery.fn.load;
9962
9963 /**
9964 * Load a url into a page
9965 */
9966 jQuery.fn.load = function( url, params, callback ) {
9967 if ( typeof url !== "string" && _load ) {
9968 return _load.apply( this, arguments );
9969 }
9970
9971 var selector, response, type,
9972 self = this,
9973 off = url.indexOf(" ");
9974
9975 if ( off >= 0 ) {
9976 selector = jQuery.trim( url.slice( off, url.length ) );
9977 url = url.slice( 0, off );
9978 }
9979
9980 // If it's a function
9981 if ( jQuery.isFunction( params ) ) {
9982
9983 // We assume that it's the callback
9984 callback = params;
9985 params = undefined;
9986
9987 // Otherwise, build a param string
9988 } else if ( params && typeof params === "object" ) {
9989 type = "POST";
9990 }
9991
9992 // If we have elements to modify, make the request
9993 if ( self.length > 0 ) {
9994 jQuery.ajax({
9995 url: url,
9996
9997 // if "type" variable is undefined, then "GET" method will be used
9998 type: type,
9999 dataType: "html",
10000 data: params
10001 }).done(function( responseText ) {
10002
10003 // Save response for use in complete callback
10004 response = arguments;
10005
10006 self.html( selector ?
10007
10008 // If a selector was specified, locate the right elements in a dummy div
10009 // Exclude scripts to avoid IE 'Permission Denied' errors
10010 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
10011
10012 // Otherwise use the full result
10013 responseText );
10014
10015 }).complete( callback && function( jqXHR, status ) {
10016 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
10017 });
10018 }
10019
10020 return this;
10021 };
10022
10023
10024
10025
10026 // Attach a bunch of functions for handling common AJAX events
10027 jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
10028 jQuery.fn[ type ] = function( fn ) {
10029 return this.on( type, fn );
10030 };
10031 });
10032
10033
10034
10035
10036 jQuery.expr.filters.animated = function( elem ) {
10037 return jQuery.grep(jQuery.timers, function( fn ) {
10038 return elem === fn.elem;
10039 }).length;
10040 };
10041
10042
10043
10044
10045
10046 var docElem = window.document.documentElement;
10047
10048 /**
10049 * Gets a window from an element
10050 */
10051 function getWindow( elem ) {
10052 return jQuery.isWindow( elem ) ?
10053 elem :
10054 elem.nodeType === 9 ?
10055 elem.defaultView || elem.parentWindow :
10056 false;
10057 }
10058
10059 jQuery.offset = {
10060 setOffset: function( elem, options, i ) {
10061 var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
10062 position = jQuery.css( elem, "position" ),
10063 curElem = jQuery( elem ),
10064 props = {};
10065
10066 // set position first, in-case top/left are set even on static elem
10067 if ( position === "static" ) {
10068 elem.style.position = "relative";
10069 }
10070
10071 curOffset = curElem.offset();
10072 curCSSTop = jQuery.css( elem, "top" );
10073 curCSSLeft = jQuery.css( elem, "left" );
10074 calculatePosition = ( position === "absolute" || position === "fixed" ) &&
10075 jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
10076
10077 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
10078 if ( calculatePosition ) {
10079 curPosition = curElem.position();
10080 curTop = curPosition.top;
10081 curLeft = curPosition.left;
10082 } else {
10083 curTop = parseFloat( curCSSTop ) || 0;
10084 curLeft = parseFloat( curCSSLeft ) || 0;
10085 }
10086
10087 if ( jQuery.isFunction( options ) ) {
10088 options = options.call( elem, i, curOffset );
10089 }
10090
10091 if ( options.top != null ) {
10092 props.top = ( options.top - curOffset.top ) + curTop;
10093 }
10094 if ( options.left != null ) {
10095 props.left = ( options.left - curOffset.left ) + curLeft;
10096 }
10097
10098 if ( "using" in options ) {
10099 options.using.call( elem, props );
10100 } else {
10101 curElem.css( props );
10102 }
10103 }
10104 };
10105
10106 jQuery.fn.extend({
10107 offset: function( options ) {
10108 if ( arguments.length ) {
10109 return options === undefined ?
10110 this :
10111 this.each(function( i ) {
10112 jQuery.offset.setOffset( this, options, i );
10113 });
10114 }
10115
10116 var docElem, win,
10117 box = { top: 0, left: 0 },
10118 elem = this[ 0 ],
10119 doc = elem && elem.ownerDocument;
10120
10121 if ( !doc ) {
10122 return;
10123 }
10124
10125 docElem = doc.documentElement;
10126
10127 // Make sure it's not a disconnected DOM node
10128 if ( !jQuery.contains( docElem, elem ) ) {
10129 return box;
10130 }
10131
10132 // If we don't have gBCR, just use 0,0 rather than error
10133 // BlackBerry 5, iOS 3 (original iPhone)
10134 if ( typeof elem.getBoundingClientRect !== strundefined ) {
10135 box = elem.getBoundingClientRect();
10136 }
10137 win = getWindow( doc );
10138 return {
10139 top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
10140 left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
10141 };
10142 },
10143
10144 position: function() {
10145 if ( !this[ 0 ] ) {
10146 return;
10147 }
10148
10149 var offsetParent, offset,
10150 parentOffset = { top: 0, left: 0 },
10151 elem = this[ 0 ];
10152
10153 // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
10154 if ( jQuery.css( elem, "position" ) === "fixed" ) {
10155 // we assume that getBoundingClientRect is available when computed position is fixed
10156 offset = elem.getBoundingClientRect();
10157 } else {
10158 // Get *real* offsetParent
10159 offsetParent = this.offsetParent();
10160
10161 // Get correct offsets
10162 offset = this.offset();
10163 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
10164 parentOffset = offsetParent.offset();
10165 }
10166
10167 // Add offsetParent borders
10168 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
10169 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
10170 }
10171
10172 // Subtract parent offsets and element margins
10173 // note: when an element has margin: auto the offsetLeft and marginLeft
10174 // are the same in Safari causing offset.left to incorrectly be 0
10175 return {
10176 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
10177 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
10178 };
10179 },
10180
10181 offsetParent: function() {
10182 return this.map(function() {
10183 var offsetParent = this.offsetParent || docElem;
10184
10185 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
10186 offsetParent = offsetParent.offsetParent;
10187 }
10188 return offsetParent || docElem;
10189 });
10190 }
10191 });
10192
10193 // Create scrollLeft and scrollTop methods
10194 jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
10195 var top = /Y/.test( prop );
10196
10197 jQuery.fn[ method ] = function( val ) {
10198 return access( this, function( elem, method, val ) {
10199 var win = getWindow( elem );
10200
10201 if ( val === undefined ) {
10202 return win ? (prop in win) ? win[ prop ] :
10203 win.document.documentElement[ method ] :
10204 elem[ method ];
10205 }
10206
10207 if ( win ) {
10208 win.scrollTo(
10209 !top ? val : jQuery( win ).scrollLeft(),
10210 top ? val : jQuery( win ).scrollTop()
10211 );
10212
10213 } else {
10214 elem[ method ] = val;
10215 }
10216 }, method, val, arguments.length, null );
10217 };
10218 });
10219
10220 // Add the top/left cssHooks using jQuery.fn.position
10221 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
10222 // getComputedStyle returns percent when specified for top/left/bottom/right
10223 // rather than make the css module depend on the offset module, we just check for it here
10224 jQuery.each( [ "top", "left" ], function( i, prop ) {
10225 jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
10226 function( elem, computed ) {
10227 if ( computed ) {
10228 computed = curCSS( elem, prop );
10229 // if curCSS returns percentage, fallback to offset
10230 return rnumnonpx.test( computed ) ?
10231 jQuery( elem ).position()[ prop ] + "px" :
10232 computed;
10233 }
10234 }
10235 );
10236 });
10237
10238
10239 // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
10240 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
10241 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
10242 // margin is only for outerHeight, outerWidth
10243 jQuery.fn[ funcName ] = function( margin, value ) {
10244 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
10245 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
10246
10247 return access( this, function( elem, type, value ) {
10248 var doc;
10249
10250 if ( jQuery.isWindow( elem ) ) {
10251 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
10252 // isn't a whole lot we can do. See pull request at this URL for discussion:
10253 // https://github.com/jquery/jquery/pull/764
10254 return elem.document.documentElement[ "client" + name ];
10255 }
10256
10257 // Get document width or height
10258 if ( elem.nodeType === 9 ) {
10259 doc = elem.documentElement;
10260
10261 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
10262 // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
10263 return Math.max(
10264 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
10265 elem.body[ "offset" + name ], doc[ "offset" + name ],
10266 doc[ "client" + name ]
10267 );
10268 }
10269
10270 return value === undefined ?
10271 // Get width or height on the element, requesting but not forcing parseFloat
10272 jQuery.css( elem, type, extra ) :
10273
10274 // Set width or height on the element
10275 jQuery.style( elem, type, value, extra );
10276 }, type, chainable ? margin : undefined, chainable, null );
10277 };
10278 });
10279 });
10280
10281
10282 // The number of elements contained in the matched element set
10283 jQuery.fn.size = function() {
10284 return this.length;
10285 };
10286
10287 jQuery.fn.andSelf = jQuery.fn.addBack;
10288
10289
10290
10291
10292 // Register as a named AMD module, since jQuery can be concatenated with other
10293 // files that may use define, but not via a proper concatenation script that
10294 // understands anonymous AMD modules. A named AMD is safest and most robust
10295 // way to register. Lowercase jquery is used because AMD module names are
10296 // derived from file names, and jQuery is normally delivered in a lowercase
10297 // file name. Do this after creating the global so that if an AMD module wants
10298 // to call noConflict to hide this version of jQuery, it will work.
10299
10300 // Note that for maximum portability, libraries that are not jQuery should
10301 // declare themselves as anonymous modules, and avoid setting a global if an
10302 // AMD loader is present. jQuery is a special case. For more information, see
10303 // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
10304
10305 if ( typeof define === "function" && define.amd ) {
10306 define( "jquery", [], function() {
10307 return jQuery;
10308 });
10309 }
10310
10311
10312
10313
10314 var
10315 // Map over jQuery in case of overwrite
10316 _jQuery = window.jQuery,
10317
10318 // Map over the $ in case of overwrite
10319 _$ = window.$;
10320
10321 jQuery.noConflict = function( deep ) {
10322 if ( window.$ === jQuery ) {
10323 window.$ = _$;
10324 }
10325
10326 if ( deep && window.jQuery === jQuery ) {
10327 window.jQuery = _jQuery;
10328 }
10329
10330 return jQuery;
10331 };
10332
10333 // Expose jQuery and $ identifiers, even in
10334 // AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
10335 // and CommonJS for browser emulators (#13566)
10336 if ( typeof noGlobal === strundefined ) {
10337 window.jQuery = window.$ = jQuery;
10338 }
10339
10340
10341
10342
10343 return jQuery;
10344
10345 }));
+0
-9597
faraday/server/www/script/jquery-1.9.1.js less more
0 /*!
1 * jQuery JavaScript Library v1.9.1
2 * http://jquery.com/
3 *
4 * Includes Sizzle.js
5 * http://sizzlejs.com/
6 *
7 * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
8 * Released under the MIT license
9 * http://jquery.org/license
10 *
11 * Date: 2013-2-4
12 */
13 (function( window, undefined ) {
14
15 // Can't do this because several apps including ASP.NET trace
16 // the stack via arguments.caller.callee and Firefox dies if
17 // you try to trace through "use strict" call chains. (#13335)
18 // Support: Firefox 18+
19 //"use strict";
20 var
21 // The deferred used on DOM ready
22 readyList,
23
24 // A central reference to the root jQuery(document)
25 rootjQuery,
26
27 // Support: IE<9
28 // For `typeof node.method` instead of `node.method !== undefined`
29 core_strundefined = typeof undefined,
30
31 // Use the correct document accordingly with window argument (sandbox)
32 document = window.document,
33 location = window.location,
34
35 // Map over jQuery in case of overwrite
36 _jQuery = window.jQuery,
37
38 // Map over the $ in case of overwrite
39 _$ = window.$,
40
41 // [[Class]] -> type pairs
42 class2type = {},
43
44 // List of deleted data cache ids, so we can reuse them
45 core_deletedIds = [],
46
47 core_version = "1.9.1",
48
49 // Save a reference to some core methods
50 core_concat = core_deletedIds.concat,
51 core_push = core_deletedIds.push,
52 core_slice = core_deletedIds.slice,
53 core_indexOf = core_deletedIds.indexOf,
54 core_toString = class2type.toString,
55 core_hasOwn = class2type.hasOwnProperty,
56 core_trim = core_version.trim,
57
58 // Define a local copy of jQuery
59 jQuery = function( selector, context ) {
60 // The jQuery object is actually just the init constructor 'enhanced'
61 return new jQuery.fn.init( selector, context, rootjQuery );
62 },
63
64 // Used for matching numbers
65 core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
66
67 // Used for splitting on whitespace
68 core_rnotwhite = /\S+/g,
69
70 // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
71 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
72
73 // A simple way to check for HTML strings
74 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
75 // Strict HTML recognition (#11290: must start with <)
76 rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
77
78 // Match a standalone tag
79 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
80
81 // JSON RegExp
82 rvalidchars = /^[\],:{}\s]*$/,
83 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
84 rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
85 rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
86
87 // Matches dashed string for camelizing
88 rmsPrefix = /^-ms-/,
89 rdashAlpha = /-([\da-z])/gi,
90
91 // Used by jQuery.camelCase as callback to replace()
92 fcamelCase = function( all, letter ) {
93 return letter.toUpperCase();
94 },
95
96 // The ready event handler
97 completed = function( event ) {
98
99 // readyState === "complete" is good enough for us to call the dom ready in oldIE
100 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
101 detach();
102 jQuery.ready();
103 }
104 },
105 // Clean-up method for dom ready events
106 detach = function() {
107 if ( document.addEventListener ) {
108 document.removeEventListener( "DOMContentLoaded", completed, false );
109 window.removeEventListener( "load", completed, false );
110
111 } else {
112 document.detachEvent( "onreadystatechange", completed );
113 window.detachEvent( "onload", completed );
114 }
115 };
116
117 jQuery.fn = jQuery.prototype = {
118 // The current version of jQuery being used
119 jquery: core_version,
120
121 constructor: jQuery,
122 init: function( selector, context, rootjQuery ) {
123 var match, elem;
124
125 // HANDLE: $(""), $(null), $(undefined), $(false)
126 if ( !selector ) {
127 return this;
128 }
129
130 // Handle HTML strings
131 if ( typeof selector === "string" ) {
132 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
133 // Assume that strings that start and end with <> are HTML and skip the regex check
134 match = [ null, selector, null ];
135
136 } else {
137 match = rquickExpr.exec( selector );
138 }
139
140 // Match html or make sure no context is specified for #id
141 if ( match && (match[1] || !context) ) {
142
143 // HANDLE: $(html) -> $(array)
144 if ( match[1] ) {
145 context = context instanceof jQuery ? context[0] : context;
146
147 // scripts is true for back-compat
148 jQuery.merge( this, jQuery.parseHTML(
149 match[1],
150 context && context.nodeType ? context.ownerDocument || context : document,
151 true
152 ) );
153
154 // HANDLE: $(html, props)
155 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
156 for ( match in context ) {
157 // Properties of context are called as methods if possible
158 if ( jQuery.isFunction( this[ match ] ) ) {
159 this[ match ]( context[ match ] );
160
161 // ...and otherwise set as attributes
162 } else {
163 this.attr( match, context[ match ] );
164 }
165 }
166 }
167
168 return this;
169
170 // HANDLE: $(#id)
171 } else {
172 elem = document.getElementById( match[2] );
173
174 // Check parentNode to catch when Blackberry 4.6 returns
175 // nodes that are no longer in the document #6963
176 if ( elem && elem.parentNode ) {
177 // Handle the case where IE and Opera return items
178 // by name instead of ID
179 if ( elem.id !== match[2] ) {
180 return rootjQuery.find( selector );
181 }
182
183 // Otherwise, we inject the element directly into the jQuery object
184 this.length = 1;
185 this[0] = elem;
186 }
187
188 this.context = document;
189 this.selector = selector;
190 return this;
191 }
192
193 // HANDLE: $(expr, $(...))
194 } else if ( !context || context.jquery ) {
195 return ( context || rootjQuery ).find( selector );
196
197 // HANDLE: $(expr, context)
198 // (which is just equivalent to: $(context).find(expr)
199 } else {
200 return this.constructor( context ).find( selector );
201 }
202
203 // HANDLE: $(DOMElement)
204 } else if ( selector.nodeType ) {
205 this.context = this[0] = selector;
206 this.length = 1;
207 return this;
208
209 // HANDLE: $(function)
210 // Shortcut for document ready
211 } else if ( jQuery.isFunction( selector ) ) {
212 return rootjQuery.ready( selector );
213 }
214
215 if ( selector.selector !== undefined ) {
216 this.selector = selector.selector;
217 this.context = selector.context;
218 }
219
220 return jQuery.makeArray( selector, this );
221 },
222
223 // Start with an empty selector
224 selector: "",
225
226 // The default length of a jQuery object is 0
227 length: 0,
228
229 // The number of elements contained in the matched element set
230 size: function() {
231 return this.length;
232 },
233
234 toArray: function() {
235 return core_slice.call( this );
236 },
237
238 // Get the Nth element in the matched element set OR
239 // Get the whole matched element set as a clean array
240 get: function( num ) {
241 return num == null ?
242
243 // Return a 'clean' array
244 this.toArray() :
245
246 // Return just the object
247 ( num < 0 ? this[ this.length + num ] : this[ num ] );
248 },
249
250 // Take an array of elements and push it onto the stack
251 // (returning the new matched element set)
252 pushStack: function( elems ) {
253
254 // Build a new jQuery matched element set
255 var ret = jQuery.merge( this.constructor(), elems );
256
257 // Add the old object onto the stack (as a reference)
258 ret.prevObject = this;
259 ret.context = this.context;
260
261 // Return the newly-formed element set
262 return ret;
263 },
264
265 // Execute a callback for every element in the matched set.
266 // (You can seed the arguments with an array of args, but this is
267 // only used internally.)
268 each: function( callback, args ) {
269 return jQuery.each( this, callback, args );
270 },
271
272 ready: function( fn ) {
273 // Add the callback
274 jQuery.ready.promise().done( fn );
275
276 return this;
277 },
278
279 slice: function() {
280 return this.pushStack( core_slice.apply( this, arguments ) );
281 },
282
283 first: function() {
284 return this.eq( 0 );
285 },
286
287 last: function() {
288 return this.eq( -1 );
289 },
290
291 eq: function( i ) {
292 var len = this.length,
293 j = +i + ( i < 0 ? len : 0 );
294 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
295 },
296
297 map: function( callback ) {
298 return this.pushStack( jQuery.map(this, function( elem, i ) {
299 return callback.call( elem, i, elem );
300 }));
301 },
302
303 end: function() {
304 return this.prevObject || this.constructor(null);
305 },
306
307 // For internal use only.
308 // Behaves like an Array's method, not like a jQuery method.
309 push: core_push,
310 sort: [].sort,
311 splice: [].splice
312 };
313
314 // Give the init function the jQuery prototype for later instantiation
315 jQuery.fn.init.prototype = jQuery.fn;
316
317 jQuery.extend = jQuery.fn.extend = function() {
318 var src, copyIsArray, copy, name, options, clone,
319 target = arguments[0] || {},
320 i = 1,
321 length = arguments.length,
322 deep = false;
323
324 // Handle a deep copy situation
325 if ( typeof target === "boolean" ) {
326 deep = target;
327 target = arguments[1] || {};
328 // skip the boolean and the target
329 i = 2;
330 }
331
332 // Handle case when target is a string or something (possible in deep copy)
333 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
334 target = {};
335 }
336
337 // extend jQuery itself if only one argument is passed
338 if ( length === i ) {
339 target = this;
340 --i;
341 }
342
343 for ( ; i < length; i++ ) {
344 // Only deal with non-null/undefined values
345 if ( (options = arguments[ i ]) != null ) {
346 // Extend the base object
347 for ( name in options ) {
348 src = target[ name ];
349 copy = options[ name ];
350
351 // Prevent never-ending loop
352 if ( target === copy ) {
353 continue;
354 }
355
356 // Recurse if we're merging plain objects or arrays
357 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
358 if ( copyIsArray ) {
359 copyIsArray = false;
360 clone = src && jQuery.isArray(src) ? src : [];
361
362 } else {
363 clone = src && jQuery.isPlainObject(src) ? src : {};
364 }
365
366 // Never move original objects, clone them
367 target[ name ] = jQuery.extend( deep, clone, copy );
368
369 // Don't bring in undefined values
370 } else if ( copy !== undefined ) {
371 target[ name ] = copy;
372 }
373 }
374 }
375 }
376
377 // Return the modified object
378 return target;
379 };
380
381 jQuery.extend({
382 noConflict: function( deep ) {
383 if ( window.$ === jQuery ) {
384 window.$ = _$;
385 }
386
387 if ( deep && window.jQuery === jQuery ) {
388 window.jQuery = _jQuery;
389 }
390
391 return jQuery;
392 },
393
394 // Is the DOM ready to be used? Set to true once it occurs.
395 isReady: false,
396
397 // A counter to track how many items to wait for before
398 // the ready event fires. See #6781
399 readyWait: 1,
400
401 // Hold (or release) the ready event
402 holdReady: function( hold ) {
403 if ( hold ) {
404 jQuery.readyWait++;
405 } else {
406 jQuery.ready( true );
407 }
408 },
409
410 // Handle when the DOM is ready
411 ready: function( wait ) {
412
413 // Abort if there are pending holds or we're already ready
414 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
415 return;
416 }
417
418 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
419 if ( !document.body ) {
420 return setTimeout( jQuery.ready );
421 }
422
423 // Remember that the DOM is ready
424 jQuery.isReady = true;
425
426 // If a normal DOM Ready event fired, decrement, and wait if need be
427 if ( wait !== true && --jQuery.readyWait > 0 ) {
428 return;
429 }
430
431 // If there are functions bound, to execute
432 readyList.resolveWith( document, [ jQuery ] );
433
434 // Trigger any bound ready events
435 if ( jQuery.fn.trigger ) {
436 jQuery( document ).trigger("ready").off("ready");
437 }
438 },
439
440 // See test/unit/core.js for details concerning isFunction.
441 // Since version 1.3, DOM methods and functions like alert
442 // aren't supported. They return false on IE (#2968).
443 isFunction: function( obj ) {
444 return jQuery.type(obj) === "function";
445 },
446
447 isArray: Array.isArray || function( obj ) {
448 return jQuery.type(obj) === "array";
449 },
450
451 isWindow: function( obj ) {
452 return obj != null && obj == obj.window;
453 },
454
455 isNumeric: function( obj ) {
456 return !isNaN( parseFloat(obj) ) && isFinite( obj );
457 },
458
459 type: function( obj ) {
460 if ( obj == null ) {
461 return String( obj );
462 }
463 return typeof obj === "object" || typeof obj === "function" ?
464 class2type[ core_toString.call(obj) ] || "object" :
465 typeof obj;
466 },
467
468 isPlainObject: function( obj ) {
469 // Must be an Object.
470 // Because of IE, we also have to check the presence of the constructor property.
471 // Make sure that DOM nodes and window objects don't pass through, as well
472 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
473 return false;
474 }
475
476 try {
477 // Not own constructor property must be Object
478 if ( obj.constructor &&
479 !core_hasOwn.call(obj, "constructor") &&
480 !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
481 return false;
482 }
483 } catch ( e ) {
484 // IE8,9 Will throw exceptions on certain host objects #9897
485 return false;
486 }
487
488 // Own properties are enumerated firstly, so to speed up,
489 // if last one is own, then all properties are own.
490
491 var key;
492 for ( key in obj ) {}
493
494 return key === undefined || core_hasOwn.call( obj, key );
495 },
496
497 isEmptyObject: function( obj ) {
498 var name;
499 for ( name in obj ) {
500 return false;
501 }
502 return true;
503 },
504
505 error: function( msg ) {
506 throw new Error( msg );
507 },
508
509 // data: string of html
510 // context (optional): If specified, the fragment will be created in this context, defaults to document
511 // keepScripts (optional): If true, will include scripts passed in the html string
512 parseHTML: function( data, context, keepScripts ) {
513 if ( !data || typeof data !== "string" ) {
514 return null;
515 }
516 if ( typeof context === "boolean" ) {
517 keepScripts = context;
518 context = false;
519 }
520 context = context || document;
521
522 var parsed = rsingleTag.exec( data ),
523 scripts = !keepScripts && [];
524
525 // Single tag
526 if ( parsed ) {
527 return [ context.createElement( parsed[1] ) ];
528 }
529
530 parsed = jQuery.buildFragment( [ data ], context, scripts );
531 if ( scripts ) {
532 jQuery( scripts ).remove();
533 }
534 return jQuery.merge( [], parsed.childNodes );
535 },
536
537 parseJSON: function( data ) {
538 // Attempt to parse using the native JSON parser first
539 if ( window.JSON && window.JSON.parse ) {
540 return window.JSON.parse( data );
541 }
542
543 if ( data === null ) {
544 return data;
545 }
546
547 if ( typeof data === "string" ) {
548
549 // Make sure leading/trailing whitespace is removed (IE can't handle it)
550 data = jQuery.trim( data );
551
552 if ( data ) {
553 // Make sure the incoming data is actual JSON
554 // Logic borrowed from http://json.org/json2.js
555 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
556 .replace( rvalidtokens, "]" )
557 .replace( rvalidbraces, "")) ) {
558
559 return ( new Function( "return " + data ) )();
560 }
561 }
562 }
563
564 jQuery.error( "Invalid JSON: " + data );
565 },
566
567 // Cross-browser xml parsing
568 parseXML: function( data ) {
569 var xml, tmp;
570 if ( !data || typeof data !== "string" ) {
571 return null;
572 }
573 try {
574 if ( window.DOMParser ) { // Standard
575 tmp = new DOMParser();
576 xml = tmp.parseFromString( data , "text/xml" );
577 } else { // IE
578 xml = new ActiveXObject( "Microsoft.XMLDOM" );
579 xml.async = "false";
580 xml.loadXML( data );
581 }
582 } catch( e ) {
583 xml = undefined;
584 }
585 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
586 jQuery.error( "Invalid XML: " + data );
587 }
588 return xml;
589 },
590
591 noop: function() {},
592
593 // Evaluates a script in a global context
594 // Workarounds based on findings by Jim Driscoll
595 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
596 globalEval: function( data ) {
597 if ( data && jQuery.trim( data ) ) {
598 // We use execScript on Internet Explorer
599 // We use an anonymous function so that context is window
600 // rather than jQuery in Firefox
601 ( window.execScript || function( data ) {
602 window[ "eval" ].call( window, data );
603 } )( data );
604 }
605 },
606
607 // Convert dashed to camelCase; used by the css and data modules
608 // Microsoft forgot to hump their vendor prefix (#9572)
609 camelCase: function( string ) {
610 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
611 },
612
613 nodeName: function( elem, name ) {
614 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
615 },
616
617 // args is for internal usage only
618 each: function( obj, callback, args ) {
619 var value,
620 i = 0,
621 length = obj.length,
622 isArray = isArraylike( obj );
623
624 if ( args ) {
625 if ( isArray ) {
626 for ( ; i < length; i++ ) {
627 value = callback.apply( obj[ i ], args );
628
629 if ( value === false ) {
630 break;
631 }
632 }
633 } else {
634 for ( i in obj ) {
635 value = callback.apply( obj[ i ], args );
636
637 if ( value === false ) {
638 break;
639 }
640 }
641 }
642
643 // A special, fast, case for the most common use of each
644 } else {
645 if ( isArray ) {
646 for ( ; i < length; i++ ) {
647 value = callback.call( obj[ i ], i, obj[ i ] );
648
649 if ( value === false ) {
650 break;
651 }
652 }
653 } else {
654 for ( i in obj ) {
655 value = callback.call( obj[ i ], i, obj[ i ] );
656
657 if ( value === false ) {
658 break;
659 }
660 }
661 }
662 }
663
664 return obj;
665 },
666
667 // Use native String.trim function wherever possible
668 trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
669 function( text ) {
670 return text == null ?
671 "" :
672 core_trim.call( text );
673 } :
674
675 // Otherwise use our own trimming functionality
676 function( text ) {
677 return text == null ?
678 "" :
679 ( text + "" ).replace( rtrim, "" );
680 },
681
682 // results is for internal usage only
683 makeArray: function( arr, results ) {
684 var ret = results || [];
685
686 if ( arr != null ) {
687 if ( isArraylike( Object(arr) ) ) {
688 jQuery.merge( ret,
689 typeof arr === "string" ?
690 [ arr ] : arr
691 );
692 } else {
693 core_push.call( ret, arr );
694 }
695 }
696
697 return ret;
698 },
699
700 inArray: function( elem, arr, i ) {
701 var len;
702
703 if ( arr ) {
704 if ( core_indexOf ) {
705 return core_indexOf.call( arr, elem, i );
706 }
707
708 len = arr.length;
709 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
710
711 for ( ; i < len; i++ ) {
712 // Skip accessing in sparse arrays
713 if ( i in arr && arr[ i ] === elem ) {
714 return i;
715 }
716 }
717 }
718
719 return -1;
720 },
721
722 merge: function( first, second ) {
723 var l = second.length,
724 i = first.length,
725 j = 0;
726
727 if ( typeof l === "number" ) {
728 for ( ; j < l; j++ ) {
729 first[ i++ ] = second[ j ];
730 }
731 } else {
732 while ( second[j] !== undefined ) {
733 first[ i++ ] = second[ j++ ];
734 }
735 }
736
737 first.length = i;
738
739 return first;
740 },
741
742 grep: function( elems, callback, inv ) {
743 var retVal,
744 ret = [],
745 i = 0,
746 length = elems.length;
747 inv = !!inv;
748
749 // Go through the array, only saving the items
750 // that pass the validator function
751 for ( ; i < length; i++ ) {
752 retVal = !!callback( elems[ i ], i );
753 if ( inv !== retVal ) {
754 ret.push( elems[ i ] );
755 }
756 }
757
758 return ret;
759 },
760
761 // arg is for internal usage only
762 map: function( elems, callback, arg ) {
763 var value,
764 i = 0,
765 length = elems.length,
766 isArray = isArraylike( elems ),
767 ret = [];
768
769 // Go through the array, translating each of the items to their
770 if ( isArray ) {
771 for ( ; i < length; i++ ) {
772 value = callback( elems[ i ], i, arg );
773
774 if ( value != null ) {
775 ret[ ret.length ] = value;
776 }
777 }
778
779 // Go through every key on the object,
780 } else {
781 for ( i in elems ) {
782 value = callback( elems[ i ], i, arg );
783
784 if ( value != null ) {
785 ret[ ret.length ] = value;
786 }
787 }
788 }
789
790 // Flatten any nested arrays
791 return core_concat.apply( [], ret );
792 },
793
794 // A global GUID counter for objects
795 guid: 1,
796
797 // Bind a function to a context, optionally partially applying any
798 // arguments.
799 proxy: function( fn, context ) {
800 var args, proxy, tmp;
801
802 if ( typeof context === "string" ) {
803 tmp = fn[ context ];
804 context = fn;
805 fn = tmp;
806 }
807
808 // Quick check to determine if target is callable, in the spec
809 // this throws a TypeError, but we will just return undefined.
810 if ( !jQuery.isFunction( fn ) ) {
811 return undefined;
812 }
813
814 // Simulated bind
815 args = core_slice.call( arguments, 2 );
816 proxy = function() {
817 return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
818 };
819
820 // Set the guid of unique handler to the same of original handler, so it can be removed
821 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
822
823 return proxy;
824 },
825
826 // Multifunctional method to get and set values of a collection
827 // The value/s can optionally be executed if it's a function
828 access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
829 var i = 0,
830 length = elems.length,
831 bulk = key == null;
832
833 // Sets many values
834 if ( jQuery.type( key ) === "object" ) {
835 chainable = true;
836 for ( i in key ) {
837 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
838 }
839
840 // Sets one value
841 } else if ( value !== undefined ) {
842 chainable = true;
843
844 if ( !jQuery.isFunction( value ) ) {
845 raw = true;
846 }
847
848 if ( bulk ) {
849 // Bulk operations run against the entire set
850 if ( raw ) {
851 fn.call( elems, value );
852 fn = null;
853
854 // ...except when executing function values
855 } else {
856 bulk = fn;
857 fn = function( elem, key, value ) {
858 return bulk.call( jQuery( elem ), value );
859 };
860 }
861 }
862
863 if ( fn ) {
864 for ( ; i < length; i++ ) {
865 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
866 }
867 }
868 }
869
870 return chainable ?
871 elems :
872
873 // Gets
874 bulk ?
875 fn.call( elems ) :
876 length ? fn( elems[0], key ) : emptyGet;
877 },
878
879 now: function() {
880 return ( new Date() ).getTime();
881 }
882 });
883
884 jQuery.ready.promise = function( obj ) {
885 if ( !readyList ) {
886
887 readyList = jQuery.Deferred();
888
889 // Catch cases where $(document).ready() is called after the browser event has already occurred.
890 // we once tried to use readyState "interactive" here, but it caused issues like the one
891 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
892 if ( document.readyState === "complete" ) {
893 // Handle it asynchronously to allow scripts the opportunity to delay ready
894 setTimeout( jQuery.ready );
895
896 // Standards-based browsers support DOMContentLoaded
897 } else if ( document.addEventListener ) {
898 // Use the handy event callback
899 document.addEventListener( "DOMContentLoaded", completed, false );
900
901 // A fallback to window.onload, that will always work
902 window.addEventListener( "load", completed, false );
903
904 // If IE event model is used
905 } else {
906 // Ensure firing before onload, maybe late but safe also for iframes
907 document.attachEvent( "onreadystatechange", completed );
908
909 // A fallback to window.onload, that will always work
910 window.attachEvent( "onload", completed );
911
912 // If IE and not a frame
913 // continually check to see if the document is ready
914 var top = false;
915
916 try {
917 top = window.frameElement == null && document.documentElement;
918 } catch(e) {}
919
920 if ( top && top.doScroll ) {
921 (function doScrollCheck() {
922 if ( !jQuery.isReady ) {
923
924 try {
925 // Use the trick by Diego Perini
926 // http://javascript.nwbox.com/IEContentLoaded/
927 top.doScroll("left");
928 } catch(e) {
929 return setTimeout( doScrollCheck, 50 );
930 }
931
932 // detach all dom ready events
933 detach();
934
935 // and execute any waiting functions
936 jQuery.ready();
937 }
938 })();
939 }
940 }
941 }
942 return readyList.promise( obj );
943 };
944
945 // Populate the class2type map
946 jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
947 class2type[ "[object " + name + "]" ] = name.toLowerCase();
948 });
949
950 function isArraylike( obj ) {
951 var length = obj.length,
952 type = jQuery.type( obj );
953
954 if ( jQuery.isWindow( obj ) ) {
955 return false;
956 }
957
958 if ( obj.nodeType === 1 && length ) {
959 return true;
960 }
961
962 return type === "array" || type !== "function" &&
963 ( length === 0 ||
964 typeof length === "number" && length > 0 && ( length - 1 ) in obj );
965 }
966
967 // All jQuery objects should point back to these
968 rootjQuery = jQuery(document);
969 // String to Object options format cache
970 var optionsCache = {};
971
972 // Convert String-formatted options into Object-formatted ones and store in cache
973 function createOptions( options ) {
974 var object = optionsCache[ options ] = {};
975 jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
976 object[ flag ] = true;
977 });
978 return object;
979 }
980
981 /*
982 * Create a callback list using the following parameters:
983 *
984 * options: an optional list of space-separated options that will change how
985 * the callback list behaves or a more traditional option object
986 *
987 * By default a callback list will act like an event callback list and can be
988 * "fired" multiple times.
989 *
990 * Possible options:
991 *
992 * once: will ensure the callback list can only be fired once (like a Deferred)
993 *
994 * memory: will keep track of previous values and will call any callback added
995 * after the list has been fired right away with the latest "memorized"
996 * values (like a Deferred)
997 *
998 * unique: will ensure a callback can only be added once (no duplicate in the list)
999 *
1000 * stopOnFalse: interrupt callings when a callback returns false
1001 *
1002 */
1003 jQuery.Callbacks = function( options ) {
1004
1005 // Convert options from String-formatted to Object-formatted if needed
1006 // (we check in cache first)
1007 options = typeof options === "string" ?
1008 ( optionsCache[ options ] || createOptions( options ) ) :
1009 jQuery.extend( {}, options );
1010
1011 var // Flag to know if list is currently firing
1012 firing,
1013 // Last fire value (for non-forgettable lists)
1014 memory,
1015 // Flag to know if list was already fired
1016 fired,
1017 // End of the loop when firing
1018 firingLength,
1019 // Index of currently firing callback (modified by remove if needed)
1020 firingIndex,
1021 // First callback to fire (used internally by add and fireWith)
1022 firingStart,
1023 // Actual callback list
1024 list = [],
1025 // Stack of fire calls for repeatable lists
1026 stack = !options.once && [],
1027 // Fire callbacks
1028 fire = function( data ) {
1029 memory = options.memory && data;
1030 fired = true;
1031 firingIndex = firingStart || 0;
1032 firingStart = 0;
1033 firingLength = list.length;
1034 firing = true;
1035 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
1036 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
1037 memory = false; // To prevent further calls using add
1038 break;
1039 }
1040 }
1041 firing = false;
1042 if ( list ) {
1043 if ( stack ) {
1044 if ( stack.length ) {
1045 fire( stack.shift() );
1046 }
1047 } else if ( memory ) {
1048 list = [];
1049 } else {
1050 self.disable();
1051 }
1052 }
1053 },
1054 // Actual Callbacks object
1055 self = {
1056 // Add a callback or a collection of callbacks to the list
1057 add: function() {
1058 if ( list ) {
1059 // First, we save the current length
1060 var start = list.length;
1061 (function add( args ) {
1062 jQuery.each( args, function( _, arg ) {
1063 var type = jQuery.type( arg );
1064 if ( type === "function" ) {
1065 if ( !options.unique || !self.has( arg ) ) {
1066 list.push( arg );
1067 }
1068 } else if ( arg && arg.length && type !== "string" ) {
1069 // Inspect recursively
1070 add( arg );
1071 }
1072 });
1073 })( arguments );
1074 // Do we need to add the callbacks to the
1075 // current firing batch?
1076 if ( firing ) {
1077 firingLength = list.length;
1078 // With memory, if we're not firing then
1079 // we should call right away
1080 } else if ( memory ) {
1081 firingStart = start;
1082 fire( memory );
1083 }
1084 }
1085 return this;
1086 },
1087 // Remove a callback from the list
1088 remove: function() {
1089 if ( list ) {
1090 jQuery.each( arguments, function( _, arg ) {
1091 var index;
1092 while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1093 list.splice( index, 1 );
1094 // Handle firing indexes
1095 if ( firing ) {
1096 if ( index <= firingLength ) {
1097 firingLength--;
1098 }
1099 if ( index <= firingIndex ) {
1100 firingIndex--;
1101 }
1102 }
1103 }
1104 });
1105 }
1106 return this;
1107 },
1108 // Check if a given callback is in the list.
1109 // If no argument is given, return whether or not list has callbacks attached.
1110 has: function( fn ) {
1111 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
1112 },
1113 // Remove all callbacks from the list
1114 empty: function() {
1115 list = [];
1116 return this;
1117 },
1118 // Have the list do nothing anymore
1119 disable: function() {
1120 list = stack = memory = undefined;
1121 return this;
1122 },
1123 // Is it disabled?
1124 disabled: function() {
1125 return !list;
1126 },
1127 // Lock the list in its current state
1128 lock: function() {
1129 stack = undefined;
1130 if ( !memory ) {
1131 self.disable();
1132 }
1133 return this;
1134 },
1135 // Is it locked?
1136 locked: function() {
1137 return !stack;
1138 },
1139 // Call all callbacks with the given context and arguments
1140 fireWith: function( context, args ) {
1141 args = args || [];
1142 args = [ context, args.slice ? args.slice() : args ];
1143 if ( list && ( !fired || stack ) ) {
1144 if ( firing ) {
1145 stack.push( args );
1146 } else {
1147 fire( args );
1148 }
1149 }
1150 return this;
1151 },
1152 // Call all the callbacks with the given arguments
1153 fire: function() {
1154 self.fireWith( this, arguments );
1155 return this;
1156 },
1157 // To know if the callbacks have already been called at least once
1158 fired: function() {
1159 return !!fired;
1160 }
1161 };
1162
1163 return self;
1164 };
1165 jQuery.extend({
1166
1167 Deferred: function( func ) {
1168 var tuples = [
1169 // action, add listener, listener list, final state
1170 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1171 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1172 [ "notify", "progress", jQuery.Callbacks("memory") ]
1173 ],
1174 state = "pending",
1175 promise = {
1176 state: function() {
1177 return state;
1178 },
1179 always: function() {
1180 deferred.done( arguments ).fail( arguments );
1181 return this;
1182 },
1183 then: function( /* fnDone, fnFail, fnProgress */ ) {
1184 var fns = arguments;
1185 return jQuery.Deferred(function( newDefer ) {
1186 jQuery.each( tuples, function( i, tuple ) {
1187 var action = tuple[ 0 ],
1188 fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
1189 // deferred[ done | fail | progress ] for forwarding actions to newDefer
1190 deferred[ tuple[1] ](function() {
1191 var returned = fn && fn.apply( this, arguments );
1192 if ( returned && jQuery.isFunction( returned.promise ) ) {
1193 returned.promise()
1194 .done( newDefer.resolve )
1195 .fail( newDefer.reject )
1196 .progress( newDefer.notify );
1197 } else {
1198 newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
1199 }
1200 });
1201 });
1202 fns = null;
1203 }).promise();
1204 },
1205 // Get a promise for this deferred
1206 // If obj is provided, the promise aspect is added to the object
1207 promise: function( obj ) {
1208 return obj != null ? jQuery.extend( obj, promise ) : promise;
1209 }
1210 },
1211 deferred = {};
1212
1213 // Keep pipe for back-compat
1214 promise.pipe = promise.then;
1215
1216 // Add list-specific methods
1217 jQuery.each( tuples, function( i, tuple ) {
1218 var list = tuple[ 2 ],
1219 stateString = tuple[ 3 ];
1220
1221 // promise[ done | fail | progress ] = list.add
1222 promise[ tuple[1] ] = list.add;
1223
1224 // Handle state
1225 if ( stateString ) {
1226 list.add(function() {
1227 // state = [ resolved | rejected ]
1228 state = stateString;
1229
1230 // [ reject_list | resolve_list ].disable; progress_list.lock
1231 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1232 }
1233
1234 // deferred[ resolve | reject | notify ]
1235 deferred[ tuple[0] ] = function() {
1236 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
1237 return this;
1238 };
1239 deferred[ tuple[0] + "With" ] = list.fireWith;
1240 });
1241
1242 // Make the deferred a promise
1243 promise.promise( deferred );
1244
1245 // Call given func if any
1246 if ( func ) {
1247 func.call( deferred, deferred );
1248 }
1249
1250 // All done!
1251 return deferred;
1252 },
1253
1254 // Deferred helper
1255 when: function( subordinate /* , ..., subordinateN */ ) {
1256 var i = 0,
1257 resolveValues = core_slice.call( arguments ),
1258 length = resolveValues.length,
1259
1260 // the count of uncompleted subordinates
1261 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1262
1263 // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1264 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1265
1266 // Update function for both resolve and progress values
1267 updateFunc = function( i, contexts, values ) {
1268 return function( value ) {
1269 contexts[ i ] = this;
1270 values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1271 if( values === progressValues ) {
1272 deferred.notifyWith( contexts, values );
1273 } else if ( !( --remaining ) ) {
1274 deferred.resolveWith( contexts, values );
1275 }
1276 };
1277 },
1278
1279 progressValues, progressContexts, resolveContexts;
1280
1281 // add listeners to Deferred subordinates; treat others as resolved
1282 if ( length > 1 ) {
1283 progressValues = new Array( length );
1284 progressContexts = new Array( length );
1285 resolveContexts = new Array( length );
1286 for ( ; i < length; i++ ) {
1287 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1288 resolveValues[ i ].promise()
1289 .done( updateFunc( i, resolveContexts, resolveValues ) )
1290 .fail( deferred.reject )
1291 .progress( updateFunc( i, progressContexts, progressValues ) );
1292 } else {
1293 --remaining;
1294 }
1295 }
1296 }
1297
1298 // if we're not waiting on anything, resolve the master
1299 if ( !remaining ) {
1300 deferred.resolveWith( resolveContexts, resolveValues );
1301 }
1302
1303 return deferred.promise();
1304 }
1305 });
1306 jQuery.support = (function() {
1307
1308 var support, all, a,
1309 input, select, fragment,
1310 opt, eventName, isSupported, i,
1311 div = document.createElement("div");
1312
1313 // Setup
1314 div.setAttribute( "className", "t" );
1315 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1316
1317 // Support tests won't run in some limited or non-browser environments
1318 all = div.getElementsByTagName("*");
1319 a = div.getElementsByTagName("a")[ 0 ];
1320 if ( !all || !a || !all.length ) {
1321 return {};
1322 }
1323
1324 // First batch of tests
1325 select = document.createElement("select");
1326 opt = select.appendChild( document.createElement("option") );
1327 input = div.getElementsByTagName("input")[ 0 ];
1328
1329 a.style.cssText = "top:1px;float:left;opacity:.5";
1330 support = {
1331 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1332 getSetAttribute: div.className !== "t",
1333
1334 // IE strips leading whitespace when .innerHTML is used
1335 leadingWhitespace: div.firstChild.nodeType === 3,
1336
1337 // Make sure that tbody elements aren't automatically inserted
1338 // IE will insert them into empty tables
1339 tbody: !div.getElementsByTagName("tbody").length,
1340
1341 // Make sure that link elements get serialized correctly by innerHTML
1342 // This requires a wrapper element in IE
1343 htmlSerialize: !!div.getElementsByTagName("link").length,
1344
1345 // Get the style information from getAttribute
1346 // (IE uses .cssText instead)
1347 style: /top/.test( a.getAttribute("style") ),
1348
1349 // Make sure that URLs aren't manipulated
1350 // (IE normalizes it by default)
1351 hrefNormalized: a.getAttribute("href") === "/a",
1352
1353 // Make sure that element opacity exists
1354 // (IE uses filter instead)
1355 // Use a regex to work around a WebKit issue. See #5145
1356 opacity: /^0.5/.test( a.style.opacity ),
1357
1358 // Verify style float existence
1359 // (IE uses styleFloat instead of cssFloat)
1360 cssFloat: !!a.style.cssFloat,
1361
1362 // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
1363 checkOn: !!input.value,
1364
1365 // Make sure that a selected-by-default option has a working selected property.
1366 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1367 optSelected: opt.selected,
1368
1369 // Tests for enctype support on a form (#6743)
1370 enctype: !!document.createElement("form").enctype,
1371
1372 // Makes sure cloning an html5 element does not cause problems
1373 // Where outerHTML is undefined, this still works
1374 html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1375
1376 // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1377 boxModel: document.compatMode === "CSS1Compat",
1378
1379 // Will be defined later
1380 deleteExpando: true,
1381 noCloneEvent: true,
1382 inlineBlockNeedsLayout: false,
1383 shrinkWrapBlocks: false,
1384 reliableMarginRight: true,
1385 boxSizingReliable: true,
1386 pixelPosition: false
1387 };
1388
1389 // Make sure checked status is properly cloned
1390 input.checked = true;
1391 support.noCloneChecked = input.cloneNode( true ).checked;
1392
1393 // Make sure that the options inside disabled selects aren't marked as disabled
1394 // (WebKit marks them as disabled)
1395 select.disabled = true;
1396 support.optDisabled = !opt.disabled;
1397
1398 // Support: IE<9
1399 try {
1400 delete div.test;
1401 } catch( e ) {
1402 support.deleteExpando = false;
1403 }
1404
1405 // Check if we can trust getAttribute("value")
1406 input = document.createElement("input");
1407 input.setAttribute( "value", "" );
1408 support.input = input.getAttribute( "value" ) === "";
1409
1410 // Check if an input maintains its value after becoming a radio
1411 input.value = "t";
1412 input.setAttribute( "type", "radio" );
1413 support.radioValue = input.value === "t";
1414
1415 // #11217 - WebKit loses check when the name is after the checked attribute
1416 input.setAttribute( "checked", "t" );
1417 input.setAttribute( "name", "t" );
1418
1419 fragment = document.createDocumentFragment();
1420 fragment.appendChild( input );
1421
1422 // Check if a disconnected checkbox will retain its checked
1423 // value of true after appended to the DOM (IE6/7)
1424 support.appendChecked = input.checked;
1425
1426 // WebKit doesn't clone checked state correctly in fragments
1427 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1428
1429 // Support: IE<9
1430 // Opera does not clone events (and typeof div.attachEvent === undefined).
1431 // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
1432 if ( div.attachEvent ) {
1433 div.attachEvent( "onclick", function() {
1434 support.noCloneEvent = false;
1435 });
1436
1437 div.cloneNode( true ).click();
1438 }
1439
1440 // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
1441 // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
1442 for ( i in { submit: true, change: true, focusin: true }) {
1443 div.setAttribute( eventName = "on" + i, "t" );
1444
1445 support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
1446 }
1447
1448 div.style.backgroundClip = "content-box";
1449 div.cloneNode( true ).style.backgroundClip = "";
1450 support.clearCloneStyle = div.style.backgroundClip === "content-box";
1451
1452 // Run tests that need a body at doc ready
1453 jQuery(function() {
1454 var container, marginDiv, tds,
1455 divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
1456 body = document.getElementsByTagName("body")[0];
1457
1458 if ( !body ) {
1459 // Return for frameset docs that don't have a body
1460 return;
1461 }
1462
1463 container = document.createElement("div");
1464 container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
1465
1466 body.appendChild( container ).appendChild( div );
1467
1468 // Support: IE8
1469 // Check if table cells still have offsetWidth/Height when they are set
1470 // to display:none and there are still other visible table cells in a
1471 // table row; if so, offsetWidth/Height are not reliable for use when
1472 // determining if an element has been hidden directly using
1473 // display:none (it is still safe to use offsets if a parent element is
1474 // hidden; don safety goggles and see bug #4512 for more information).
1475 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1476 tds = div.getElementsByTagName("td");
1477 tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1478 isSupported = ( tds[ 0 ].offsetHeight === 0 );
1479
1480 tds[ 0 ].style.display = "";
1481 tds[ 1 ].style.display = "none";
1482
1483 // Support: IE8
1484 // Check if empty table cells still have offsetWidth/Height
1485 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1486
1487 // Check box-sizing and margin behavior
1488 div.innerHTML = "";
1489 div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
1490 support.boxSizing = ( div.offsetWidth === 4 );
1491 support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1492
1493 // Use window.getComputedStyle because jsdom on node.js will break without it.
1494 if ( window.getComputedStyle ) {
1495 support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1496 support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
1497
1498 // Check if div with explicit width and no margin-right incorrectly
1499 // gets computed margin-right based on width of container. (#3333)
1500 // Fails in WebKit before Feb 2011 nightlies
1501 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1502 marginDiv = div.appendChild( document.createElement("div") );
1503 marginDiv.style.cssText = div.style.cssText = divReset;
1504 marginDiv.style.marginRight = marginDiv.style.width = "0";
1505 div.style.width = "1px";
1506
1507 support.reliableMarginRight =
1508 !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
1509 }
1510
1511 if ( typeof div.style.zoom !== core_strundefined ) {
1512 // Support: IE<8
1513 // Check if natively block-level elements act like inline-block
1514 // elements when setting their display to 'inline' and giving
1515 // them layout
1516 div.innerHTML = "";
1517 div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
1518 support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
1519
1520 // Support: IE6
1521 // Check if elements with layout shrink-wrap their children
1522 div.style.display = "block";
1523 div.innerHTML = "<div></div>";
1524 div.firstChild.style.width = "5px";
1525 support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
1526
1527 if ( support.inlineBlockNeedsLayout ) {
1528 // Prevent IE 6 from affecting layout for positioned elements #11048
1529 // Prevent IE from shrinking the body in IE 7 mode #12869
1530 // Support: IE<8
1531 body.style.zoom = 1;
1532 }
1533 }
1534
1535 body.removeChild( container );
1536
1537 // Null elements to avoid leaks in IE
1538 container = div = tds = marginDiv = null;
1539 });
1540
1541 // Null elements to avoid leaks in IE
1542 all = select = fragment = opt = a = input = null;
1543
1544 return support;
1545 })();
1546
1547 var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
1548 rmultiDash = /([A-Z])/g;
1549
1550 function internalData( elem, name, data, pvt /* Internal Use Only */ ){
1551 if ( !jQuery.acceptData( elem ) ) {
1552 return;
1553 }
1554
1555 var thisCache, ret,
1556 internalKey = jQuery.expando,
1557 getByName = typeof name === "string",
1558
1559 // We have to handle DOM nodes and JS objects differently because IE6-7
1560 // can't GC object references properly across the DOM-JS boundary
1561 isNode = elem.nodeType,
1562
1563 // Only DOM nodes need the global jQuery cache; JS object data is
1564 // attached directly to the object so GC can occur automatically
1565 cache = isNode ? jQuery.cache : elem,
1566
1567 // Only defining an ID for JS objects if its cache already exists allows
1568 // the code to shortcut on the same path as a DOM node with no cache
1569 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
1570
1571 // Avoid doing any more work than we need to when trying to get data on an
1572 // object that has no data at all
1573 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
1574 return;
1575 }
1576
1577 if ( !id ) {
1578 // Only DOM nodes need a new unique ID for each element since their data
1579 // ends up in the global cache
1580 if ( isNode ) {
1581 elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
1582 } else {
1583 id = internalKey;
1584 }
1585 }
1586
1587 if ( !cache[ id ] ) {
1588 cache[ id ] = {};
1589
1590 // Avoids exposing jQuery metadata on plain JS objects when the object
1591 // is serialized using JSON.stringify
1592 if ( !isNode ) {
1593 cache[ id ].toJSON = jQuery.noop;
1594 }
1595 }
1596
1597 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1598 // shallow copied over onto the existing cache
1599 if ( typeof name === "object" || typeof name === "function" ) {
1600 if ( pvt ) {
1601 cache[ id ] = jQuery.extend( cache[ id ], name );
1602 } else {
1603 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1604 }
1605 }
1606
1607 thisCache = cache[ id ];
1608
1609 // jQuery data() is stored in a separate object inside the object's internal data
1610 // cache in order to avoid key collisions between internal data and user-defined
1611 // data.
1612 if ( !pvt ) {
1613 if ( !thisCache.data ) {
1614 thisCache.data = {};
1615 }
1616
1617 thisCache = thisCache.data;
1618 }
1619
1620 if ( data !== undefined ) {
1621 thisCache[ jQuery.camelCase( name ) ] = data;
1622 }
1623
1624 // Check for both converted-to-camel and non-converted data property names
1625 // If a data property was specified
1626 if ( getByName ) {
1627
1628 // First Try to find as-is property data
1629 ret = thisCache[ name ];
1630
1631 // Test for null|undefined property data
1632 if ( ret == null ) {
1633
1634 // Try to find the camelCased property
1635 ret = thisCache[ jQuery.camelCase( name ) ];
1636 }
1637 } else {
1638 ret = thisCache;
1639 }
1640
1641 return ret;
1642 }
1643
1644 function internalRemoveData( elem, name, pvt ) {
1645 if ( !jQuery.acceptData( elem ) ) {
1646 return;
1647 }
1648
1649 var i, l, thisCache,
1650 isNode = elem.nodeType,
1651
1652 // See jQuery.data for more information
1653 cache = isNode ? jQuery.cache : elem,
1654 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1655
1656 // If there is already no cache entry for this object, there is no
1657 // purpose in continuing
1658 if ( !cache[ id ] ) {
1659 return;
1660 }
1661
1662 if ( name ) {
1663
1664 thisCache = pvt ? cache[ id ] : cache[ id ].data;
1665
1666 if ( thisCache ) {
1667
1668 // Support array or space separated string names for data keys
1669 if ( !jQuery.isArray( name ) ) {
1670
1671 // try the string as a key before any manipulation
1672 if ( name in thisCache ) {
1673 name = [ name ];
1674 } else {
1675
1676 // split the camel cased version by spaces unless a key with the spaces exists
1677 name = jQuery.camelCase( name );
1678 if ( name in thisCache ) {
1679 name = [ name ];
1680 } else {
1681 name = name.split(" ");
1682 }
1683 }
1684 } else {
1685 // If "name" is an array of keys...
1686 // When data is initially created, via ("key", "val") signature,
1687 // keys will be converted to camelCase.
1688 // Since there is no way to tell _how_ a key was added, remove
1689 // both plain key and camelCase key. #12786
1690 // This will only penalize the array argument path.
1691 name = name.concat( jQuery.map( name, jQuery.camelCase ) );
1692 }
1693
1694 for ( i = 0, l = name.length; i < l; i++ ) {
1695 delete thisCache[ name[i] ];
1696 }
1697
1698 // If there is no data left in the cache, we want to continue
1699 // and let the cache object itself get destroyed
1700 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1701 return;
1702 }
1703 }
1704 }
1705
1706 // See jQuery.data for more information
1707 if ( !pvt ) {
1708 delete cache[ id ].data;
1709
1710 // Don't destroy the parent cache unless the internal data object
1711 // had been the only thing left in it
1712 if ( !isEmptyDataObject( cache[ id ] ) ) {
1713 return;
1714 }
1715 }
1716
1717 // Destroy the cache
1718 if ( isNode ) {
1719 jQuery.cleanData( [ elem ], true );
1720
1721 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
1722 } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
1723 delete cache[ id ];
1724
1725 // When all else fails, null
1726 } else {
1727 cache[ id ] = null;
1728 }
1729 }
1730
1731 jQuery.extend({
1732 cache: {},
1733
1734 // Unique for each copy of jQuery on the page
1735 // Non-digits removed to match rinlinejQuery
1736 expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
1737
1738 // The following elements throw uncatchable exceptions if you
1739 // attempt to add expando properties to them.
1740 noData: {
1741 "embed": true,
1742 // Ban all objects except for Flash (which handle expandos)
1743 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1744 "applet": true
1745 },
1746
1747 hasData: function( elem ) {
1748 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1749 return !!elem && !isEmptyDataObject( elem );
1750 },
1751
1752 data: function( elem, name, data ) {
1753 return internalData( elem, name, data );
1754 },
1755
1756 removeData: function( elem, name ) {
1757 return internalRemoveData( elem, name );
1758 },
1759
1760 // For internal use only.
1761 _data: function( elem, name, data ) {
1762 return internalData( elem, name, data, true );
1763 },
1764
1765 _removeData: function( elem, name ) {
1766 return internalRemoveData( elem, name, true );
1767 },
1768
1769 // A method for determining if a DOM node can handle the data expando
1770 acceptData: function( elem ) {
1771 // Do not set data on non-element because it will not be cleared (#8335).
1772 if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
1773 return false;
1774 }
1775
1776 var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
1777
1778 // nodes accept data unless otherwise specified; rejection can be conditional
1779 return !noData || noData !== true && elem.getAttribute("classid") === noData;
1780 }
1781 });
1782
1783 jQuery.fn.extend({
1784 data: function( key, value ) {
1785 var attrs, name,
1786 elem = this[0],
1787 i = 0,
1788 data = null;
1789
1790 // Gets all values
1791 if ( key === undefined ) {
1792 if ( this.length ) {
1793 data = jQuery.data( elem );
1794
1795 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
1796 attrs = elem.attributes;
1797 for ( ; i < attrs.length; i++ ) {
1798 name = attrs[i].name;
1799
1800 if ( !name.indexOf( "data-" ) ) {
1801 name = jQuery.camelCase( name.slice(5) );
1802
1803 dataAttr( elem, name, data[ name ] );
1804 }
1805 }
1806 jQuery._data( elem, "parsedAttrs", true );
1807 }
1808 }
1809
1810 return data;
1811 }
1812
1813 // Sets multiple values
1814 if ( typeof key === "object" ) {
1815 return this.each(function() {
1816 jQuery.data( this, key );
1817 });
1818 }
1819
1820 return jQuery.access( this, function( value ) {
1821
1822 if ( value === undefined ) {
1823 // Try to fetch any internally stored data first
1824 return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
1825 }
1826
1827 this.each(function() {
1828 jQuery.data( this, key, value );
1829 });
1830 }, null, value, arguments.length > 1, null, true );
1831 },
1832
1833 removeData: function( key ) {
1834 return this.each(function() {
1835 jQuery.removeData( this, key );
1836 });
1837 }
1838 });
1839
1840 function dataAttr( elem, key, data ) {
1841 // If nothing was found internally, try to fetch any
1842 // data from the HTML5 data-* attribute
1843 if ( data === undefined && elem.nodeType === 1 ) {
1844
1845 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1846
1847 data = elem.getAttribute( name );
1848
1849 if ( typeof data === "string" ) {
1850 try {
1851 data = data === "true" ? true :
1852 data === "false" ? false :
1853 data === "null" ? null :
1854 // Only convert to a number if it doesn't change the string
1855 +data + "" === data ? +data :
1856 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1857 data;
1858 } catch( e ) {}
1859
1860 // Make sure we set the data so it isn't changed later
1861 jQuery.data( elem, key, data );
1862
1863 } else {
1864 data = undefined;
1865 }
1866 }
1867
1868 return data;
1869 }
1870
1871 // checks a cache object for emptiness
1872 function isEmptyDataObject( obj ) {
1873 var name;
1874 for ( name in obj ) {
1875
1876 // if the public data object is empty, the private is still empty
1877 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1878 continue;
1879 }
1880 if ( name !== "toJSON" ) {
1881 return false;
1882 }
1883 }
1884
1885 return true;
1886 }
1887 jQuery.extend({
1888 queue: function( elem, type, data ) {
1889 var queue;
1890
1891 if ( elem ) {
1892 type = ( type || "fx" ) + "queue";
1893 queue = jQuery._data( elem, type );
1894
1895 // Speed up dequeue by getting out quickly if this is just a lookup
1896 if ( data ) {
1897 if ( !queue || jQuery.isArray(data) ) {
1898 queue = jQuery._data( elem, type, jQuery.makeArray(data) );
1899 } else {
1900 queue.push( data );
1901 }
1902 }
1903 return queue || [];
1904 }
1905 },
1906
1907 dequeue: function( elem, type ) {
1908 type = type || "fx";
1909
1910 var queue = jQuery.queue( elem, type ),
1911 startLength = queue.length,
1912 fn = queue.shift(),
1913 hooks = jQuery._queueHooks( elem, type ),
1914 next = function() {
1915 jQuery.dequeue( elem, type );
1916 };
1917
1918 // If the fx queue is dequeued, always remove the progress sentinel
1919 if ( fn === "inprogress" ) {
1920 fn = queue.shift();
1921 startLength--;
1922 }
1923
1924 hooks.cur = fn;
1925 if ( fn ) {
1926
1927 // Add a progress sentinel to prevent the fx queue from being
1928 // automatically dequeued
1929 if ( type === "fx" ) {
1930 queue.unshift( "inprogress" );
1931 }
1932
1933 // clear up the last queue stop function
1934 delete hooks.stop;
1935 fn.call( elem, next, hooks );
1936 }
1937
1938 if ( !startLength && hooks ) {
1939 hooks.empty.fire();
1940 }
1941 },
1942
1943 // not intended for public consumption - generates a queueHooks object, or returns the current one
1944 _queueHooks: function( elem, type ) {
1945 var key = type + "queueHooks";
1946 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
1947 empty: jQuery.Callbacks("once memory").add(function() {
1948 jQuery._removeData( elem, type + "queue" );
1949 jQuery._removeData( elem, key );
1950 })
1951 });
1952 }
1953 });
1954
1955 jQuery.fn.extend({
1956 queue: function( type, data ) {
1957 var setter = 2;
1958
1959 if ( typeof type !== "string" ) {
1960 data = type;
1961 type = "fx";
1962 setter--;
1963 }
1964
1965 if ( arguments.length < setter ) {
1966 return jQuery.queue( this[0], type );
1967 }
1968
1969 return data === undefined ?
1970 this :
1971 this.each(function() {
1972 var queue = jQuery.queue( this, type, data );
1973
1974 // ensure a hooks for this queue
1975 jQuery._queueHooks( this, type );
1976
1977 if ( type === "fx" && queue[0] !== "inprogress" ) {
1978 jQuery.dequeue( this, type );
1979 }
1980 });
1981 },
1982 dequeue: function( type ) {
1983 return this.each(function() {
1984 jQuery.dequeue( this, type );
1985 });
1986 },
1987 // Based off of the plugin by Clint Helfers, with permission.
1988 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1989 delay: function( time, type ) {
1990 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
1991 type = type || "fx";
1992
1993 return this.queue( type, function( next, hooks ) {
1994 var timeout = setTimeout( next, time );
1995 hooks.stop = function() {
1996 clearTimeout( timeout );
1997 };
1998 });
1999 },
2000 clearQueue: function( type ) {
2001 return this.queue( type || "fx", [] );
2002 },
2003 // Get a promise resolved when queues of a certain type
2004 // are emptied (fx is the type by default)
2005 promise: function( type, obj ) {
2006 var tmp,
2007 count = 1,
2008 defer = jQuery.Deferred(),
2009 elements = this,
2010 i = this.length,
2011 resolve = function() {
2012 if ( !( --count ) ) {
2013 defer.resolveWith( elements, [ elements ] );
2014 }
2015 };
2016
2017 if ( typeof type !== "string" ) {
2018 obj = type;
2019 type = undefined;
2020 }
2021 type = type || "fx";
2022
2023 while( i-- ) {
2024 tmp = jQuery._data( elements[ i ], type + "queueHooks" );
2025 if ( tmp && tmp.empty ) {
2026 count++;
2027 tmp.empty.add( resolve );
2028 }
2029 }
2030 resolve();
2031 return defer.promise( obj );
2032 }
2033 });
2034 var nodeHook, boolHook,
2035 rclass = /[\t\r\n]/g,
2036 rreturn = /\r/g,
2037 rfocusable = /^(?:input|select|textarea|button|object)$/i,
2038 rclickable = /^(?:a|area)$/i,
2039 rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
2040 ruseDefault = /^(?:checked|selected)$/i,
2041 getSetAttribute = jQuery.support.getSetAttribute,
2042 getSetInput = jQuery.support.input;
2043
2044 jQuery.fn.extend({
2045 attr: function( name, value ) {
2046 return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
2047 },
2048
2049 removeAttr: function( name ) {
2050 return this.each(function() {
2051 jQuery.removeAttr( this, name );
2052 });
2053 },
2054
2055 prop: function( name, value ) {
2056 return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2057 },
2058
2059 removeProp: function( name ) {
2060 name = jQuery.propFix[ name ] || name;
2061 return this.each(function() {
2062 // try/catch handles cases where IE balks (such as removing a property on window)
2063 try {
2064 this[ name ] = undefined;
2065 delete this[ name ];
2066 } catch( e ) {}
2067 });
2068 },
2069
2070 addClass: function( value ) {
2071 var classes, elem, cur, clazz, j,
2072 i = 0,
2073 len = this.length,
2074 proceed = typeof value === "string" && value;
2075
2076 if ( jQuery.isFunction( value ) ) {
2077 return this.each(function( j ) {
2078 jQuery( this ).addClass( value.call( this, j, this.className ) );
2079 });
2080 }
2081
2082 if ( proceed ) {
2083 // The disjunction here is for better compressibility (see removeClass)
2084 classes = ( value || "" ).match( core_rnotwhite ) || [];
2085
2086 for ( ; i < len; i++ ) {
2087 elem = this[ i ];
2088 cur = elem.nodeType === 1 && ( elem.className ?
2089 ( " " + elem.className + " " ).replace( rclass, " " ) :
2090 " "
2091 );
2092
2093 if ( cur ) {
2094 j = 0;
2095 while ( (clazz = classes[j++]) ) {
2096 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
2097 cur += clazz + " ";
2098 }
2099 }
2100 elem.className = jQuery.trim( cur );
2101
2102 }
2103 }
2104 }
2105
2106 return this;
2107 },
2108
2109 removeClass: function( value ) {
2110 var classes, elem, cur, clazz, j,
2111 i = 0,
2112 len = this.length,
2113 proceed = arguments.length === 0 || typeof value === "string" && value;
2114
2115 if ( jQuery.isFunction( value ) ) {
2116 return this.each(function( j ) {
2117 jQuery( this ).removeClass( value.call( this, j, this.className ) );
2118 });
2119 }
2120 if ( proceed ) {
2121 classes = ( value || "" ).match( core_rnotwhite ) || [];
2122
2123 for ( ; i < len; i++ ) {
2124 elem = this[ i ];
2125 // This expression is here for better compressibility (see addClass)
2126 cur = elem.nodeType === 1 && ( elem.className ?
2127 ( " " + elem.className + " " ).replace( rclass, " " ) :
2128 ""
2129 );
2130
2131 if ( cur ) {
2132 j = 0;
2133 while ( (clazz = classes[j++]) ) {
2134 // Remove *all* instances
2135 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
2136 cur = cur.replace( " " + clazz + " ", " " );
2137 }
2138 }
2139 elem.className = value ? jQuery.trim( cur ) : "";
2140 }
2141 }
2142 }
2143
2144 return this;
2145 },
2146
2147 toggleClass: function( value, stateVal ) {
2148 var type = typeof value,
2149 isBool = typeof stateVal === "boolean";
2150
2151 if ( jQuery.isFunction( value ) ) {
2152 return this.each(function( i ) {
2153 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2154 });
2155 }
2156
2157 return this.each(function() {
2158 if ( type === "string" ) {
2159 // toggle individual class names
2160 var className,
2161 i = 0,
2162 self = jQuery( this ),
2163 state = stateVal,
2164 classNames = value.match( core_rnotwhite ) || [];
2165
2166 while ( (className = classNames[ i++ ]) ) {
2167 // check each className given, space separated list
2168 state = isBool ? state : !self.hasClass( className );
2169 self[ state ? "addClass" : "removeClass" ]( className );
2170 }
2171
2172 // Toggle whole class name
2173 } else if ( type === core_strundefined || type === "boolean" ) {
2174 if ( this.className ) {
2175 // store className if set
2176 jQuery._data( this, "__className__", this.className );
2177 }
2178
2179 // If the element has a class name or if we're passed "false",
2180 // then remove the whole classname (if there was one, the above saved it).
2181 // Otherwise bring back whatever was previously saved (if anything),
2182 // falling back to the empty string if nothing was stored.
2183 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2184 }
2185 });
2186 },
2187
2188 hasClass: function( selector ) {
2189 var className = " " + selector + " ",
2190 i = 0,
2191 l = this.length;
2192 for ( ; i < l; i++ ) {
2193 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
2194 return true;
2195 }
2196 }
2197
2198 return false;
2199 },
2200
2201 val: function( value ) {
2202 var ret, hooks, isFunction,
2203 elem = this[0];
2204
2205 if ( !arguments.length ) {
2206 if ( elem ) {
2207 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
2208
2209 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2210 return ret;
2211 }
2212
2213 ret = elem.value;
2214
2215 return typeof ret === "string" ?
2216 // handle most common string cases
2217 ret.replace(rreturn, "") :
2218 // handle cases where value is null/undef or number
2219 ret == null ? "" : ret;
2220 }
2221
2222 return;
2223 }
2224
2225 isFunction = jQuery.isFunction( value );
2226
2227 return this.each(function( i ) {
2228 var val,
2229 self = jQuery(this);
2230
2231 if ( this.nodeType !== 1 ) {
2232 return;
2233 }
2234
2235 if ( isFunction ) {
2236 val = value.call( this, i, self.val() );
2237 } else {
2238 val = value;
2239 }
2240
2241 // Treat null/undefined as ""; convert numbers to string
2242 if ( val == null ) {
2243 val = "";
2244 } else if ( typeof val === "number" ) {
2245 val += "";
2246 } else if ( jQuery.isArray( val ) ) {
2247 val = jQuery.map(val, function ( value ) {
2248 return value == null ? "" : value + "";
2249 });
2250 }
2251
2252 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
2253
2254 // If set returns undefined, fall back to normal setting
2255 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2256 this.value = val;
2257 }
2258 });
2259 }
2260 });
2261
2262 jQuery.extend({
2263 valHooks: {
2264 option: {
2265 get: function( elem ) {
2266 // attributes.value is undefined in Blackberry 4.7 but
2267 // uses .value. See #6932
2268 var val = elem.attributes.value;
2269 return !val || val.specified ? elem.value : elem.text;
2270 }
2271 },
2272 select: {
2273 get: function( elem ) {
2274 var value, option,
2275 options = elem.options,
2276 index = elem.selectedIndex,
2277 one = elem.type === "select-one" || index < 0,
2278 values = one ? null : [],
2279 max = one ? index + 1 : options.length,
2280 i = index < 0 ?
2281 max :
2282 one ? index : 0;
2283
2284 // Loop through all the selected options
2285 for ( ; i < max; i++ ) {
2286 option = options[ i ];
2287
2288 // oldIE doesn't update selected after form reset (#2551)
2289 if ( ( option.selected || i === index ) &&
2290 // Don't return options that are disabled or in a disabled optgroup
2291 ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
2292 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
2293
2294 // Get the specific value for the option
2295 value = jQuery( option ).val();
2296
2297 // We don't need an array for one selects
2298 if ( one ) {
2299 return value;
2300 }
2301
2302 // Multi-Selects return an array
2303 values.push( value );
2304 }
2305 }
2306
2307 return values;
2308 },
2309
2310 set: function( elem, value ) {
2311 var values = jQuery.makeArray( value );
2312
2313 jQuery(elem).find("option").each(function() {
2314 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2315 });
2316
2317 if ( !values.length ) {
2318 elem.selectedIndex = -1;
2319 }
2320 return values;
2321 }
2322 }
2323 },
2324
2325 attr: function( elem, name, value ) {
2326 var hooks, notxml, ret,
2327 nType = elem.nodeType;
2328
2329 // don't get/set attributes on text, comment and attribute nodes
2330 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2331 return;
2332 }
2333
2334 // Fallback to prop when attributes are not supported
2335 if ( typeof elem.getAttribute === core_strundefined ) {
2336 return jQuery.prop( elem, name, value );
2337 }
2338
2339 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2340
2341 // All attributes are lowercase
2342 // Grab necessary hook if one is defined
2343 if ( notxml ) {
2344 name = name.toLowerCase();
2345 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2346 }
2347
2348 if ( value !== undefined ) {
2349
2350 if ( value === null ) {
2351 jQuery.removeAttr( elem, name );
2352
2353 } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2354 return ret;
2355
2356 } else {
2357 elem.setAttribute( name, value + "" );
2358 return value;
2359 }
2360
2361 } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2362 return ret;
2363
2364 } else {
2365
2366 // In IE9+, Flash objects don't have .getAttribute (#12945)
2367 // Support: IE9+
2368 if ( typeof elem.getAttribute !== core_strundefined ) {
2369 ret = elem.getAttribute( name );
2370 }
2371
2372 // Non-existent attributes return null, we normalize to undefined
2373 return ret == null ?
2374 undefined :
2375 ret;
2376 }
2377 },
2378
2379 removeAttr: function( elem, value ) {
2380 var name, propName,
2381 i = 0,
2382 attrNames = value && value.match( core_rnotwhite );
2383
2384 if ( attrNames && elem.nodeType === 1 ) {
2385 while ( (name = attrNames[i++]) ) {
2386 propName = jQuery.propFix[ name ] || name;
2387
2388 // Boolean attributes get special treatment (#10870)
2389 if ( rboolean.test( name ) ) {
2390 // Set corresponding property to false for boolean attributes
2391 // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
2392 if ( !getSetAttribute && ruseDefault.test( name ) ) {
2393 elem[ jQuery.camelCase( "default-" + name ) ] =
2394 elem[ propName ] = false;
2395 } else {
2396 elem[ propName ] = false;
2397 }
2398
2399 // See #9699 for explanation of this approach (setting first, then removal)
2400 } else {
2401 jQuery.attr( elem, name, "" );
2402 }
2403
2404 elem.removeAttribute( getSetAttribute ? name : propName );
2405 }
2406 }
2407 },
2408
2409 attrHooks: {
2410 type: {
2411 set: function( elem, value ) {
2412 if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2413 // Setting the type on a radio button after the value resets the value in IE6-9
2414 // Reset value to default in case type is set after value during creation
2415 var val = elem.value;
2416 elem.setAttribute( "type", value );
2417 if ( val ) {
2418 elem.value = val;
2419 }
2420 return value;
2421 }
2422 }
2423 }
2424 },
2425
2426 propFix: {
2427 tabindex: "tabIndex",
2428 readonly: "readOnly",
2429 "for": "htmlFor",
2430 "class": "className",
2431 maxlength: "maxLength",
2432 cellspacing: "cellSpacing",
2433 cellpadding: "cellPadding",
2434 rowspan: "rowSpan",
2435 colspan: "colSpan",
2436 usemap: "useMap",
2437 frameborder: "frameBorder",
2438 contenteditable: "contentEditable"
2439 },
2440
2441 prop: function( elem, name, value ) {
2442 var ret, hooks, notxml,
2443 nType = elem.nodeType;
2444
2445 // don't get/set properties on text, comment and attribute nodes
2446 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2447 return;
2448 }
2449
2450 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2451
2452 if ( notxml ) {
2453 // Fix name and attach hooks
2454 name = jQuery.propFix[ name ] || name;
2455 hooks = jQuery.propHooks[ name ];
2456 }
2457
2458 if ( value !== undefined ) {
2459 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2460 return ret;
2461
2462 } else {
2463 return ( elem[ name ] = value );
2464 }
2465
2466 } else {
2467 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2468 return ret;
2469
2470 } else {
2471 return elem[ name ];
2472 }
2473 }
2474 },
2475
2476 propHooks: {
2477 tabIndex: {
2478 get: function( elem ) {
2479 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2480 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2481 var attributeNode = elem.getAttributeNode("tabindex");
2482
2483 return attributeNode && attributeNode.specified ?
2484 parseInt( attributeNode.value, 10 ) :
2485 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2486 0 :
2487 undefined;
2488 }
2489 }
2490 }
2491 });
2492
2493 // Hook for boolean attributes
2494 boolHook = {
2495 get: function( elem, name ) {
2496 var
2497 // Use .prop to determine if this attribute is understood as boolean
2498 prop = jQuery.prop( elem, name ),
2499
2500 // Fetch it accordingly
2501 attr = typeof prop === "boolean" && elem.getAttribute( name ),
2502 detail = typeof prop === "boolean" ?
2503
2504 getSetInput && getSetAttribute ?
2505 attr != null :
2506 // oldIE fabricates an empty string for missing boolean attributes
2507 // and conflates checked/selected into attroperties
2508 ruseDefault.test( name ) ?
2509 elem[ jQuery.camelCase( "default-" + name ) ] :
2510 !!attr :
2511
2512 // fetch an attribute node for properties not recognized as boolean
2513 elem.getAttributeNode( name );
2514
2515 return detail && detail.value !== false ?
2516 name.toLowerCase() :
2517 undefined;
2518 },
2519 set: function( elem, value, name ) {
2520 if ( value === false ) {
2521 // Remove boolean attributes when set to false
2522 jQuery.removeAttr( elem, name );
2523 } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
2524 // IE<8 needs the *property* name
2525 elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
2526
2527 // Use defaultChecked and defaultSelected for oldIE
2528 } else {
2529 elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
2530 }
2531
2532 return name;
2533 }
2534 };
2535
2536 // fix oldIE value attroperty
2537 if ( !getSetInput || !getSetAttribute ) {
2538 jQuery.attrHooks.value = {
2539 get: function( elem, name ) {
2540 var ret = elem.getAttributeNode( name );
2541 return jQuery.nodeName( elem, "input" ) ?
2542
2543 // Ignore the value *property* by using defaultValue
2544 elem.defaultValue :
2545
2546 ret && ret.specified ? ret.value : undefined;
2547 },
2548 set: function( elem, value, name ) {
2549 if ( jQuery.nodeName( elem, "input" ) ) {
2550 // Does not return so that setAttribute is also used
2551 elem.defaultValue = value;
2552 } else {
2553 // Use nodeHook if defined (#1954); otherwise setAttribute is fine
2554 return nodeHook && nodeHook.set( elem, value, name );
2555 }
2556 }
2557 };
2558 }
2559
2560 // IE6/7 do not support getting/setting some attributes with get/setAttribute
2561 if ( !getSetAttribute ) {
2562
2563 // Use this for any attribute in IE6/7
2564 // This fixes almost every IE6/7 issue
2565 nodeHook = jQuery.valHooks.button = {
2566 get: function( elem, name ) {
2567 var ret = elem.getAttributeNode( name );
2568 return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
2569 ret.value :
2570 undefined;
2571 },
2572 set: function( elem, value, name ) {
2573 // Set the existing or create a new attribute node
2574 var ret = elem.getAttributeNode( name );
2575 if ( !ret ) {
2576 elem.setAttributeNode(
2577 (ret = elem.ownerDocument.createAttribute( name ))
2578 );
2579 }
2580
2581 ret.value = value += "";
2582
2583 // Break association with cloned elements by also using setAttribute (#9646)
2584 return name === "value" || value === elem.getAttribute( name ) ?
2585 value :
2586 undefined;
2587 }
2588 };
2589
2590 // Set contenteditable to false on removals(#10429)
2591 // Setting to empty string throws an error as an invalid value
2592 jQuery.attrHooks.contenteditable = {
2593 get: nodeHook.get,
2594 set: function( elem, value, name ) {
2595 nodeHook.set( elem, value === "" ? false : value, name );
2596 }
2597 };
2598
2599 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2600 // This is for removals
2601 jQuery.each([ "width", "height" ], function( i, name ) {
2602 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2603 set: function( elem, value ) {
2604 if ( value === "" ) {
2605 elem.setAttribute( name, "auto" );
2606 return value;
2607 }
2608 }
2609 });
2610 });
2611 }
2612
2613
2614 // Some attributes require a special call on IE
2615 // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2616 if ( !jQuery.support.hrefNormalized ) {
2617 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2618 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2619 get: function( elem ) {
2620 var ret = elem.getAttribute( name, 2 );
2621 return ret == null ? undefined : ret;
2622 }
2623 });
2624 });
2625
2626 // href/src property should get the full normalized URL (#10299/#12915)
2627 jQuery.each([ "href", "src" ], function( i, name ) {
2628 jQuery.propHooks[ name ] = {
2629 get: function( elem ) {
2630 return elem.getAttribute( name, 4 );
2631 }
2632 };
2633 });
2634 }
2635
2636 if ( !jQuery.support.style ) {
2637 jQuery.attrHooks.style = {
2638 get: function( elem ) {
2639 // Return undefined in the case of empty string
2640 // Note: IE uppercases css property names, but if we were to .toLowerCase()
2641 // .cssText, that would destroy case senstitivity in URL's, like in "background"
2642 return elem.style.cssText || undefined;
2643 },
2644 set: function( elem, value ) {
2645 return ( elem.style.cssText = value + "" );
2646 }
2647 };
2648 }
2649
2650 // Safari mis-reports the default selected property of an option
2651 // Accessing the parent's selectedIndex property fixes it
2652 if ( !jQuery.support.optSelected ) {
2653 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2654 get: function( elem ) {
2655 var parent = elem.parentNode;
2656
2657 if ( parent ) {
2658 parent.selectedIndex;
2659
2660 // Make sure that it also works with optgroups, see #5701
2661 if ( parent.parentNode ) {
2662 parent.parentNode.selectedIndex;
2663 }
2664 }
2665 return null;
2666 }
2667 });
2668 }
2669
2670 // IE6/7 call enctype encoding
2671 if ( !jQuery.support.enctype ) {
2672 jQuery.propFix.enctype = "encoding";
2673 }
2674
2675 // Radios and checkboxes getter/setter
2676 if ( !jQuery.support.checkOn ) {
2677 jQuery.each([ "radio", "checkbox" ], function() {
2678 jQuery.valHooks[ this ] = {
2679 get: function( elem ) {
2680 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2681 return elem.getAttribute("value") === null ? "on" : elem.value;
2682 }
2683 };
2684 });
2685 }
2686 jQuery.each([ "radio", "checkbox" ], function() {
2687 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2688 set: function( elem, value ) {
2689 if ( jQuery.isArray( value ) ) {
2690 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2691 }
2692 }
2693 });
2694 });
2695 var rformElems = /^(?:input|select|textarea)$/i,
2696 rkeyEvent = /^key/,
2697 rmouseEvent = /^(?:mouse|contextmenu)|click/,
2698 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2699 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
2700
2701 function returnTrue() {
2702 return true;
2703 }
2704
2705 function returnFalse() {
2706 return false;
2707 }
2708
2709 /*
2710 * Helper functions for managing events -- not part of the public interface.
2711 * Props to Dean Edwards' addEvent library for many of the ideas.
2712 */
2713 jQuery.event = {
2714
2715 global: {},
2716
2717 add: function( elem, types, handler, data, selector ) {
2718 var tmp, events, t, handleObjIn,
2719 special, eventHandle, handleObj,
2720 handlers, type, namespaces, origType,
2721 elemData = jQuery._data( elem );
2722
2723 // Don't attach events to noData or text/comment nodes (but allow plain objects)
2724 if ( !elemData ) {
2725 return;
2726 }
2727
2728 // Caller can pass in an object of custom data in lieu of the handler
2729 if ( handler.handler ) {
2730 handleObjIn = handler;
2731 handler = handleObjIn.handler;
2732 selector = handleObjIn.selector;
2733 }
2734
2735 // Make sure that the handler has a unique ID, used to find/remove it later
2736 if ( !handler.guid ) {
2737 handler.guid = jQuery.guid++;
2738 }
2739
2740 // Init the element's event structure and main handler, if this is the first
2741 if ( !(events = elemData.events) ) {
2742 events = elemData.events = {};
2743 }
2744 if ( !(eventHandle = elemData.handle) ) {
2745 eventHandle = elemData.handle = function( e ) {
2746 // Discard the second event of a jQuery.event.trigger() and
2747 // when an event is called after a page has unloaded
2748 return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
2749 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2750 undefined;
2751 };
2752 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2753 eventHandle.elem = elem;
2754 }
2755
2756 // Handle multiple events separated by a space
2757 // jQuery(...).bind("mouseover mouseout", fn);
2758 types = ( types || "" ).match( core_rnotwhite ) || [""];
2759 t = types.length;
2760 while ( t-- ) {
2761 tmp = rtypenamespace.exec( types[t] ) || [];
2762 type = origType = tmp[1];
2763 namespaces = ( tmp[2] || "" ).split( "." ).sort();
2764
2765 // If event changes its type, use the special event handlers for the changed type
2766 special = jQuery.event.special[ type ] || {};
2767
2768 // If selector defined, determine special event api type, otherwise given type
2769 type = ( selector ? special.delegateType : special.bindType ) || type;
2770
2771 // Update special based on newly reset type
2772 special = jQuery.event.special[ type ] || {};
2773
2774 // handleObj is passed to all event handlers
2775 handleObj = jQuery.extend({
2776 type: type,
2777 origType: origType,
2778 data: data,
2779 handler: handler,
2780 guid: handler.guid,
2781 selector: selector,
2782 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
2783 namespace: namespaces.join(".")
2784 }, handleObjIn );
2785
2786 // Init the event handler queue if we're the first
2787 if ( !(handlers = events[ type ]) ) {
2788 handlers = events[ type ] = [];
2789 handlers.delegateCount = 0;
2790
2791 // Only use addEventListener/attachEvent if the special events handler returns false
2792 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2793 // Bind the global event handler to the element
2794 if ( elem.addEventListener ) {
2795 elem.addEventListener( type, eventHandle, false );
2796
2797 } else if ( elem.attachEvent ) {
2798 elem.attachEvent( "on" + type, eventHandle );
2799 }
2800 }
2801 }
2802
2803 if ( special.add ) {
2804 special.add.call( elem, handleObj );
2805
2806 if ( !handleObj.handler.guid ) {
2807 handleObj.handler.guid = handler.guid;
2808 }
2809 }
2810
2811 // Add to the element's handler list, delegates in front
2812 if ( selector ) {
2813 handlers.splice( handlers.delegateCount++, 0, handleObj );
2814 } else {
2815 handlers.push( handleObj );
2816 }
2817
2818 // Keep track of which events have ever been used, for event optimization
2819 jQuery.event.global[ type ] = true;
2820 }
2821
2822 // Nullify elem to prevent memory leaks in IE
2823 elem = null;
2824 },
2825
2826 // Detach an event or set of events from an element
2827 remove: function( elem, types, handler, selector, mappedTypes ) {
2828 var j, handleObj, tmp,
2829 origCount, t, events,
2830 special, handlers, type,
2831 namespaces, origType,
2832 elemData = jQuery.hasData( elem ) && jQuery._data( elem );
2833
2834 if ( !elemData || !(events = elemData.events) ) {
2835 return;
2836 }
2837
2838 // Once for each type.namespace in types; type may be omitted
2839 types = ( types || "" ).match( core_rnotwhite ) || [""];
2840 t = types.length;
2841 while ( t-- ) {
2842 tmp = rtypenamespace.exec( types[t] ) || [];
2843 type = origType = tmp[1];
2844 namespaces = ( tmp[2] || "" ).split( "." ).sort();
2845
2846 // Unbind all events (on this namespace, if provided) for the element
2847 if ( !type ) {
2848 for ( type in events ) {
2849 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
2850 }
2851 continue;
2852 }
2853
2854 special = jQuery.event.special[ type ] || {};
2855 type = ( selector ? special.delegateType : special.bindType ) || type;
2856 handlers = events[ type ] || [];
2857 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
2858
2859 // Remove matching events
2860 origCount = j = handlers.length;
2861 while ( j-- ) {
2862 handleObj = handlers[ j ];
2863
2864 if ( ( mappedTypes || origType === handleObj.origType ) &&
2865 ( !handler || handler.guid === handleObj.guid ) &&
2866 ( !tmp || tmp.test( handleObj.namespace ) ) &&
2867 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
2868 handlers.splice( j, 1 );
2869
2870 if ( handleObj.selector ) {
2871 handlers.delegateCount--;
2872 }
2873 if ( special.remove ) {
2874 special.remove.call( elem, handleObj );
2875 }
2876 }
2877 }
2878
2879 // Remove generic event handler if we removed something and no more handlers exist
2880 // (avoids potential for endless recursion during removal of special event handlers)
2881 if ( origCount && !handlers.length ) {
2882 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
2883 jQuery.removeEvent( elem, type, elemData.handle );
2884 }
2885
2886 delete events[ type ];
2887 }
2888 }
2889
2890 // Remove the expando if it's no longer used
2891 if ( jQuery.isEmptyObject( events ) ) {
2892 delete elemData.handle;
2893
2894 // removeData also checks for emptiness and clears the expando if empty
2895 // so use it instead of delete
2896 jQuery._removeData( elem, "events" );
2897 }
2898 },
2899
2900 trigger: function( event, data, elem, onlyHandlers ) {
2901 var handle, ontype, cur,
2902 bubbleType, special, tmp, i,
2903 eventPath = [ elem || document ],
2904 type = core_hasOwn.call( event, "type" ) ? event.type : event,
2905 namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
2906
2907 cur = tmp = elem = elem || document;
2908
2909 // Don't do events on text and comment nodes
2910 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2911 return;
2912 }
2913
2914 // focus/blur morphs to focusin/out; ensure we're not firing them right now
2915 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
2916 return;
2917 }
2918
2919 if ( type.indexOf(".") >= 0 ) {
2920 // Namespaced trigger; create a regexp to match event type in handle()
2921 namespaces = type.split(".");
2922 type = namespaces.shift();
2923 namespaces.sort();
2924 }
2925 ontype = type.indexOf(":") < 0 && "on" + type;
2926
2927 // Caller can pass in a jQuery.Event object, Object, or just an event type string
2928 event = event[ jQuery.expando ] ?
2929 event :
2930 new jQuery.Event( type, typeof event === "object" && event );
2931
2932 event.isTrigger = true;
2933 event.namespace = namespaces.join(".");
2934 event.namespace_re = event.namespace ?
2935 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
2936 null;
2937
2938 // Clean up the event in case it is being reused
2939 event.result = undefined;
2940 if ( !event.target ) {
2941 event.target = elem;
2942 }
2943
2944 // Clone any incoming data and prepend the event, creating the handler arg list
2945 data = data == null ?
2946 [ event ] :
2947 jQuery.makeArray( data, [ event ] );
2948
2949 // Allow special events to draw outside the lines
2950 special = jQuery.event.special[ type ] || {};
2951 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
2952 return;
2953 }
2954
2955 // Determine event propagation path in advance, per W3C events spec (#9951)
2956 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
2957 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
2958
2959 bubbleType = special.delegateType || type;
2960 if ( !rfocusMorph.test( bubbleType + type ) ) {
2961 cur = cur.parentNode;
2962 }
2963 for ( ; cur; cur = cur.parentNode ) {
2964 eventPath.push( cur );
2965 tmp = cur;
2966 }
2967
2968 // Only add window if we got to document (e.g., not plain obj or detached DOM)
2969 if ( tmp === (elem.ownerDocument || document) ) {
2970 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
2971 }
2972 }
2973
2974 // Fire handlers on the event path
2975 i = 0;
2976 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
2977
2978 event.type = i > 1 ?
2979 bubbleType :
2980 special.bindType || type;
2981
2982 // jQuery handler
2983 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
2984 if ( handle ) {
2985 handle.apply( cur, data );
2986 }
2987
2988 // Native handler
2989 handle = ontype && cur[ ontype ];
2990 if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
2991 event.preventDefault();
2992 }
2993 }
2994 event.type = type;
2995
2996 // If nobody prevented the default action, do it now
2997 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
2998
2999 if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
3000 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
3001
3002 // Call a native DOM method on the target with the same name name as the event.
3003 // Can't use an .isFunction() check here because IE6/7 fails that test.
3004 // Don't do default actions on window, that's where global variables be (#6170)
3005 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
3006
3007 // Don't re-trigger an onFOO event when we call its FOO() method
3008 tmp = elem[ ontype ];
3009
3010 if ( tmp ) {
3011 elem[ ontype ] = null;
3012 }
3013
3014 // Prevent re-triggering of the same event, since we already bubbled it above
3015 jQuery.event.triggered = type;
3016 try {
3017 elem[ type ]();
3018 } catch ( e ) {
3019 // IE<9 dies on focus/blur to hidden element (#1486,#12518)
3020 // only reproducible on winXP IE8 native, not IE9 in IE8 mode
3021 }
3022 jQuery.event.triggered = undefined;
3023
3024 if ( tmp ) {
3025 elem[ ontype ] = tmp;
3026 }
3027 }
3028 }
3029 }
3030
3031 return event.result;
3032 },
3033
3034 dispatch: function( event ) {
3035
3036 // Make a writable jQuery.Event from the native event object
3037 event = jQuery.event.fix( event );
3038
3039 var i, ret, handleObj, matched, j,
3040 handlerQueue = [],
3041 args = core_slice.call( arguments ),
3042 handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
3043 special = jQuery.event.special[ event.type ] || {};
3044
3045 // Use the fix-ed jQuery.Event rather than the (read-only) native event
3046 args[0] = event;
3047 event.delegateTarget = this;
3048
3049 // Call the preDispatch hook for the mapped type, and let it bail if desired
3050 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
3051 return;
3052 }
3053
3054 // Determine handlers
3055 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
3056
3057 // Run delegates first; they may want to stop propagation beneath us
3058 i = 0;
3059 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
3060 event.currentTarget = matched.elem;
3061
3062 j = 0;
3063 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
3064
3065 // Triggered event must either 1) have no namespace, or
3066 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3067 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
3068
3069 event.handleObj = handleObj;
3070 event.data = handleObj.data;
3071
3072 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
3073 .apply( matched.elem, args );
3074
3075 if ( ret !== undefined ) {
3076 if ( (event.result = ret) === false ) {
3077 event.preventDefault();
3078 event.stopPropagation();
3079 }
3080 }
3081 }
3082 }
3083 }
3084
3085 // Call the postDispatch hook for the mapped type
3086 if ( special.postDispatch ) {
3087 special.postDispatch.call( this, event );
3088 }
3089
3090 return event.result;
3091 },
3092
3093 handlers: function( event, handlers ) {
3094 var sel, handleObj, matches, i,
3095 handlerQueue = [],
3096 delegateCount = handlers.delegateCount,
3097 cur = event.target;
3098
3099 // Find delegate handlers
3100 // Black-hole SVG <use> instance trees (#13180)
3101 // Avoid non-left-click bubbling in Firefox (#3861)
3102 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
3103
3104 for ( ; cur != this; cur = cur.parentNode || this ) {
3105
3106 // Don't check non-elements (#13208)
3107 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
3108 if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
3109 matches = [];
3110 for ( i = 0; i < delegateCount; i++ ) {
3111 handleObj = handlers[ i ];
3112
3113 // Don't conflict with Object.prototype properties (#13203)
3114 sel = handleObj.selector + " ";
3115
3116 if ( matches[ sel ] === undefined ) {
3117 matches[ sel ] = handleObj.needsContext ?
3118 jQuery( sel, this ).index( cur ) >= 0 :
3119 jQuery.find( sel, this, null, [ cur ] ).length;
3120 }
3121 if ( matches[ sel ] ) {
3122 matches.push( handleObj );
3123 }
3124 }
3125 if ( matches.length ) {
3126 handlerQueue.push({ elem: cur, handlers: matches });
3127 }
3128 }
3129 }
3130 }
3131
3132 // Add the remaining (directly-bound) handlers
3133 if ( delegateCount < handlers.length ) {
3134 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
3135 }
3136
3137 return handlerQueue;
3138 },
3139
3140 fix: function( event ) {
3141 if ( event[ jQuery.expando ] ) {
3142 return event;
3143 }
3144
3145 // Create a writable copy of the event object and normalize some properties
3146 var i, prop, copy,
3147 type = event.type,
3148 originalEvent = event,
3149 fixHook = this.fixHooks[ type ];
3150
3151 if ( !fixHook ) {
3152 this.fixHooks[ type ] = fixHook =
3153 rmouseEvent.test( type ) ? this.mouseHooks :
3154 rkeyEvent.test( type ) ? this.keyHooks :
3155 {};
3156 }
3157 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3158
3159 event = new jQuery.Event( originalEvent );
3160
3161 i = copy.length;
3162 while ( i-- ) {
3163 prop = copy[ i ];
3164 event[ prop ] = originalEvent[ prop ];
3165 }
3166
3167 // Support: IE<9
3168 // Fix target property (#1925)
3169 if ( !event.target ) {
3170 event.target = originalEvent.srcElement || document;
3171 }
3172
3173 // Support: Chrome 23+, Safari?
3174 // Target should not be a text node (#504, #13143)
3175 if ( event.target.nodeType === 3 ) {
3176 event.target = event.target.parentNode;
3177 }
3178
3179 // Support: IE<9
3180 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
3181 event.metaKey = !!event.metaKey;
3182
3183 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
3184 },
3185
3186 // Includes some event props shared by KeyEvent and MouseEvent
3187 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3188
3189 fixHooks: {},
3190
3191 keyHooks: {
3192 props: "char charCode key keyCode".split(" "),
3193 filter: function( event, original ) {
3194
3195 // Add which for key events
3196 if ( event.which == null ) {
3197 event.which = original.charCode != null ? original.charCode : original.keyCode;
3198 }
3199
3200 return event;
3201 }
3202 },
3203
3204 mouseHooks: {
3205 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3206 filter: function( event, original ) {
3207 var body, eventDoc, doc,
3208 button = original.button,
3209 fromElement = original.fromElement;
3210
3211 // Calculate pageX/Y if missing and clientX/Y available
3212 if ( event.pageX == null && original.clientX != null ) {
3213 eventDoc = event.target.ownerDocument || document;
3214 doc = eventDoc.documentElement;
3215 body = eventDoc.body;
3216
3217 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3218 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3219 }
3220
3221 // Add relatedTarget, if necessary
3222 if ( !event.relatedTarget && fromElement ) {
3223 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3224 }
3225
3226 // Add which for click: 1 === left; 2 === middle; 3 === right
3227 // Note: button is not normalized, so don't use it
3228 if ( !event.which && button !== undefined ) {
3229 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3230 }
3231
3232 return event;
3233 }
3234 },
3235
3236 special: {
3237 load: {
3238 // Prevent triggered image.load events from bubbling to window.load
3239 noBubble: true
3240 },
3241 click: {
3242 // For checkbox, fire native event so checked state will be right
3243 trigger: function() {
3244 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
3245 this.click();
3246 return false;
3247 }
3248 }
3249 },
3250 focus: {
3251 // Fire native event if possible so blur/focus sequence is correct
3252 trigger: function() {
3253 if ( this !== document.activeElement && this.focus ) {
3254 try {
3255 this.focus();
3256 return false;
3257 } catch ( e ) {
3258 // Support: IE<9
3259 // If we error on focus to hidden element (#1486, #12518),
3260 // let .trigger() run the handlers
3261 }
3262 }
3263 },
3264 delegateType: "focusin"
3265 },
3266 blur: {
3267 trigger: function() {
3268 if ( this === document.activeElement && this.blur ) {
3269 this.blur();
3270 return false;
3271 }
3272 },
3273 delegateType: "focusout"
3274 },
3275
3276 beforeunload: {
3277 postDispatch: function( event ) {
3278
3279 // Even when returnValue equals to undefined Firefox will still show alert
3280 if ( event.result !== undefined ) {
3281 event.originalEvent.returnValue = event.result;
3282 }
3283 }
3284 }
3285 },
3286
3287 simulate: function( type, elem, event, bubble ) {
3288 // Piggyback on a donor event to simulate a different one.
3289 // Fake originalEvent to avoid donor's stopPropagation, but if the
3290 // simulated event prevents default then we do the same on the donor.
3291 var e = jQuery.extend(
3292 new jQuery.Event(),
3293 event,
3294 { type: type,
3295 isSimulated: true,
3296 originalEvent: {}
3297 }
3298 );
3299 if ( bubble ) {
3300 jQuery.event.trigger( e, null, elem );
3301 } else {
3302 jQuery.event.dispatch.call( elem, e );
3303 }
3304 if ( e.isDefaultPrevented() ) {
3305 event.preventDefault();
3306 }
3307 }
3308 };
3309
3310 jQuery.removeEvent = document.removeEventListener ?
3311 function( elem, type, handle ) {
3312 if ( elem.removeEventListener ) {
3313 elem.removeEventListener( type, handle, false );
3314 }
3315 } :
3316 function( elem, type, handle ) {
3317 var name = "on" + type;
3318
3319 if ( elem.detachEvent ) {
3320
3321 // #8545, #7054, preventing memory leaks for custom events in IE6-8
3322 // detachEvent needed property on element, by name of that event, to properly expose it to GC
3323 if ( typeof elem[ name ] === core_strundefined ) {
3324 elem[ name ] = null;
3325 }
3326
3327 elem.detachEvent( name, handle );
3328 }
3329 };
3330
3331 jQuery.Event = function( src, props ) {
3332 // Allow instantiation without the 'new' keyword
3333 if ( !(this instanceof jQuery.Event) ) {
3334 return new jQuery.Event( src, props );
3335 }
3336
3337 // Event object
3338 if ( src && src.type ) {
3339 this.originalEvent = src;
3340 this.type = src.type;
3341
3342 // Events bubbling up the document may have been marked as prevented
3343 // by a handler lower down the tree; reflect the correct value.
3344 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3345 src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3346
3347 // Event type
3348 } else {
3349 this.type = src;
3350 }
3351
3352 // Put explicitly provided properties onto the event object
3353 if ( props ) {
3354 jQuery.extend( this, props );
3355 }
3356
3357 // Create a timestamp if incoming event doesn't have one
3358 this.timeStamp = src && src.timeStamp || jQuery.now();
3359
3360 // Mark it as fixed
3361 this[ jQuery.expando ] = true;
3362 };
3363
3364 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3365 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3366 jQuery.Event.prototype = {
3367 isDefaultPrevented: returnFalse,
3368 isPropagationStopped: returnFalse,
3369 isImmediatePropagationStopped: returnFalse,
3370
3371 preventDefault: function() {
3372 var e = this.originalEvent;
3373
3374 this.isDefaultPrevented = returnTrue;
3375 if ( !e ) {
3376 return;
3377 }
3378
3379 // If preventDefault exists, run it on the original event
3380 if ( e.preventDefault ) {
3381 e.preventDefault();
3382
3383 // Support: IE
3384 // Otherwise set the returnValue property of the original event to false
3385 } else {
3386 e.returnValue = false;
3387 }
3388 },
3389 stopPropagation: function() {
3390 var e = this.originalEvent;
3391
3392 this.isPropagationStopped = returnTrue;
3393 if ( !e ) {
3394 return;
3395 }
3396 // If stopPropagation exists, run it on the original event
3397 if ( e.stopPropagation ) {
3398 e.stopPropagation();
3399 }
3400
3401 // Support: IE
3402 // Set the cancelBubble property of the original event to true
3403 e.cancelBubble = true;
3404 },
3405 stopImmediatePropagation: function() {
3406 this.isImmediatePropagationStopped = returnTrue;
3407 this.stopPropagation();
3408 }
3409 };
3410
3411 // Create mouseenter/leave events using mouseover/out and event-time checks
3412 jQuery.each({
3413 mouseenter: "mouseover",
3414 mouseleave: "mouseout"
3415 }, function( orig, fix ) {
3416 jQuery.event.special[ orig ] = {
3417 delegateType: fix,
3418 bindType: fix,
3419
3420 handle: function( event ) {
3421 var ret,
3422 target = this,
3423 related = event.relatedTarget,
3424 handleObj = event.handleObj;
3425
3426 // For mousenter/leave call the handler if related is outside the target.
3427 // NB: No relatedTarget if the mouse left/entered the browser window
3428 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3429 event.type = handleObj.origType;
3430 ret = handleObj.handler.apply( this, arguments );
3431 event.type = fix;
3432 }
3433 return ret;
3434 }
3435 };
3436 });
3437
3438 // IE submit delegation
3439 if ( !jQuery.support.submitBubbles ) {
3440
3441 jQuery.event.special.submit = {
3442 setup: function() {
3443 // Only need this for delegated form submit events
3444 if ( jQuery.nodeName( this, "form" ) ) {
3445 return false;
3446 }
3447
3448 // Lazy-add a submit handler when a descendant form may potentially be submitted
3449 jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
3450 // Node name check avoids a VML-related crash in IE (#9807)
3451 var elem = e.target,
3452 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
3453 if ( form && !jQuery._data( form, "submitBubbles" ) ) {
3454 jQuery.event.add( form, "submit._submit", function( event ) {
3455 event._submit_bubble = true;
3456 });
3457 jQuery._data( form, "submitBubbles", true );
3458 }
3459 });
3460 // return undefined since we don't need an event listener
3461 },
3462
3463 postDispatch: function( event ) {
3464 // If form was submitted by the user, bubble the event up the tree
3465 if ( event._submit_bubble ) {
3466 delete event._submit_bubble;
3467 if ( this.parentNode && !event.isTrigger ) {
3468 jQuery.event.simulate( "submit", this.parentNode, event, true );
3469 }
3470 }
3471 },
3472
3473 teardown: function() {
3474 // Only need this for delegated form submit events
3475 if ( jQuery.nodeName( this, "form" ) ) {
3476 return false;
3477 }
3478
3479 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
3480 jQuery.event.remove( this, "._submit" );
3481 }
3482 };
3483 }
3484
3485 // IE change delegation and checkbox/radio fix
3486 if ( !jQuery.support.changeBubbles ) {
3487
3488 jQuery.event.special.change = {
3489
3490 setup: function() {
3491
3492 if ( rformElems.test( this.nodeName ) ) {
3493 // IE doesn't fire change on a check/radio until blur; trigger it on click
3494 // after a propertychange. Eat the blur-change in special.change.handle.
3495 // This still fires onchange a second time for check/radio after blur.
3496 if ( this.type === "checkbox" || this.type === "radio" ) {
3497 jQuery.event.add( this, "propertychange._change", function( event ) {
3498 if ( event.originalEvent.propertyName === "checked" ) {
3499 this._just_changed = true;
3500 }
3501 });
3502 jQuery.event.add( this, "click._change", function( event ) {
3503 if ( this._just_changed && !event.isTrigger ) {
3504 this._just_changed = false;
3505 }
3506 // Allow triggered, simulated change events (#11500)
3507 jQuery.event.simulate( "change", this, event, true );
3508 });
3509 }
3510 return false;
3511 }
3512 // Delegated event; lazy-add a change handler on descendant inputs
3513 jQuery.event.add( this, "beforeactivate._change", function( e ) {
3514 var elem = e.target;
3515
3516 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
3517 jQuery.event.add( elem, "change._change", function( event ) {
3518 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
3519 jQuery.event.simulate( "change", this.parentNode, event, true );
3520 }
3521 });
3522 jQuery._data( elem, "changeBubbles", true );
3523 }
3524 });
3525 },
3526
3527 handle: function( event ) {
3528 var elem = event.target;
3529
3530 // Swallow native change events from checkbox/radio, we already triggered them above
3531 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
3532 return event.handleObj.handler.apply( this, arguments );
3533 }
3534 },
3535
3536 teardown: function() {
3537 jQuery.event.remove( this, "._change" );
3538
3539 return !rformElems.test( this.nodeName );
3540 }
3541 };
3542 }
3543
3544 // Create "bubbling" focus and blur events
3545 if ( !jQuery.support.focusinBubbles ) {
3546 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
3547
3548 // Attach a single capturing handler while someone wants focusin/focusout
3549 var attaches = 0,
3550 handler = function( event ) {
3551 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
3552 };
3553
3554 jQuery.event.special[ fix ] = {
3555 setup: function() {
3556 if ( attaches++ === 0 ) {
3557 document.addEventListener( orig, handler, true );
3558 }
3559 },
3560 teardown: function() {
3561 if ( --attaches === 0 ) {
3562 document.removeEventListener( orig, handler, true );
3563 }
3564 }
3565 };
3566 });
3567 }
3568
3569 jQuery.fn.extend({
3570
3571 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
3572 var type, origFn;
3573
3574 // Types can be a map of types/handlers
3575 if ( typeof types === "object" ) {
3576 // ( types-Object, selector, data )
3577 if ( typeof selector !== "string" ) {
3578 // ( types-Object, data )
3579 data = data || selector;
3580 selector = undefined;
3581 }
3582 for ( type in types ) {
3583 this.on( type, selector, data, types[ type ], one );
3584 }
3585 return this;
3586 }
3587
3588 if ( data == null && fn == null ) {
3589 // ( types, fn )
3590 fn = selector;
3591 data = selector = undefined;
3592 } else if ( fn == null ) {
3593 if ( typeof selector === "string" ) {
3594 // ( types, selector, fn )
3595 fn = data;
3596 data = undefined;
3597 } else {
3598 // ( types, data, fn )
3599 fn = data;
3600 data = selector;
3601 selector = undefined;
3602 }
3603 }
3604 if ( fn === false ) {
3605 fn = returnFalse;
3606 } else if ( !fn ) {
3607 return this;
3608 }
3609
3610 if ( one === 1 ) {
3611 origFn = fn;
3612 fn = function( event ) {
3613 // Can use an empty set, since event contains the info
3614 jQuery().off( event );
3615 return origFn.apply( this, arguments );
3616 };
3617 // Use same guid so caller can remove using origFn
3618 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
3619 }
3620 return this.each( function() {
3621 jQuery.event.add( this, types, fn, data, selector );
3622 });
3623 },
3624 one: function( types, selector, data, fn ) {
3625 return this.on( types, selector, data, fn, 1 );
3626 },
3627 off: function( types, selector, fn ) {
3628 var handleObj, type;
3629 if ( types && types.preventDefault && types.handleObj ) {
3630 // ( event ) dispatched jQuery.Event
3631 handleObj = types.handleObj;
3632 jQuery( types.delegateTarget ).off(
3633 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
3634 handleObj.selector,
3635 handleObj.handler
3636 );
3637 return this;
3638 }
3639 if ( typeof types === "object" ) {
3640 // ( types-object [, selector] )
3641 for ( type in types ) {
3642 this.off( type, selector, types[ type ] );
3643 }
3644 return this;
3645 }
3646 if ( selector === false || typeof selector === "function" ) {
3647 // ( types [, fn] )
3648 fn = selector;
3649 selector = undefined;
3650 }
3651 if ( fn === false ) {
3652 fn = returnFalse;
3653 }
3654 return this.each(function() {
3655 jQuery.event.remove( this, types, fn, selector );
3656 });
3657 },
3658
3659 bind: function( types, data, fn ) {
3660 return this.on( types, null, data, fn );
3661 },
3662 unbind: function( types, fn ) {
3663 return this.off( types, null, fn );
3664 },
3665
3666 delegate: function( selector, types, data, fn ) {
3667 return this.on( types, selector, data, fn );
3668 },
3669 undelegate: function( selector, types, fn ) {
3670 // ( namespace ) or ( selector, types [, fn] )
3671 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3672 },
3673
3674 trigger: function( type, data ) {
3675 return this.each(function() {
3676 jQuery.event.trigger( type, data, this );
3677 });
3678 },
3679 triggerHandler: function( type, data ) {
3680 var elem = this[0];
3681 if ( elem ) {
3682 return jQuery.event.trigger( type, data, elem, true );
3683 }
3684 }
3685 });
3686 /*!
3687 * Sizzle CSS Selector Engine
3688 * Copyright 2012 jQuery Foundation and other contributors
3689 * Released under the MIT license
3690 * http://sizzlejs.com/
3691 */
3692 (function( window, undefined ) {
3693
3694 var i,
3695 cachedruns,
3696 Expr,
3697 getText,
3698 isXML,
3699 compile,
3700 hasDuplicate,
3701 outermostContext,
3702
3703 // Local document vars
3704 setDocument,
3705 document,
3706 docElem,
3707 documentIsXML,
3708 rbuggyQSA,
3709 rbuggyMatches,
3710 matches,
3711 contains,
3712 sortOrder,
3713
3714 // Instance-specific data
3715 expando = "sizzle" + -(new Date()),
3716 preferredDoc = window.document,
3717 support = {},
3718 dirruns = 0,
3719 done = 0,
3720 classCache = createCache(),
3721 tokenCache = createCache(),
3722 compilerCache = createCache(),
3723
3724 // General-purpose constants
3725 strundefined = typeof undefined,
3726 MAX_NEGATIVE = 1 << 31,
3727
3728 // Array methods
3729 arr = [],
3730 pop = arr.pop,
3731 push = arr.push,
3732 slice = arr.slice,
3733 // Use a stripped-down indexOf if we can't use a native one
3734 indexOf = arr.indexOf || function( elem ) {
3735 var i = 0,
3736 len = this.length;
3737 for ( ; i < len; i++ ) {
3738 if ( this[i] === elem ) {
3739 return i;
3740 }
3741 }
3742 return -1;
3743 },
3744
3745
3746 // Regular expressions
3747
3748 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
3749 whitespace = "[\\x20\\t\\r\\n\\f]",
3750 // http://www.w3.org/TR/css3-syntax/#characters
3751 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
3752
3753 // Loosely modeled on CSS identifier characters
3754 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
3755 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
3756 identifier = characterEncoding.replace( "w", "w#" ),
3757
3758 // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
3759 operators = "([*^$|!~]?=)",
3760 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
3761 "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
3762
3763 // Prefer arguments quoted,
3764 // then not containing pseudos/brackets,
3765 // then attribute selectors/non-parenthetical expressions,
3766 // then anything else
3767 // These preferences are here to reduce the number of selectors
3768 // needing tokenize in the PSEUDO preFilter
3769 pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
3770
3771 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
3772 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
3773
3774 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
3775 rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
3776 rpseudo = new RegExp( pseudos ),
3777 ridentifier = new RegExp( "^" + identifier + "$" ),
3778
3779 matchExpr = {
3780 "ID": new RegExp( "^#(" + characterEncoding + ")" ),
3781 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
3782 "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
3783 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
3784 "ATTR": new RegExp( "^" + attributes ),
3785 "PSEUDO": new RegExp( "^" + pseudos ),
3786 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
3787 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
3788 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
3789 // For use in libraries implementing .is()
3790 // We use this for POS matching in `select`
3791 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
3792 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
3793 },
3794
3795 rsibling = /[\x20\t\r\n\f]*[+~]/,
3796
3797 rnative = /^[^{]+\{\s*\[native code/,
3798
3799 // Easily-parseable/retrievable ID or TAG or CLASS selectors
3800 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
3801
3802 rinputs = /^(?:input|select|textarea|button)$/i,
3803 rheader = /^h\d$/i,
3804
3805 rescape = /'|\\/g,
3806 rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
3807
3808 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
3809 runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
3810 funescape = function( _, escaped ) {
3811 var high = "0x" + escaped - 0x10000;
3812 // NaN means non-codepoint
3813 return high !== high ?
3814 escaped :
3815 // BMP codepoint
3816 high < 0 ?
3817 String.fromCharCode( high + 0x10000 ) :
3818 // Supplemental Plane codepoint (surrogate pair)
3819 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
3820 };
3821
3822 // Use a stripped-down slice if we can't use a native one
3823 try {
3824 slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
3825 } catch ( e ) {
3826 slice = function( i ) {
3827 var elem,
3828 results = [];
3829 while ( (elem = this[i++]) ) {
3830 results.push( elem );
3831 }
3832 return results;
3833 };
3834 }
3835
3836 /**
3837 * For feature detection
3838 * @param {Function} fn The function to test for native support
3839 */
3840 function isNative( fn ) {
3841 return rnative.test( fn + "" );
3842 }
3843
3844 /**
3845 * Create key-value caches of limited size
3846 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
3847 * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
3848 * deleting the oldest entry
3849 */
3850 function createCache() {
3851 var cache,
3852 keys = [];
3853
3854 return (cache = function( key, value ) {
3855 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
3856 if ( keys.push( key += " " ) > Expr.cacheLength ) {
3857 // Only keep the most recent entries
3858 delete cache[ keys.shift() ];
3859 }
3860 return (cache[ key ] = value);
3861 });
3862 }
3863
3864 /**
3865 * Mark a function for special use by Sizzle
3866 * @param {Function} fn The function to mark
3867 */
3868 function markFunction( fn ) {
3869 fn[ expando ] = true;
3870 return fn;
3871 }
3872
3873 /**
3874 * Support testing using an element
3875 * @param {Function} fn Passed the created div and expects a boolean result
3876 */
3877 function assert( fn ) {
3878 var div = document.createElement("div");
3879
3880 try {
3881 return fn( div );
3882 } catch (e) {
3883 return false;
3884 } finally {
3885 // release memory in IE
3886 div = null;
3887 }
3888 }
3889
3890 function Sizzle( selector, context, results, seed ) {
3891 var match, elem, m, nodeType,
3892 // QSA vars
3893 i, groups, old, nid, newContext, newSelector;
3894
3895 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
3896 setDocument( context );
3897 }
3898
3899 context = context || document;
3900 results = results || [];
3901
3902 if ( !selector || typeof selector !== "string" ) {
3903 return results;
3904 }
3905
3906 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
3907 return [];
3908 }
3909
3910 if ( !documentIsXML && !seed ) {
3911
3912 // Shortcuts
3913 if ( (match = rquickExpr.exec( selector )) ) {
3914 // Speed-up: Sizzle("#ID")
3915 if ( (m = match[1]) ) {
3916 if ( nodeType === 9 ) {
3917 elem = context.getElementById( m );
3918 // Check parentNode to catch when Blackberry 4.6 returns
3919 // nodes that are no longer in the document #6963
3920 if ( elem && elem.parentNode ) {
3921 // Handle the case where IE, Opera, and Webkit return items
3922 // by name instead of ID
3923 if ( elem.id === m ) {
3924 results.push( elem );
3925 return results;
3926 }
3927 } else {
3928 return results;
3929 }
3930 } else {
3931 // Context is not a document
3932 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
3933 contains( context, elem ) && elem.id === m ) {
3934 results.push( elem );
3935 return results;
3936 }
3937 }
3938
3939 // Speed-up: Sizzle("TAG")
3940 } else if ( match[2] ) {
3941 push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
3942 return results;
3943
3944 // Speed-up: Sizzle(".CLASS")
3945 } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
3946 push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
3947 return results;
3948 }
3949 }
3950
3951 // QSA path
3952 if ( support.qsa && !rbuggyQSA.test(selector) ) {
3953 old = true;
3954 nid = expando;
3955 newContext = context;
3956 newSelector = nodeType === 9 && selector;
3957
3958 // qSA works strangely on Element-rooted queries
3959 // We can work around this by specifying an extra ID on the root
3960 // and working up from there (Thanks to Andrew Dupont for the technique)
3961 // IE 8 doesn't work on object elements
3962 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
3963 groups = tokenize( selector );
3964
3965 if ( (old = context.getAttribute("id")) ) {
3966 nid = old.replace( rescape, "\\$&" );
3967 } else {
3968 context.setAttribute( "id", nid );
3969 }
3970 nid = "[id='" + nid + "'] ";
3971
3972 i = groups.length;
3973 while ( i-- ) {
3974 groups[i] = nid + toSelector( groups[i] );
3975 }
3976 newContext = rsibling.test( selector ) && context.parentNode || context;
3977 newSelector = groups.join(",");
3978 }
3979
3980 if ( newSelector ) {
3981 try {
3982 push.apply( results, slice.call( newContext.querySelectorAll(
3983 newSelector
3984 ), 0 ) );
3985 return results;
3986 } catch(qsaError) {
3987 } finally {
3988 if ( !old ) {
3989 context.removeAttribute("id");
3990 }
3991 }
3992 }
3993 }
3994 }
3995
3996 // All others
3997 return select( selector.replace( rtrim, "$1" ), context, results, seed );
3998 }
3999
4000 /**
4001 * Detect xml
4002 * @param {Element|Object} elem An element or a document
4003 */
4004 isXML = Sizzle.isXML = function( elem ) {
4005 // documentElement is verified for cases where it doesn't yet exist
4006 // (such as loading iframes in IE - #4833)
4007 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4008 return documentElement ? documentElement.nodeName !== "HTML" : false;
4009 };
4010
4011 /**
4012 * Sets document-related variables once based on the current document
4013 * @param {Element|Object} [doc] An element or document object to use to set the document
4014 * @returns {Object} Returns the current document
4015 */
4016 setDocument = Sizzle.setDocument = function( node ) {
4017 var doc = node ? node.ownerDocument || node : preferredDoc;
4018
4019 // If no document and documentElement is available, return
4020 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4021 return document;
4022 }
4023
4024 // Set our document
4025 document = doc;
4026 docElem = doc.documentElement;
4027
4028 // Support tests
4029 documentIsXML = isXML( doc );
4030
4031 // Check if getElementsByTagName("*") returns only elements
4032 support.tagNameNoComments = assert(function( div ) {
4033 div.appendChild( doc.createComment("") );
4034 return !div.getElementsByTagName("*").length;
4035 });
4036
4037 // Check if attributes should be retrieved by attribute nodes
4038 support.attributes = assert(function( div ) {
4039 div.innerHTML = "<select></select>";
4040 var type = typeof div.lastChild.getAttribute("multiple");
4041 // IE8 returns a string for some attributes even when not present
4042 return type !== "boolean" && type !== "string";
4043 });
4044
4045 // Check if getElementsByClassName can be trusted
4046 support.getByClassName = assert(function( div ) {
4047 // Opera can't find a second classname (in 9.6)
4048 div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
4049 if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
4050 return false;
4051 }
4052
4053 // Safari 3.2 caches class attributes and doesn't catch changes
4054 div.lastChild.className = "e";
4055 return div.getElementsByClassName("e").length === 2;
4056 });
4057
4058 // Check if getElementById returns elements by name
4059 // Check if getElementsByName privileges form controls or returns elements by ID
4060 support.getByName = assert(function( div ) {
4061 // Inject content
4062 div.id = expando + 0;
4063 div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
4064 docElem.insertBefore( div, docElem.firstChild );
4065
4066 // Test
4067 var pass = doc.getElementsByName &&
4068 // buggy browsers will return fewer than the correct 2
4069 doc.getElementsByName( expando ).length === 2 +
4070 // buggy browsers will return more than the correct 0
4071 doc.getElementsByName( expando + 0 ).length;
4072 support.getIdNotName = !doc.getElementById( expando );
4073
4074 // Cleanup
4075 docElem.removeChild( div );
4076
4077 return pass;
4078 });
4079
4080 // IE6/7 return modified attributes
4081 Expr.attrHandle = assert(function( div ) {
4082 div.innerHTML = "<a href='#'></a>";
4083 return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
4084 div.firstChild.getAttribute("href") === "#";
4085 }) ?
4086 {} :
4087 {
4088 "href": function( elem ) {
4089 return elem.getAttribute( "href", 2 );
4090 },
4091 "type": function( elem ) {
4092 return elem.getAttribute("type");
4093 }
4094 };
4095
4096 // ID find and filter
4097 if ( support.getIdNotName ) {
4098 Expr.find["ID"] = function( id, context ) {
4099 if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4100 var m = context.getElementById( id );
4101 // Check parentNode to catch when Blackberry 4.6 returns
4102 // nodes that are no longer in the document #6963
4103 return m && m.parentNode ? [m] : [];
4104 }
4105 };
4106 Expr.filter["ID"] = function( id ) {
4107 var attrId = id.replace( runescape, funescape );
4108 return function( elem ) {
4109 return elem.getAttribute("id") === attrId;
4110 };
4111 };
4112 } else {
4113 Expr.find["ID"] = function( id, context ) {
4114 if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4115 var m = context.getElementById( id );
4116
4117 return m ?
4118 m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
4119 [m] :
4120 undefined :
4121 [];
4122 }
4123 };
4124 Expr.filter["ID"] = function( id ) {
4125 var attrId = id.replace( runescape, funescape );
4126 return function( elem ) {
4127 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
4128 return node && node.value === attrId;
4129 };
4130 };
4131 }
4132
4133 // Tag
4134 Expr.find["TAG"] = support.tagNameNoComments ?
4135 function( tag, context ) {
4136 if ( typeof context.getElementsByTagName !== strundefined ) {
4137 return context.getElementsByTagName( tag );
4138 }
4139 } :
4140 function( tag, context ) {
4141 var elem,
4142 tmp = [],
4143 i = 0,
4144 results = context.getElementsByTagName( tag );
4145
4146 // Filter out possible comments
4147 if ( tag === "*" ) {
4148 while ( (elem = results[i++]) ) {
4149 if ( elem.nodeType === 1 ) {
4150 tmp.push( elem );
4151 }
4152 }
4153
4154 return tmp;
4155 }
4156 return results;
4157 };
4158
4159 // Name
4160 Expr.find["NAME"] = support.getByName && function( tag, context ) {
4161 if ( typeof context.getElementsByName !== strundefined ) {
4162 return context.getElementsByName( name );
4163 }
4164 };
4165
4166 // Class
4167 Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
4168 if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
4169 return context.getElementsByClassName( className );
4170 }
4171 };
4172
4173 // QSA and matchesSelector support
4174
4175 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
4176 rbuggyMatches = [];
4177
4178 // qSa(:focus) reports false when true (Chrome 21),
4179 // no need to also add to buggyMatches since matches checks buggyQSA
4180 // A support test would require too much code (would include document ready)
4181 rbuggyQSA = [ ":focus" ];
4182
4183 if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
4184 // Build QSA regex
4185 // Regex strategy adopted from Diego Perini
4186 assert(function( div ) {
4187 // Select is set to empty string on purpose
4188 // This is to test IE's treatment of not explictly
4189 // setting a boolean content attribute,
4190 // since its presence should be enough
4191 // http://bugs.jquery.com/ticket/12359
4192 div.innerHTML = "<select><option selected=''></option></select>";
4193
4194 // IE8 - Some boolean attributes are not treated correctly
4195 if ( !div.querySelectorAll("[selected]").length ) {
4196 rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
4197 }
4198
4199 // Webkit/Opera - :checked should return selected option elements
4200 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4201 // IE8 throws error here and will not see later tests
4202 if ( !div.querySelectorAll(":checked").length ) {
4203 rbuggyQSA.push(":checked");
4204 }
4205 });
4206
4207 assert(function( div ) {
4208
4209 // Opera 10-12/IE8 - ^= $= *= and empty values
4210 // Should not select anything
4211 div.innerHTML = "<input type='hidden' i=''/>";
4212 if ( div.querySelectorAll("[i^='']").length ) {
4213 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
4214 }
4215
4216 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
4217 // IE8 throws error here and will not see later tests
4218 if ( !div.querySelectorAll(":enabled").length ) {
4219 rbuggyQSA.push( ":enabled", ":disabled" );
4220 }
4221
4222 // Opera 10-11 does not throw on post-comma invalid pseudos
4223 div.querySelectorAll("*,:x");
4224 rbuggyQSA.push(",.*:");
4225 });
4226 }
4227
4228 if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
4229 docElem.mozMatchesSelector ||
4230 docElem.webkitMatchesSelector ||
4231 docElem.oMatchesSelector ||
4232 docElem.msMatchesSelector) )) ) {
4233
4234 assert(function( div ) {
4235 // Check to see if it's possible to do matchesSelector
4236 // on a disconnected node (IE 9)
4237 support.disconnectedMatch = matches.call( div, "div" );
4238
4239 // This should fail with an exception
4240 // Gecko does not error, returns false instead
4241 matches.call( div, "[s!='']:x" );
4242 rbuggyMatches.push( "!=", pseudos );
4243 });
4244 }
4245
4246 rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
4247 rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
4248
4249 // Element contains another
4250 // Purposefully does not implement inclusive descendent
4251 // As in, an element does not contain itself
4252 contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
4253 function( a, b ) {
4254 var adown = a.nodeType === 9 ? a.documentElement : a,
4255 bup = b && b.parentNode;
4256 return a === bup || !!( bup && bup.nodeType === 1 && (
4257 adown.contains ?
4258 adown.contains( bup ) :
4259 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
4260 ));
4261 } :
4262 function( a, b ) {
4263 if ( b ) {
4264 while ( (b = b.parentNode) ) {
4265 if ( b === a ) {
4266 return true;
4267 }
4268 }
4269 }
4270 return false;
4271 };
4272
4273 // Document order sorting
4274 sortOrder = docElem.compareDocumentPosition ?
4275 function( a, b ) {
4276 var compare;
4277
4278 if ( a === b ) {
4279 hasDuplicate = true;
4280 return 0;
4281 }
4282
4283 if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
4284 if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
4285 if ( a === doc || contains( preferredDoc, a ) ) {
4286 return -1;
4287 }
4288 if ( b === doc || contains( preferredDoc, b ) ) {
4289 return 1;
4290 }
4291 return 0;
4292 }
4293 return compare & 4 ? -1 : 1;
4294 }
4295
4296 return a.compareDocumentPosition ? -1 : 1;
4297 } :
4298 function( a, b ) {
4299 var cur,
4300 i = 0,
4301 aup = a.parentNode,
4302 bup = b.parentNode,
4303 ap = [ a ],
4304 bp = [ b ];
4305
4306 // Exit early if the nodes are identical
4307 if ( a === b ) {
4308 hasDuplicate = true;
4309 return 0;
4310
4311 // Parentless nodes are either documents or disconnected
4312 } else if ( !aup || !bup ) {
4313 return a === doc ? -1 :
4314 b === doc ? 1 :
4315 aup ? -1 :
4316 bup ? 1 :
4317 0;
4318
4319 // If the nodes are siblings, we can do a quick check
4320 } else if ( aup === bup ) {
4321 return siblingCheck( a, b );
4322 }
4323
4324 // Otherwise we need full lists of their ancestors for comparison
4325 cur = a;
4326 while ( (cur = cur.parentNode) ) {
4327 ap.unshift( cur );
4328 }
4329 cur = b;
4330 while ( (cur = cur.parentNode) ) {
4331 bp.unshift( cur );
4332 }
4333
4334 // Walk down the tree looking for a discrepancy
4335 while ( ap[i] === bp[i] ) {
4336 i++;
4337 }
4338
4339 return i ?
4340 // Do a sibling check if the nodes have a common ancestor
4341 siblingCheck( ap[i], bp[i] ) :
4342
4343 // Otherwise nodes in our document sort first
4344 ap[i] === preferredDoc ? -1 :
4345 bp[i] === preferredDoc ? 1 :
4346 0;
4347 };
4348
4349 // Always assume the presence of duplicates if sort doesn't
4350 // pass them to our comparison function (as in Google Chrome).
4351 hasDuplicate = false;
4352 [0, 0].sort( sortOrder );
4353 support.detectDuplicates = hasDuplicate;
4354
4355 return document;
4356 };
4357
4358 Sizzle.matches = function( expr, elements ) {
4359 return Sizzle( expr, null, null, elements );
4360 };
4361
4362 Sizzle.matchesSelector = function( elem, expr ) {
4363 // Set document vars if needed
4364 if ( ( elem.ownerDocument || elem ) !== document ) {
4365 setDocument( elem );
4366 }
4367
4368 // Make sure that attribute selectors are quoted
4369 expr = expr.replace( rattributeQuotes, "='$1']" );
4370
4371 // rbuggyQSA always contains :focus, so no need for an existence check
4372 if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
4373 try {
4374 var ret = matches.call( elem, expr );
4375
4376 // IE 9's matchesSelector returns false on disconnected nodes
4377 if ( ret || support.disconnectedMatch ||
4378 // As well, disconnected nodes are said to be in a document
4379 // fragment in IE 9
4380 elem.document && elem.document.nodeType !== 11 ) {
4381 return ret;
4382 }
4383 } catch(e) {}
4384 }
4385
4386 return Sizzle( expr, document, null, [elem] ).length > 0;
4387 };
4388
4389 Sizzle.contains = function( context, elem ) {
4390 // Set document vars if needed
4391 if ( ( context.ownerDocument || context ) !== document ) {
4392 setDocument( context );
4393 }
4394 return contains( context, elem );
4395 };
4396
4397 Sizzle.attr = function( elem, name ) {
4398 var val;
4399
4400 // Set document vars if needed
4401 if ( ( elem.ownerDocument || elem ) !== document ) {
4402 setDocument( elem );
4403 }
4404
4405 if ( !documentIsXML ) {
4406 name = name.toLowerCase();
4407 }
4408 if ( (val = Expr.attrHandle[ name ]) ) {
4409 return val( elem );
4410 }
4411 if ( documentIsXML || support.attributes ) {
4412 return elem.getAttribute( name );
4413 }
4414 return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
4415 name :
4416 val && val.specified ? val.value : null;
4417 };
4418
4419 Sizzle.error = function( msg ) {
4420 throw new Error( "Syntax error, unrecognized expression: " + msg );
4421 };
4422
4423 // Document sorting and removing duplicates
4424 Sizzle.uniqueSort = function( results ) {
4425 var elem,
4426 duplicates = [],
4427 i = 1,
4428 j = 0;
4429
4430 // Unless we *know* we can detect duplicates, assume their presence
4431 hasDuplicate = !support.detectDuplicates;
4432 results.sort( sortOrder );
4433
4434 if ( hasDuplicate ) {
4435 for ( ; (elem = results[i]); i++ ) {
4436 if ( elem === results[ i - 1 ] ) {
4437 j = duplicates.push( i );
4438 }
4439 }
4440 while ( j-- ) {
4441 results.splice( duplicates[ j ], 1 );
4442 }
4443 }
4444
4445 return results;
4446 };
4447
4448 function siblingCheck( a, b ) {
4449 var cur = b && a,
4450 diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
4451
4452 // Use IE sourceIndex if available on both nodes
4453 if ( diff ) {
4454 return diff;
4455 }
4456
4457 // Check if b follows a
4458 if ( cur ) {
4459 while ( (cur = cur.nextSibling) ) {
4460 if ( cur === b ) {
4461 return -1;
4462 }
4463 }
4464 }
4465
4466 return a ? 1 : -1;
4467 }
4468
4469 // Returns a function to use in pseudos for input types
4470 function createInputPseudo( type ) {
4471 return function( elem ) {
4472 var name = elem.nodeName.toLowerCase();
4473 return name === "input" && elem.type === type;
4474 };
4475 }
4476
4477 // Returns a function to use in pseudos for buttons
4478 function createButtonPseudo( type ) {
4479 return function( elem ) {
4480 var name = elem.nodeName.toLowerCase();
4481 return (name === "input" || name === "button") && elem.type === type;
4482 };
4483 }
4484
4485 // Returns a function to use in pseudos for positionals
4486 function createPositionalPseudo( fn ) {
4487 return markFunction(function( argument ) {
4488 argument = +argument;
4489 return markFunction(function( seed, matches ) {
4490 var j,
4491 matchIndexes = fn( [], seed.length, argument ),
4492 i = matchIndexes.length;
4493
4494 // Match elements found at the specified indexes
4495 while ( i-- ) {
4496 if ( seed[ (j = matchIndexes[i]) ] ) {
4497 seed[j] = !(matches[j] = seed[j]);
4498 }
4499 }
4500 });
4501 });
4502 }
4503
4504 /**
4505 * Utility function for retrieving the text value of an array of DOM nodes
4506 * @param {Array|Element} elem
4507 */
4508 getText = Sizzle.getText = function( elem ) {
4509 var node,
4510 ret = "",
4511 i = 0,
4512 nodeType = elem.nodeType;
4513
4514 if ( !nodeType ) {
4515 // If no nodeType, this is expected to be an array
4516 for ( ; (node = elem[i]); i++ ) {
4517 // Do not traverse comment nodes
4518 ret += getText( node );
4519 }
4520 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
4521 // Use textContent for elements
4522 // innerText usage removed for consistency of new lines (see #11153)
4523 if ( typeof elem.textContent === "string" ) {
4524 return elem.textContent;
4525 } else {
4526 // Traverse its children
4527 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4528 ret += getText( elem );
4529 }
4530 }
4531 } else if ( nodeType === 3 || nodeType === 4 ) {
4532 return elem.nodeValue;
4533 }
4534 // Do not include comment or processing instruction nodes
4535
4536 return ret;
4537 };
4538
4539 Expr = Sizzle.selectors = {
4540
4541 // Can be adjusted by the user
4542 cacheLength: 50,
4543
4544 createPseudo: markFunction,
4545
4546 match: matchExpr,
4547
4548 find: {},
4549
4550 relative: {
4551 ">": { dir: "parentNode", first: true },
4552 " ": { dir: "parentNode" },
4553 "+": { dir: "previousSibling", first: true },
4554 "~": { dir: "previousSibling" }
4555 },
4556
4557 preFilter: {
4558 "ATTR": function( match ) {
4559 match[1] = match[1].replace( runescape, funescape );
4560
4561 // Move the given value to match[3] whether quoted or unquoted
4562 match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
4563
4564 if ( match[2] === "~=" ) {
4565 match[3] = " " + match[3] + " ";
4566 }
4567
4568 return match.slice( 0, 4 );
4569 },
4570
4571 "CHILD": function( match ) {
4572 /* matches from matchExpr["CHILD"]
4573 1 type (only|nth|...)
4574 2 what (child|of-type)
4575 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4576 4 xn-component of xn+y argument ([+-]?\d*n|)
4577 5 sign of xn-component
4578 6 x of xn-component
4579 7 sign of y-component
4580 8 y of y-component
4581 */
4582 match[1] = match[1].toLowerCase();
4583
4584 if ( match[1].slice( 0, 3 ) === "nth" ) {
4585 // nth-* requires argument
4586 if ( !match[3] ) {
4587 Sizzle.error( match[0] );
4588 }
4589
4590 // numeric x and y parameters for Expr.filter.CHILD
4591 // remember that false/true cast respectively to 0/1
4592 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
4593 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
4594
4595 // other types prohibit arguments
4596 } else if ( match[3] ) {
4597 Sizzle.error( match[0] );
4598 }
4599
4600 return match;
4601 },
4602
4603 "PSEUDO": function( match ) {
4604 var excess,
4605 unquoted = !match[5] && match[2];
4606
4607 if ( matchExpr["CHILD"].test( match[0] ) ) {
4608 return null;
4609 }
4610
4611 // Accept quoted arguments as-is
4612 if ( match[4] ) {
4613 match[2] = match[4];
4614
4615 // Strip excess characters from unquoted arguments
4616 } else if ( unquoted && rpseudo.test( unquoted ) &&
4617 // Get excess from tokenize (recursively)
4618 (excess = tokenize( unquoted, true )) &&
4619 // advance to the next closing parenthesis
4620 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
4621
4622 // excess is a negative index
4623 match[0] = match[0].slice( 0, excess );
4624 match[2] = unquoted.slice( 0, excess );
4625 }
4626
4627 // Return only captures needed by the pseudo filter method (type and argument)
4628 return match.slice( 0, 3 );
4629 }
4630 },
4631
4632 filter: {
4633
4634 "TAG": function( nodeName ) {
4635 if ( nodeName === "*" ) {
4636 return function() { return true; };
4637 }
4638
4639 nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
4640 return function( elem ) {
4641 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
4642 };
4643 },
4644
4645 "CLASS": function( className ) {
4646 var pattern = classCache[ className + " " ];
4647
4648 return pattern ||
4649 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
4650 classCache( className, function( elem ) {
4651 return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
4652 });
4653 },
4654
4655 "ATTR": function( name, operator, check ) {
4656 return function( elem ) {
4657 var result = Sizzle.attr( elem, name );
4658
4659 if ( result == null ) {
4660 return operator === "!=";
4661 }
4662 if ( !operator ) {
4663 return true;
4664 }
4665
4666 result += "";
4667
4668 return operator === "=" ? result === check :
4669 operator === "!=" ? result !== check :
4670 operator === "^=" ? check && result.indexOf( check ) === 0 :
4671 operator === "*=" ? check && result.indexOf( check ) > -1 :
4672 operator === "$=" ? check && result.slice( -check.length ) === check :
4673 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
4674 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
4675 false;
4676 };
4677 },
4678
4679 "CHILD": function( type, what, argument, first, last ) {
4680 var simple = type.slice( 0, 3 ) !== "nth",
4681 forward = type.slice( -4 ) !== "last",
4682 ofType = what === "of-type";
4683
4684 return first === 1 && last === 0 ?
4685
4686 // Shortcut for :nth-*(n)
4687 function( elem ) {
4688 return !!elem.parentNode;
4689 } :
4690
4691 function( elem, context, xml ) {
4692 var cache, outerCache, node, diff, nodeIndex, start,
4693 dir = simple !== forward ? "nextSibling" : "previousSibling",
4694 parent = elem.parentNode,
4695 name = ofType && elem.nodeName.toLowerCase(),
4696 useCache = !xml && !ofType;
4697
4698 if ( parent ) {
4699
4700 // :(first|last|only)-(child|of-type)
4701 if ( simple ) {
4702 while ( dir ) {
4703 node = elem;
4704 while ( (node = node[ dir ]) ) {
4705 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
4706 return false;
4707 }
4708 }
4709 // Reverse direction for :only-* (if we haven't yet done so)
4710 start = dir = type === "only" && !start && "nextSibling";
4711 }
4712 return true;
4713 }
4714
4715 start = [ forward ? parent.firstChild : parent.lastChild ];
4716
4717 // non-xml :nth-child(...) stores cache data on `parent`
4718 if ( forward && useCache ) {
4719 // Seek `elem` from a previously-cached index
4720 outerCache = parent[ expando ] || (parent[ expando ] = {});
4721 cache = outerCache[ type ] || [];
4722 nodeIndex = cache[0] === dirruns && cache[1];
4723 diff = cache[0] === dirruns && cache[2];
4724 node = nodeIndex && parent.childNodes[ nodeIndex ];
4725
4726 while ( (node = ++nodeIndex && node && node[ dir ] ||
4727
4728 // Fallback to seeking `elem` from the start
4729 (diff = nodeIndex = 0) || start.pop()) ) {
4730
4731 // When found, cache indexes on `parent` and break
4732 if ( node.nodeType === 1 && ++diff && node === elem ) {
4733 outerCache[ type ] = [ dirruns, nodeIndex, diff ];
4734 break;
4735 }
4736 }
4737
4738 // Use previously-cached element index if available
4739 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
4740 diff = cache[1];
4741
4742 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
4743 } else {
4744 // Use the same loop as above to seek `elem` from the start
4745 while ( (node = ++nodeIndex && node && node[ dir ] ||
4746 (diff = nodeIndex = 0) || start.pop()) ) {
4747
4748 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
4749 // Cache the index of each encountered element
4750 if ( useCache ) {
4751 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
4752 }
4753
4754 if ( node === elem ) {
4755 break;
4756 }
4757 }
4758 }
4759 }
4760
4761 // Incorporate the offset, then check against cycle size
4762 diff -= last;
4763 return diff === first || ( diff % first === 0 && diff / first >= 0 );
4764 }
4765 };
4766 },
4767
4768 "PSEUDO": function( pseudo, argument ) {
4769 // pseudo-class names are case-insensitive
4770 // http://www.w3.org/TR/selectors/#pseudo-classes
4771 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
4772 // Remember that setFilters inherits from pseudos
4773 var args,
4774 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
4775 Sizzle.error( "unsupported pseudo: " + pseudo );
4776
4777 // The user may use createPseudo to indicate that
4778 // arguments are needed to create the filter function
4779 // just as Sizzle does
4780 if ( fn[ expando ] ) {
4781 return fn( argument );
4782 }
4783
4784 // But maintain support for old signatures
4785 if ( fn.length > 1 ) {
4786 args = [ pseudo, pseudo, "", argument ];
4787 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
4788 markFunction(function( seed, matches ) {
4789 var idx,
4790 matched = fn( seed, argument ),
4791 i = matched.length;
4792 while ( i-- ) {
4793 idx = indexOf.call( seed, matched[i] );
4794 seed[ idx ] = !( matches[ idx ] = matched[i] );
4795 }
4796 }) :
4797 function( elem ) {
4798 return fn( elem, 0, args );
4799 };
4800 }
4801
4802 return fn;
4803 }
4804 },
4805
4806 pseudos: {
4807 // Potentially complex pseudos
4808 "not": markFunction(function( selector ) {
4809 // Trim the selector passed to compile
4810 // to avoid treating leading and trailing
4811 // spaces as combinators
4812 var input = [],
4813 results = [],
4814 matcher = compile( selector.replace( rtrim, "$1" ) );
4815
4816 return matcher[ expando ] ?
4817 markFunction(function( seed, matches, context, xml ) {
4818 var elem,
4819 unmatched = matcher( seed, null, xml, [] ),
4820 i = seed.length;
4821
4822 // Match elements unmatched by `matcher`
4823 while ( i-- ) {
4824 if ( (elem = unmatched[i]) ) {
4825 seed[i] = !(matches[i] = elem);
4826 }
4827 }
4828 }) :
4829 function( elem, context, xml ) {
4830 input[0] = elem;
4831 matcher( input, null, xml, results );
4832 return !results.pop();
4833 };
4834 }),
4835
4836 "has": markFunction(function( selector ) {
4837 return function( elem ) {
4838 return Sizzle( selector, elem ).length > 0;
4839 };
4840 }),
4841
4842 "contains": markFunction(function( text ) {
4843 return function( elem ) {
4844 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
4845 };
4846 }),
4847
4848 // "Whether an element is represented by a :lang() selector
4849 // is based solely on the element's language value
4850 // being equal to the identifier C,
4851 // or beginning with the identifier C immediately followed by "-".
4852 // The matching of C against the element's language value is performed case-insensitively.
4853 // The identifier C does not have to be a valid language name."
4854 // http://www.w3.org/TR/selectors/#lang-pseudo
4855 "lang": markFunction( function( lang ) {
4856 // lang value must be a valid identifider
4857 if ( !ridentifier.test(lang || "") ) {
4858 Sizzle.error( "unsupported lang: " + lang );
4859 }
4860 lang = lang.replace( runescape, funescape ).toLowerCase();
4861 return function( elem ) {
4862 var elemLang;
4863 do {
4864 if ( (elemLang = documentIsXML ?
4865 elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
4866 elem.lang) ) {
4867
4868 elemLang = elemLang.toLowerCase();
4869 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
4870 }
4871 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
4872 return false;
4873 };
4874 }),
4875
4876 // Miscellaneous
4877 "target": function( elem ) {
4878 var hash = window.location && window.location.hash;
4879 return hash && hash.slice( 1 ) === elem.id;
4880 },
4881
4882 "root": function( elem ) {
4883 return elem === docElem;
4884 },
4885
4886 "focus": function( elem ) {
4887 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
4888 },
4889
4890 // Boolean properties
4891 "enabled": function( elem ) {
4892 return elem.disabled === false;
4893 },
4894
4895 "disabled": function( elem ) {
4896 return elem.disabled === true;
4897 },
4898
4899 "checked": function( elem ) {
4900 // In CSS3, :checked should return both checked and selected elements
4901 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4902 var nodeName = elem.nodeName.toLowerCase();
4903 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
4904 },
4905
4906 "selected": function( elem ) {
4907 // Accessing this property makes selected-by-default
4908 // options in Safari work properly
4909 if ( elem.parentNode ) {
4910 elem.parentNode.selectedIndex;
4911 }
4912
4913 return elem.selected === true;
4914 },
4915
4916 // Contents
4917 "empty": function( elem ) {
4918 // http://www.w3.org/TR/selectors/#empty-pseudo
4919 // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
4920 // not comment, processing instructions, or others
4921 // Thanks to Diego Perini for the nodeName shortcut
4922 // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
4923 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4924 if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
4925 return false;
4926 }
4927 }
4928 return true;
4929 },
4930
4931 "parent": function( elem ) {
4932 return !Expr.pseudos["empty"]( elem );
4933 },
4934
4935 // Element/input types
4936 "header": function( elem ) {
4937 return rheader.test( elem.nodeName );
4938 },
4939
4940 "input": function( elem ) {
4941 return rinputs.test( elem.nodeName );
4942 },
4943
4944 "button": function( elem ) {
4945 var name = elem.nodeName.toLowerCase();
4946 return name === "input" && elem.type === "button" || name === "button";
4947 },
4948
4949 "text": function( elem ) {
4950 var attr;
4951 // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
4952 // use getAttribute instead to test this case
4953 return elem.nodeName.toLowerCase() === "input" &&
4954 elem.type === "text" &&
4955 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
4956 },
4957
4958 // Position-in-collection
4959 "first": createPositionalPseudo(function() {
4960 return [ 0 ];
4961 }),
4962
4963 "last": createPositionalPseudo(function( matchIndexes, length ) {
4964 return [ length - 1 ];
4965 }),
4966
4967 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
4968 return [ argument < 0 ? argument + length : argument ];
4969 }),
4970
4971 "even": createPositionalPseudo(function( matchIndexes, length ) {
4972 var i = 0;
4973 for ( ; i < length; i += 2 ) {
4974 matchIndexes.push( i );
4975 }
4976 return matchIndexes;
4977 }),
4978
4979 "odd": createPositionalPseudo(function( matchIndexes, length ) {
4980 var i = 1;
4981 for ( ; i < length; i += 2 ) {
4982 matchIndexes.push( i );
4983 }
4984 return matchIndexes;
4985 }),
4986
4987 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4988 var i = argument < 0 ? argument + length : argument;
4989 for ( ; --i >= 0; ) {
4990 matchIndexes.push( i );
4991 }
4992 return matchIndexes;
4993 }),
4994
4995 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4996 var i = argument < 0 ? argument + length : argument;
4997 for ( ; ++i < length; ) {
4998 matchIndexes.push( i );
4999 }
5000 return matchIndexes;
5001 })
5002 }
5003 };
5004
5005 // Add button/input type pseudos
5006 for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
5007 Expr.pseudos[ i ] = createInputPseudo( i );
5008 }
5009 for ( i in { submit: true, reset: true } ) {
5010 Expr.pseudos[ i ] = createButtonPseudo( i );
5011 }
5012
5013 function tokenize( selector, parseOnly ) {
5014 var matched, match, tokens, type,
5015 soFar, groups, preFilters,
5016 cached = tokenCache[ selector + " " ];
5017
5018 if ( cached ) {
5019 return parseOnly ? 0 : cached.slice( 0 );
5020 }
5021
5022 soFar = selector;
5023 groups = [];
5024 preFilters = Expr.preFilter;
5025
5026 while ( soFar ) {
5027
5028 // Comma and first run
5029 if ( !matched || (match = rcomma.exec( soFar )) ) {
5030 if ( match ) {
5031 // Don't consume trailing commas as valid
5032 soFar = soFar.slice( match[0].length ) || soFar;
5033 }
5034 groups.push( tokens = [] );
5035 }
5036
5037 matched = false;
5038
5039 // Combinators
5040 if ( (match = rcombinators.exec( soFar )) ) {
5041 matched = match.shift();
5042 tokens.push( {
5043 value: matched,
5044 // Cast descendant combinators to space
5045 type: match[0].replace( rtrim, " " )
5046 } );
5047 soFar = soFar.slice( matched.length );
5048 }
5049
5050 // Filters
5051 for ( type in Expr.filter ) {
5052 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5053 (match = preFilters[ type ]( match ))) ) {
5054 matched = match.shift();
5055 tokens.push( {
5056 value: matched,
5057 type: type,
5058 matches: match
5059 } );
5060 soFar = soFar.slice( matched.length );
5061 }
5062 }
5063
5064 if ( !matched ) {
5065 break;
5066 }
5067 }
5068
5069 // Return the length of the invalid excess
5070 // if we're just parsing
5071 // Otherwise, throw an error or return tokens
5072 return parseOnly ?
5073 soFar.length :
5074 soFar ?
5075 Sizzle.error( selector ) :
5076 // Cache the tokens
5077 tokenCache( selector, groups ).slice( 0 );
5078 }
5079
5080 function toSelector( tokens ) {
5081 var i = 0,
5082 len = tokens.length,
5083 selector = "";
5084 for ( ; i < len; i++ ) {
5085 selector += tokens[i].value;
5086 }
5087 return selector;
5088 }
5089
5090 function addCombinator( matcher, combinator, base ) {
5091 var dir = combinator.dir,
5092 checkNonElements = base && dir === "parentNode",
5093 doneName = done++;
5094
5095 return combinator.first ?
5096 // Check against closest ancestor/preceding element
5097 function( elem, context, xml ) {
5098 while ( (elem = elem[ dir ]) ) {
5099 if ( elem.nodeType === 1 || checkNonElements ) {
5100 return matcher( elem, context, xml );
5101 }
5102 }
5103 } :
5104
5105 // Check against all ancestor/preceding elements
5106 function( elem, context, xml ) {
5107 var data, cache, outerCache,
5108 dirkey = dirruns + " " + doneName;
5109
5110 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
5111 if ( xml ) {
5112 while ( (elem = elem[ dir ]) ) {
5113 if ( elem.nodeType === 1 || checkNonElements ) {
5114 if ( matcher( elem, context, xml ) ) {
5115 return true;
5116 }
5117 }
5118 }
5119 } else {
5120 while ( (elem = elem[ dir ]) ) {
5121 if ( elem.nodeType === 1 || checkNonElements ) {
5122 outerCache = elem[ expando ] || (elem[ expando ] = {});
5123 if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
5124 if ( (data = cache[1]) === true || data === cachedruns ) {
5125 return data === true;
5126 }
5127 } else {
5128 cache = outerCache[ dir ] = [ dirkey ];
5129 cache[1] = matcher( elem, context, xml ) || cachedruns;
5130 if ( cache[1] === true ) {
5131 return true;
5132 }
5133 }
5134 }
5135 }
5136 }
5137 };
5138 }
5139
5140 function elementMatcher( matchers ) {
5141 return matchers.length > 1 ?
5142 function( elem, context, xml ) {
5143 var i = matchers.length;
5144 while ( i-- ) {
5145 if ( !matchers[i]( elem, context, xml ) ) {
5146 return false;
5147 }
5148 }
5149 return true;
5150 } :
5151 matchers[0];
5152 }
5153
5154 function condense( unmatched, map, filter, context, xml ) {
5155 var elem,
5156 newUnmatched = [],
5157 i = 0,
5158 len = unmatched.length,
5159 mapped = map != null;
5160
5161 for ( ; i < len; i++ ) {
5162 if ( (elem = unmatched[i]) ) {
5163 if ( !filter || filter( elem, context, xml ) ) {
5164 newUnmatched.push( elem );
5165 if ( mapped ) {
5166 map.push( i );
5167 }
5168 }
5169 }
5170 }
5171
5172 return newUnmatched;
5173 }
5174
5175 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5176 if ( postFilter && !postFilter[ expando ] ) {
5177 postFilter = setMatcher( postFilter );
5178 }
5179 if ( postFinder && !postFinder[ expando ] ) {
5180 postFinder = setMatcher( postFinder, postSelector );
5181 }
5182 return markFunction(function( seed, results, context, xml ) {
5183 var temp, i, elem,
5184 preMap = [],
5185 postMap = [],
5186 preexisting = results.length,
5187
5188 // Get initial elements from seed or context
5189 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5190
5191 // Prefilter to get matcher input, preserving a map for seed-results synchronization
5192 matcherIn = preFilter && ( seed || !selector ) ?
5193 condense( elems, preMap, preFilter, context, xml ) :
5194 elems,
5195
5196 matcherOut = matcher ?
5197 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
5198 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5199
5200 // ...intermediate processing is necessary
5201 [] :
5202
5203 // ...otherwise use results directly
5204 results :
5205 matcherIn;
5206
5207 // Find primary matches
5208 if ( matcher ) {
5209 matcher( matcherIn, matcherOut, context, xml );
5210 }
5211
5212 // Apply postFilter
5213 if ( postFilter ) {
5214 temp = condense( matcherOut, postMap );
5215 postFilter( temp, [], context, xml );
5216
5217 // Un-match failing elements by moving them back to matcherIn
5218 i = temp.length;
5219 while ( i-- ) {
5220 if ( (elem = temp[i]) ) {
5221 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5222 }
5223 }
5224 }
5225
5226 if ( seed ) {
5227 if ( postFinder || preFilter ) {
5228 if ( postFinder ) {
5229 // Get the final matcherOut by condensing this intermediate into postFinder contexts
5230 temp = [];
5231 i = matcherOut.length;
5232 while ( i-- ) {
5233 if ( (elem = matcherOut[i]) ) {
5234 // Restore matcherIn since elem is not yet a final match
5235 temp.push( (matcherIn[i] = elem) );
5236 }
5237 }
5238 postFinder( null, (matcherOut = []), temp, xml );
5239 }
5240
5241 // Move matched elements from seed to results to keep them synchronized
5242 i = matcherOut.length;
5243 while ( i-- ) {
5244 if ( (elem = matcherOut[i]) &&
5245 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
5246
5247 seed[temp] = !(results[temp] = elem);
5248 }
5249 }
5250 }
5251
5252 // Add elements to results, through postFinder if defined
5253 } else {
5254 matcherOut = condense(
5255 matcherOut === results ?
5256 matcherOut.splice( preexisting, matcherOut.length ) :
5257 matcherOut
5258 );
5259 if ( postFinder ) {
5260 postFinder( null, results, matcherOut, xml );
5261 } else {
5262 push.apply( results, matcherOut );
5263 }
5264 }
5265 });
5266 }
5267
5268 function matcherFromTokens( tokens ) {
5269 var checkContext, matcher, j,
5270 len = tokens.length,
5271 leadingRelative = Expr.relative[ tokens[0].type ],
5272 implicitRelative = leadingRelative || Expr.relative[" "],
5273 i = leadingRelative ? 1 : 0,
5274
5275 // The foundational matcher ensures that elements are reachable from top-level context(s)
5276 matchContext = addCombinator( function( elem ) {
5277 return elem === checkContext;
5278 }, implicitRelative, true ),
5279 matchAnyContext = addCombinator( function( elem ) {
5280 return indexOf.call( checkContext, elem ) > -1;
5281 }, implicitRelative, true ),
5282 matchers = [ function( elem, context, xml ) {
5283 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
5284 (checkContext = context).nodeType ?
5285 matchContext( elem, context, xml ) :
5286 matchAnyContext( elem, context, xml ) );
5287 } ];
5288
5289 for ( ; i < len; i++ ) {
5290 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
5291 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
5292 } else {
5293 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
5294
5295 // Return special upon seeing a positional matcher
5296 if ( matcher[ expando ] ) {
5297 // Find the next relative operator (if any) for proper handling
5298 j = ++i;
5299 for ( ; j < len; j++ ) {
5300 if ( Expr.relative[ tokens[j].type ] ) {
5301 break;
5302 }
5303 }
5304 return setMatcher(
5305 i > 1 && elementMatcher( matchers ),
5306 i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
5307 matcher,
5308 i < j && matcherFromTokens( tokens.slice( i, j ) ),
5309 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
5310 j < len && toSelector( tokens )
5311 );
5312 }
5313 matchers.push( matcher );
5314 }
5315 }
5316
5317 return elementMatcher( matchers );
5318 }
5319
5320 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
5321 // A counter to specify which element is currently being matched
5322 var matcherCachedRuns = 0,
5323 bySet = setMatchers.length > 0,
5324 byElement = elementMatchers.length > 0,
5325 superMatcher = function( seed, context, xml, results, expandContext ) {
5326 var elem, j, matcher,
5327 setMatched = [],
5328 matchedCount = 0,
5329 i = "0",
5330 unmatched = seed && [],
5331 outermost = expandContext != null,
5332 contextBackup = outermostContext,
5333 // We must always have either seed elements or context
5334 elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
5335 // Use integer dirruns iff this is the outermost matcher
5336 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
5337
5338 if ( outermost ) {
5339 outermostContext = context !== document && context;
5340 cachedruns = matcherCachedRuns;
5341 }
5342
5343 // Add elements passing elementMatchers directly to results
5344 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
5345 for ( ; (elem = elems[i]) != null; i++ ) {
5346 if ( byElement && elem ) {
5347 j = 0;
5348 while ( (matcher = elementMatchers[j++]) ) {
5349 if ( matcher( elem, context, xml ) ) {
5350 results.push( elem );
5351 break;
5352 }
5353 }
5354 if ( outermost ) {
5355 dirruns = dirrunsUnique;
5356 cachedruns = ++matcherCachedRuns;
5357 }
5358 }
5359
5360 // Track unmatched elements for set filters
5361 if ( bySet ) {
5362 // They will have gone through all possible matchers
5363 if ( (elem = !matcher && elem) ) {
5364 matchedCount--;
5365 }
5366
5367 // Lengthen the array for every element, matched or not
5368 if ( seed ) {
5369 unmatched.push( elem );
5370 }
5371 }
5372 }
5373
5374 // Apply set filters to unmatched elements
5375 matchedCount += i;
5376 if ( bySet && i !== matchedCount ) {
5377 j = 0;
5378 while ( (matcher = setMatchers[j++]) ) {
5379 matcher( unmatched, setMatched, context, xml );
5380 }
5381
5382 if ( seed ) {
5383 // Reintegrate element matches to eliminate the need for sorting
5384 if ( matchedCount > 0 ) {
5385 while ( i-- ) {
5386 if ( !(unmatched[i] || setMatched[i]) ) {
5387 setMatched[i] = pop.call( results );
5388 }
5389 }
5390 }
5391
5392 // Discard index placeholder values to get only actual matches
5393 setMatched = condense( setMatched );
5394 }
5395
5396 // Add matches to results
5397 push.apply( results, setMatched );
5398
5399 // Seedless set matches succeeding multiple successful matchers stipulate sorting
5400 if ( outermost && !seed && setMatched.length > 0 &&
5401 ( matchedCount + setMatchers.length ) > 1 ) {
5402
5403 Sizzle.uniqueSort( results );
5404 }
5405 }
5406
5407 // Override manipulation of globals by nested matchers
5408 if ( outermost ) {
5409 dirruns = dirrunsUnique;
5410 outermostContext = contextBackup;
5411 }
5412
5413 return unmatched;
5414 };
5415
5416 return bySet ?
5417 markFunction( superMatcher ) :
5418 superMatcher;
5419 }
5420
5421 compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
5422 var i,
5423 setMatchers = [],
5424 elementMatchers = [],
5425 cached = compilerCache[ selector + " " ];
5426
5427 if ( !cached ) {
5428 // Generate a function of recursive functions that can be used to check each element
5429 if ( !group ) {
5430 group = tokenize( selector );
5431 }
5432 i = group.length;
5433 while ( i-- ) {
5434 cached = matcherFromTokens( group[i] );
5435 if ( cached[ expando ] ) {
5436 setMatchers.push( cached );
5437 } else {
5438 elementMatchers.push( cached );
5439 }
5440 }
5441
5442 // Cache the compiled function
5443 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
5444 }
5445 return cached;
5446 };
5447
5448 function multipleContexts( selector, contexts, results ) {
5449 var i = 0,
5450 len = contexts.length;
5451 for ( ; i < len; i++ ) {
5452 Sizzle( selector, contexts[i], results );
5453 }
5454 return results;
5455 }
5456
5457 function select( selector, context, results, seed ) {
5458 var i, tokens, token, type, find,
5459 match = tokenize( selector );
5460
5461 if ( !seed ) {
5462 // Try to minimize operations if there is only one group
5463 if ( match.length === 1 ) {
5464
5465 // Take a shortcut and set the context if the root selector is an ID
5466 tokens = match[0] = match[0].slice( 0 );
5467 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
5468 context.nodeType === 9 && !documentIsXML &&
5469 Expr.relative[ tokens[1].type ] ) {
5470
5471 context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
5472 if ( !context ) {
5473 return results;
5474 }
5475
5476 selector = selector.slice( tokens.shift().value.length );
5477 }
5478
5479 // Fetch a seed set for right-to-left matching
5480 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
5481 while ( i-- ) {
5482 token = tokens[i];
5483
5484 // Abort if we hit a combinator
5485 if ( Expr.relative[ (type = token.type) ] ) {
5486 break;
5487 }
5488 if ( (find = Expr.find[ type ]) ) {
5489 // Search, expanding context for leading sibling combinators
5490 if ( (seed = find(
5491 token.matches[0].replace( runescape, funescape ),
5492 rsibling.test( tokens[0].type ) && context.parentNode || context
5493 )) ) {
5494
5495 // If seed is empty or no tokens remain, we can return early
5496 tokens.splice( i, 1 );
5497 selector = seed.length && toSelector( tokens );
5498 if ( !selector ) {
5499 push.apply( results, slice.call( seed, 0 ) );
5500 return results;
5501 }
5502
5503 break;
5504 }
5505 }
5506 }
5507 }
5508 }
5509
5510 // Compile and execute a filtering function
5511 // Provide `match` to avoid retokenization if we modified the selector above
5512 compile( selector, match )(
5513 seed,
5514 context,
5515 documentIsXML,
5516 results,
5517 rsibling.test( selector )
5518 );
5519 return results;
5520 }
5521
5522 // Deprecated
5523 Expr.pseudos["nth"] = Expr.pseudos["eq"];
5524
5525 // Easy API for creating new setFilters
5526 function setFilters() {}
5527 Expr.filters = setFilters.prototype = Expr.pseudos;
5528 Expr.setFilters = new setFilters();
5529
5530 // Initialize with the default document
5531 setDocument();
5532
5533 // Override sizzle attribute retrieval
5534 Sizzle.attr = jQuery.attr;
5535 jQuery.find = Sizzle;
5536 jQuery.expr = Sizzle.selectors;
5537 jQuery.expr[":"] = jQuery.expr.pseudos;
5538 jQuery.unique = Sizzle.uniqueSort;
5539 jQuery.text = Sizzle.getText;
5540 jQuery.isXMLDoc = Sizzle.isXML;
5541 jQuery.contains = Sizzle.contains;
5542
5543
5544 })( window );
5545 var runtil = /Until$/,
5546 rparentsprev = /^(?:parents|prev(?:Until|All))/,
5547 isSimple = /^.[^:#\[\.,]*$/,
5548 rneedsContext = jQuery.expr.match.needsContext,
5549 // methods guaranteed to produce a unique set when starting from a unique set
5550 guaranteedUnique = {
5551 children: true,
5552 contents: true,
5553 next: true,
5554 prev: true
5555 };
5556
5557 jQuery.fn.extend({
5558 find: function( selector ) {
5559 var i, ret, self,
5560 len = this.length;
5561
5562 if ( typeof selector !== "string" ) {
5563 self = this;
5564 return this.pushStack( jQuery( selector ).filter(function() {
5565 for ( i = 0; i < len; i++ ) {
5566 if ( jQuery.contains( self[ i ], this ) ) {
5567 return true;
5568 }
5569 }
5570 }) );
5571 }
5572
5573 ret = [];
5574 for ( i = 0; i < len; i++ ) {
5575 jQuery.find( selector, this[ i ], ret );
5576 }
5577
5578 // Needed because $( selector, context ) becomes $( context ).find( selector )
5579 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
5580 ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
5581 return ret;
5582 },
5583
5584 has: function( target ) {
5585 var i,
5586 targets = jQuery( target, this ),
5587 len = targets.length;
5588
5589 return this.filter(function() {
5590 for ( i = 0; i < len; i++ ) {
5591 if ( jQuery.contains( this, targets[i] ) ) {
5592 return true;
5593 }
5594 }
5595 });
5596 },
5597
5598 not: function( selector ) {
5599 return this.pushStack( winnow(this, selector, false) );
5600 },
5601
5602 filter: function( selector ) {
5603 return this.pushStack( winnow(this, selector, true) );
5604 },
5605
5606 is: function( selector ) {
5607 return !!selector && (
5608 typeof selector === "string" ?
5609 // If this is a positional/relative selector, check membership in the returned set
5610 // so $("p:first").is("p:last") won't return true for a doc with two "p".
5611 rneedsContext.test( selector ) ?
5612 jQuery( selector, this.context ).index( this[0] ) >= 0 :
5613 jQuery.filter( selector, this ).length > 0 :
5614 this.filter( selector ).length > 0 );
5615 },
5616
5617 closest: function( selectors, context ) {
5618 var cur,
5619 i = 0,
5620 l = this.length,
5621 ret = [],
5622 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
5623 jQuery( selectors, context || this.context ) :
5624 0;
5625
5626 for ( ; i < l; i++ ) {
5627 cur = this[i];
5628
5629 while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
5630 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5631 ret.push( cur );
5632 break;
5633 }
5634 cur = cur.parentNode;
5635 }
5636 }
5637
5638 return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
5639 },
5640
5641 // Determine the position of an element within
5642 // the matched set of elements
5643 index: function( elem ) {
5644
5645 // No argument, return index in parent
5646 if ( !elem ) {
5647 return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
5648 }
5649
5650 // index in selector
5651 if ( typeof elem === "string" ) {
5652 return jQuery.inArray( this[0], jQuery( elem ) );
5653 }
5654
5655 // Locate the position of the desired element
5656 return jQuery.inArray(
5657 // If it receives a jQuery object, the first element is used
5658 elem.jquery ? elem[0] : elem, this );
5659 },
5660
5661 add: function( selector, context ) {
5662 var set = typeof selector === "string" ?
5663 jQuery( selector, context ) :
5664 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5665 all = jQuery.merge( this.get(), set );
5666
5667 return this.pushStack( jQuery.unique(all) );
5668 },
5669
5670 addBack: function( selector ) {
5671 return this.add( selector == null ?
5672 this.prevObject : this.prevObject.filter(selector)
5673 );
5674 }
5675 });
5676
5677 jQuery.fn.andSelf = jQuery.fn.addBack;
5678
5679 function sibling( cur, dir ) {
5680 do {
5681 cur = cur[ dir ];
5682 } while ( cur && cur.nodeType !== 1 );
5683
5684 return cur;
5685 }
5686
5687 jQuery.each({
5688 parent: function( elem ) {
5689 var parent = elem.parentNode;
5690 return parent && parent.nodeType !== 11 ? parent : null;
5691 },
5692 parents: function( elem ) {
5693 return jQuery.dir( elem, "parentNode" );
5694 },
5695 parentsUntil: function( elem, i, until ) {
5696 return jQuery.dir( elem, "parentNode", until );
5697 },
5698 next: function( elem ) {
5699 return sibling( elem, "nextSibling" );
5700 },
5701 prev: function( elem ) {
5702 return sibling( elem, "previousSibling" );
5703 },
5704 nextAll: function( elem ) {
5705 return jQuery.dir( elem, "nextSibling" );
5706 },
5707 prevAll: function( elem ) {
5708 return jQuery.dir( elem, "previousSibling" );
5709 },
5710 nextUntil: function( elem, i, until ) {
5711 return jQuery.dir( elem, "nextSibling", until );
5712 },
5713 prevUntil: function( elem, i, until ) {
5714 return jQuery.dir( elem, "previousSibling", until );
5715 },
5716 siblings: function( elem ) {
5717 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
5718 },
5719 children: function( elem ) {
5720 return jQuery.sibling( elem.firstChild );
5721 },
5722 contents: function( elem ) {
5723 return jQuery.nodeName( elem, "iframe" ) ?
5724 elem.contentDocument || elem.contentWindow.document :
5725 jQuery.merge( [], elem.childNodes );
5726 }
5727 }, function( name, fn ) {
5728 jQuery.fn[ name ] = function( until, selector ) {
5729 var ret = jQuery.map( this, fn, until );
5730
5731 if ( !runtil.test( name ) ) {
5732 selector = until;
5733 }
5734
5735 if ( selector && typeof selector === "string" ) {
5736 ret = jQuery.filter( selector, ret );
5737 }
5738
5739 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
5740
5741 if ( this.length > 1 && rparentsprev.test( name ) ) {
5742 ret = ret.reverse();
5743 }
5744
5745 return this.pushStack( ret );
5746 };
5747 });
5748
5749 jQuery.extend({
5750 filter: function( expr, elems, not ) {
5751 if ( not ) {
5752 expr = ":not(" + expr + ")";
5753 }
5754
5755 return elems.length === 1 ?
5756 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
5757 jQuery.find.matches(expr, elems);
5758 },
5759
5760 dir: function( elem, dir, until ) {
5761 var matched = [],
5762 cur = elem[ dir ];
5763
5764 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5765 if ( cur.nodeType === 1 ) {
5766 matched.push( cur );
5767 }
5768 cur = cur[dir];
5769 }
5770 return matched;
5771 },
5772
5773 sibling: function( n, elem ) {
5774 var r = [];
5775
5776 for ( ; n; n = n.nextSibling ) {
5777 if ( n.nodeType === 1 && n !== elem ) {
5778 r.push( n );
5779 }
5780 }
5781
5782 return r;
5783 }
5784 });
5785
5786 // Implement the identical functionality for filter and not
5787 function winnow( elements, qualifier, keep ) {
5788
5789 // Can't pass null or undefined to indexOf in Firefox 4
5790 // Set to 0 to skip string check
5791 qualifier = qualifier || 0;
5792
5793 if ( jQuery.isFunction( qualifier ) ) {
5794 return jQuery.grep(elements, function( elem, i ) {
5795 var retVal = !!qualifier.call( elem, i, elem );
5796 return retVal === keep;
5797 });
5798
5799 } else if ( qualifier.nodeType ) {
5800 return jQuery.grep(elements, function( elem ) {
5801 return ( elem === qualifier ) === keep;
5802 });
5803
5804 } else if ( typeof qualifier === "string" ) {
5805 var filtered = jQuery.grep(elements, function( elem ) {
5806 return elem.nodeType === 1;
5807 });
5808
5809 if ( isSimple.test( qualifier ) ) {
5810 return jQuery.filter(qualifier, filtered, !keep);
5811 } else {
5812 qualifier = jQuery.filter( qualifier, filtered );
5813 }
5814 }
5815
5816 return jQuery.grep(elements, function( elem ) {
5817 return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
5818 });
5819 }
5820 function createSafeFragment( document ) {
5821 var list = nodeNames.split( "|" ),
5822 safeFrag = document.createDocumentFragment();
5823
5824 if ( safeFrag.createElement ) {
5825 while ( list.length ) {
5826 safeFrag.createElement(
5827 list.pop()
5828 );
5829 }
5830 }
5831 return safeFrag;
5832 }
5833
5834 var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5835 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5836 rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5837 rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5838 rleadingWhitespace = /^\s+/,
5839 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5840 rtagName = /<([\w:]+)/,
5841 rtbody = /<tbody/i,
5842 rhtml = /<|&#?\w+;/,
5843 rnoInnerhtml = /<(?:script|style|link)/i,
5844 manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
5845 // checked="checked" or checked
5846 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5847 rscriptType = /^$|\/(?:java|ecma)script/i,
5848 rscriptTypeMasked = /^true\/(.*)/,
5849 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5850
5851 // We have to close these tags to support XHTML (#13200)
5852 wrapMap = {
5853 option: [ 1, "<select multiple='multiple'>", "</select>" ],
5854 legend: [ 1, "<fieldset>", "</fieldset>" ],
5855 area: [ 1, "<map>", "</map>" ],
5856 param: [ 1, "<object>", "</object>" ],
5857 thead: [ 1, "<table>", "</table>" ],
5858 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5859 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5860 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5861
5862 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5863 // unless wrapped in a div with non-breaking characters in front of it.
5864 _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
5865 },
5866 safeFragment = createSafeFragment( document ),
5867 fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5868
5869 wrapMap.optgroup = wrapMap.option;
5870 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5871 wrapMap.th = wrapMap.td;
5872
5873 jQuery.fn.extend({
5874 text: function( value ) {
5875 return jQuery.access( this, function( value ) {
5876 return value === undefined ?
5877 jQuery.text( this ) :
5878 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5879 }, null, value, arguments.length );
5880 },
5881
5882 wrapAll: function( html ) {
5883 if ( jQuery.isFunction( html ) ) {
5884 return this.each(function(i) {
5885 jQuery(this).wrapAll( html.call(this, i) );
5886 });
5887 }
5888
5889 if ( this[0] ) {
5890 // The elements to wrap the target around
5891 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
5892
5893 if ( this[0].parentNode ) {
5894 wrap.insertBefore( this[0] );
5895 }
5896
5897 wrap.map(function() {
5898 var elem = this;
5899
5900 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
5901 elem = elem.firstChild;
5902 }
5903
5904 return elem;
5905 }).append( this );
5906 }
5907
5908 return this;
5909 },
5910
5911 wrapInner: function( html ) {
5912 if ( jQuery.isFunction( html ) ) {
5913 return this.each(function(i) {
5914 jQuery(this).wrapInner( html.call(this, i) );
5915 });
5916 }
5917
5918 return this.each(function() {
5919 var self = jQuery( this ),
5920 contents = self.contents();
5921
5922 if ( contents.length ) {
5923 contents.wrapAll( html );
5924
5925 } else {
5926 self.append( html );
5927 }
5928 });
5929 },
5930
5931 wrap: function( html ) {
5932 var isFunction = jQuery.isFunction( html );
5933
5934 return this.each(function(i) {
5935 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
5936 });
5937 },
5938
5939 unwrap: function() {
5940 return this.parent().each(function() {
5941 if ( !jQuery.nodeName( this, "body" ) ) {
5942 jQuery( this ).replaceWith( this.childNodes );
5943 }
5944 }).end();
5945 },
5946
5947 append: function() {
5948 return this.domManip(arguments, true, function( elem ) {
5949 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5950 this.appendChild( elem );
5951 }
5952 });
5953 },
5954
5955 prepend: function() {
5956 return this.domManip(arguments, true, function( elem ) {
5957 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5958 this.insertBefore( elem, this.firstChild );
5959 }
5960 });
5961 },
5962
5963 before: function() {
5964 return this.domManip( arguments, false, function( elem ) {
5965 if ( this.parentNode ) {
5966 this.parentNode.insertBefore( elem, this );
5967 }
5968 });
5969 },
5970
5971 after: function() {
5972 return this.domManip( arguments, false, function( elem ) {
5973 if ( this.parentNode ) {
5974 this.parentNode.insertBefore( elem, this.nextSibling );
5975 }
5976 });
5977 },
5978
5979 // keepData is for internal use only--do not document
5980 remove: function( selector, keepData ) {
5981 var elem,
5982 i = 0;
5983
5984 for ( ; (elem = this[i]) != null; i++ ) {
5985 if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
5986 if ( !keepData && elem.nodeType === 1 ) {
5987 jQuery.cleanData( getAll( elem ) );
5988 }
5989
5990 if ( elem.parentNode ) {
5991 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
5992 setGlobalEval( getAll( elem, "script" ) );
5993 }
5994 elem.parentNode.removeChild( elem );
5995 }
5996 }
5997 }
5998
5999 return this;
6000 },
6001
6002 empty: function() {
6003 var elem,
6004 i = 0;
6005
6006 for ( ; (elem = this[i]) != null; i++ ) {
6007 // Remove element nodes and prevent memory leaks
6008 if ( elem.nodeType === 1 ) {
6009 jQuery.cleanData( getAll( elem, false ) );
6010 }
6011
6012 // Remove any remaining nodes
6013 while ( elem.firstChild ) {
6014 elem.removeChild( elem.firstChild );
6015 }
6016
6017 // If this is a select, ensure that it displays empty (#12336)
6018 // Support: IE<9
6019 if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
6020 elem.options.length = 0;
6021 }
6022 }
6023
6024 return this;
6025 },
6026
6027 clone: function( dataAndEvents, deepDataAndEvents ) {
6028 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6029 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6030
6031 return this.map( function () {
6032 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6033 });
6034 },
6035
6036 html: function( value ) {
6037 return jQuery.access( this, function( value ) {
6038 var elem = this[0] || {},
6039 i = 0,
6040 l = this.length;
6041
6042 if ( value === undefined ) {
6043 return elem.nodeType === 1 ?
6044 elem.innerHTML.replace( rinlinejQuery, "" ) :
6045 undefined;
6046 }
6047
6048 // See if we can take a shortcut and just use innerHTML
6049 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6050 ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
6051 ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
6052 !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
6053
6054 value = value.replace( rxhtmlTag, "<$1></$2>" );
6055
6056 try {
6057 for (; i < l; i++ ) {
6058 // Remove element nodes and prevent memory leaks
6059 elem = this[i] || {};
6060 if ( elem.nodeType === 1 ) {
6061 jQuery.cleanData( getAll( elem, false ) );
6062 elem.innerHTML = value;
6063 }
6064 }
6065
6066 elem = 0;
6067
6068 // If using innerHTML throws an exception, use the fallback method
6069 } catch(e) {}
6070 }
6071
6072 if ( elem ) {
6073 this.empty().append( value );
6074 }
6075 }, null, value, arguments.length );
6076 },
6077
6078 replaceWith: function( value ) {
6079 var isFunc = jQuery.isFunction( value );
6080
6081 // Make sure that the elements are removed from the DOM before they are inserted
6082 // this can help fix replacing a parent with child elements
6083 if ( !isFunc && typeof value !== "string" ) {
6084 value = jQuery( value ).not( this ).detach();
6085 }
6086
6087 return this.domManip( [ value ], true, function( elem ) {
6088 var next = this.nextSibling,
6089 parent = this.parentNode;
6090
6091 if ( parent ) {
6092 jQuery( this ).remove();
6093 parent.insertBefore( elem, next );
6094 }
6095 });
6096 },
6097
6098 detach: function( selector ) {
6099 return this.remove( selector, true );
6100 },
6101
6102 domManip: function( args, table, callback ) {
6103
6104 // Flatten any nested arrays
6105 args = core_concat.apply( [], args );
6106
6107 var first, node, hasScripts,
6108 scripts, doc, fragment,
6109 i = 0,
6110 l = this.length,
6111 set = this,
6112 iNoClone = l - 1,
6113 value = args[0],
6114 isFunction = jQuery.isFunction( value );
6115
6116 // We can't cloneNode fragments that contain checked, in WebKit
6117 if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
6118 return this.each(function( index ) {
6119 var self = set.eq( index );
6120 if ( isFunction ) {
6121 args[0] = value.call( this, index, table ? self.html() : undefined );
6122 }
6123 self.domManip( args, table, callback );
6124 });
6125 }
6126
6127 if ( l ) {
6128 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
6129 first = fragment.firstChild;
6130
6131 if ( fragment.childNodes.length === 1 ) {
6132 fragment = first;
6133 }
6134
6135 if ( first ) {
6136 table = table && jQuery.nodeName( first, "tr" );
6137 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6138 hasScripts = scripts.length;
6139
6140 // Use the original fragment for the last item instead of the first because it can end up
6141 // being emptied incorrectly in certain situations (#8070).
6142 for ( ; i < l; i++ ) {
6143 node = fragment;
6144
6145 if ( i !== iNoClone ) {
6146 node = jQuery.clone( node, true, true );
6147
6148 // Keep references to cloned scripts for later restoration
6149 if ( hasScripts ) {
6150 jQuery.merge( scripts, getAll( node, "script" ) );
6151 }
6152 }
6153
6154 callback.call(
6155 table && jQuery.nodeName( this[i], "table" ) ?
6156 findOrAppend( this[i], "tbody" ) :
6157 this[i],
6158 node,
6159 i
6160 );
6161 }
6162
6163 if ( hasScripts ) {
6164 doc = scripts[ scripts.length - 1 ].ownerDocument;
6165
6166 // Reenable scripts
6167 jQuery.map( scripts, restoreScript );
6168
6169 // Evaluate executable scripts on first document insertion
6170 for ( i = 0; i < hasScripts; i++ ) {
6171 node = scripts[ i ];
6172 if ( rscriptType.test( node.type || "" ) &&
6173 !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
6174
6175 if ( node.src ) {
6176 // Hope ajax is available...
6177 jQuery.ajax({
6178 url: node.src,
6179 type: "GET",
6180 dataType: "script",
6181 async: false,
6182 global: false,
6183 "throws": true
6184 });
6185 } else {
6186 jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
6187 }
6188 }
6189 }
6190 }
6191
6192 // Fix #11809: Avoid leaking memory
6193 fragment = first = null;
6194 }
6195 }
6196
6197 return this;
6198 }
6199 });
6200
6201 function findOrAppend( elem, tag ) {
6202 return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
6203 }
6204
6205 // Replace/restore the type attribute of script elements for safe DOM manipulation
6206 function disableScript( elem ) {
6207 var attr = elem.getAttributeNode("type");
6208 elem.type = ( attr && attr.specified ) + "/" + elem.type;
6209 return elem;
6210 }
6211 function restoreScript( elem ) {
6212 var match = rscriptTypeMasked.exec( elem.type );
6213 if ( match ) {
6214 elem.type = match[1];
6215 } else {
6216 elem.removeAttribute("type");
6217 }
6218 return elem;
6219 }
6220
6221 // Mark scripts as having already been evaluated
6222 function setGlobalEval( elems, refElements ) {
6223 var elem,
6224 i = 0;
6225 for ( ; (elem = elems[i]) != null; i++ ) {
6226 jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
6227 }
6228 }
6229
6230 function cloneCopyEvent( src, dest ) {
6231
6232 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6233 return;
6234 }
6235
6236 var type, i, l,
6237 oldData = jQuery._data( src ),
6238 curData = jQuery._data( dest, oldData ),
6239 events = oldData.events;
6240
6241 if ( events ) {
6242 delete curData.handle;
6243 curData.events = {};
6244
6245 for ( type in events ) {
6246 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6247 jQuery.event.add( dest, type, events[ type ][ i ] );
6248 }
6249 }
6250 }
6251
6252 // make the cloned public data object a copy from the original
6253 if ( curData.data ) {
6254 curData.data = jQuery.extend( {}, curData.data );
6255 }
6256 }
6257
6258 function fixCloneNodeIssues( src, dest ) {
6259 var nodeName, e, data;
6260
6261 // We do not need to do anything for non-Elements
6262 if ( dest.nodeType !== 1 ) {
6263 return;
6264 }
6265
6266 nodeName = dest.nodeName.toLowerCase();
6267
6268 // IE6-8 copies events bound via attachEvent when using cloneNode.
6269 if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
6270 data = jQuery._data( dest );
6271
6272 for ( e in data.events ) {
6273 jQuery.removeEvent( dest, e, data.handle );
6274 }
6275
6276 // Event data gets referenced instead of copied if the expando gets copied too
6277 dest.removeAttribute( jQuery.expando );
6278 }
6279
6280 // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
6281 if ( nodeName === "script" && dest.text !== src.text ) {
6282 disableScript( dest ).text = src.text;
6283 restoreScript( dest );
6284
6285 // IE6-10 improperly clones children of object elements using classid.
6286 // IE10 throws NoModificationAllowedError if parent is null, #12132.
6287 } else if ( nodeName === "object" ) {
6288 if ( dest.parentNode ) {
6289 dest.outerHTML = src.outerHTML;
6290 }
6291
6292 // This path appears unavoidable for IE9. When cloning an object
6293 // element in IE9, the outerHTML strategy above is not sufficient.
6294 // If the src has innerHTML and the destination does not,
6295 // copy the src.innerHTML into the dest.innerHTML. #10324
6296 if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
6297 dest.innerHTML = src.innerHTML;
6298 }
6299
6300 } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
6301 // IE6-8 fails to persist the checked state of a cloned checkbox
6302 // or radio button. Worse, IE6-7 fail to give the cloned element
6303 // a checked appearance if the defaultChecked value isn't also set
6304
6305 dest.defaultChecked = dest.checked = src.checked;
6306
6307 // IE6-7 get confused and end up setting the value of a cloned
6308 // checkbox/radio button to an empty string instead of "on"
6309 if ( dest.value !== src.value ) {
6310 dest.value = src.value;
6311 }
6312
6313 // IE6-8 fails to return the selected option to the default selected
6314 // state when cloning options
6315 } else if ( nodeName === "option" ) {
6316 dest.defaultSelected = dest.selected = src.defaultSelected;
6317
6318 // IE6-8 fails to set the defaultValue to the correct value when
6319 // cloning other types of input fields
6320 } else if ( nodeName === "input" || nodeName === "textarea" ) {
6321 dest.defaultValue = src.defaultValue;
6322 }
6323 }
6324
6325 jQuery.each({
6326 appendTo: "append",
6327 prependTo: "prepend",
6328 insertBefore: "before",
6329 insertAfter: "after",
6330 replaceAll: "replaceWith"
6331 }, function( name, original ) {
6332 jQuery.fn[ name ] = function( selector ) {
6333 var elems,
6334 i = 0,
6335 ret = [],
6336 insert = jQuery( selector ),
6337 last = insert.length - 1;
6338
6339 for ( ; i <= last; i++ ) {
6340 elems = i === last ? this : this.clone(true);
6341 jQuery( insert[i] )[ original ]( elems );
6342
6343 // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6344 core_push.apply( ret, elems.get() );
6345 }
6346
6347 return this.pushStack( ret );
6348 };
6349 });
6350
6351 function getAll( context, tag ) {
6352 var elems, elem,
6353 i = 0,
6354 found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
6355 typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
6356 undefined;
6357
6358 if ( !found ) {
6359 for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
6360 if ( !tag || jQuery.nodeName( elem, tag ) ) {
6361 found.push( elem );
6362 } else {
6363 jQuery.merge( found, getAll( elem, tag ) );
6364 }
6365 }
6366 }
6367
6368 return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
6369 jQuery.merge( [ context ], found ) :
6370 found;
6371 }
6372
6373 // Used in buildFragment, fixes the defaultChecked property
6374 function fixDefaultChecked( elem ) {
6375 if ( manipulation_rcheckableType.test( elem.type ) ) {
6376 elem.defaultChecked = elem.checked;
6377 }
6378 }
6379
6380 jQuery.extend({
6381 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6382 var destElements, node, clone, i, srcElements,
6383 inPage = jQuery.contains( elem.ownerDocument, elem );
6384
6385 if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6386 clone = elem.cloneNode( true );
6387
6388 // IE<=8 does not properly clone detached, unknown element nodes
6389 } else {
6390 fragmentDiv.innerHTML = elem.outerHTML;
6391 fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6392 }
6393
6394 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6395 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6396
6397 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
6398 destElements = getAll( clone );
6399 srcElements = getAll( elem );
6400
6401 // Fix all IE cloning issues
6402 for ( i = 0; (node = srcElements[i]) != null; ++i ) {
6403 // Ensure that the destination node is not null; Fixes #9587
6404 if ( destElements[i] ) {
6405 fixCloneNodeIssues( node, destElements[i] );
6406 }
6407 }
6408 }
6409
6410 // Copy the events from the original to the clone
6411 if ( dataAndEvents ) {
6412 if ( deepDataAndEvents ) {
6413 srcElements = srcElements || getAll( elem );
6414 destElements = destElements || getAll( clone );
6415
6416 for ( i = 0; (node = srcElements[i]) != null; i++ ) {
6417 cloneCopyEvent( node, destElements[i] );
6418 }
6419 } else {
6420 cloneCopyEvent( elem, clone );
6421 }
6422 }
6423
6424 // Preserve script evaluation history
6425 destElements = getAll( clone, "script" );
6426 if ( destElements.length > 0 ) {
6427 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6428 }
6429
6430 destElements = srcElements = node = null;
6431
6432 // Return the cloned set
6433 return clone;
6434 },
6435
6436 buildFragment: function( elems, context, scripts, selection ) {
6437 var j, elem, contains,
6438 tmp, tag, tbody, wrap,
6439 l = elems.length,
6440
6441 // Ensure a safe fragment
6442 safe = createSafeFragment( context ),
6443
6444 nodes = [],
6445 i = 0;
6446
6447 for ( ; i < l; i++ ) {
6448 elem = elems[ i ];
6449
6450 if ( elem || elem === 0 ) {
6451
6452 // Add nodes directly
6453 if ( jQuery.type( elem ) === "object" ) {
6454 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
6455
6456 // Convert non-html into a text node
6457 } else if ( !rhtml.test( elem ) ) {
6458 nodes.push( context.createTextNode( elem ) );
6459
6460 // Convert html into DOM nodes
6461 } else {
6462 tmp = tmp || safe.appendChild( context.createElement("div") );
6463
6464 // Deserialize a standard representation
6465 tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
6466 wrap = wrapMap[ tag ] || wrapMap._default;
6467
6468 tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
6469
6470 // Descend through wrappers to the right content
6471 j = wrap[0];
6472 while ( j-- ) {
6473 tmp = tmp.lastChild;
6474 }
6475
6476 // Manually add leading whitespace removed by IE
6477 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6478 nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
6479 }
6480
6481 // Remove IE's autoinserted <tbody> from table fragments
6482 if ( !jQuery.support.tbody ) {
6483
6484 // String was a <table>, *may* have spurious <tbody>
6485 elem = tag === "table" && !rtbody.test( elem ) ?
6486 tmp.firstChild :
6487
6488 // String was a bare <thead> or <tfoot>
6489 wrap[1] === "<table>" && !rtbody.test( elem ) ?
6490 tmp :
6491 0;
6492
6493 j = elem && elem.childNodes.length;
6494 while ( j-- ) {
6495 if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
6496 elem.removeChild( tbody );
6497 }
6498 }
6499 }
6500
6501 jQuery.merge( nodes, tmp.childNodes );
6502
6503 // Fix #12392 for WebKit and IE > 9
6504 tmp.textContent = "";
6505
6506 // Fix #12392 for oldIE
6507 while ( tmp.firstChild ) {
6508 tmp.removeChild( tmp.firstChild );
6509 }
6510
6511 // Remember the top-level container for proper cleanup
6512 tmp = safe.lastChild;
6513 }
6514 }
6515 }
6516
6517 // Fix #11356: Clear elements from fragment
6518 if ( tmp ) {
6519 safe.removeChild( tmp );
6520 }
6521
6522 // Reset defaultChecked for any radios and checkboxes
6523 // about to be appended to the DOM in IE 6/7 (#8060)
6524 if ( !jQuery.support.appendChecked ) {
6525 jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
6526 }
6527
6528 i = 0;
6529 while ( (elem = nodes[ i++ ]) ) {
6530
6531 // #4087 - If origin and destination elements are the same, and this is
6532 // that element, do not do anything
6533 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
6534 continue;
6535 }
6536
6537 contains = jQuery.contains( elem.ownerDocument, elem );
6538
6539 // Append to fragment
6540 tmp = getAll( safe.appendChild( elem ), "script" );
6541
6542 // Preserve script evaluation history
6543 if ( contains ) {
6544 setGlobalEval( tmp );
6545 }
6546
6547 // Capture executables
6548 if ( scripts ) {
6549 j = 0;
6550 while ( (elem = tmp[ j++ ]) ) {
6551 if ( rscriptType.test( elem.type || "" ) ) {
6552 scripts.push( elem );
6553 }
6554 }
6555 }
6556 }
6557
6558 tmp = null;
6559
6560 return safe;
6561 },
6562
6563 cleanData: function( elems, /* internal */ acceptData ) {
6564 var elem, type, id, data,
6565 i = 0,
6566 internalKey = jQuery.expando,
6567 cache = jQuery.cache,
6568 deleteExpando = jQuery.support.deleteExpando,
6569 special = jQuery.event.special;
6570
6571 for ( ; (elem = elems[i]) != null; i++ ) {
6572
6573 if ( acceptData || jQuery.acceptData( elem ) ) {
6574
6575 id = elem[ internalKey ];
6576 data = id && cache[ id ];
6577
6578 if ( data ) {
6579 if ( data.events ) {
6580 for ( type in data.events ) {
6581 if ( special[ type ] ) {
6582 jQuery.event.remove( elem, type );
6583
6584 // This is a shortcut to avoid jQuery.event.remove's overhead
6585 } else {
6586 jQuery.removeEvent( elem, type, data.handle );
6587 }
6588 }
6589 }
6590
6591 // Remove cache only if it was not already removed by jQuery.event.remove
6592 if ( cache[ id ] ) {
6593
6594 delete cache[ id ];
6595
6596 // IE does not allow us to delete expando properties from nodes,
6597 // nor does it have a removeAttribute function on Document nodes;
6598 // we must handle all of these cases
6599 if ( deleteExpando ) {
6600 delete elem[ internalKey ];
6601
6602 } else if ( typeof elem.removeAttribute !== core_strundefined ) {
6603 elem.removeAttribute( internalKey );
6604
6605 } else {
6606 elem[ internalKey ] = null;
6607 }
6608
6609 core_deletedIds.push( id );
6610 }
6611 }
6612 }
6613 }
6614 }
6615 });
6616 var iframe, getStyles, curCSS,
6617 ralpha = /alpha\([^)]*\)/i,
6618 ropacity = /opacity\s*=\s*([^)]*)/,
6619 rposition = /^(top|right|bottom|left)$/,
6620 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6621 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6622 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6623 rmargin = /^margin/,
6624 rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
6625 rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
6626 rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
6627 elemdisplay = { BODY: "block" },
6628
6629 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6630 cssNormalTransform = {
6631 letterSpacing: 0,
6632 fontWeight: 400
6633 },
6634
6635 cssExpand = [ "Top", "Right", "Bottom", "Left" ],
6636 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6637
6638 // return a css property mapped to a potentially vendor prefixed property
6639 function vendorPropName( style, name ) {
6640
6641 // shortcut for names that are not vendor prefixed
6642 if ( name in style ) {
6643 return name;
6644 }
6645
6646 // check for vendor prefixed names
6647 var capName = name.charAt(0).toUpperCase() + name.slice(1),
6648 origName = name,
6649 i = cssPrefixes.length;
6650
6651 while ( i-- ) {
6652 name = cssPrefixes[ i ] + capName;
6653 if ( name in style ) {
6654 return name;
6655 }
6656 }
6657
6658 return origName;
6659 }
6660
6661 function isHidden( elem, el ) {
6662 // isHidden might be called from jQuery#filter function;
6663 // in that case, element will be second argument
6664 elem = el || elem;
6665 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
6666 }
6667
6668 function showHide( elements, show ) {
6669 var display, elem, hidden,
6670 values = [],
6671 index = 0,
6672 length = elements.length;
6673
6674 for ( ; index < length; index++ ) {
6675 elem = elements[ index ];
6676 if ( !elem.style ) {
6677 continue;
6678 }
6679
6680 values[ index ] = jQuery._data( elem, "olddisplay" );
6681 display = elem.style.display;
6682 if ( show ) {
6683 // Reset the inline display of this element to learn if it is
6684 // being hidden by cascaded rules or not
6685 if ( !values[ index ] && display === "none" ) {
6686 elem.style.display = "";
6687 }
6688
6689 // Set elements which have been overridden with display: none
6690 // in a stylesheet to whatever the default browser style is
6691 // for such an element
6692 if ( elem.style.display === "" && isHidden( elem ) ) {
6693 values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
6694 }
6695 } else {
6696
6697 if ( !values[ index ] ) {
6698 hidden = isHidden( elem );
6699
6700 if ( display && display !== "none" || !hidden ) {
6701 jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6702 }
6703 }
6704 }
6705 }
6706
6707 // Set the display of most of the elements in a second loop
6708 // to avoid the constant reflow
6709 for ( index = 0; index < length; index++ ) {
6710 elem = elements[ index ];
6711 if ( !elem.style ) {
6712 continue;
6713 }
6714 if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6715 elem.style.display = show ? values[ index ] || "" : "none";
6716 }
6717 }
6718
6719 return elements;
6720 }
6721
6722 jQuery.fn.extend({
6723 css: function( name, value ) {
6724 return jQuery.access( this, function( elem, name, value ) {
6725 var len, styles,
6726 map = {},
6727 i = 0;
6728
6729 if ( jQuery.isArray( name ) ) {
6730 styles = getStyles( elem );
6731 len = name.length;
6732
6733 for ( ; i < len; i++ ) {
6734 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6735 }
6736
6737 return map;
6738 }
6739
6740 return value !== undefined ?
6741 jQuery.style( elem, name, value ) :
6742 jQuery.css( elem, name );
6743 }, name, value, arguments.length > 1 );
6744 },
6745 show: function() {
6746 return showHide( this, true );
6747 },
6748 hide: function() {
6749 return showHide( this );
6750 },
6751 toggle: function( state ) {
6752 var bool = typeof state === "boolean";
6753
6754 return this.each(function() {
6755 if ( bool ? state : isHidden( this ) ) {
6756 jQuery( this ).show();
6757 } else {
6758 jQuery( this ).hide();
6759 }
6760 });
6761 }
6762 });
6763
6764 jQuery.extend({
6765 // Add in style property hooks for overriding the default
6766 // behavior of getting and setting a style property
6767 cssHooks: {
6768 opacity: {
6769 get: function( elem, computed ) {
6770 if ( computed ) {
6771 // We should always get a number back from opacity
6772 var ret = curCSS( elem, "opacity" );
6773 return ret === "" ? "1" : ret;
6774 }
6775 }
6776 }
6777 },
6778
6779 // Exclude the following css properties to add px
6780 cssNumber: {
6781 "columnCount": true,
6782 "fillOpacity": true,
6783 "fontWeight": true,
6784 "lineHeight": true,
6785 "opacity": true,
6786 "orphans": true,
6787 "widows": true,
6788 "zIndex": true,
6789 "zoom": true
6790 },
6791
6792 // Add in properties whose names you wish to fix before
6793 // setting or getting the value
6794 cssProps: {
6795 // normalize float css property
6796 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6797 },
6798
6799 // Get and set the style property on a DOM Node
6800 style: function( elem, name, value, extra ) {
6801 // Don't set styles on text and comment nodes
6802 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6803 return;
6804 }
6805
6806 // Make sure that we're working with the right name
6807 var ret, type, hooks,
6808 origName = jQuery.camelCase( name ),
6809 style = elem.style;
6810
6811 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6812
6813 // gets hook for the prefixed version
6814 // followed by the unprefixed version
6815 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6816
6817 // Check if we're setting a value
6818 if ( value !== undefined ) {
6819 type = typeof value;
6820
6821 // convert relative number strings (+= or -=) to relative numbers. #7345
6822 if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6823 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6824 // Fixes bug #9237
6825 type = "number";
6826 }
6827
6828 // Make sure that NaN and null values aren't set. See: #7116
6829 if ( value == null || type === "number" && isNaN( value ) ) {
6830 return;
6831 }
6832
6833 // If a number was passed in, add 'px' to the (except for certain CSS properties)
6834 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6835 value += "px";
6836 }
6837
6838 // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
6839 // but it would mean to define eight (for every problematic property) identical functions
6840 if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
6841 style[ name ] = "inherit";
6842 }
6843
6844 // If a hook was provided, use that value, otherwise just set the specified value
6845 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6846
6847 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6848 // Fixes bug #5509
6849 try {
6850 style[ name ] = value;
6851 } catch(e) {}
6852 }
6853
6854 } else {
6855 // If a hook was provided get the non-computed value from there
6856 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6857 return ret;
6858 }
6859
6860 // Otherwise just get the value from the style object
6861 return style[ name ];
6862 }
6863 },
6864
6865 css: function( elem, name, extra, styles ) {
6866 var num, val, hooks,
6867 origName = jQuery.camelCase( name );
6868
6869 // Make sure that we're working with the right name
6870 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6871
6872 // gets hook for the prefixed version
6873 // followed by the unprefixed version
6874 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6875
6876 // If a hook was provided get the computed value from there
6877 if ( hooks && "get" in hooks ) {
6878 val = hooks.get( elem, true, extra );
6879 }
6880
6881 // Otherwise, if a way to get the computed value exists, use that
6882 if ( val === undefined ) {
6883 val = curCSS( elem, name, styles );
6884 }
6885
6886 //convert "normal" to computed value
6887 if ( val === "normal" && name in cssNormalTransform ) {
6888 val = cssNormalTransform[ name ];
6889 }
6890
6891 // Return, converting to number if forced or a qualifier was provided and val looks numeric
6892 if ( extra === "" || extra ) {
6893 num = parseFloat( val );
6894 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6895 }
6896 return val;
6897 },
6898
6899 // A method for quickly swapping in/out CSS properties to get correct calculations
6900 swap: function( elem, options, callback, args ) {
6901 var ret, name,
6902 old = {};
6903
6904 // Remember the old values, and insert the new ones
6905 for ( name in options ) {
6906 old[ name ] = elem.style[ name ];
6907 elem.style[ name ] = options[ name ];
6908 }
6909
6910 ret = callback.apply( elem, args || [] );
6911
6912 // Revert the old values
6913 for ( name in options ) {
6914 elem.style[ name ] = old[ name ];
6915 }
6916
6917 return ret;
6918 }
6919 });
6920
6921 // NOTE: we've included the "window" in window.getComputedStyle
6922 // because jsdom on node.js will break without it.
6923 if ( window.getComputedStyle ) {
6924 getStyles = function( elem ) {
6925 return window.getComputedStyle( elem, null );
6926 };
6927
6928 curCSS = function( elem, name, _computed ) {
6929 var width, minWidth, maxWidth,
6930 computed = _computed || getStyles( elem ),
6931
6932 // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6933 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
6934 style = elem.style;
6935
6936 if ( computed ) {
6937
6938 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6939 ret = jQuery.style( elem, name );
6940 }
6941
6942 // A tribute to the "awesome hack by Dean Edwards"
6943 // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6944 // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6945 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6946 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6947
6948 // Remember the original values
6949 width = style.width;
6950 minWidth = style.minWidth;
6951 maxWidth = style.maxWidth;
6952
6953 // Put in the new values to get a computed value out
6954 style.minWidth = style.maxWidth = style.width = ret;
6955 ret = computed.width;
6956
6957 // Revert the changed values
6958 style.width = width;
6959 style.minWidth = minWidth;
6960 style.maxWidth = maxWidth;
6961 }
6962 }
6963
6964 return ret;
6965 };
6966 } else if ( document.documentElement.currentStyle ) {
6967 getStyles = function( elem ) {
6968 return elem.currentStyle;
6969 };
6970
6971 curCSS = function( elem, name, _computed ) {
6972 var left, rs, rsLeft,
6973 computed = _computed || getStyles( elem ),
6974 ret = computed ? computed[ name ] : undefined,
6975 style = elem.style;
6976
6977 // Avoid setting ret to empty string here
6978 // so we don't default to auto
6979 if ( ret == null && style && style[ name ] ) {
6980 ret = style[ name ];
6981 }
6982
6983 // From the awesome hack by Dean Edwards
6984 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6985
6986 // If we're not dealing with a regular pixel number
6987 // but a number that has a weird ending, we need to convert it to pixels
6988 // but not position css attributes, as those are proportional to the parent element instead
6989 // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
6990 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
6991
6992 // Remember the original values
6993 left = style.left;
6994 rs = elem.runtimeStyle;
6995 rsLeft = rs && rs.left;
6996
6997 // Put in the new values to get a computed value out
6998 if ( rsLeft ) {
6999 rs.left = elem.currentStyle.left;
7000 }
7001 style.left = name === "fontSize" ? "1em" : ret;
7002 ret = style.pixelLeft + "px";
7003
7004 // Revert the changed values
7005 style.left = left;
7006 if ( rsLeft ) {
7007 rs.left = rsLeft;
7008 }
7009 }
7010
7011 return ret === "" ? "auto" : ret;
7012 };
7013 }
7014
7015 function setPositiveNumber( elem, value, subtract ) {
7016 var matches = rnumsplit.exec( value );
7017 return matches ?
7018 // Guard against undefined "subtract", e.g., when used as in cssHooks
7019 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
7020 value;
7021 }
7022
7023 function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
7024 var i = extra === ( isBorderBox ? "border" : "content" ) ?
7025 // If we already have the right measurement, avoid augmentation
7026 4 :
7027 // Otherwise initialize for horizontal or vertical properties
7028 name === "width" ? 1 : 0,
7029
7030 val = 0;
7031
7032 for ( ; i < 4; i += 2 ) {
7033 // both box models exclude margin, so add it if we want it
7034 if ( extra === "margin" ) {
7035 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
7036 }
7037
7038 if ( isBorderBox ) {
7039 // border-box includes padding, so remove it if we want content
7040 if ( extra === "content" ) {
7041 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7042 }
7043
7044 // at this point, extra isn't border nor margin, so remove border
7045 if ( extra !== "margin" ) {
7046 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7047 }
7048 } else {
7049 // at this point, extra isn't content, so add padding
7050 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7051
7052 // at this point, extra isn't content nor padding, so add border
7053 if ( extra !== "padding" ) {
7054 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7055 }
7056 }
7057 }
7058
7059 return val;
7060 }
7061
7062 function getWidthOrHeight( elem, name, extra ) {
7063
7064 // Start with offset property, which is equivalent to the border-box value
7065 var valueIsBorderBox = true,
7066 val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7067 styles = getStyles( elem ),
7068 isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
7069
7070 // some non-html elements return undefined for offsetWidth, so check for null/undefined
7071 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
7072 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
7073 if ( val <= 0 || val == null ) {
7074 // Fall back to computed then uncomputed css if necessary
7075 val = curCSS( elem, name, styles );
7076 if ( val < 0 || val == null ) {
7077 val = elem.style[ name ];
7078 }
7079
7080 // Computed unit is not pixels. Stop here and return.
7081 if ( rnumnonpx.test(val) ) {
7082 return val;
7083 }
7084
7085 // we need the check for style in case a browser which returns unreliable values
7086 // for getComputedStyle silently falls back to the reliable elem.style
7087 valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
7088
7089 // Normalize "", auto, and prepare for extra
7090 val = parseFloat( val ) || 0;
7091 }
7092
7093 // use the active box-sizing model to add/subtract irrelevant styles
7094 return ( val +
7095 augmentWidthOrHeight(
7096 elem,
7097 name,
7098 extra || ( isBorderBox ? "border" : "content" ),
7099 valueIsBorderBox,
7100 styles
7101 )
7102 ) + "px";
7103 }
7104
7105 // Try to determine the default display value of an element
7106 function css_defaultDisplay( nodeName ) {
7107 var doc = document,
7108 display = elemdisplay[ nodeName ];
7109
7110 if ( !display ) {
7111 display = actualDisplay( nodeName, doc );
7112
7113 // If the simple way fails, read from inside an iframe
7114 if ( display === "none" || !display ) {
7115 // Use the already-created iframe if possible
7116 iframe = ( iframe ||
7117 jQuery("<iframe frameborder='0' width='0' height='0'/>")
7118 .css( "cssText", "display:block !important" )
7119 ).appendTo( doc.documentElement );
7120
7121 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
7122 doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
7123 doc.write("<!doctype html><html><body>");
7124 doc.close();
7125
7126 display = actualDisplay( nodeName, doc );
7127 iframe.detach();
7128 }
7129
7130 // Store the correct default display
7131 elemdisplay[ nodeName ] = display;
7132 }
7133
7134 return display;
7135 }
7136
7137 // Called ONLY from within css_defaultDisplay
7138 function actualDisplay( name, doc ) {
7139 var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
7140 display = jQuery.css( elem[0], "display" );
7141 elem.remove();
7142 return display;
7143 }
7144
7145 jQuery.each([ "height", "width" ], function( i, name ) {
7146 jQuery.cssHooks[ name ] = {
7147 get: function( elem, computed, extra ) {
7148 if ( computed ) {
7149 // certain elements can have dimension info if we invisibly show them
7150 // however, it must have a current display style that would benefit from this
7151 return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
7152 jQuery.swap( elem, cssShow, function() {
7153 return getWidthOrHeight( elem, name, extra );
7154 }) :
7155 getWidthOrHeight( elem, name, extra );
7156 }
7157 },
7158
7159 set: function( elem, value, extra ) {
7160 var styles = extra && getStyles( elem );
7161 return setPositiveNumber( elem, value, extra ?
7162 augmentWidthOrHeight(
7163 elem,
7164 name,
7165 extra,
7166 jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7167 styles
7168 ) : 0
7169 );
7170 }
7171 };
7172 });
7173
7174 if ( !jQuery.support.opacity ) {
7175 jQuery.cssHooks.opacity = {
7176 get: function( elem, computed ) {
7177 // IE uses filters for opacity
7178 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7179 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7180 computed ? "1" : "";
7181 },
7182
7183 set: function( elem, value ) {
7184 var style = elem.style,
7185 currentStyle = elem.currentStyle,
7186 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7187 filter = currentStyle && currentStyle.filter || style.filter || "";
7188
7189 // IE has trouble with opacity if it does not have layout
7190 // Force it by setting the zoom level
7191 style.zoom = 1;
7192
7193 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7194 // if value === "", then remove inline opacity #12685
7195 if ( ( value >= 1 || value === "" ) &&
7196 jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7197 style.removeAttribute ) {
7198
7199 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7200 // if "filter:" is present at all, clearType is disabled, we want to avoid this
7201 // style.removeAttribute is IE Only, but so apparently is this code path...
7202 style.removeAttribute( "filter" );
7203
7204 // if there is no filter style applied in a css rule or unset inline opacity, we are done
7205 if ( value === "" || currentStyle && !currentStyle.filter ) {
7206 return;
7207 }
7208 }
7209
7210 // otherwise, set new filter values
7211 style.filter = ralpha.test( filter ) ?
7212 filter.replace( ralpha, opacity ) :
7213 filter + " " + opacity;
7214 }
7215 };
7216 }
7217
7218 // These hooks cannot be added until DOM ready because the support test
7219 // for it is not run until after DOM ready
7220 jQuery(function() {
7221 if ( !jQuery.support.reliableMarginRight ) {
7222 jQuery.cssHooks.marginRight = {
7223 get: function( elem, computed ) {
7224 if ( computed ) {
7225 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7226 // Work around by temporarily setting element display to inline-block
7227 return jQuery.swap( elem, { "display": "inline-block" },
7228 curCSS, [ elem, "marginRight" ] );
7229 }
7230 }
7231 };
7232 }
7233
7234 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
7235 // getComputedStyle returns percent when specified for top/left/bottom/right
7236 // rather than make the css module depend on the offset module, we just check for it here
7237 if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
7238 jQuery.each( [ "top", "left" ], function( i, prop ) {
7239 jQuery.cssHooks[ prop ] = {
7240 get: function( elem, computed ) {
7241 if ( computed ) {
7242 computed = curCSS( elem, prop );
7243 // if curCSS returns percentage, fallback to offset
7244 return rnumnonpx.test( computed ) ?
7245 jQuery( elem ).position()[ prop ] + "px" :
7246 computed;
7247 }
7248 }
7249 };
7250 });
7251 }
7252
7253 });
7254
7255 if ( jQuery.expr && jQuery.expr.filters ) {
7256 jQuery.expr.filters.hidden = function( elem ) {
7257 // Support: Opera <= 12.12
7258 // Opera reports offsetWidths and offsetHeights less than zero on some elements
7259 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
7260 (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7261 };
7262
7263 jQuery.expr.filters.visible = function( elem ) {
7264 return !jQuery.expr.filters.hidden( elem );
7265 };
7266 }
7267
7268 // These hooks are used by animate to expand properties
7269 jQuery.each({
7270 margin: "",
7271 padding: "",
7272 border: "Width"
7273 }, function( prefix, suffix ) {
7274 jQuery.cssHooks[ prefix + suffix ] = {
7275 expand: function( value ) {
7276 var i = 0,
7277 expanded = {},
7278
7279 // assumes a single number if not a string
7280 parts = typeof value === "string" ? value.split(" ") : [ value ];
7281
7282 for ( ; i < 4; i++ ) {
7283 expanded[ prefix + cssExpand[ i ] + suffix ] =
7284 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7285 }
7286
7287 return expanded;
7288 }
7289 };
7290
7291 if ( !rmargin.test( prefix ) ) {
7292 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7293 }
7294 });
7295 var r20 = /%20/g,
7296 rbracket = /\[\]$/,
7297 rCRLF = /\r?\n/g,
7298 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
7299 rsubmittable = /^(?:input|select|textarea|keygen)/i;
7300
7301 jQuery.fn.extend({
7302 serialize: function() {
7303 return jQuery.param( this.serializeArray() );
7304 },
7305 serializeArray: function() {
7306 return this.map(function(){
7307 // Can add propHook for "elements" to filter or add form elements
7308 var elements = jQuery.prop( this, "elements" );
7309 return elements ? jQuery.makeArray( elements ) : this;
7310 })
7311 .filter(function(){
7312 var type = this.type;
7313 // Use .is(":disabled") so that fieldset[disabled] works
7314 return this.name && !jQuery( this ).is( ":disabled" ) &&
7315 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
7316 ( this.checked || !manipulation_rcheckableType.test( type ) );
7317 })
7318 .map(function( i, elem ){
7319 var val = jQuery( this ).val();
7320
7321 return val == null ?
7322 null :
7323 jQuery.isArray( val ) ?
7324 jQuery.map( val, function( val ){
7325 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7326 }) :
7327 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7328 }).get();
7329 }
7330 });
7331
7332 //Serialize an array of form elements or a set of
7333 //key/values into a query string
7334 jQuery.param = function( a, traditional ) {
7335 var prefix,
7336 s = [],
7337 add = function( key, value ) {
7338 // If value is a function, invoke it and return its value
7339 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
7340 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7341 };
7342
7343 // Set traditional to true for jQuery <= 1.3.2 behavior.
7344 if ( traditional === undefined ) {
7345 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
7346 }
7347
7348 // If an array was passed in, assume that it is an array of form elements.
7349 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7350 // Serialize the form elements
7351 jQuery.each( a, function() {
7352 add( this.name, this.value );
7353 });
7354
7355 } else {
7356 // If traditional, encode the "old" way (the way 1.3.2 or older
7357 // did it), otherwise encode params recursively.
7358 for ( prefix in a ) {
7359 buildParams( prefix, a[ prefix ], traditional, add );
7360 }
7361 }
7362
7363 // Return the resulting serialization
7364 return s.join( "&" ).replace( r20, "+" );
7365 };
7366
7367 function buildParams( prefix, obj, traditional, add ) {
7368 var name;
7369
7370 if ( jQuery.isArray( obj ) ) {
7371 // Serialize array item.
7372 jQuery.each( obj, function( i, v ) {
7373 if ( traditional || rbracket.test( prefix ) ) {
7374 // Treat each array item as a scalar.
7375 add( prefix, v );
7376
7377 } else {
7378 // Item is non-scalar (array or object), encode its numeric index.
7379 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
7380 }
7381 });
7382
7383 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
7384 // Serialize object item.
7385 for ( name in obj ) {
7386 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7387 }
7388
7389 } else {
7390 // Serialize scalar item.
7391 add( prefix, obj );
7392 }
7393 }
7394 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
7395 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7396 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
7397
7398 // Handle event binding
7399 jQuery.fn[ name ] = function( data, fn ) {
7400 return arguments.length > 0 ?
7401 this.on( name, null, data, fn ) :
7402 this.trigger( name );
7403 };
7404 });
7405
7406 jQuery.fn.hover = function( fnOver, fnOut ) {
7407 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7408 };
7409 var
7410 // Document location
7411 ajaxLocParts,
7412 ajaxLocation,
7413 ajax_nonce = jQuery.now(),
7414
7415 ajax_rquery = /\?/,
7416 rhash = /#.*$/,
7417 rts = /([?&])_=[^&]*/,
7418 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7419 // #7653, #8125, #8152: local protocol detection
7420 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7421 rnoContent = /^(?:GET|HEAD)$/,
7422 rprotocol = /^\/\//,
7423 rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
7424
7425 // Keep a copy of the old load method
7426 _load = jQuery.fn.load,
7427
7428 /* Prefilters
7429 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7430 * 2) These are called:
7431 * - BEFORE asking for a transport
7432 * - AFTER param serialization (s.data is a string if s.processData is true)
7433 * 3) key is the dataType
7434 * 4) the catchall symbol "*" can be used
7435 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7436 */
7437 prefilters = {},
7438
7439 /* Transports bindings
7440 * 1) key is the dataType
7441 * 2) the catchall symbol "*" can be used
7442 * 3) selection will start with transport dataType and THEN go to "*" if needed
7443 */
7444 transports = {},
7445
7446 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7447 allTypes = "*/".concat("*");
7448
7449 // #8138, IE may throw an exception when accessing
7450 // a field from window.location if document.domain has been set
7451 try {
7452 ajaxLocation = location.href;
7453 } catch( e ) {
7454 // Use the href attribute of an A element
7455 // since IE will modify it given document.location
7456 ajaxLocation = document.createElement( "a" );
7457 ajaxLocation.href = "";
7458 ajaxLocation = ajaxLocation.href;
7459 }
7460
7461 // Segment location into parts
7462 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7463
7464 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7465 function addToPrefiltersOrTransports( structure ) {
7466
7467 // dataTypeExpression is optional and defaults to "*"
7468 return function( dataTypeExpression, func ) {
7469
7470 if ( typeof dataTypeExpression !== "string" ) {
7471 func = dataTypeExpression;
7472 dataTypeExpression = "*";
7473 }
7474
7475 var dataType,
7476 i = 0,
7477 dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
7478
7479 if ( jQuery.isFunction( func ) ) {
7480 // For each dataType in the dataTypeExpression
7481 while ( (dataType = dataTypes[i++]) ) {
7482 // Prepend if requested
7483 if ( dataType[0] === "+" ) {
7484 dataType = dataType.slice( 1 ) || "*";
7485 (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7486
7487 // Otherwise append
7488 } else {
7489 (structure[ dataType ] = structure[ dataType ] || []).push( func );
7490 }
7491 }
7492 }
7493 };
7494 }
7495
7496 // Base inspection function for prefilters and transports
7497 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7498
7499 var inspected = {},
7500 seekingTransport = ( structure === transports );
7501
7502 function inspect( dataType ) {
7503 var selected;
7504 inspected[ dataType ] = true;
7505 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7506 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7507 if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7508 options.dataTypes.unshift( dataTypeOrTransport );
7509 inspect( dataTypeOrTransport );
7510 return false;
7511 } else if ( seekingTransport ) {
7512 return !( selected = dataTypeOrTransport );
7513 }
7514 });
7515 return selected;
7516 }
7517
7518 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7519 }
7520
7521 // A special extend for ajax options
7522 // that takes "flat" options (not to be deep extended)
7523 // Fixes #9887
7524 function ajaxExtend( target, src ) {
7525 var deep, key,
7526 flatOptions = jQuery.ajaxSettings.flatOptions || {};
7527
7528 for ( key in src ) {
7529 if ( src[ key ] !== undefined ) {
7530 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7531 }
7532 }
7533 if ( deep ) {
7534 jQuery.extend( true, target, deep );
7535 }
7536
7537 return target;
7538 }
7539
7540 jQuery.fn.load = function( url, params, callback ) {
7541 if ( typeof url !== "string" && _load ) {
7542 return _load.apply( this, arguments );
7543 }
7544
7545 var selector, response, type,
7546 self = this,
7547 off = url.indexOf(" ");
7548
7549 if ( off >= 0 ) {
7550 selector = url.slice( off, url.length );
7551 url = url.slice( 0, off );
7552 }
7553
7554 // If it's a function
7555 if ( jQuery.isFunction( params ) ) {
7556
7557 // We assume that it's the callback
7558 callback = params;
7559 params = undefined;
7560
7561 // Otherwise, build a param string
7562 } else if ( params && typeof params === "object" ) {
7563 type = "POST";
7564 }
7565
7566 // If we have elements to modify, make the request
7567 if ( self.length > 0 ) {
7568 jQuery.ajax({
7569 url: url,
7570
7571 // if "type" variable is undefined, then "GET" method will be used
7572 type: type,
7573 dataType: "html",
7574 data: params
7575 }).done(function( responseText ) {
7576
7577 // Save response for use in complete callback
7578 response = arguments;
7579
7580 self.html( selector ?
7581
7582 // If a selector was specified, locate the right elements in a dummy div
7583 // Exclude scripts to avoid IE 'Permission Denied' errors
7584 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
7585
7586 // Otherwise use the full result
7587 responseText );
7588
7589 }).complete( callback && function( jqXHR, status ) {
7590 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
7591 });
7592 }
7593
7594 return this;
7595 };
7596
7597 // Attach a bunch of functions for handling common AJAX events
7598 jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
7599 jQuery.fn[ type ] = function( fn ){
7600 return this.on( type, fn );
7601 };
7602 });
7603
7604 jQuery.each( [ "get", "post" ], function( i, method ) {
7605 jQuery[ method ] = function( url, data, callback, type ) {
7606 // shift arguments if data argument was omitted
7607 if ( jQuery.isFunction( data ) ) {
7608 type = type || callback;
7609 callback = data;
7610 data = undefined;
7611 }
7612
7613 return jQuery.ajax({
7614 url: url,
7615 type: method,
7616 dataType: type,
7617 data: data,
7618 success: callback
7619 });
7620 };
7621 });
7622
7623 jQuery.extend({
7624
7625 // Counter for holding the number of active queries
7626 active: 0,
7627
7628 // Last-Modified header cache for next request
7629 lastModified: {},
7630 etag: {},
7631
7632 ajaxSettings: {
7633 url: ajaxLocation,
7634 type: "GET",
7635 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7636 global: true,
7637 processData: true,
7638 async: true,
7639 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7640 /*
7641 timeout: 0,
7642 data: null,
7643 dataType: null,
7644 username: null,
7645 password: null,
7646 cache: null,
7647 throws: false,
7648 traditional: false,
7649 headers: {},
7650 */
7651
7652 accepts: {
7653 "*": allTypes,
7654 text: "text/plain",
7655 html: "text/html",
7656 xml: "application/xml, text/xml",
7657 json: "application/json, text/javascript"
7658 },
7659
7660 contents: {
7661 xml: /xml/,
7662 html: /html/,
7663 json: /json/
7664 },
7665
7666 responseFields: {
7667 xml: "responseXML",
7668 text: "responseText"
7669 },
7670
7671 // Data converters
7672 // Keys separate source (or catchall "*") and destination types with a single space
7673 converters: {
7674
7675 // Convert anything to text
7676 "* text": window.String,
7677
7678 // Text to html (true = no transformation)
7679 "text html": true,
7680
7681 // Evaluate text as a json expression
7682 "text json": jQuery.parseJSON,
7683
7684 // Parse text as xml
7685 "text xml": jQuery.parseXML
7686 },
7687
7688 // For options that shouldn't be deep extended:
7689 // you can add your own custom options here if
7690 // and when you create one that shouldn't be
7691 // deep extended (see ajaxExtend)
7692 flatOptions: {
7693 url: true,
7694 context: true
7695 }
7696 },
7697
7698 // Creates a full fledged settings object into target
7699 // with both ajaxSettings and settings fields.
7700 // If target is omitted, writes into ajaxSettings.
7701 ajaxSetup: function( target, settings ) {
7702 return settings ?
7703
7704 // Building a settings object
7705 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7706
7707 // Extending ajaxSettings
7708 ajaxExtend( jQuery.ajaxSettings, target );
7709 },
7710
7711 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7712 ajaxTransport: addToPrefiltersOrTransports( transports ),
7713
7714 // Main method
7715 ajax: function( url, options ) {
7716
7717 // If url is an object, simulate pre-1.5 signature
7718 if ( typeof url === "object" ) {
7719 options = url;
7720 url = undefined;
7721 }
7722
7723 // Force options to be an object
7724 options = options || {};
7725
7726 var // Cross-domain detection vars
7727 parts,
7728 // Loop variable
7729 i,
7730 // URL without anti-cache param
7731 cacheURL,
7732 // Response headers as string
7733 responseHeadersString,
7734 // timeout handle
7735 timeoutTimer,
7736
7737 // To know if global events are to be dispatched
7738 fireGlobals,
7739
7740 transport,
7741 // Response headers
7742 responseHeaders,
7743 // Create the final options object
7744 s = jQuery.ajaxSetup( {}, options ),
7745 // Callbacks context
7746 callbackContext = s.context || s,
7747 // Context for global events is callbackContext if it is a DOM node or jQuery collection
7748 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7749 jQuery( callbackContext ) :
7750 jQuery.event,
7751 // Deferreds
7752 deferred = jQuery.Deferred(),
7753 completeDeferred = jQuery.Callbacks("once memory"),
7754 // Status-dependent callbacks
7755 statusCode = s.statusCode || {},
7756 // Headers (they are sent all at once)
7757 requestHeaders = {},
7758 requestHeadersNames = {},
7759 // The jqXHR state
7760 state = 0,
7761 // Default abort message
7762 strAbort = "canceled",
7763 // Fake xhr
7764 jqXHR = {
7765 readyState: 0,
7766
7767 // Builds headers hashtable if needed
7768 getResponseHeader: function( key ) {
7769 var match;
7770 if ( state === 2 ) {
7771 if ( !responseHeaders ) {
7772 responseHeaders = {};
7773 while ( (match = rheaders.exec( responseHeadersString )) ) {
7774 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7775 }
7776 }
7777 match = responseHeaders[ key.toLowerCase() ];
7778 }
7779 return match == null ? null : match;
7780 },
7781
7782 // Raw string
7783 getAllResponseHeaders: function() {
7784 return state === 2 ? responseHeadersString : null;
7785 },
7786
7787 // Caches the header
7788 setRequestHeader: function( name, value ) {
7789 var lname = name.toLowerCase();
7790 if ( !state ) {
7791 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7792 requestHeaders[ name ] = value;
7793 }
7794 return this;
7795 },
7796
7797 // Overrides response content-type header
7798 overrideMimeType: function( type ) {
7799 if ( !state ) {
7800 s.mimeType = type;
7801 }
7802 return this;
7803 },
7804
7805 // Status-dependent callbacks
7806 statusCode: function( map ) {
7807 var code;
7808 if ( map ) {
7809 if ( state < 2 ) {
7810 for ( code in map ) {
7811 // Lazy-add the new callback in a way that preserves old ones
7812 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
7813 }
7814 } else {
7815 // Execute the appropriate callbacks
7816 jqXHR.always( map[ jqXHR.status ] );
7817 }
7818 }
7819 return this;
7820 },
7821
7822 // Cancel the request
7823 abort: function( statusText ) {
7824 var finalText = statusText || strAbort;
7825 if ( transport ) {
7826 transport.abort( finalText );
7827 }
7828 done( 0, finalText );
7829 return this;
7830 }
7831 };
7832
7833 // Attach deferreds
7834 deferred.promise( jqXHR ).complete = completeDeferred.add;
7835 jqXHR.success = jqXHR.done;
7836 jqXHR.error = jqXHR.fail;
7837
7838 // Remove hash character (#7531: and string promotion)
7839 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7840 // Handle falsy url in the settings object (#10093: consistency with old signature)
7841 // We also use the url parameter if available
7842 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7843
7844 // Alias method option to type as per ticket #12004
7845 s.type = options.method || options.type || s.method || s.type;
7846
7847 // Extract dataTypes list
7848 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
7849
7850 // A cross-domain request is in order when we have a protocol:host:port mismatch
7851 if ( s.crossDomain == null ) {
7852 parts = rurl.exec( s.url.toLowerCase() );
7853 s.crossDomain = !!( parts &&
7854 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
7855 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7856 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7857 );
7858 }
7859
7860 // Convert data if not already a string
7861 if ( s.data && s.processData && typeof s.data !== "string" ) {
7862 s.data = jQuery.param( s.data, s.traditional );
7863 }
7864
7865 // Apply prefilters
7866 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7867
7868 // If request was aborted inside a prefilter, stop there
7869 if ( state === 2 ) {
7870 return jqXHR;
7871 }
7872
7873 // We can fire global events as of now if asked to
7874 fireGlobals = s.global;
7875
7876 // Watch for a new set of requests
7877 if ( fireGlobals && jQuery.active++ === 0 ) {
7878 jQuery.event.trigger("ajaxStart");
7879 }
7880
7881 // Uppercase the type
7882 s.type = s.type.toUpperCase();
7883
7884 // Determine if request has content
7885 s.hasContent = !rnoContent.test( s.type );
7886
7887 // Save the URL in case we're toying with the If-Modified-Since
7888 // and/or If-None-Match header later on
7889 cacheURL = s.url;
7890
7891 // More options handling for requests with no content
7892 if ( !s.hasContent ) {
7893
7894 // If data is available, append data to url
7895 if ( s.data ) {
7896 cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
7897 // #9682: remove data so that it's not used in an eventual retry
7898 delete s.data;
7899 }
7900
7901 // Add anti-cache in url if needed
7902 if ( s.cache === false ) {
7903 s.url = rts.test( cacheURL ) ?
7904
7905 // If there is already a '_' parameter, set its value
7906 cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
7907
7908 // Otherwise add one to the end
7909 cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
7910 }
7911 }
7912
7913 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7914 if ( s.ifModified ) {
7915 if ( jQuery.lastModified[ cacheURL ] ) {
7916 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
7917 }
7918 if ( jQuery.etag[ cacheURL ] ) {
7919 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
7920 }
7921 }
7922
7923 // Set the correct header, if data is being sent
7924 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7925 jqXHR.setRequestHeader( "Content-Type", s.contentType );
7926 }
7927
7928 // Set the Accepts header for the server, depending on the dataType
7929 jqXHR.setRequestHeader(
7930 "Accept",
7931 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7932 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
7933 s.accepts[ "*" ]
7934 );
7935
7936 // Check for headers option
7937 for ( i in s.headers ) {
7938 jqXHR.setRequestHeader( i, s.headers[ i ] );
7939 }
7940
7941 // Allow custom headers/mimetypes and early abort
7942 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7943 // Abort if not done already and return
7944 return jqXHR.abort();
7945 }
7946
7947 // aborting is no longer a cancellation
7948 strAbort = "abort";
7949
7950 // Install callbacks on deferreds
7951 for ( i in { success: 1, error: 1, complete: 1 } ) {
7952 jqXHR[ i ]( s[ i ] );
7953 }
7954
7955 // Get transport
7956 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
7957
7958 // If no transport, we auto-abort
7959 if ( !transport ) {
7960 done( -1, "No Transport" );
7961 } else {
7962 jqXHR.readyState = 1;
7963
7964 // Send global event
7965 if ( fireGlobals ) {
7966 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
7967 }
7968 // Timeout
7969 if ( s.async && s.timeout > 0 ) {
7970 timeoutTimer = setTimeout(function() {
7971 jqXHR.abort("timeout");
7972 }, s.timeout );
7973 }
7974
7975 try {
7976 state = 1;
7977 transport.send( requestHeaders, done );
7978 } catch ( e ) {
7979 // Propagate exception as error if not done
7980 if ( state < 2 ) {
7981 done( -1, e );
7982 // Simply rethrow otherwise
7983 } else {
7984 throw e;
7985 }
7986 }
7987 }
7988
7989 // Callback for when everything is done
7990 function done( status, nativeStatusText, responses, headers ) {
7991 var isSuccess, success, error, response, modified,
7992 statusText = nativeStatusText;
7993
7994 // Called once
7995 if ( state === 2 ) {
7996 return;
7997 }
7998
7999 // State is "done" now
8000 state = 2;
8001
8002 // Clear timeout if it exists
8003 if ( timeoutTimer ) {
8004 clearTimeout( timeoutTimer );
8005 }
8006
8007 // Dereference transport for early garbage collection
8008 // (no matter how long the jqXHR object will be used)
8009 transport = undefined;
8010
8011 // Cache response headers
8012 responseHeadersString = headers || "";
8013
8014 // Set readyState
8015 jqXHR.readyState = status > 0 ? 4 : 0;
8016
8017 // Get response data
8018 if ( responses ) {
8019 response = ajaxHandleResponses( s, jqXHR, responses );
8020 }
8021
8022 // If successful, handle type chaining
8023 if ( status >= 200 && status < 300 || status === 304 ) {
8024
8025 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8026 if ( s.ifModified ) {
8027 modified = jqXHR.getResponseHeader("Last-Modified");
8028 if ( modified ) {
8029 jQuery.lastModified[ cacheURL ] = modified;
8030 }
8031 modified = jqXHR.getResponseHeader("etag");
8032 if ( modified ) {
8033 jQuery.etag[ cacheURL ] = modified;
8034 }
8035 }
8036
8037 // if no content
8038 if ( status === 204 ) {
8039 isSuccess = true;
8040 statusText = "nocontent";
8041
8042 // if not modified
8043 } else if ( status === 304 ) {
8044 isSuccess = true;
8045 statusText = "notmodified";
8046
8047 // If we have data, let's convert it
8048 } else {
8049 isSuccess = ajaxConvert( s, response );
8050 statusText = isSuccess.state;
8051 success = isSuccess.data;
8052 error = isSuccess.error;
8053 isSuccess = !error;
8054 }
8055 } else {
8056 // We extract error from statusText
8057 // then normalize statusText and status for non-aborts
8058 error = statusText;
8059 if ( status || !statusText ) {
8060 statusText = "error";
8061 if ( status < 0 ) {
8062 status = 0;
8063 }
8064 }
8065 }
8066
8067 // Set data for the fake xhr object
8068 jqXHR.status = status;
8069 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8070
8071 // Success/Error
8072 if ( isSuccess ) {
8073 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8074 } else {
8075 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8076 }
8077
8078 // Status-dependent callbacks
8079 jqXHR.statusCode( statusCode );
8080 statusCode = undefined;
8081
8082 if ( fireGlobals ) {
8083 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8084 [ jqXHR, s, isSuccess ? success : error ] );
8085 }
8086
8087 // Complete
8088 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8089
8090 if ( fireGlobals ) {
8091 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8092 // Handle the global AJAX counter
8093 if ( !( --jQuery.active ) ) {
8094 jQuery.event.trigger("ajaxStop");
8095 }
8096 }
8097 }
8098
8099 return jqXHR;
8100 },
8101
8102 getScript: function( url, callback ) {
8103 return jQuery.get( url, undefined, callback, "script" );
8104 },
8105
8106 getJSON: function( url, data, callback ) {
8107 return jQuery.get( url, data, callback, "json" );
8108 }
8109 });
8110
8111 /* Handles responses to an ajax request:
8112 * - sets all responseXXX fields accordingly
8113 * - finds the right dataType (mediates between content-type and expected dataType)
8114 * - returns the corresponding response
8115 */
8116 function ajaxHandleResponses( s, jqXHR, responses ) {
8117 var firstDataType, ct, finalDataType, type,
8118 contents = s.contents,
8119 dataTypes = s.dataTypes,
8120 responseFields = s.responseFields;
8121
8122 // Fill responseXXX fields
8123 for ( type in responseFields ) {
8124 if ( type in responses ) {
8125 jqXHR[ responseFields[type] ] = responses[ type ];
8126 }
8127 }
8128
8129 // Remove auto dataType and get content-type in the process
8130 while( dataTypes[ 0 ] === "*" ) {
8131 dataTypes.shift();
8132 if ( ct === undefined ) {
8133 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8134 }
8135 }
8136
8137 // Check if we're dealing with a known content-type
8138 if ( ct ) {
8139 for ( type in contents ) {
8140 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8141 dataTypes.unshift( type );
8142 break;
8143 }
8144 }
8145 }
8146
8147 // Check to see if we have a response for the expected dataType
8148 if ( dataTypes[ 0 ] in responses ) {
8149 finalDataType = dataTypes[ 0 ];
8150 } else {
8151 // Try convertible dataTypes
8152 for ( type in responses ) {
8153 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8154 finalDataType = type;
8155 break;
8156 }
8157 if ( !firstDataType ) {
8158 firstDataType = type;
8159 }
8160 }
8161 // Or just use first one
8162 finalDataType = finalDataType || firstDataType;
8163 }
8164
8165 // If we found a dataType
8166 // We add the dataType to the list if needed
8167 // and return the corresponding response
8168 if ( finalDataType ) {
8169 if ( finalDataType !== dataTypes[ 0 ] ) {
8170 dataTypes.unshift( finalDataType );
8171 }
8172 return responses[ finalDataType ];
8173 }
8174 }
8175
8176 // Chain conversions given the request and the original response
8177 function ajaxConvert( s, response ) {
8178 var conv2, current, conv, tmp,
8179 converters = {},
8180 i = 0,
8181 // Work with a copy of dataTypes in case we need to modify it for conversion
8182 dataTypes = s.dataTypes.slice(),
8183 prev = dataTypes[ 0 ];
8184
8185 // Apply the dataFilter if provided
8186 if ( s.dataFilter ) {
8187 response = s.dataFilter( response, s.dataType );
8188 }
8189
8190 // Create converters map with lowercased keys
8191 if ( dataTypes[ 1 ] ) {
8192 for ( conv in s.converters ) {
8193 converters[ conv.toLowerCase() ] = s.converters[ conv ];
8194 }
8195 }
8196
8197 // Convert to each sequential dataType, tolerating list modification
8198 for ( ; (current = dataTypes[++i]); ) {
8199
8200 // There's only work to do if current dataType is non-auto
8201 if ( current !== "*" ) {
8202
8203 // Convert response if prev dataType is non-auto and differs from current
8204 if ( prev !== "*" && prev !== current ) {
8205
8206 // Seek a direct converter
8207 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8208
8209 // If none found, seek a pair
8210 if ( !conv ) {
8211 for ( conv2 in converters ) {
8212
8213 // If conv2 outputs current
8214 tmp = conv2.split(" ");
8215 if ( tmp[ 1 ] === current ) {
8216
8217 // If prev can be converted to accepted input
8218 conv = converters[ prev + " " + tmp[ 0 ] ] ||
8219 converters[ "* " + tmp[ 0 ] ];
8220 if ( conv ) {
8221 // Condense equivalence converters
8222 if ( conv === true ) {
8223 conv = converters[ conv2 ];
8224
8225 // Otherwise, insert the intermediate dataType
8226 } else if ( converters[ conv2 ] !== true ) {
8227 current = tmp[ 0 ];
8228 dataTypes.splice( i--, 0, current );
8229 }
8230
8231 break;
8232 }
8233 }
8234 }
8235 }
8236
8237 // Apply converter (if not an equivalence)
8238 if ( conv !== true ) {
8239
8240 // Unless errors are allowed to bubble, catch and return them
8241 if ( conv && s["throws"] ) {
8242 response = conv( response );
8243 } else {
8244 try {
8245 response = conv( response );
8246 } catch ( e ) {
8247 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8248 }
8249 }
8250 }
8251 }
8252
8253 // Update prev for next iteration
8254 prev = current;
8255 }
8256 }
8257
8258 return { state: "success", data: response };
8259 }
8260 // Install script dataType
8261 jQuery.ajaxSetup({
8262 accepts: {
8263 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8264 },
8265 contents: {
8266 script: /(?:java|ecma)script/
8267 },
8268 converters: {
8269 "text script": function( text ) {
8270 jQuery.globalEval( text );
8271 return text;
8272 }
8273 }
8274 });
8275
8276 // Handle cache's special case and global
8277 jQuery.ajaxPrefilter( "script", function( s ) {
8278 if ( s.cache === undefined ) {
8279 s.cache = false;
8280 }
8281 if ( s.crossDomain ) {
8282 s.type = "GET";
8283 s.global = false;
8284 }
8285 });
8286
8287 // Bind script tag hack transport
8288 jQuery.ajaxTransport( "script", function(s) {
8289
8290 // This transport only deals with cross domain requests
8291 if ( s.crossDomain ) {
8292
8293 var script,
8294 head = document.head || jQuery("head")[0] || document.documentElement;
8295
8296 return {
8297
8298 send: function( _, callback ) {
8299
8300 script = document.createElement("script");
8301
8302 script.async = true;
8303
8304 if ( s.scriptCharset ) {
8305 script.charset = s.scriptCharset;
8306 }
8307
8308 script.src = s.url;
8309
8310 // Attach handlers for all browsers
8311 script.onload = script.onreadystatechange = function( _, isAbort ) {
8312
8313 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8314
8315 // Handle memory leak in IE
8316 script.onload = script.onreadystatechange = null;
8317
8318 // Remove the script
8319 if ( script.parentNode ) {
8320 script.parentNode.removeChild( script );
8321 }
8322
8323 // Dereference the script
8324 script = null;
8325
8326 // Callback if not abort
8327 if ( !isAbort ) {
8328 callback( 200, "success" );
8329 }
8330 }
8331 };
8332
8333 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
8334 // Use native DOM manipulation to avoid our domManip AJAX trickery
8335 head.insertBefore( script, head.firstChild );
8336 },
8337
8338 abort: function() {
8339 if ( script ) {
8340 script.onload( undefined, true );
8341 }
8342 }
8343 };
8344 }
8345 });
8346 var oldCallbacks = [],
8347 rjsonp = /(=)\?(?=&|$)|\?\?/;
8348
8349 // Default jsonp settings
8350 jQuery.ajaxSetup({
8351 jsonp: "callback",
8352 jsonpCallback: function() {
8353 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
8354 this[ callback ] = true;
8355 return callback;
8356 }
8357 });
8358
8359 // Detect, normalize options and install callbacks for jsonp requests
8360 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8361
8362 var callbackName, overwritten, responseContainer,
8363 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8364 "url" :
8365 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8366 );
8367
8368 // Handle iff the expected data type is "jsonp" or we have a parameter to set
8369 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8370
8371 // Get callback name, remembering preexisting value associated with it
8372 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8373 s.jsonpCallback() :
8374 s.jsonpCallback;
8375
8376 // Insert callback into url or form data
8377 if ( jsonProp ) {
8378 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8379 } else if ( s.jsonp !== false ) {
8380 s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8381 }
8382
8383 // Use data converter to retrieve json after script execution
8384 s.converters["script json"] = function() {
8385 if ( !responseContainer ) {
8386 jQuery.error( callbackName + " was not called" );
8387 }
8388 return responseContainer[ 0 ];
8389 };
8390
8391 // force json dataType
8392 s.dataTypes[ 0 ] = "json";
8393
8394 // Install callback
8395 overwritten = window[ callbackName ];
8396 window[ callbackName ] = function() {
8397 responseContainer = arguments;
8398 };
8399
8400 // Clean-up function (fires after converters)
8401 jqXHR.always(function() {
8402 // Restore preexisting value
8403 window[ callbackName ] = overwritten;
8404
8405 // Save back as free
8406 if ( s[ callbackName ] ) {
8407 // make sure that re-using the options doesn't screw things around
8408 s.jsonpCallback = originalSettings.jsonpCallback;
8409
8410 // save the callback name for future use
8411 oldCallbacks.push( callbackName );
8412 }
8413
8414 // Call if it was a function and we have a response
8415 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8416 overwritten( responseContainer[ 0 ] );
8417 }
8418
8419 responseContainer = overwritten = undefined;
8420 });
8421
8422 // Delegate to script
8423 return "script";
8424 }
8425 });
8426 var xhrCallbacks, xhrSupported,
8427 xhrId = 0,
8428 // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8429 xhrOnUnloadAbort = window.ActiveXObject && function() {
8430 // Abort all pending requests
8431 var key;
8432 for ( key in xhrCallbacks ) {
8433 xhrCallbacks[ key ]( undefined, true );
8434 }
8435 };
8436
8437 // Functions to create xhrs
8438 function createStandardXHR() {
8439 try {
8440 return new window.XMLHttpRequest();
8441 } catch( e ) {}
8442 }
8443
8444 function createActiveXHR() {
8445 try {
8446 return new window.ActiveXObject("Microsoft.XMLHTTP");
8447 } catch( e ) {}
8448 }
8449
8450 // Create the request object
8451 // (This is still attached to ajaxSettings for backward compatibility)
8452 jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8453 /* Microsoft failed to properly
8454 * implement the XMLHttpRequest in IE7 (can't request local files),
8455 * so we use the ActiveXObject when it is available
8456 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8457 * we need a fallback.
8458 */
8459 function() {
8460 return !this.isLocal && createStandardXHR() || createActiveXHR();
8461 } :
8462 // For all other browsers, use the standard XMLHttpRequest object
8463 createStandardXHR;
8464
8465 // Determine support properties
8466 xhrSupported = jQuery.ajaxSettings.xhr();
8467 jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8468 xhrSupported = jQuery.support.ajax = !!xhrSupported;
8469
8470 // Create transport if the browser can provide an xhr
8471 if ( xhrSupported ) {
8472
8473 jQuery.ajaxTransport(function( s ) {
8474 // Cross domain only allowed if supported through XMLHttpRequest
8475 if ( !s.crossDomain || jQuery.support.cors ) {
8476
8477 var callback;
8478
8479 return {
8480 send: function( headers, complete ) {
8481
8482 // Get a new xhr
8483 var handle, i,
8484 xhr = s.xhr();
8485
8486 // Open the socket
8487 // Passing null username, generates a login popup on Opera (#2865)
8488 if ( s.username ) {
8489 xhr.open( s.type, s.url, s.async, s.username, s.password );
8490 } else {
8491 xhr.open( s.type, s.url, s.async );
8492 }
8493
8494 // Apply custom fields if provided
8495 if ( s.xhrFields ) {
8496 for ( i in s.xhrFields ) {
8497 xhr[ i ] = s.xhrFields[ i ];
8498 }
8499 }
8500
8501 // Override mime type if needed
8502 if ( s.mimeType && xhr.overrideMimeType ) {
8503 xhr.overrideMimeType( s.mimeType );
8504 }
8505
8506 // X-Requested-With header
8507 // For cross-domain requests, seeing as conditions for a preflight are
8508 // akin to a jigsaw puzzle, we simply never set it to be sure.
8509 // (it can always be set on a per-request basis or even using ajaxSetup)
8510 // For same-domain requests, won't change header if already provided.
8511 if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8512 headers["X-Requested-With"] = "XMLHttpRequest";
8513 }
8514
8515 // Need an extra try/catch for cross domain requests in Firefox 3
8516 try {
8517 for ( i in headers ) {
8518 xhr.setRequestHeader( i, headers[ i ] );
8519 }
8520 } catch( err ) {}
8521
8522 // Do send the request
8523 // This may raise an exception which is actually
8524 // handled in jQuery.ajax (so no try/catch here)
8525 xhr.send( ( s.hasContent && s.data ) || null );
8526
8527 // Listener
8528 callback = function( _, isAbort ) {
8529 var status, responseHeaders, statusText, responses;
8530
8531 // Firefox throws exceptions when accessing properties
8532 // of an xhr when a network error occurred
8533 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8534 try {
8535
8536 // Was never called and is aborted or complete
8537 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8538
8539 // Only called once
8540 callback = undefined;
8541
8542 // Do not keep as active anymore
8543 if ( handle ) {
8544 xhr.onreadystatechange = jQuery.noop;
8545 if ( xhrOnUnloadAbort ) {
8546 delete xhrCallbacks[ handle ];
8547 }
8548 }
8549
8550 // If it's an abort
8551 if ( isAbort ) {
8552 // Abort it manually if needed
8553 if ( xhr.readyState !== 4 ) {
8554 xhr.abort();
8555 }
8556 } else {
8557 responses = {};
8558 status = xhr.status;
8559 responseHeaders = xhr.getAllResponseHeaders();
8560
8561 // When requesting binary data, IE6-9 will throw an exception
8562 // on any attempt to access responseText (#11426)
8563 if ( typeof xhr.responseText === "string" ) {
8564 responses.text = xhr.responseText;
8565 }
8566
8567 // Firefox throws an exception when accessing
8568 // statusText for faulty cross-domain requests
8569 try {
8570 statusText = xhr.statusText;
8571 } catch( e ) {
8572 // We normalize with Webkit giving an empty statusText
8573 statusText = "";
8574 }
8575
8576 // Filter status for non standard behaviors
8577
8578 // If the request is local and we have data: assume a success
8579 // (success with no data won't get notified, that's the best we
8580 // can do given current implementations)
8581 if ( !status && s.isLocal && !s.crossDomain ) {
8582 status = responses.text ? 200 : 404;
8583 // IE - #1450: sometimes returns 1223 when it should be 204
8584 } else if ( status === 1223 ) {
8585 status = 204;
8586 }
8587 }
8588 }
8589 } catch( firefoxAccessException ) {
8590 if ( !isAbort ) {
8591 complete( -1, firefoxAccessException );
8592 }
8593 }
8594
8595 // Call complete if needed
8596 if ( responses ) {
8597 complete( status, statusText, responses, responseHeaders );
8598 }
8599 };
8600
8601 if ( !s.async ) {
8602 // if we're in sync mode we fire the callback
8603 callback();
8604 } else if ( xhr.readyState === 4 ) {
8605 // (IE6 & IE7) if it's in cache and has been
8606 // retrieved directly we need to fire the callback
8607 setTimeout( callback );
8608 } else {
8609 handle = ++xhrId;
8610 if ( xhrOnUnloadAbort ) {
8611 // Create the active xhrs callbacks list if needed
8612 // and attach the unload handler
8613 if ( !xhrCallbacks ) {
8614 xhrCallbacks = {};
8615 jQuery( window ).unload( xhrOnUnloadAbort );
8616 }
8617 // Add to list of active xhrs callbacks
8618 xhrCallbacks[ handle ] = callback;
8619 }
8620 xhr.onreadystatechange = callback;
8621 }
8622 },
8623
8624 abort: function() {
8625 if ( callback ) {
8626 callback( undefined, true );
8627 }
8628 }
8629 };
8630 }
8631 });
8632 }
8633 var fxNow, timerId,
8634 rfxtypes = /^(?:toggle|show|hide)$/,
8635 rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
8636 rrun = /queueHooks$/,
8637 animationPrefilters = [ defaultPrefilter ],
8638 tweeners = {
8639 "*": [function( prop, value ) {
8640 var end, unit,
8641 tween = this.createTween( prop, value ),
8642 parts = rfxnum.exec( value ),
8643 target = tween.cur(),
8644 start = +target || 0,
8645 scale = 1,
8646 maxIterations = 20;
8647
8648 if ( parts ) {
8649 end = +parts[2];
8650 unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8651
8652 // We need to compute starting value
8653 if ( unit !== "px" && start ) {
8654 // Iteratively approximate from a nonzero starting point
8655 // Prefer the current property, because this process will be trivial if it uses the same units
8656 // Fallback to end or a simple constant
8657 start = jQuery.css( tween.elem, prop, true ) || end || 1;
8658
8659 do {
8660 // If previous iteration zeroed out, double until we get *something*
8661 // Use a string for doubling factor so we don't accidentally see scale as unchanged below
8662 scale = scale || ".5";
8663
8664 // Adjust and apply
8665 start = start / scale;
8666 jQuery.style( tween.elem, prop, start + unit );
8667
8668 // Update scale, tolerating zero or NaN from tween.cur()
8669 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8670 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8671 }
8672
8673 tween.unit = unit;
8674 tween.start = start;
8675 // If a +=/-= token was provided, we're doing a relative animation
8676 tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
8677 }
8678 return tween;
8679 }]
8680 };
8681
8682 // Animations created synchronously will run synchronously
8683 function createFxNow() {
8684 setTimeout(function() {
8685 fxNow = undefined;
8686 });
8687 return ( fxNow = jQuery.now() );
8688 }
8689
8690 function createTweens( animation, props ) {
8691 jQuery.each( props, function( prop, value ) {
8692 var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8693 index = 0,
8694 length = collection.length;
8695 for ( ; index < length; index++ ) {
8696 if ( collection[ index ].call( animation, prop, value ) ) {
8697
8698 // we're done with this property
8699 return;
8700 }
8701 }
8702 });
8703 }
8704
8705 function Animation( elem, properties, options ) {
8706 var result,
8707 stopped,
8708 index = 0,
8709 length = animationPrefilters.length,
8710 deferred = jQuery.Deferred().always( function() {
8711 // don't match elem in the :animated selector
8712 delete tick.elem;
8713 }),
8714 tick = function() {
8715 if ( stopped ) {
8716 return false;
8717 }
8718 var currentTime = fxNow || createFxNow(),
8719 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8720 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8721 temp = remaining / animation.duration || 0,
8722 percent = 1 - temp,
8723 index = 0,
8724 length = animation.tweens.length;
8725
8726 for ( ; index < length ; index++ ) {
8727 animation.tweens[ index ].run( percent );
8728 }
8729
8730 deferred.notifyWith( elem, [ animation, percent, remaining ]);
8731
8732 if ( percent < 1 && length ) {
8733 return remaining;
8734 } else {
8735 deferred.resolveWith( elem, [ animation ] );
8736 return false;
8737 }
8738 },
8739 animation = deferred.promise({
8740 elem: elem,
8741 props: jQuery.extend( {}, properties ),
8742 opts: jQuery.extend( true, { specialEasing: {} }, options ),
8743 originalProperties: properties,
8744 originalOptions: options,
8745 startTime: fxNow || createFxNow(),
8746 duration: options.duration,
8747 tweens: [],
8748 createTween: function( prop, end ) {
8749 var tween = jQuery.Tween( elem, animation.opts, prop, end,
8750 animation.opts.specialEasing[ prop ] || animation.opts.easing );
8751 animation.tweens.push( tween );
8752 return tween;
8753 },
8754 stop: function( gotoEnd ) {
8755 var index = 0,
8756 // if we are going to the end, we want to run all the tweens
8757 // otherwise we skip this part
8758 length = gotoEnd ? animation.tweens.length : 0;
8759 if ( stopped ) {
8760 return this;
8761 }
8762 stopped = true;
8763 for ( ; index < length ; index++ ) {
8764 animation.tweens[ index ].run( 1 );
8765 }
8766
8767 // resolve when we played the last frame
8768 // otherwise, reject
8769 if ( gotoEnd ) {
8770 deferred.resolveWith( elem, [ animation, gotoEnd ] );
8771 } else {
8772 deferred.rejectWith( elem, [ animation, gotoEnd ] );
8773 }
8774 return this;
8775 }
8776 }),
8777 props = animation.props;
8778
8779 propFilter( props, animation.opts.specialEasing );
8780
8781 for ( ; index < length ; index++ ) {
8782 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
8783 if ( result ) {
8784 return result;
8785 }
8786 }
8787
8788 createTweens( animation, props );
8789
8790 if ( jQuery.isFunction( animation.opts.start ) ) {
8791 animation.opts.start.call( elem, animation );
8792 }
8793
8794 jQuery.fx.timer(
8795 jQuery.extend( tick, {
8796 elem: elem,
8797 anim: animation,
8798 queue: animation.opts.queue
8799 })
8800 );
8801
8802 // attach callbacks from options
8803 return animation.progress( animation.opts.progress )
8804 .done( animation.opts.done, animation.opts.complete )
8805 .fail( animation.opts.fail )
8806 .always( animation.opts.always );
8807 }
8808
8809 function propFilter( props, specialEasing ) {
8810 var value, name, index, easing, hooks;
8811
8812 // camelCase, specialEasing and expand cssHook pass
8813 for ( index in props ) {
8814 name = jQuery.camelCase( index );
8815 easing = specialEasing[ name ];
8816 value = props[ index ];
8817 if ( jQuery.isArray( value ) ) {
8818 easing = value[ 1 ];
8819 value = props[ index ] = value[ 0 ];
8820 }
8821
8822 if ( index !== name ) {
8823 props[ name ] = value;
8824 delete props[ index ];
8825 }
8826
8827 hooks = jQuery.cssHooks[ name ];
8828 if ( hooks && "expand" in hooks ) {
8829 value = hooks.expand( value );
8830 delete props[ name ];
8831
8832 // not quite $.extend, this wont overwrite keys already present.
8833 // also - reusing 'index' from above because we have the correct "name"
8834 for ( index in value ) {
8835 if ( !( index in props ) ) {
8836 props[ index ] = value[ index ];
8837 specialEasing[ index ] = easing;
8838 }
8839 }
8840 } else {
8841 specialEasing[ name ] = easing;
8842 }
8843 }
8844 }
8845
8846 jQuery.Animation = jQuery.extend( Animation, {
8847
8848 tweener: function( props, callback ) {
8849 if ( jQuery.isFunction( props ) ) {
8850 callback = props;
8851 props = [ "*" ];
8852 } else {
8853 props = props.split(" ");
8854 }
8855
8856 var prop,
8857 index = 0,
8858 length = props.length;
8859
8860 for ( ; index < length ; index++ ) {
8861 prop = props[ index ];
8862 tweeners[ prop ] = tweeners[ prop ] || [];
8863 tweeners[ prop ].unshift( callback );
8864 }
8865 },
8866
8867 prefilter: function( callback, prepend ) {
8868 if ( prepend ) {
8869 animationPrefilters.unshift( callback );
8870 } else {
8871 animationPrefilters.push( callback );
8872 }
8873 }
8874 });
8875
8876 function defaultPrefilter( elem, props, opts ) {
8877 /*jshint validthis:true */
8878 var prop, index, length,
8879 value, dataShow, toggle,
8880 tween, hooks, oldfire,
8881 anim = this,
8882 style = elem.style,
8883 orig = {},
8884 handled = [],
8885 hidden = elem.nodeType && isHidden( elem );
8886
8887 // handle queue: false promises
8888 if ( !opts.queue ) {
8889 hooks = jQuery._queueHooks( elem, "fx" );
8890 if ( hooks.unqueued == null ) {
8891 hooks.unqueued = 0;
8892 oldfire = hooks.empty.fire;
8893 hooks.empty.fire = function() {
8894 if ( !hooks.unqueued ) {
8895 oldfire();
8896 }
8897 };
8898 }
8899 hooks.unqueued++;
8900
8901 anim.always(function() {
8902 // doing this makes sure that the complete handler will be called
8903 // before this completes
8904 anim.always(function() {
8905 hooks.unqueued--;
8906 if ( !jQuery.queue( elem, "fx" ).length ) {
8907 hooks.empty.fire();
8908 }
8909 });
8910 });
8911 }
8912
8913 // height/width overflow pass
8914 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
8915 // Make sure that nothing sneaks out
8916 // Record all 3 overflow attributes because IE does not
8917 // change the overflow attribute when overflowX and
8918 // overflowY are set to the same value
8919 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
8920
8921 // Set display property to inline-block for height/width
8922 // animations on inline elements that are having width/height animated
8923 if ( jQuery.css( elem, "display" ) === "inline" &&
8924 jQuery.css( elem, "float" ) === "none" ) {
8925
8926 // inline-level elements accept inline-block;
8927 // block-level elements need to be inline with layout
8928 if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
8929 style.display = "inline-block";
8930
8931 } else {
8932 style.zoom = 1;
8933 }
8934 }
8935 }
8936
8937 if ( opts.overflow ) {
8938 style.overflow = "hidden";
8939 if ( !jQuery.support.shrinkWrapBlocks ) {
8940 anim.always(function() {
8941 style.overflow = opts.overflow[ 0 ];
8942 style.overflowX = opts.overflow[ 1 ];
8943 style.overflowY = opts.overflow[ 2 ];
8944 });
8945 }
8946 }
8947
8948
8949 // show/hide pass
8950 for ( index in props ) {
8951 value = props[ index ];
8952 if ( rfxtypes.exec( value ) ) {
8953 delete props[ index ];
8954 toggle = toggle || value === "toggle";
8955 if ( value === ( hidden ? "hide" : "show" ) ) {
8956 continue;
8957 }
8958 handled.push( index );
8959 }
8960 }
8961
8962 length = handled.length;
8963 if ( length ) {
8964 dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
8965 if ( "hidden" in dataShow ) {
8966 hidden = dataShow.hidden;
8967 }
8968
8969 // store state if its toggle - enables .stop().toggle() to "reverse"
8970 if ( toggle ) {
8971 dataShow.hidden = !hidden;
8972 }
8973 if ( hidden ) {
8974 jQuery( elem ).show();
8975 } else {
8976 anim.done(function() {
8977 jQuery( elem ).hide();
8978 });
8979 }
8980 anim.done(function() {
8981 var prop;
8982 jQuery._removeData( elem, "fxshow" );
8983 for ( prop in orig ) {
8984 jQuery.style( elem, prop, orig[ prop ] );
8985 }
8986 });
8987 for ( index = 0 ; index < length ; index++ ) {
8988 prop = handled[ index ];
8989 tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
8990 orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
8991
8992 if ( !( prop in dataShow ) ) {
8993 dataShow[ prop ] = tween.start;
8994 if ( hidden ) {
8995 tween.end = tween.start;
8996 tween.start = prop === "width" || prop === "height" ? 1 : 0;
8997 }
8998 }
8999 }
9000 }
9001 }
9002
9003 function Tween( elem, options, prop, end, easing ) {
9004 return new Tween.prototype.init( elem, options, prop, end, easing );
9005 }
9006 jQuery.Tween = Tween;
9007
9008 Tween.prototype = {
9009 constructor: Tween,
9010 init: function( elem, options, prop, end, easing, unit ) {
9011 this.elem = elem;
9012 this.prop = prop;
9013 this.easing = easing || "swing";
9014 this.options = options;
9015 this.start = this.now = this.cur();
9016 this.end = end;
9017 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
9018 },
9019 cur: function() {
9020 var hooks = Tween.propHooks[ this.prop ];
9021
9022 return hooks && hooks.get ?
9023 hooks.get( this ) :
9024 Tween.propHooks._default.get( this );
9025 },
9026 run: function( percent ) {
9027 var eased,
9028 hooks = Tween.propHooks[ this.prop ];
9029
9030 if ( this.options.duration ) {
9031 this.pos = eased = jQuery.easing[ this.easing ](
9032 percent, this.options.duration * percent, 0, 1, this.options.duration
9033 );
9034 } else {
9035 this.pos = eased = percent;
9036 }
9037 this.now = ( this.end - this.start ) * eased + this.start;
9038
9039 if ( this.options.step ) {
9040 this.options.step.call( this.elem, this.now, this );
9041 }
9042
9043 if ( hooks && hooks.set ) {
9044 hooks.set( this );
9045 } else {
9046 Tween.propHooks._default.set( this );
9047 }
9048 return this;
9049 }
9050 };
9051
9052 Tween.prototype.init.prototype = Tween.prototype;
9053
9054 Tween.propHooks = {
9055 _default: {
9056 get: function( tween ) {
9057 var result;
9058
9059 if ( tween.elem[ tween.prop ] != null &&
9060 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
9061 return tween.elem[ tween.prop ];
9062 }
9063
9064 // passing an empty string as a 3rd parameter to .css will automatically
9065 // attempt a parseFloat and fallback to a string if the parse fails
9066 // so, simple values such as "10px" are parsed to Float.
9067 // complex values such as "rotate(1rad)" are returned as is.
9068 result = jQuery.css( tween.elem, tween.prop, "" );
9069 // Empty strings, null, undefined and "auto" are converted to 0.
9070 return !result || result === "auto" ? 0 : result;
9071 },
9072 set: function( tween ) {
9073 // use step hook for back compat - use cssHook if its there - use .style if its
9074 // available and use plain properties where available
9075 if ( jQuery.fx.step[ tween.prop ] ) {
9076 jQuery.fx.step[ tween.prop ]( tween );
9077 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
9078 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
9079 } else {
9080 tween.elem[ tween.prop ] = tween.now;
9081 }
9082 }
9083 }
9084 };
9085
9086 // Remove in 2.0 - this supports IE8's panic based approach
9087 // to setting things on disconnected nodes
9088
9089 Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
9090 set: function( tween ) {
9091 if ( tween.elem.nodeType && tween.elem.parentNode ) {
9092 tween.elem[ tween.prop ] = tween.now;
9093 }
9094 }
9095 };
9096
9097 jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9098 var cssFn = jQuery.fn[ name ];
9099 jQuery.fn[ name ] = function( speed, easing, callback ) {
9100 return speed == null || typeof speed === "boolean" ?
9101 cssFn.apply( this, arguments ) :
9102 this.animate( genFx( name, true ), speed, easing, callback );
9103 };
9104 });
9105
9106 jQuery.fn.extend({
9107 fadeTo: function( speed, to, easing, callback ) {
9108
9109 // show any hidden elements after setting opacity to 0
9110 return this.filter( isHidden ).css( "opacity", 0 ).show()
9111
9112 // animate to the value specified
9113 .end().animate({ opacity: to }, speed, easing, callback );
9114 },
9115 animate: function( prop, speed, easing, callback ) {
9116 var empty = jQuery.isEmptyObject( prop ),
9117 optall = jQuery.speed( speed, easing, callback ),
9118 doAnimation = function() {
9119 // Operate on a copy of prop so per-property easing won't be lost
9120 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9121 doAnimation.finish = function() {
9122 anim.stop( true );
9123 };
9124 // Empty animations, or finishing resolves immediately
9125 if ( empty || jQuery._data( this, "finish" ) ) {
9126 anim.stop( true );
9127 }
9128 };
9129 doAnimation.finish = doAnimation;
9130
9131 return empty || optall.queue === false ?
9132 this.each( doAnimation ) :
9133 this.queue( optall.queue, doAnimation );
9134 },
9135 stop: function( type, clearQueue, gotoEnd ) {
9136 var stopQueue = function( hooks ) {
9137 var stop = hooks.stop;
9138 delete hooks.stop;
9139 stop( gotoEnd );
9140 };
9141
9142 if ( typeof type !== "string" ) {
9143 gotoEnd = clearQueue;
9144 clearQueue = type;
9145 type = undefined;
9146 }
9147 if ( clearQueue && type !== false ) {
9148 this.queue( type || "fx", [] );
9149 }
9150
9151 return this.each(function() {
9152 var dequeue = true,
9153 index = type != null && type + "queueHooks",
9154 timers = jQuery.timers,
9155 data = jQuery._data( this );
9156
9157 if ( index ) {
9158 if ( data[ index ] && data[ index ].stop ) {
9159 stopQueue( data[ index ] );
9160 }
9161 } else {
9162 for ( index in data ) {
9163 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9164 stopQueue( data[ index ] );
9165 }
9166 }
9167 }
9168
9169 for ( index = timers.length; index--; ) {
9170 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9171 timers[ index ].anim.stop( gotoEnd );
9172 dequeue = false;
9173 timers.splice( index, 1 );
9174 }
9175 }
9176
9177 // start the next in the queue if the last step wasn't forced
9178 // timers currently will call their complete callbacks, which will dequeue
9179 // but only if they were gotoEnd
9180 if ( dequeue || !gotoEnd ) {
9181 jQuery.dequeue( this, type );
9182 }
9183 });
9184 },
9185 finish: function( type ) {
9186 if ( type !== false ) {
9187 type = type || "fx";
9188 }
9189 return this.each(function() {
9190 var index,
9191 data = jQuery._data( this ),
9192 queue = data[ type + "queue" ],
9193 hooks = data[ type + "queueHooks" ],
9194 timers = jQuery.timers,
9195 length = queue ? queue.length : 0;
9196
9197 // enable finishing flag on private data
9198 data.finish = true;
9199
9200 // empty the queue first
9201 jQuery.queue( this, type, [] );
9202
9203 if ( hooks && hooks.cur && hooks.cur.finish ) {
9204 hooks.cur.finish.call( this );
9205 }
9206
9207 // look for any active animations, and finish them
9208 for ( index = timers.length; index--; ) {
9209 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
9210 timers[ index ].anim.stop( true );
9211 timers.splice( index, 1 );
9212 }
9213 }
9214
9215 // look for any animations in the old queue and finish them
9216 for ( index = 0; index < length; index++ ) {
9217 if ( queue[ index ] && queue[ index ].finish ) {
9218 queue[ index ].finish.call( this );
9219 }
9220 }
9221
9222 // turn off finishing flag
9223 delete data.finish;
9224 });
9225 }
9226 });
9227
9228 // Generate parameters to create a standard animation
9229 function genFx( type, includeWidth ) {
9230 var which,
9231 attrs = { height: type },
9232 i = 0;
9233
9234 // if we include width, step value is 1 to do all cssExpand values,
9235 // if we don't include width, step value is 2 to skip over Left and Right
9236 includeWidth = includeWidth? 1 : 0;
9237 for( ; i < 4 ; i += 2 - includeWidth ) {
9238 which = cssExpand[ i ];
9239 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
9240 }
9241
9242 if ( includeWidth ) {
9243 attrs.opacity = attrs.width = type;
9244 }
9245
9246 return attrs;
9247 }
9248
9249 // Generate shortcuts for custom animations
9250 jQuery.each({
9251 slideDown: genFx("show"),
9252 slideUp: genFx("hide"),
9253 slideToggle: genFx("toggle"),
9254 fadeIn: { opacity: "show" },
9255 fadeOut: { opacity: "hide" },
9256 fadeToggle: { opacity: "toggle" }
9257 }, function( name, props ) {
9258 jQuery.fn[ name ] = function( speed, easing, callback ) {
9259 return this.animate( props, speed, easing, callback );
9260 };
9261 });
9262
9263 jQuery.speed = function( speed, easing, fn ) {
9264 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9265 complete: fn || !fn && easing ||
9266 jQuery.isFunction( speed ) && speed,
9267 duration: speed,
9268 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9269 };
9270
9271 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9272 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9273
9274 // normalize opt.queue - true/undefined/null -> "fx"
9275 if ( opt.queue == null || opt.queue === true ) {
9276 opt.queue = "fx";
9277 }
9278
9279 // Queueing
9280 opt.old = opt.complete;
9281
9282 opt.complete = function() {
9283 if ( jQuery.isFunction( opt.old ) ) {
9284 opt.old.call( this );
9285 }
9286
9287 if ( opt.queue ) {
9288 jQuery.dequeue( this, opt.queue );
9289 }
9290 };
9291
9292 return opt;
9293 };
9294
9295 jQuery.easing = {
9296 linear: function( p ) {
9297 return p;
9298 },
9299 swing: function( p ) {
9300 return 0.5 - Math.cos( p*Math.PI ) / 2;
9301 }
9302 };
9303
9304 jQuery.timers = [];
9305 jQuery.fx = Tween.prototype.init;
9306 jQuery.fx.tick = function() {
9307 var timer,
9308 timers = jQuery.timers,
9309 i = 0;
9310
9311 fxNow = jQuery.now();
9312
9313 for ( ; i < timers.length; i++ ) {
9314 timer = timers[ i ];
9315 // Checks the timer has not already been removed
9316 if ( !timer() && timers[ i ] === timer ) {
9317 timers.splice( i--, 1 );
9318 }
9319 }
9320
9321 if ( !timers.length ) {
9322 jQuery.fx.stop();
9323 }
9324 fxNow = undefined;
9325 };
9326
9327 jQuery.fx.timer = function( timer ) {
9328 if ( timer() && jQuery.timers.push( timer ) ) {
9329 jQuery.fx.start();
9330 }
9331 };
9332
9333 jQuery.fx.interval = 13;
9334
9335 jQuery.fx.start = function() {
9336 if ( !timerId ) {
9337 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9338 }
9339 };
9340
9341 jQuery.fx.stop = function() {
9342 clearInterval( timerId );
9343 timerId = null;
9344 };
9345
9346 jQuery.fx.speeds = {
9347 slow: 600,
9348 fast: 200,
9349 // Default speed
9350 _default: 400
9351 };
9352
9353 // Back Compat <1.8 extension point
9354 jQuery.fx.step = {};
9355
9356 if ( jQuery.expr && jQuery.expr.filters ) {
9357 jQuery.expr.filters.animated = function( elem ) {
9358 return jQuery.grep(jQuery.timers, function( fn ) {
9359 return elem === fn.elem;
9360 }).length;
9361 };
9362 }
9363 jQuery.fn.offset = function( options ) {
9364 if ( arguments.length ) {
9365 return options === undefined ?
9366 this :
9367 this.each(function( i ) {
9368 jQuery.offset.setOffset( this, options, i );
9369 });
9370 }
9371
9372 var docElem, win,
9373 box = { top: 0, left: 0 },
9374 elem = this[ 0 ],
9375 doc = elem && elem.ownerDocument;
9376
9377 if ( !doc ) {
9378 return;
9379 }
9380
9381 docElem = doc.documentElement;
9382
9383 // Make sure it's not a disconnected DOM node
9384 if ( !jQuery.contains( docElem, elem ) ) {
9385 return box;
9386 }
9387
9388 // If we don't have gBCR, just use 0,0 rather than error
9389 // BlackBerry 5, iOS 3 (original iPhone)
9390 if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
9391 box = elem.getBoundingClientRect();
9392 }
9393 win = getWindow( doc );
9394 return {
9395 top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
9396 left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
9397 };
9398 };
9399
9400 jQuery.offset = {
9401
9402 setOffset: function( elem, options, i ) {
9403 var position = jQuery.css( elem, "position" );
9404
9405 // set position first, in-case top/left are set even on static elem
9406 if ( position === "static" ) {
9407 elem.style.position = "relative";
9408 }
9409
9410 var curElem = jQuery( elem ),
9411 curOffset = curElem.offset(),
9412 curCSSTop = jQuery.css( elem, "top" ),
9413 curCSSLeft = jQuery.css( elem, "left" ),
9414 calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9415 props = {}, curPosition = {}, curTop, curLeft;
9416
9417 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9418 if ( calculatePosition ) {
9419 curPosition = curElem.position();
9420 curTop = curPosition.top;
9421 curLeft = curPosition.left;
9422 } else {
9423 curTop = parseFloat( curCSSTop ) || 0;
9424 curLeft = parseFloat( curCSSLeft ) || 0;
9425 }
9426
9427 if ( jQuery.isFunction( options ) ) {
9428 options = options.call( elem, i, curOffset );
9429 }
9430
9431 if ( options.top != null ) {
9432 props.top = ( options.top - curOffset.top ) + curTop;
9433 }
9434 if ( options.left != null ) {
9435 props.left = ( options.left - curOffset.left ) + curLeft;
9436 }
9437
9438 if ( "using" in options ) {
9439 options.using.call( elem, props );
9440 } else {
9441 curElem.css( props );
9442 }
9443 }
9444 };
9445
9446
9447 jQuery.fn.extend({
9448
9449 position: function() {
9450 if ( !this[ 0 ] ) {
9451 return;
9452 }
9453
9454 var offsetParent, offset,
9455 parentOffset = { top: 0, left: 0 },
9456 elem = this[ 0 ];
9457
9458 // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
9459 if ( jQuery.css( elem, "position" ) === "fixed" ) {
9460 // we assume that getBoundingClientRect is available when computed position is fixed
9461 offset = elem.getBoundingClientRect();
9462 } else {
9463 // Get *real* offsetParent
9464 offsetParent = this.offsetParent();
9465
9466 // Get correct offsets
9467 offset = this.offset();
9468 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9469 parentOffset = offsetParent.offset();
9470 }
9471
9472 // Add offsetParent borders
9473 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9474 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9475 }
9476
9477 // Subtract parent offsets and element margins
9478 // note: when an element has margin: auto the offsetLeft and marginLeft
9479 // are the same in Safari causing offset.left to incorrectly be 0
9480 return {
9481 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9482 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
9483 };
9484 },
9485
9486 offsetParent: function() {
9487 return this.map(function() {
9488 var offsetParent = this.offsetParent || document.documentElement;
9489 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
9490 offsetParent = offsetParent.offsetParent;
9491 }
9492 return offsetParent || document.documentElement;
9493 });
9494 }
9495 });
9496
9497
9498 // Create scrollLeft and scrollTop methods
9499 jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
9500 var top = /Y/.test( prop );
9501
9502 jQuery.fn[ method ] = function( val ) {
9503 return jQuery.access( this, function( elem, method, val ) {
9504 var win = getWindow( elem );
9505
9506 if ( val === undefined ) {
9507 return win ? (prop in win) ? win[ prop ] :
9508 win.document.documentElement[ method ] :
9509 elem[ method ];
9510 }
9511
9512 if ( win ) {
9513 win.scrollTo(
9514 !top ? val : jQuery( win ).scrollLeft(),
9515 top ? val : jQuery( win ).scrollTop()
9516 );
9517
9518 } else {
9519 elem[ method ] = val;
9520 }
9521 }, method, val, arguments.length, null );
9522 };
9523 });
9524
9525 function getWindow( elem ) {
9526 return jQuery.isWindow( elem ) ?
9527 elem :
9528 elem.nodeType === 9 ?
9529 elem.defaultView || elem.parentWindow :
9530 false;
9531 }
9532 // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9533 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9534 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9535 // margin is only for outerHeight, outerWidth
9536 jQuery.fn[ funcName ] = function( margin, value ) {
9537 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9538 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9539
9540 return jQuery.access( this, function( elem, type, value ) {
9541 var doc;
9542
9543 if ( jQuery.isWindow( elem ) ) {
9544 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9545 // isn't a whole lot we can do. See pull request at this URL for discussion:
9546 // https://github.com/jquery/jquery/pull/764
9547 return elem.document.documentElement[ "client" + name ];
9548 }
9549
9550 // Get document width or height
9551 if ( elem.nodeType === 9 ) {
9552 doc = elem.documentElement;
9553
9554 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
9555 // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
9556 return Math.max(
9557 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9558 elem.body[ "offset" + name ], doc[ "offset" + name ],
9559 doc[ "client" + name ]
9560 );
9561 }
9562
9563 return value === undefined ?
9564 // Get width or height on the element, requesting but not forcing parseFloat
9565 jQuery.css( elem, type, extra ) :
9566
9567 // Set width or height on the element
9568 jQuery.style( elem, type, value, extra );
9569 }, type, chainable ? margin : undefined, chainable, null );
9570 };
9571 });
9572 });
9573 // Limit scope pollution from any deprecated API
9574 // (function() {
9575
9576 // })();
9577 // Expose jQuery to the global object
9578 window.jQuery = window.$ = jQuery;
9579
9580 // Expose jQuery as an AMD module, but only for AMD loaders that
9581 // understand the issues with loading multiple versions of jQuery
9582 // in a page that all might call define(). The loader will indicate
9583 // they have special allowances for multiple jQuery versions by
9584 // specifying define.amd.jQuery = true. Register as a named module,
9585 // since jQuery can be concatenated with other files that may use define,
9586 // but not use a proper concatenation script that understands anonymous
9587 // AMD modules. A named AMD is safest and most robust way to register.
9588 // Lowercase jquery is used because AMD module names are derived from
9589 // file names, and jQuery is normally delivered in a lowercase file name.
9590 // Do this after creating the global so that if an AMD module wants to call
9591 // noConflict to hide this version of jQuery, it will work.
9592 if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9593 define( "jquery", [], function () { return jQuery; } );
9594 }
9595
9596 })( window );
+0
-5
faraday/server/www/script/jquery-1.9.1.min.js less more
0 /*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
1 //@ sourceMappingURL=jquery.min.map
2 */(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
3 return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&&gt(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
4 }b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
+0
-9472
faraday/server/www/script/jquery.js less more
0 /*!
1 * jQuery JavaScript Library v1.8.3
2 * http://jquery.com/
3 *
4 * Includes Sizzle.js
5 * http://sizzlejs.com/
6 *
7 * Copyright 2012 jQuery Foundation and other contributors
8 * Released under the MIT license
9 * http://jquery.org/license
10 *
11 * Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time)
12 */
13 (function( window, undefined ) {
14 var
15 // A central reference to the root jQuery(document)
16 rootjQuery,
17
18 // The deferred used on DOM ready
19 readyList,
20
21 // Use the correct document accordingly with window argument (sandbox)
22 document = window.document,
23 location = window.location,
24 navigator = window.navigator,
25
26 // Map over jQuery in case of overwrite
27 _jQuery = window.jQuery,
28
29 // Map over the $ in case of overwrite
30 _$ = window.$,
31
32 // Save a reference to some core methods
33 core_push = Array.prototype.push,
34 core_slice = Array.prototype.slice,
35 core_indexOf = Array.prototype.indexOf,
36 core_toString = Object.prototype.toString,
37 core_hasOwn = Object.prototype.hasOwnProperty,
38 core_trim = String.prototype.trim,
39
40 // Define a local copy of jQuery
41 jQuery = function( selector, context ) {
42 // The jQuery object is actually just the init constructor 'enhanced'
43 return new jQuery.fn.init( selector, context, rootjQuery );
44 },
45
46 // Used for matching numbers
47 core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,
48
49 // Used for detecting and trimming whitespace
50 core_rnotwhite = /\S/,
51 core_rspace = /\s+/,
52
53 // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
54 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
55
56 // A simple way to check for HTML strings
57 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
58 rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
59
60 // Match a standalone tag
61 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
62
63 // JSON RegExp
64 rvalidchars = /^[\],:{}\s]*$/,
65 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
66 rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
67 rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,
68
69 // Matches dashed string for camelizing
70 rmsPrefix = /^-ms-/,
71 rdashAlpha = /-([\da-z])/gi,
72
73 // Used by jQuery.camelCase as callback to replace()
74 fcamelCase = function( all, letter ) {
75 return ( letter + "" ).toUpperCase();
76 },
77
78 // The ready event handler and self cleanup method
79 DOMContentLoaded = function() {
80 if ( document.addEventListener ) {
81 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
82 jQuery.ready();
83 } else if ( document.readyState === "complete" ) {
84 // we're here because readyState === "complete" in oldIE
85 // which is good enough for us to call the dom ready!
86 document.detachEvent( "onreadystatechange", DOMContentLoaded );
87 jQuery.ready();
88 }
89 },
90
91 // [[Class]] -> type pairs
92 class2type = {};
93
94 jQuery.fn = jQuery.prototype = {
95 constructor: jQuery,
96 init: function( selector, context, rootjQuery ) {
97 var match, elem, ret, doc;
98
99 // Handle $(""), $(null), $(undefined), $(false)
100 if ( !selector ) {
101 return this;
102 }
103
104 // Handle $(DOMElement)
105 if ( selector.nodeType ) {
106 this.context = this[0] = selector;
107 this.length = 1;
108 return this;
109 }
110
111 // Handle HTML strings
112 if ( typeof selector === "string" ) {
113 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
114 // Assume that strings that start and end with <> are HTML and skip the regex check
115 match = [ null, selector, null ];
116
117 } else {
118 match = rquickExpr.exec( selector );
119 }
120
121 // Match html or make sure no context is specified for #id
122 if ( match && (match[1] || !context) ) {
123
124 // HANDLE: $(html) -> $(array)
125 if ( match[1] ) {
126 context = context instanceof jQuery ? context[0] : context;
127 doc = ( context && context.nodeType ? context.ownerDocument || context : document );
128
129 // scripts is true for back-compat
130 selector = jQuery.parseHTML( match[1], doc, true );
131 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
132 this.attr.call( selector, context, true );
133 }
134
135 return jQuery.merge( this, selector );
136
137 // HANDLE: $(#id)
138 } else {
139 elem = document.getElementById( match[2] );
140
141 // Check parentNode to catch when Blackberry 4.6 returns
142 // nodes that are no longer in the document #6963
143 if ( elem && elem.parentNode ) {
144 // Handle the case where IE and Opera return items
145 // by name instead of ID
146 if ( elem.id !== match[2] ) {
147 return rootjQuery.find( selector );
148 }
149
150 // Otherwise, we inject the element directly into the jQuery object
151 this.length = 1;
152 this[0] = elem;
153 }
154
155 this.context = document;
156 this.selector = selector;
157 return this;
158 }
159
160 // HANDLE: $(expr, $(...))
161 } else if ( !context || context.jquery ) {
162 return ( context || rootjQuery ).find( selector );
163
164 // HANDLE: $(expr, context)
165 // (which is just equivalent to: $(context).find(expr)
166 } else {
167 return this.constructor( context ).find( selector );
168 }
169
170 // HANDLE: $(function)
171 // Shortcut for document ready
172 } else if ( jQuery.isFunction( selector ) ) {
173 return rootjQuery.ready( selector );
174 }
175
176 if ( selector.selector !== undefined ) {
177 this.selector = selector.selector;
178 this.context = selector.context;
179 }
180
181 return jQuery.makeArray( selector, this );
182 },
183
184 // Start with an empty selector
185 selector: "",
186
187 // The current version of jQuery being used
188 jquery: "1.8.3",
189
190 // The default length of a jQuery object is 0
191 length: 0,
192
193 // The number of elements contained in the matched element set
194 size: function() {
195 return this.length;
196 },
197
198 toArray: function() {
199 return core_slice.call( this );
200 },
201
202 // Get the Nth element in the matched element set OR
203 // Get the whole matched element set as a clean array
204 get: function( num ) {
205 return num == null ?
206
207 // Return a 'clean' array
208 this.toArray() :
209
210 // Return just the object
211 ( num < 0 ? this[ this.length + num ] : this[ num ] );
212 },
213
214 // Take an array of elements and push it onto the stack
215 // (returning the new matched element set)
216 pushStack: function( elems, name, selector ) {
217
218 // Build a new jQuery matched element set
219 var ret = jQuery.merge( this.constructor(), elems );
220
221 // Add the old object onto the stack (as a reference)
222 ret.prevObject = this;
223
224 ret.context = this.context;
225
226 if ( name === "find" ) {
227 ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
228 } else if ( name ) {
229 ret.selector = this.selector + "." + name + "(" + selector + ")";
230 }
231
232 // Return the newly-formed element set
233 return ret;
234 },
235
236 // Execute a callback for every element in the matched set.
237 // (You can seed the arguments with an array of args, but this is
238 // only used internally.)
239 each: function( callback, args ) {
240 return jQuery.each( this, callback, args );
241 },
242
243 ready: function( fn ) {
244 // Add the callback
245 jQuery.ready.promise().done( fn );
246
247 return this;
248 },
249
250 eq: function( i ) {
251 i = +i;
252 return i === -1 ?
253 this.slice( i ) :
254 this.slice( i, i + 1 );
255 },
256
257 first: function() {
258 return this.eq( 0 );
259 },
260
261 last: function() {
262 return this.eq( -1 );
263 },
264
265 slice: function() {
266 return this.pushStack( core_slice.apply( this, arguments ),
267 "slice", core_slice.call(arguments).join(",") );
268 },
269
270 map: function( callback ) {
271 return this.pushStack( jQuery.map(this, function( elem, i ) {
272 return callback.call( elem, i, elem );
273 }));
274 },
275
276 end: function() {
277 return this.prevObject || this.constructor(null);
278 },
279
280 // For internal use only.
281 // Behaves like an Array's method, not like a jQuery method.
282 push: core_push,
283 sort: [].sort,
284 splice: [].splice
285 };
286
287 // Give the init function the jQuery prototype for later instantiation
288 jQuery.fn.init.prototype = jQuery.fn;
289
290 jQuery.extend = jQuery.fn.extend = function() {
291 var options, name, src, copy, copyIsArray, clone,
292 target = arguments[0] || {},
293 i = 1,
294 length = arguments.length,
295 deep = false;
296
297 // Handle a deep copy situation
298 if ( typeof target === "boolean" ) {
299 deep = target;
300 target = arguments[1] || {};
301 // skip the boolean and the target
302 i = 2;
303 }
304
305 // Handle case when target is a string or something (possible in deep copy)
306 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
307 target = {};
308 }
309
310 // extend jQuery itself if only one argument is passed
311 if ( length === i ) {
312 target = this;
313 --i;
314 }
315
316 for ( ; i < length; i++ ) {
317 // Only deal with non-null/undefined values
318 if ( (options = arguments[ i ]) != null ) {
319 // Extend the base object
320 for ( name in options ) {
321 src = target[ name ];
322 copy = options[ name ];
323
324 // Prevent never-ending loop
325 if ( target === copy ) {
326 continue;
327 }
328
329 // Recurse if we're merging plain objects or arrays
330 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
331 if ( copyIsArray ) {
332 copyIsArray = false;
333 clone = src && jQuery.isArray(src) ? src : [];
334
335 } else {
336 clone = src && jQuery.isPlainObject(src) ? src : {};
337 }
338
339 // Never move original objects, clone them
340 target[ name ] = jQuery.extend( deep, clone, copy );
341
342 // Don't bring in undefined values
343 } else if ( copy !== undefined ) {
344 target[ name ] = copy;
345 }
346 }
347 }
348 }
349
350 // Return the modified object
351 return target;
352 };
353
354 jQuery.extend({
355 noConflict: function( deep ) {
356 if ( window.$ === jQuery ) {
357 window.$ = _$;
358 }
359
360 if ( deep && window.jQuery === jQuery ) {
361 window.jQuery = _jQuery;
362 }
363
364 return jQuery;
365 },
366
367 // Is the DOM ready to be used? Set to true once it occurs.
368 isReady: false,
369
370 // A counter to track how many items to wait for before
371 // the ready event fires. See #6781
372 readyWait: 1,
373
374 // Hold (or release) the ready event
375 holdReady: function( hold ) {
376 if ( hold ) {
377 jQuery.readyWait++;
378 } else {
379 jQuery.ready( true );
380 }
381 },
382
383 // Handle when the DOM is ready
384 ready: function( wait ) {
385
386 // Abort if there are pending holds or we're already ready
387 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
388 return;
389 }
390
391 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
392 if ( !document.body ) {
393 return setTimeout( jQuery.ready, 1 );
394 }
395
396 // Remember that the DOM is ready
397 jQuery.isReady = true;
398
399 // If a normal DOM Ready event fired, decrement, and wait if need be
400 if ( wait !== true && --jQuery.readyWait > 0 ) {
401 return;
402 }
403
404 // If there are functions bound, to execute
405 readyList.resolveWith( document, [ jQuery ] );
406
407 // Trigger any bound ready events
408 if ( jQuery.fn.trigger ) {
409 jQuery( document ).trigger("ready").off("ready");
410 }
411 },
412
413 // See test/unit/core.js for details concerning isFunction.
414 // Since version 1.3, DOM methods and functions like alert
415 // aren't supported. They return false on IE (#2968).
416 isFunction: function( obj ) {
417 return jQuery.type(obj) === "function";
418 },
419
420 isArray: Array.isArray || function( obj ) {
421 return jQuery.type(obj) === "array";
422 },
423
424 isWindow: function( obj ) {
425 return obj != null && obj == obj.window;
426 },
427
428 isNumeric: function( obj ) {
429 return !isNaN( parseFloat(obj) ) && isFinite( obj );
430 },
431
432 type: function( obj ) {
433 return obj == null ?
434 String( obj ) :
435 class2type[ core_toString.call(obj) ] || "object";
436 },
437
438 isPlainObject: function( obj ) {
439 // Must be an Object.
440 // Because of IE, we also have to check the presence of the constructor property.
441 // Make sure that DOM nodes and window objects don't pass through, as well
442 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
443 return false;
444 }
445
446 try {
447 // Not own constructor property must be Object
448 if ( obj.constructor &&
449 !core_hasOwn.call(obj, "constructor") &&
450 !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
451 return false;
452 }
453 } catch ( e ) {
454 // IE8,9 Will throw exceptions on certain host objects #9897
455 return false;
456 }
457
458 // Own properties are enumerated firstly, so to speed up,
459 // if last one is own, then all properties are own.
460
461 var key;
462 for ( key in obj ) {}
463
464 return key === undefined || core_hasOwn.call( obj, key );
465 },
466
467 isEmptyObject: function( obj ) {
468 var name;
469 for ( name in obj ) {
470 return false;
471 }
472 return true;
473 },
474
475 error: function( msg ) {
476 throw new Error( msg );
477 },
478
479 // data: string of html
480 // context (optional): If specified, the fragment will be created in this context, defaults to document
481 // scripts (optional): If true, will include scripts passed in the html string
482 parseHTML: function( data, context, scripts ) {
483 var parsed;
484 if ( !data || typeof data !== "string" ) {
485 return null;
486 }
487 if ( typeof context === "boolean" ) {
488 scripts = context;
489 context = 0;
490 }
491 context = context || document;
492
493 // Single tag
494 if ( (parsed = rsingleTag.exec( data )) ) {
495 return [ context.createElement( parsed[1] ) ];
496 }
497
498 parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
499 return jQuery.merge( [],
500 (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
501 },
502
503 parseJSON: function( data ) {
504 if ( !data || typeof data !== "string") {
505 return null;
506 }
507
508 // Make sure leading/trailing whitespace is removed (IE can't handle it)
509 data = jQuery.trim( data );
510
511 // Attempt to parse using the native JSON parser first
512 if ( window.JSON && window.JSON.parse ) {
513 return window.JSON.parse( data );
514 }
515
516 // Make sure the incoming data is actual JSON
517 // Logic borrowed from http://json.org/json2.js
518 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
519 .replace( rvalidtokens, "]" )
520 .replace( rvalidbraces, "")) ) {
521
522 return ( new Function( "return " + data ) )();
523
524 }
525 jQuery.error( "Invalid JSON: " + data );
526 },
527
528 // Cross-browser xml parsing
529 parseXML: function( data ) {
530 var xml, tmp;
531 if ( !data || typeof data !== "string" ) {
532 return null;
533 }
534 try {
535 if ( window.DOMParser ) { // Standard
536 tmp = new DOMParser();
537 xml = tmp.parseFromString( data , "text/xml" );
538 } else { // IE
539 xml = new ActiveXObject( "Microsoft.XMLDOM" );
540 xml.async = "false";
541 xml.loadXML( data );
542 }
543 } catch( e ) {
544 xml = undefined;
545 }
546 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
547 jQuery.error( "Invalid XML: " + data );
548 }
549 return xml;
550 },
551
552 noop: function() {},
553
554 // Evaluates a script in a global context
555 // Workarounds based on findings by Jim Driscoll
556 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
557 globalEval: function( data ) {
558 if ( data && core_rnotwhite.test( data ) ) {
559 // We use execScript on Internet Explorer
560 // We use an anonymous function so that context is window
561 // rather than jQuery in Firefox
562 ( window.execScript || function( data ) {
563 window[ "eval" ].call( window, data );
564 } )( data );
565 }
566 },
567
568 // Convert dashed to camelCase; used by the css and data modules
569 // Microsoft forgot to hump their vendor prefix (#9572)
570 camelCase: function( string ) {
571 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
572 },
573
574 nodeName: function( elem, name ) {
575 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
576 },
577
578 // args is for internal usage only
579 each: function( obj, callback, args ) {
580 var name,
581 i = 0,
582 length = obj.length,
583 isObj = length === undefined || jQuery.isFunction( obj );
584
585 if ( args ) {
586 if ( isObj ) {
587 for ( name in obj ) {
588 if ( callback.apply( obj[ name ], args ) === false ) {
589 break;
590 }
591 }
592 } else {
593 for ( ; i < length; ) {
594 if ( callback.apply( obj[ i++ ], args ) === false ) {
595 break;
596 }
597 }
598 }
599
600 // A special, fast, case for the most common use of each
601 } else {
602 if ( isObj ) {
603 for ( name in obj ) {
604 if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) {
605 break;
606 }
607 }
608 } else {
609 for ( ; i < length; ) {
610 if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) {
611 break;
612 }
613 }
614 }
615 }
616
617 return obj;
618 },
619
620 // Use native String.trim function wherever possible
621 trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
622 function( text ) {
623 return text == null ?
624 "" :
625 core_trim.call( text );
626 } :
627
628 // Otherwise use our own trimming functionality
629 function( text ) {
630 return text == null ?
631 "" :
632 ( text + "" ).replace( rtrim, "" );
633 },
634
635 // results is for internal usage only
636 makeArray: function( arr, results ) {
637 var type,
638 ret = results || [];
639
640 if ( arr != null ) {
641 // The window, strings (and functions) also have 'length'
642 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
643 type = jQuery.type( arr );
644
645 if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) {
646 core_push.call( ret, arr );
647 } else {
648 jQuery.merge( ret, arr );
649 }
650 }
651
652 return ret;
653 },
654
655 inArray: function( elem, arr, i ) {
656 var len;
657
658 if ( arr ) {
659 if ( core_indexOf ) {
660 return core_indexOf.call( arr, elem, i );
661 }
662
663 len = arr.length;
664 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
665
666 for ( ; i < len; i++ ) {
667 // Skip accessing in sparse arrays
668 if ( i in arr && arr[ i ] === elem ) {
669 return i;
670 }
671 }
672 }
673
674 return -1;
675 },
676
677 merge: function( first, second ) {
678 var l = second.length,
679 i = first.length,
680 j = 0;
681
682 if ( typeof l === "number" ) {
683 for ( ; j < l; j++ ) {
684 first[ i++ ] = second[ j ];
685 }
686
687 } else {
688 while ( second[j] !== undefined ) {
689 first[ i++ ] = second[ j++ ];
690 }
691 }
692
693 first.length = i;
694
695 return first;
696 },
697
698 grep: function( elems, callback, inv ) {
699 var retVal,
700 ret = [],
701 i = 0,
702 length = elems.length;
703 inv = !!inv;
704
705 // Go through the array, only saving the items
706 // that pass the validator function
707 for ( ; i < length; i++ ) {
708 retVal = !!callback( elems[ i ], i );
709 if ( inv !== retVal ) {
710 ret.push( elems[ i ] );
711 }
712 }
713
714 return ret;
715 },
716
717 // arg is for internal usage only
718 map: function( elems, callback, arg ) {
719 var value, key,
720 ret = [],
721 i = 0,
722 length = elems.length,
723 // jquery objects are treated as arrays
724 isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
725
726 // Go through the array, translating each of the items to their
727 if ( isArray ) {
728 for ( ; i < length; i++ ) {
729 value = callback( elems[ i ], i, arg );
730
731 if ( value != null ) {
732 ret[ ret.length ] = value;
733 }
734 }
735
736 // Go through every key on the object,
737 } else {
738 for ( key in elems ) {
739 value = callback( elems[ key ], key, arg );
740
741 if ( value != null ) {
742 ret[ ret.length ] = value;
743 }
744 }
745 }
746
747 // Flatten any nested arrays
748 return ret.concat.apply( [], ret );
749 },
750
751 // A global GUID counter for objects
752 guid: 1,
753
754 // Bind a function to a context, optionally partially applying any
755 // arguments.
756 proxy: function( fn, context ) {
757 var tmp, args, proxy;
758
759 if ( typeof context === "string" ) {
760 tmp = fn[ context ];
761 context = fn;
762 fn = tmp;
763 }
764
765 // Quick check to determine if target is callable, in the spec
766 // this throws a TypeError, but we will just return undefined.
767 if ( !jQuery.isFunction( fn ) ) {
768 return undefined;
769 }
770
771 // Simulated bind
772 args = core_slice.call( arguments, 2 );
773 proxy = function() {
774 return fn.apply( context, args.concat( core_slice.call( arguments ) ) );
775 };
776
777 // Set the guid of unique handler to the same of original handler, so it can be removed
778 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
779
780 return proxy;
781 },
782
783 // Multifunctional method to get and set values of a collection
784 // The value/s can optionally be executed if it's a function
785 access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
786 var exec,
787 bulk = key == null,
788 i = 0,
789 length = elems.length;
790
791 // Sets many values
792 if ( key && typeof key === "object" ) {
793 for ( i in key ) {
794 jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
795 }
796 chainable = 1;
797
798 // Sets one value
799 } else if ( value !== undefined ) {
800 // Optionally, function values get executed if exec is true
801 exec = pass === undefined && jQuery.isFunction( value );
802
803 if ( bulk ) {
804 // Bulk operations only iterate when executing function values
805 if ( exec ) {
806 exec = fn;
807 fn = function( elem, key, value ) {
808 return exec.call( jQuery( elem ), value );
809 };
810
811 // Otherwise they run against the entire set
812 } else {
813 fn.call( elems, value );
814 fn = null;
815 }
816 }
817
818 if ( fn ) {
819 for (; i < length; i++ ) {
820 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
821 }
822 }
823
824 chainable = 1;
825 }
826
827 return chainable ?
828 elems :
829
830 // Gets
831 bulk ?
832 fn.call( elems ) :
833 length ? fn( elems[0], key ) : emptyGet;
834 },
835
836 now: function() {
837 return ( new Date() ).getTime();
838 }
839 });
840
841 jQuery.ready.promise = function( obj ) {
842 if ( !readyList ) {
843
844 readyList = jQuery.Deferred();
845
846 // Catch cases where $(document).ready() is called after the browser event has already occurred.
847 // we once tried to use readyState "interactive" here, but it caused issues like the one
848 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
849 if ( document.readyState === "complete" ) {
850 // Handle it asynchronously to allow scripts the opportunity to delay ready
851 setTimeout( jQuery.ready, 1 );
852
853 // Standards-based browsers support DOMContentLoaded
854 } else if ( document.addEventListener ) {
855 // Use the handy event callback
856 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
857
858 // A fallback to window.onload, that will always work
859 window.addEventListener( "load", jQuery.ready, false );
860
861 // If IE event model is used
862 } else {
863 // Ensure firing before onload, maybe late but safe also for iframes
864 document.attachEvent( "onreadystatechange", DOMContentLoaded );
865
866 // A fallback to window.onload, that will always work
867 window.attachEvent( "onload", jQuery.ready );
868
869 // If IE and not a frame
870 // continually check to see if the document is ready
871 var top = false;
872
873 try {
874 top = window.frameElement == null && document.documentElement;
875 } catch(e) {}
876
877 if ( top && top.doScroll ) {
878 (function doScrollCheck() {
879 if ( !jQuery.isReady ) {
880
881 try {
882 // Use the trick by Diego Perini
883 // http://javascript.nwbox.com/IEContentLoaded/
884 top.doScroll("left");
885 } catch(e) {
886 return setTimeout( doScrollCheck, 50 );
887 }
888
889 // and execute any waiting functions
890 jQuery.ready();
891 }
892 })();
893 }
894 }
895 }
896 return readyList.promise( obj );
897 };
898
899 // Populate the class2type map
900 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
901 class2type[ "[object " + name + "]" ] = name.toLowerCase();
902 });
903
904 // All jQuery objects should point back to these
905 rootjQuery = jQuery(document);
906 // String to Object options format cache
907 var optionsCache = {};
908
909 // Convert String-formatted options into Object-formatted ones and store in cache
910 function createOptions( options ) {
911 var object = optionsCache[ options ] = {};
912 jQuery.each( options.split( core_rspace ), function( _, flag ) {
913 object[ flag ] = true;
914 });
915 return object;
916 }
917
918 /*
919 * Create a callback list using the following parameters:
920 *
921 * options: an optional list of space-separated options that will change how
922 * the callback list behaves or a more traditional option object
923 *
924 * By default a callback list will act like an event callback list and can be
925 * "fired" multiple times.
926 *
927 * Possible options:
928 *
929 * once: will ensure the callback list can only be fired once (like a Deferred)
930 *
931 * memory: will keep track of previous values and will call any callback added
932 * after the list has been fired right away with the latest "memorized"
933 * values (like a Deferred)
934 *
935 * unique: will ensure a callback can only be added once (no duplicate in the list)
936 *
937 * stopOnFalse: interrupt callings when a callback returns false
938 *
939 */
940 jQuery.Callbacks = function( options ) {
941
942 // Convert options from String-formatted to Object-formatted if needed
943 // (we check in cache first)
944 options = typeof options === "string" ?
945 ( optionsCache[ options ] || createOptions( options ) ) :
946 jQuery.extend( {}, options );
947
948 var // Last fire value (for non-forgettable lists)
949 memory,
950 // Flag to know if list was already fired
951 fired,
952 // Flag to know if list is currently firing
953 firing,
954 // First callback to fire (used internally by add and fireWith)
955 firingStart,
956 // End of the loop when firing
957 firingLength,
958 // Index of currently firing callback (modified by remove if needed)
959 firingIndex,
960 // Actual callback list
961 list = [],
962 // Stack of fire calls for repeatable lists
963 stack = !options.once && [],
964 // Fire callbacks
965 fire = function( data ) {
966 memory = options.memory && data;
967 fired = true;
968 firingIndex = firingStart || 0;
969 firingStart = 0;
970 firingLength = list.length;
971 firing = true;
972 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
973 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
974 memory = false; // To prevent further calls using add
975 break;
976 }
977 }
978 firing = false;
979 if ( list ) {
980 if ( stack ) {
981 if ( stack.length ) {
982 fire( stack.shift() );
983 }
984 } else if ( memory ) {
985 list = [];
986 } else {
987 self.disable();
988 }
989 }
990 },
991 // Actual Callbacks object
992 self = {
993 // Add a callback or a collection of callbacks to the list
994 add: function() {
995 if ( list ) {
996 // First, we save the current length
997 var start = list.length;
998 (function add( args ) {
999 jQuery.each( args, function( _, arg ) {
1000 var type = jQuery.type( arg );
1001 if ( type === "function" ) {
1002 if ( !options.unique || !self.has( arg ) ) {
1003 list.push( arg );
1004 }
1005 } else if ( arg && arg.length && type !== "string" ) {
1006 // Inspect recursively
1007 add( arg );
1008 }
1009 });
1010 })( arguments );
1011 // Do we need to add the callbacks to the
1012 // current firing batch?
1013 if ( firing ) {
1014 firingLength = list.length;
1015 // With memory, if we're not firing then
1016 // we should call right away
1017 } else if ( memory ) {
1018 firingStart = start;
1019 fire( memory );
1020 }
1021 }
1022 return this;
1023 },
1024 // Remove a callback from the list
1025 remove: function() {
1026 if ( list ) {
1027 jQuery.each( arguments, function( _, arg ) {
1028 var index;
1029 while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1030 list.splice( index, 1 );
1031 // Handle firing indexes
1032 if ( firing ) {
1033 if ( index <= firingLength ) {
1034 firingLength--;
1035 }
1036 if ( index <= firingIndex ) {
1037 firingIndex--;
1038 }
1039 }
1040 }
1041 });
1042 }
1043 return this;
1044 },
1045 // Control if a given callback is in the list
1046 has: function( fn ) {
1047 return jQuery.inArray( fn, list ) > -1;
1048 },
1049 // Remove all callbacks from the list
1050 empty: function() {
1051 list = [];
1052 return this;
1053 },
1054 // Have the list do nothing anymore
1055 disable: function() {
1056 list = stack = memory = undefined;
1057 return this;
1058 },
1059 // Is it disabled?
1060 disabled: function() {
1061 return !list;
1062 },
1063 // Lock the list in its current state
1064 lock: function() {
1065 stack = undefined;
1066 if ( !memory ) {
1067 self.disable();
1068 }
1069 return this;
1070 },
1071 // Is it locked?
1072 locked: function() {
1073 return !stack;
1074 },
1075 // Call all callbacks with the given context and arguments
1076 fireWith: function( context, args ) {
1077 args = args || [];
1078 args = [ context, args.slice ? args.slice() : args ];
1079 if ( list && ( !fired || stack ) ) {
1080 if ( firing ) {
1081 stack.push( args );
1082 } else {
1083 fire( args );
1084 }
1085 }
1086 return this;
1087 },
1088 // Call all the callbacks with the given arguments
1089 fire: function() {
1090 self.fireWith( this, arguments );
1091 return this;
1092 },
1093 // To know if the callbacks have already been called at least once
1094 fired: function() {
1095 return !!fired;
1096 }
1097 };
1098
1099 return self;
1100 };
1101 jQuery.extend({
1102
1103 Deferred: function( func ) {
1104 var tuples = [
1105 // action, add listener, listener list, final state
1106 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1107 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1108 [ "notify", "progress", jQuery.Callbacks("memory") ]
1109 ],
1110 state = "pending",
1111 promise = {
1112 state: function() {
1113 return state;
1114 },
1115 always: function() {
1116 deferred.done( arguments ).fail( arguments );
1117 return this;
1118 },
1119 then: function( /* fnDone, fnFail, fnProgress */ ) {
1120 var fns = arguments;
1121 return jQuery.Deferred(function( newDefer ) {
1122 jQuery.each( tuples, function( i, tuple ) {
1123 var action = tuple[ 0 ],
1124 fn = fns[ i ];
1125 // deferred[ done | fail | progress ] for forwarding actions to newDefer
1126 deferred[ tuple[1] ]( jQuery.isFunction( fn ) ?
1127 function() {
1128 var returned = fn.apply( this, arguments );
1129 if ( returned && jQuery.isFunction( returned.promise ) ) {
1130 returned.promise()
1131 .done( newDefer.resolve )
1132 .fail( newDefer.reject )
1133 .progress( newDefer.notify );
1134 } else {
1135 newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
1136 }
1137 } :
1138 newDefer[ action ]
1139 );
1140 });
1141 fns = null;
1142 }).promise();
1143 },
1144 // Get a promise for this deferred
1145 // If obj is provided, the promise aspect is added to the object
1146 promise: function( obj ) {
1147 return obj != null ? jQuery.extend( obj, promise ) : promise;
1148 }
1149 },
1150 deferred = {};
1151
1152 // Keep pipe for back-compat
1153 promise.pipe = promise.then;
1154
1155 // Add list-specific methods
1156 jQuery.each( tuples, function( i, tuple ) {
1157 var list = tuple[ 2 ],
1158 stateString = tuple[ 3 ];
1159
1160 // promise[ done | fail | progress ] = list.add
1161 promise[ tuple[1] ] = list.add;
1162
1163 // Handle state
1164 if ( stateString ) {
1165 list.add(function() {
1166 // state = [ resolved | rejected ]
1167 state = stateString;
1168
1169 // [ reject_list | resolve_list ].disable; progress_list.lock
1170 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1171 }
1172
1173 // deferred[ resolve | reject | notify ] = list.fire
1174 deferred[ tuple[0] ] = list.fire;
1175 deferred[ tuple[0] + "With" ] = list.fireWith;
1176 });
1177
1178 // Make the deferred a promise
1179 promise.promise( deferred );
1180
1181 // Call given func if any
1182 if ( func ) {
1183 func.call( deferred, deferred );
1184 }
1185
1186 // All done!
1187 return deferred;
1188 },
1189
1190 // Deferred helper
1191 when: function( subordinate /* , ..., subordinateN */ ) {
1192 var i = 0,
1193 resolveValues = core_slice.call( arguments ),
1194 length = resolveValues.length,
1195
1196 // the count of uncompleted subordinates
1197 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1198
1199 // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1200 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1201
1202 // Update function for both resolve and progress values
1203 updateFunc = function( i, contexts, values ) {
1204 return function( value ) {
1205 contexts[ i ] = this;
1206 values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1207 if( values === progressValues ) {
1208 deferred.notifyWith( contexts, values );
1209 } else if ( !( --remaining ) ) {
1210 deferred.resolveWith( contexts, values );
1211 }
1212 };
1213 },
1214
1215 progressValues, progressContexts, resolveContexts;
1216
1217 // add listeners to Deferred subordinates; treat others as resolved
1218 if ( length > 1 ) {
1219 progressValues = new Array( length );
1220 progressContexts = new Array( length );
1221 resolveContexts = new Array( length );
1222 for ( ; i < length; i++ ) {
1223 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1224 resolveValues[ i ].promise()
1225 .done( updateFunc( i, resolveContexts, resolveValues ) )
1226 .fail( deferred.reject )
1227 .progress( updateFunc( i, progressContexts, progressValues ) );
1228 } else {
1229 --remaining;
1230 }
1231 }
1232 }
1233
1234 // if we're not waiting on anything, resolve the master
1235 if ( !remaining ) {
1236 deferred.resolveWith( resolveContexts, resolveValues );
1237 }
1238
1239 return deferred.promise();
1240 }
1241 });
1242 jQuery.support = (function() {
1243
1244 var support,
1245 all,
1246 a,
1247 select,
1248 opt,
1249 input,
1250 fragment,
1251 eventName,
1252 i,
1253 isSupported,
1254 clickFn,
1255 div = document.createElement("div");
1256
1257 // Setup
1258 div.setAttribute( "className", "t" );
1259 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1260
1261 // Support tests won't run in some limited or non-browser environments
1262 all = div.getElementsByTagName("*");
1263 a = div.getElementsByTagName("a")[ 0 ];
1264 if ( !all || !a || !all.length ) {
1265 return {};
1266 }
1267
1268 // First batch of tests
1269 select = document.createElement("select");
1270 opt = select.appendChild( document.createElement("option") );
1271 input = div.getElementsByTagName("input")[ 0 ];
1272
1273 a.style.cssText = "top:1px;float:left;opacity:.5";
1274 support = {
1275 // IE strips leading whitespace when .innerHTML is used
1276 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1277
1278 // Make sure that tbody elements aren't automatically inserted
1279 // IE will insert them into empty tables
1280 tbody: !div.getElementsByTagName("tbody").length,
1281
1282 // Make sure that link elements get serialized correctly by innerHTML
1283 // This requires a wrapper element in IE
1284 htmlSerialize: !!div.getElementsByTagName("link").length,
1285
1286 // Get the style information from getAttribute
1287 // (IE uses .cssText instead)
1288 style: /top/.test( a.getAttribute("style") ),
1289
1290 // Make sure that URLs aren't manipulated
1291 // (IE normalizes it by default)
1292 hrefNormalized: ( a.getAttribute("href") === "/a" ),
1293
1294 // Make sure that element opacity exists
1295 // (IE uses filter instead)
1296 // Use a regex to work around a WebKit issue. See #5145
1297 opacity: /^0.5/.test( a.style.opacity ),
1298
1299 // Verify style float existence
1300 // (IE uses styleFloat instead of cssFloat)
1301 cssFloat: !!a.style.cssFloat,
1302
1303 // Make sure that if no value is specified for a checkbox
1304 // that it defaults to "on".
1305 // (WebKit defaults to "" instead)
1306 checkOn: ( input.value === "on" ),
1307
1308 // Make sure that a selected-by-default option has a working selected property.
1309 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1310 optSelected: opt.selected,
1311
1312 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1313 getSetAttribute: div.className !== "t",
1314
1315 // Tests for enctype support on a form (#6743)
1316 enctype: !!document.createElement("form").enctype,
1317
1318 // Makes sure cloning an html5 element does not cause problems
1319 // Where outerHTML is undefined, this still works
1320 html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1321
1322 // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1323 boxModel: ( document.compatMode === "CSS1Compat" ),
1324
1325 // Will be defined later
1326 submitBubbles: true,
1327 changeBubbles: true,
1328 focusinBubbles: false,
1329 deleteExpando: true,
1330 noCloneEvent: true,
1331 inlineBlockNeedsLayout: false,
1332 shrinkWrapBlocks: false,
1333 reliableMarginRight: true,
1334 boxSizingReliable: true,
1335 pixelPosition: false
1336 };
1337
1338 // Make sure checked status is properly cloned
1339 input.checked = true;
1340 support.noCloneChecked = input.cloneNode( true ).checked;
1341
1342 // Make sure that the options inside disabled selects aren't marked as disabled
1343 // (WebKit marks them as disabled)
1344 select.disabled = true;
1345 support.optDisabled = !opt.disabled;
1346
1347 // Test to see if it's possible to delete an expando from an element
1348 // Fails in Internet Explorer
1349 try {
1350 delete div.test;
1351 } catch( e ) {
1352 support.deleteExpando = false;
1353 }
1354
1355 if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
1356 div.attachEvent( "onclick", clickFn = function() {
1357 // Cloning a node shouldn't copy over any
1358 // bound event handlers (IE does this)
1359 support.noCloneEvent = false;
1360 });
1361 div.cloneNode( true ).fireEvent("onclick");
1362 div.detachEvent( "onclick", clickFn );
1363 }
1364
1365 // Check if a radio maintains its value
1366 // after being appended to the DOM
1367 input = document.createElement("input");
1368 input.value = "t";
1369 input.setAttribute( "type", "radio" );
1370 support.radioValue = input.value === "t";
1371
1372 input.setAttribute( "checked", "checked" );
1373
1374 // #11217 - WebKit loses check when the name is after the checked attribute
1375 input.setAttribute( "name", "t" );
1376
1377 div.appendChild( input );
1378 fragment = document.createDocumentFragment();
1379 fragment.appendChild( div.lastChild );
1380
1381 // WebKit doesn't clone checked state correctly in fragments
1382 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1383
1384 // Check if a disconnected checkbox will retain its checked
1385 // value of true after appended to the DOM (IE6/7)
1386 support.appendChecked = input.checked;
1387
1388 fragment.removeChild( input );
1389 fragment.appendChild( div );
1390
1391 // Technique from Juriy Zaytsev
1392 // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
1393 // We only care about the case where non-standard event systems
1394 // are used, namely in IE. Short-circuiting here helps us to
1395 // avoid an eval call (in setAttribute) which can cause CSP
1396 // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
1397 if ( div.attachEvent ) {
1398 for ( i in {
1399 submit: true,
1400 change: true,
1401 focusin: true
1402 }) {
1403 eventName = "on" + i;
1404 isSupported = ( eventName in div );
1405 if ( !isSupported ) {
1406 div.setAttribute( eventName, "return;" );
1407 isSupported = ( typeof div[ eventName ] === "function" );
1408 }
1409 support[ i + "Bubbles" ] = isSupported;
1410 }
1411 }
1412
1413 // Run tests that need a body at doc ready
1414 jQuery(function() {
1415 var container, div, tds, marginDiv,
1416 divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;",
1417 body = document.getElementsByTagName("body")[0];
1418
1419 if ( !body ) {
1420 // Return for frameset docs that don't have a body
1421 return;
1422 }
1423
1424 container = document.createElement("div");
1425 container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px";
1426 body.insertBefore( container, body.firstChild );
1427
1428 // Construct the test element
1429 div = document.createElement("div");
1430 container.appendChild( div );
1431
1432 // Check if table cells still have offsetWidth/Height when they are set
1433 // to display:none and there are still other visible table cells in a
1434 // table row; if so, offsetWidth/Height are not reliable for use when
1435 // determining if an element has been hidden directly using
1436 // display:none (it is still safe to use offsets if a parent element is
1437 // hidden; don safety goggles and see bug #4512 for more information).
1438 // (only IE 8 fails this test)
1439 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1440 tds = div.getElementsByTagName("td");
1441 tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1442 isSupported = ( tds[ 0 ].offsetHeight === 0 );
1443
1444 tds[ 0 ].style.display = "";
1445 tds[ 1 ].style.display = "none";
1446
1447 // Check if empty table cells still have offsetWidth/Height
1448 // (IE <= 8 fail this test)
1449 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1450
1451 // Check box-sizing and margin behavior
1452 div.innerHTML = "";
1453 div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
1454 support.boxSizing = ( div.offsetWidth === 4 );
1455 support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1456
1457 // NOTE: To any future maintainer, we've window.getComputedStyle
1458 // because jsdom on node.js will break without it.
1459 if ( window.getComputedStyle ) {
1460 support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1461 support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
1462
1463 // Check if div with explicit width and no margin-right incorrectly
1464 // gets computed margin-right based on width of container. For more
1465 // info see bug #3333
1466 // Fails in WebKit before Feb 2011 nightlies
1467 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1468 marginDiv = document.createElement("div");
1469 marginDiv.style.cssText = div.style.cssText = divReset;
1470 marginDiv.style.marginRight = marginDiv.style.width = "0";
1471 div.style.width = "1px";
1472 div.appendChild( marginDiv );
1473 support.reliableMarginRight =
1474 !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
1475 }
1476
1477 if ( typeof div.style.zoom !== "undefined" ) {
1478 // Check if natively block-level elements act like inline-block
1479 // elements when setting their display to 'inline' and giving
1480 // them layout
1481 // (IE < 8 does this)
1482 div.innerHTML = "";
1483 div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
1484 support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
1485
1486 // Check if elements with layout shrink-wrap their children
1487 // (IE 6 does this)
1488 div.style.display = "block";
1489 div.style.overflow = "visible";
1490 div.innerHTML = "<div></div>";
1491 div.firstChild.style.width = "5px";
1492 support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
1493
1494 container.style.zoom = 1;
1495 }
1496
1497 // Null elements to avoid leaks in IE
1498 body.removeChild( container );
1499 container = div = tds = marginDiv = null;
1500 });
1501
1502 // Null elements to avoid leaks in IE
1503 fragment.removeChild( div );
1504 all = a = select = opt = input = fragment = div = null;
1505
1506 return support;
1507 })();
1508 var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
1509 rmultiDash = /([A-Z])/g;
1510
1511 jQuery.extend({
1512 cache: {},
1513
1514 deletedIds: [],
1515
1516 // Remove at next major release (1.9/2.0)
1517 uuid: 0,
1518
1519 // Unique for each copy of jQuery on the page
1520 // Non-digits removed to match rinlinejQuery
1521 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
1522
1523 // The following elements throw uncatchable exceptions if you
1524 // attempt to add expando properties to them.
1525 noData: {
1526 "embed": true,
1527 // Ban all objects except for Flash (which handle expandos)
1528 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1529 "applet": true
1530 },
1531
1532 hasData: function( elem ) {
1533 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1534 return !!elem && !isEmptyDataObject( elem );
1535 },
1536
1537 data: function( elem, name, data, pvt /* Internal Use Only */ ) {
1538 if ( !jQuery.acceptData( elem ) ) {
1539 return;
1540 }
1541
1542 var thisCache, ret,
1543 internalKey = jQuery.expando,
1544 getByName = typeof name === "string",
1545
1546 // We have to handle DOM nodes and JS objects differently because IE6-7
1547 // can't GC object references properly across the DOM-JS boundary
1548 isNode = elem.nodeType,
1549
1550 // Only DOM nodes need the global jQuery cache; JS object data is
1551 // attached directly to the object so GC can occur automatically
1552 cache = isNode ? jQuery.cache : elem,
1553
1554 // Only defining an ID for JS objects if its cache already exists allows
1555 // the code to shortcut on the same path as a DOM node with no cache
1556 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
1557
1558 // Avoid doing any more work than we need to when trying to get data on an
1559 // object that has no data at all
1560 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
1561 return;
1562 }
1563
1564 if ( !id ) {
1565 // Only DOM nodes need a new unique ID for each element since their data
1566 // ends up in the global cache
1567 if ( isNode ) {
1568 elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++;
1569 } else {
1570 id = internalKey;
1571 }
1572 }
1573
1574 if ( !cache[ id ] ) {
1575 cache[ id ] = {};
1576
1577 // Avoids exposing jQuery metadata on plain JS objects when the object
1578 // is serialized using JSON.stringify
1579 if ( !isNode ) {
1580 cache[ id ].toJSON = jQuery.noop;
1581 }
1582 }
1583
1584 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1585 // shallow copied over onto the existing cache
1586 if ( typeof name === "object" || typeof name === "function" ) {
1587 if ( pvt ) {
1588 cache[ id ] = jQuery.extend( cache[ id ], name );
1589 } else {
1590 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1591 }
1592 }
1593
1594 thisCache = cache[ id ];
1595
1596 // jQuery data() is stored in a separate object inside the object's internal data
1597 // cache in order to avoid key collisions between internal data and user-defined
1598 // data.
1599 if ( !pvt ) {
1600 if ( !thisCache.data ) {
1601 thisCache.data = {};
1602 }
1603
1604 thisCache = thisCache.data;
1605 }
1606
1607 if ( data !== undefined ) {
1608 thisCache[ jQuery.camelCase( name ) ] = data;
1609 }
1610
1611 // Check for both converted-to-camel and non-converted data property names
1612 // If a data property was specified
1613 if ( getByName ) {
1614
1615 // First Try to find as-is property data
1616 ret = thisCache[ name ];
1617
1618 // Test for null|undefined property data
1619 if ( ret == null ) {
1620
1621 // Try to find the camelCased property
1622 ret = thisCache[ jQuery.camelCase( name ) ];
1623 }
1624 } else {
1625 ret = thisCache;
1626 }
1627
1628 return ret;
1629 },
1630
1631 removeData: function( elem, name, pvt /* Internal Use Only */ ) {
1632 if ( !jQuery.acceptData( elem ) ) {
1633 return;
1634 }
1635
1636 var thisCache, i, l,
1637
1638 isNode = elem.nodeType,
1639
1640 // See jQuery.data for more information
1641 cache = isNode ? jQuery.cache : elem,
1642 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1643
1644 // If there is already no cache entry for this object, there is no
1645 // purpose in continuing
1646 if ( !cache[ id ] ) {
1647 return;
1648 }
1649
1650 if ( name ) {
1651
1652 thisCache = pvt ? cache[ id ] : cache[ id ].data;
1653
1654 if ( thisCache ) {
1655
1656 // Support array or space separated string names for data keys
1657 if ( !jQuery.isArray( name ) ) {
1658
1659 // try the string as a key before any manipulation
1660 if ( name in thisCache ) {
1661 name = [ name ];
1662 } else {
1663
1664 // split the camel cased version by spaces unless a key with the spaces exists
1665 name = jQuery.camelCase( name );
1666 if ( name in thisCache ) {
1667 name = [ name ];
1668 } else {
1669 name = name.split(" ");
1670 }
1671 }
1672 }
1673
1674 for ( i = 0, l = name.length; i < l; i++ ) {
1675 delete thisCache[ name[i] ];
1676 }
1677
1678 // If there is no data left in the cache, we want to continue
1679 // and let the cache object itself get destroyed
1680 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1681 return;
1682 }
1683 }
1684 }
1685
1686 // See jQuery.data for more information
1687 if ( !pvt ) {
1688 delete cache[ id ].data;
1689
1690 // Don't destroy the parent cache unless the internal data object
1691 // had been the only thing left in it
1692 if ( !isEmptyDataObject( cache[ id ] ) ) {
1693 return;
1694 }
1695 }
1696
1697 // Destroy the cache
1698 if ( isNode ) {
1699 jQuery.cleanData( [ elem ], true );
1700
1701 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
1702 } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
1703 delete cache[ id ];
1704
1705 // When all else fails, null
1706 } else {
1707 cache[ id ] = null;
1708 }
1709 },
1710
1711 // For internal use only.
1712 _data: function( elem, name, data ) {
1713 return jQuery.data( elem, name, data, true );
1714 },
1715
1716 // A method for determining if a DOM node can handle the data expando
1717 acceptData: function( elem ) {
1718 var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
1719
1720 // nodes accept data unless otherwise specified; rejection can be conditional
1721 return !noData || noData !== true && elem.getAttribute("classid") === noData;
1722 }
1723 });
1724
1725 jQuery.fn.extend({
1726 data: function( key, value ) {
1727 var parts, part, attr, name, l,
1728 elem = this[0],
1729 i = 0,
1730 data = null;
1731
1732 // Gets all values
1733 if ( key === undefined ) {
1734 if ( this.length ) {
1735 data = jQuery.data( elem );
1736
1737 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
1738 attr = elem.attributes;
1739 for ( l = attr.length; i < l; i++ ) {
1740 name = attr[i].name;
1741
1742 if ( !name.indexOf( "data-" ) ) {
1743 name = jQuery.camelCase( name.substring(5) );
1744
1745 dataAttr( elem, name, data[ name ] );
1746 }
1747 }
1748 jQuery._data( elem, "parsedAttrs", true );
1749 }
1750 }
1751
1752 return data;
1753 }
1754
1755 // Sets multiple values
1756 if ( typeof key === "object" ) {
1757 return this.each(function() {
1758 jQuery.data( this, key );
1759 });
1760 }
1761
1762 parts = key.split( ".", 2 );
1763 parts[1] = parts[1] ? "." + parts[1] : "";
1764 part = parts[1] + "!";
1765
1766 return jQuery.access( this, function( value ) {
1767
1768 if ( value === undefined ) {
1769 data = this.triggerHandler( "getData" + part, [ parts[0] ] );
1770
1771 // Try to fetch any internally stored data first
1772 if ( data === undefined && elem ) {
1773 data = jQuery.data( elem, key );
1774 data = dataAttr( elem, key, data );
1775 }
1776
1777 return data === undefined && parts[1] ?
1778 this.data( parts[0] ) :
1779 data;
1780 }
1781
1782 parts[1] = value;
1783 this.each(function() {
1784 var self = jQuery( this );
1785
1786 self.triggerHandler( "setData" + part, parts );
1787 jQuery.data( this, key, value );
1788 self.triggerHandler( "changeData" + part, parts );
1789 });
1790 }, null, value, arguments.length > 1, null, false );
1791 },
1792
1793 removeData: function( key ) {
1794 return this.each(function() {
1795 jQuery.removeData( this, key );
1796 });
1797 }
1798 });
1799
1800 function dataAttr( elem, key, data ) {
1801 // If nothing was found internally, try to fetch any
1802 // data from the HTML5 data-* attribute
1803 if ( data === undefined && elem.nodeType === 1 ) {
1804
1805 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1806
1807 data = elem.getAttribute( name );
1808
1809 if ( typeof data === "string" ) {
1810 try {
1811 data = data === "true" ? true :
1812 data === "false" ? false :
1813 data === "null" ? null :
1814 // Only convert to a number if it doesn't change the string
1815 +data + "" === data ? +data :
1816 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1817 data;
1818 } catch( e ) {}
1819
1820 // Make sure we set the data so it isn't changed later
1821 jQuery.data( elem, key, data );
1822
1823 } else {
1824 data = undefined;
1825 }
1826 }
1827
1828 return data;
1829 }
1830
1831 // checks a cache object for emptiness
1832 function isEmptyDataObject( obj ) {
1833 var name;
1834 for ( name in obj ) {
1835
1836 // if the public data object is empty, the private is still empty
1837 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1838 continue;
1839 }
1840 if ( name !== "toJSON" ) {
1841 return false;
1842 }
1843 }
1844
1845 return true;
1846 }
1847 jQuery.extend({
1848 queue: function( elem, type, data ) {
1849 var queue;
1850
1851 if ( elem ) {
1852 type = ( type || "fx" ) + "queue";
1853 queue = jQuery._data( elem, type );
1854
1855 // Speed up dequeue by getting out quickly if this is just a lookup
1856 if ( data ) {
1857 if ( !queue || jQuery.isArray(data) ) {
1858 queue = jQuery._data( elem, type, jQuery.makeArray(data) );
1859 } else {
1860 queue.push( data );
1861 }
1862 }
1863 return queue || [];
1864 }
1865 },
1866
1867 dequeue: function( elem, type ) {
1868 type = type || "fx";
1869
1870 var queue = jQuery.queue( elem, type ),
1871 startLength = queue.length,
1872 fn = queue.shift(),
1873 hooks = jQuery._queueHooks( elem, type ),
1874 next = function() {
1875 jQuery.dequeue( elem, type );
1876 };
1877
1878 // If the fx queue is dequeued, always remove the progress sentinel
1879 if ( fn === "inprogress" ) {
1880 fn = queue.shift();
1881 startLength--;
1882 }
1883
1884 if ( fn ) {
1885
1886 // Add a progress sentinel to prevent the fx queue from being
1887 // automatically dequeued
1888 if ( type === "fx" ) {
1889 queue.unshift( "inprogress" );
1890 }
1891
1892 // clear up the last queue stop function
1893 delete hooks.stop;
1894 fn.call( elem, next, hooks );
1895 }
1896
1897 if ( !startLength && hooks ) {
1898 hooks.empty.fire();
1899 }
1900 },
1901
1902 // not intended for public consumption - generates a queueHooks object, or returns the current one
1903 _queueHooks: function( elem, type ) {
1904 var key = type + "queueHooks";
1905 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
1906 empty: jQuery.Callbacks("once memory").add(function() {
1907 jQuery.removeData( elem, type + "queue", true );
1908 jQuery.removeData( elem, key, true );
1909 })
1910 });
1911 }
1912 });
1913
1914 jQuery.fn.extend({
1915 queue: function( type, data ) {
1916 var setter = 2;
1917
1918 if ( typeof type !== "string" ) {
1919 data = type;
1920 type = "fx";
1921 setter--;
1922 }
1923
1924 if ( arguments.length < setter ) {
1925 return jQuery.queue( this[0], type );
1926 }
1927
1928 return data === undefined ?
1929 this :
1930 this.each(function() {
1931 var queue = jQuery.queue( this, type, data );
1932
1933 // ensure a hooks for this queue
1934 jQuery._queueHooks( this, type );
1935
1936 if ( type === "fx" && queue[0] !== "inprogress" ) {
1937 jQuery.dequeue( this, type );
1938 }
1939 });
1940 },
1941 dequeue: function( type ) {
1942 return this.each(function() {
1943 jQuery.dequeue( this, type );
1944 });
1945 },
1946 // Based off of the plugin by Clint Helfers, with permission.
1947 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1948 delay: function( time, type ) {
1949 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
1950 type = type || "fx";
1951
1952 return this.queue( type, function( next, hooks ) {
1953 var timeout = setTimeout( next, time );
1954 hooks.stop = function() {
1955 clearTimeout( timeout );
1956 };
1957 });
1958 },
1959 clearQueue: function( type ) {
1960 return this.queue( type || "fx", [] );
1961 },
1962 // Get a promise resolved when queues of a certain type
1963 // are emptied (fx is the type by default)
1964 promise: function( type, obj ) {
1965 var tmp,
1966 count = 1,
1967 defer = jQuery.Deferred(),
1968 elements = this,
1969 i = this.length,
1970 resolve = function() {
1971 if ( !( --count ) ) {
1972 defer.resolveWith( elements, [ elements ] );
1973 }
1974 };
1975
1976 if ( typeof type !== "string" ) {
1977 obj = type;
1978 type = undefined;
1979 }
1980 type = type || "fx";
1981
1982 while( i-- ) {
1983 tmp = jQuery._data( elements[ i ], type + "queueHooks" );
1984 if ( tmp && tmp.empty ) {
1985 count++;
1986 tmp.empty.add( resolve );
1987 }
1988 }
1989 resolve();
1990 return defer.promise( obj );
1991 }
1992 });
1993 var nodeHook, boolHook, fixSpecified,
1994 rclass = /[\t\r\n]/g,
1995 rreturn = /\r/g,
1996 rtype = /^(?:button|input)$/i,
1997 rfocusable = /^(?:button|input|object|select|textarea)$/i,
1998 rclickable = /^a(?:rea|)$/i,
1999 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
2000 getSetAttribute = jQuery.support.getSetAttribute;
2001
2002 jQuery.fn.extend({
2003 attr: function( name, value ) {
2004 return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
2005 },
2006
2007 removeAttr: function( name ) {
2008 return this.each(function() {
2009 jQuery.removeAttr( this, name );
2010 });
2011 },
2012
2013 prop: function( name, value ) {
2014 return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2015 },
2016
2017 removeProp: function( name ) {
2018 name = jQuery.propFix[ name ] || name;
2019 return this.each(function() {
2020 // try/catch handles cases where IE balks (such as removing a property on window)
2021 try {
2022 this[ name ] = undefined;
2023 delete this[ name ];
2024 } catch( e ) {}
2025 });
2026 },
2027
2028 addClass: function( value ) {
2029 var classNames, i, l, elem,
2030 setClass, c, cl;
2031
2032 if ( jQuery.isFunction( value ) ) {
2033 return this.each(function( j ) {
2034 jQuery( this ).addClass( value.call(this, j, this.className) );
2035 });
2036 }
2037
2038 if ( value && typeof value === "string" ) {
2039 classNames = value.split( core_rspace );
2040
2041 for ( i = 0, l = this.length; i < l; i++ ) {
2042 elem = this[ i ];
2043
2044 if ( elem.nodeType === 1 ) {
2045 if ( !elem.className && classNames.length === 1 ) {
2046 elem.className = value;
2047
2048 } else {
2049 setClass = " " + elem.className + " ";
2050
2051 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2052 if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {
2053 setClass += classNames[ c ] + " ";
2054 }
2055 }
2056 elem.className = jQuery.trim( setClass );
2057 }
2058 }
2059 }
2060 }
2061
2062 return this;
2063 },
2064
2065 removeClass: function( value ) {
2066 var removes, className, elem, c, cl, i, l;
2067
2068 if ( jQuery.isFunction( value ) ) {
2069 return this.each(function( j ) {
2070 jQuery( this ).removeClass( value.call(this, j, this.className) );
2071 });
2072 }
2073 if ( (value && typeof value === "string") || value === undefined ) {
2074 removes = ( value || "" ).split( core_rspace );
2075
2076 for ( i = 0, l = this.length; i < l; i++ ) {
2077 elem = this[ i ];
2078 if ( elem.nodeType === 1 && elem.className ) {
2079
2080 className = (" " + elem.className + " ").replace( rclass, " " );
2081
2082 // loop over each item in the removal list
2083 for ( c = 0, cl = removes.length; c < cl; c++ ) {
2084 // Remove until there is nothing to remove,
2085 while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) {
2086 className = className.replace( " " + removes[ c ] + " " , " " );
2087 }
2088 }
2089 elem.className = value ? jQuery.trim( className ) : "";
2090 }
2091 }
2092 }
2093
2094 return this;
2095 },
2096
2097 toggleClass: function( value, stateVal ) {
2098 var type = typeof value,
2099 isBool = typeof stateVal === "boolean";
2100
2101 if ( jQuery.isFunction( value ) ) {
2102 return this.each(function( i ) {
2103 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2104 });
2105 }
2106
2107 return this.each(function() {
2108 if ( type === "string" ) {
2109 // toggle individual class names
2110 var className,
2111 i = 0,
2112 self = jQuery( this ),
2113 state = stateVal,
2114 classNames = value.split( core_rspace );
2115
2116 while ( (className = classNames[ i++ ]) ) {
2117 // check each className given, space separated list
2118 state = isBool ? state : !self.hasClass( className );
2119 self[ state ? "addClass" : "removeClass" ]( className );
2120 }
2121
2122 } else if ( type === "undefined" || type === "boolean" ) {
2123 if ( this.className ) {
2124 // store className if set
2125 jQuery._data( this, "__className__", this.className );
2126 }
2127
2128 // toggle whole className
2129 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2130 }
2131 });
2132 },
2133
2134 hasClass: function( selector ) {
2135 var className = " " + selector + " ",
2136 i = 0,
2137 l = this.length;
2138 for ( ; i < l; i++ ) {
2139 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
2140 return true;
2141 }
2142 }
2143
2144 return false;
2145 },
2146
2147 val: function( value ) {
2148 var hooks, ret, isFunction,
2149 elem = this[0];
2150
2151 if ( !arguments.length ) {
2152 if ( elem ) {
2153 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
2154
2155 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2156 return ret;
2157 }
2158
2159 ret = elem.value;
2160
2161 return typeof ret === "string" ?
2162 // handle most common string cases
2163 ret.replace(rreturn, "") :
2164 // handle cases where value is null/undef or number
2165 ret == null ? "" : ret;
2166 }
2167
2168 return;
2169 }
2170
2171 isFunction = jQuery.isFunction( value );
2172
2173 return this.each(function( i ) {
2174 var val,
2175 self = jQuery(this);
2176
2177 if ( this.nodeType !== 1 ) {
2178 return;
2179 }
2180
2181 if ( isFunction ) {
2182 val = value.call( this, i, self.val() );
2183 } else {
2184 val = value;
2185 }
2186
2187 // Treat null/undefined as ""; convert numbers to string
2188 if ( val == null ) {
2189 val = "";
2190 } else if ( typeof val === "number" ) {
2191 val += "";
2192 } else if ( jQuery.isArray( val ) ) {
2193 val = jQuery.map(val, function ( value ) {
2194 return value == null ? "" : value + "";
2195 });
2196 }
2197
2198 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
2199
2200 // If set returns undefined, fall back to normal setting
2201 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2202 this.value = val;
2203 }
2204 });
2205 }
2206 });
2207
2208 jQuery.extend({
2209 valHooks: {
2210 option: {
2211 get: function( elem ) {
2212 // attributes.value is undefined in Blackberry 4.7 but
2213 // uses .value. See #6932
2214 var val = elem.attributes.value;
2215 return !val || val.specified ? elem.value : elem.text;
2216 }
2217 },
2218 select: {
2219 get: function( elem ) {
2220 var value, option,
2221 options = elem.options,
2222 index = elem.selectedIndex,
2223 one = elem.type === "select-one" || index < 0,
2224 values = one ? null : [],
2225 max = one ? index + 1 : options.length,
2226 i = index < 0 ?
2227 max :
2228 one ? index : 0;
2229
2230 // Loop through all the selected options
2231 for ( ; i < max; i++ ) {
2232 option = options[ i ];
2233
2234 // oldIE doesn't update selected after form reset (#2551)
2235 if ( ( option.selected || i === index ) &&
2236 // Don't return options that are disabled or in a disabled optgroup
2237 ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
2238 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
2239
2240 // Get the specific value for the option
2241 value = jQuery( option ).val();
2242
2243 // We don't need an array for one selects
2244 if ( one ) {
2245 return value;
2246 }
2247
2248 // Multi-Selects return an array
2249 values.push( value );
2250 }
2251 }
2252
2253 return values;
2254 },
2255
2256 set: function( elem, value ) {
2257 var values = jQuery.makeArray( value );
2258
2259 jQuery(elem).find("option").each(function() {
2260 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2261 });
2262
2263 if ( !values.length ) {
2264 elem.selectedIndex = -1;
2265 }
2266 return values;
2267 }
2268 }
2269 },
2270
2271 // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9
2272 attrFn: {},
2273
2274 attr: function( elem, name, value, pass ) {
2275 var ret, hooks, notxml,
2276 nType = elem.nodeType;
2277
2278 // don't get/set attributes on text, comment and attribute nodes
2279 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2280 return;
2281 }
2282
2283 if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
2284 return jQuery( elem )[ name ]( value );
2285 }
2286
2287 // Fallback to prop when attributes are not supported
2288 if ( typeof elem.getAttribute === "undefined" ) {
2289 return jQuery.prop( elem, name, value );
2290 }
2291
2292 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2293
2294 // All attributes are lowercase
2295 // Grab necessary hook if one is defined
2296 if ( notxml ) {
2297 name = name.toLowerCase();
2298 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2299 }
2300
2301 if ( value !== undefined ) {
2302
2303 if ( value === null ) {
2304 jQuery.removeAttr( elem, name );
2305 return;
2306
2307 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
2308 return ret;
2309
2310 } else {
2311 elem.setAttribute( name, value + "" );
2312 return value;
2313 }
2314
2315 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
2316 return ret;
2317
2318 } else {
2319
2320 ret = elem.getAttribute( name );
2321
2322 // Non-existent attributes return null, we normalize to undefined
2323 return ret === null ?
2324 undefined :
2325 ret;
2326 }
2327 },
2328
2329 removeAttr: function( elem, value ) {
2330 var propName, attrNames, name, isBool,
2331 i = 0;
2332
2333 if ( value && elem.nodeType === 1 ) {
2334
2335 attrNames = value.split( core_rspace );
2336
2337 for ( ; i < attrNames.length; i++ ) {
2338 name = attrNames[ i ];
2339
2340 if ( name ) {
2341 propName = jQuery.propFix[ name ] || name;
2342 isBool = rboolean.test( name );
2343
2344 // See #9699 for explanation of this approach (setting first, then removal)
2345 // Do not do this for boolean attributes (see #10870)
2346 if ( !isBool ) {
2347 jQuery.attr( elem, name, "" );
2348 }
2349 elem.removeAttribute( getSetAttribute ? name : propName );
2350
2351 // Set corresponding property to false for boolean attributes
2352 if ( isBool && propName in elem ) {
2353 elem[ propName ] = false;
2354 }
2355 }
2356 }
2357 }
2358 },
2359
2360 attrHooks: {
2361 type: {
2362 set: function( elem, value ) {
2363 // We can't allow the type property to be changed (since it causes problems in IE)
2364 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
2365 jQuery.error( "type property can't be changed" );
2366 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2367 // Setting the type on a radio button after the value resets the value in IE6-9
2368 // Reset value to it's default in case type is set after value
2369 // This is for element creation
2370 var val = elem.value;
2371 elem.setAttribute( "type", value );
2372 if ( val ) {
2373 elem.value = val;
2374 }
2375 return value;
2376 }
2377 }
2378 },
2379 // Use the value property for back compat
2380 // Use the nodeHook for button elements in IE6/7 (#1954)
2381 value: {
2382 get: function( elem, name ) {
2383 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2384 return nodeHook.get( elem, name );
2385 }
2386 return name in elem ?
2387 elem.value :
2388 null;
2389 },
2390 set: function( elem, value, name ) {
2391 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
2392 return nodeHook.set( elem, value, name );
2393 }
2394 // Does not return so that setAttribute is also used
2395 elem.value = value;
2396 }
2397 }
2398 },
2399
2400 propFix: {
2401 tabindex: "tabIndex",
2402 readonly: "readOnly",
2403 "for": "htmlFor",
2404 "class": "className",
2405 maxlength: "maxLength",
2406 cellspacing: "cellSpacing",
2407 cellpadding: "cellPadding",
2408 rowspan: "rowSpan",
2409 colspan: "colSpan",
2410 usemap: "useMap",
2411 frameborder: "frameBorder",
2412 contenteditable: "contentEditable"
2413 },
2414
2415 prop: function( elem, name, value ) {
2416 var ret, hooks, notxml,
2417 nType = elem.nodeType;
2418
2419 // don't get/set properties on text, comment and attribute nodes
2420 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2421 return;
2422 }
2423
2424 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2425
2426 if ( notxml ) {
2427 // Fix name and attach hooks
2428 name = jQuery.propFix[ name ] || name;
2429 hooks = jQuery.propHooks[ name ];
2430 }
2431
2432 if ( value !== undefined ) {
2433 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2434 return ret;
2435
2436 } else {
2437 return ( elem[ name ] = value );
2438 }
2439
2440 } else {
2441 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2442 return ret;
2443
2444 } else {
2445 return elem[ name ];
2446 }
2447 }
2448 },
2449
2450 propHooks: {
2451 tabIndex: {
2452 get: function( elem ) {
2453 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2454 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2455 var attributeNode = elem.getAttributeNode("tabindex");
2456
2457 return attributeNode && attributeNode.specified ?
2458 parseInt( attributeNode.value, 10 ) :
2459 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2460 0 :
2461 undefined;
2462 }
2463 }
2464 }
2465 });
2466
2467 // Hook for boolean attributes
2468 boolHook = {
2469 get: function( elem, name ) {
2470 // Align boolean attributes with corresponding properties
2471 // Fall back to attribute presence where some booleans are not supported
2472 var attrNode,
2473 property = jQuery.prop( elem, name );
2474 return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
2475 name.toLowerCase() :
2476 undefined;
2477 },
2478 set: function( elem, value, name ) {
2479 var propName;
2480 if ( value === false ) {
2481 // Remove boolean attributes when set to false
2482 jQuery.removeAttr( elem, name );
2483 } else {
2484 // value is true since we know at this point it's type boolean and not false
2485 // Set boolean attributes to the same name and set the DOM property
2486 propName = jQuery.propFix[ name ] || name;
2487 if ( propName in elem ) {
2488 // Only set the IDL specifically if it already exists on the element
2489 elem[ propName ] = true;
2490 }
2491
2492 elem.setAttribute( name, name.toLowerCase() );
2493 }
2494 return name;
2495 }
2496 };
2497
2498 // IE6/7 do not support getting/setting some attributes with get/setAttribute
2499 if ( !getSetAttribute ) {
2500
2501 fixSpecified = {
2502 name: true,
2503 id: true,
2504 coords: true
2505 };
2506
2507 // Use this for any attribute in IE6/7
2508 // This fixes almost every IE6/7 issue
2509 nodeHook = jQuery.valHooks.button = {
2510 get: function( elem, name ) {
2511 var ret;
2512 ret = elem.getAttributeNode( name );
2513 return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
2514 ret.value :
2515 undefined;
2516 },
2517 set: function( elem, value, name ) {
2518 // Set the existing or create a new attribute node
2519 var ret = elem.getAttributeNode( name );
2520 if ( !ret ) {
2521 ret = document.createAttribute( name );
2522 elem.setAttributeNode( ret );
2523 }
2524 return ( ret.value = value + "" );
2525 }
2526 };
2527
2528 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2529 // This is for removals
2530 jQuery.each([ "width", "height" ], function( i, name ) {
2531 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2532 set: function( elem, value ) {
2533 if ( value === "" ) {
2534 elem.setAttribute( name, "auto" );
2535 return value;
2536 }
2537 }
2538 });
2539 });
2540
2541 // Set contenteditable to false on removals(#10429)
2542 // Setting to empty string throws an error as an invalid value
2543 jQuery.attrHooks.contenteditable = {
2544 get: nodeHook.get,
2545 set: function( elem, value, name ) {
2546 if ( value === "" ) {
2547 value = "false";
2548 }
2549 nodeHook.set( elem, value, name );
2550 }
2551 };
2552 }
2553
2554
2555 // Some attributes require a special call on IE
2556 if ( !jQuery.support.hrefNormalized ) {
2557 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2558 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2559 get: function( elem ) {
2560 var ret = elem.getAttribute( name, 2 );
2561 return ret === null ? undefined : ret;
2562 }
2563 });
2564 });
2565 }
2566
2567 if ( !jQuery.support.style ) {
2568 jQuery.attrHooks.style = {
2569 get: function( elem ) {
2570 // Return undefined in the case of empty string
2571 // Normalize to lowercase since IE uppercases css property names
2572 return elem.style.cssText.toLowerCase() || undefined;
2573 },
2574 set: function( elem, value ) {
2575 return ( elem.style.cssText = value + "" );
2576 }
2577 };
2578 }
2579
2580 // Safari mis-reports the default selected property of an option
2581 // Accessing the parent's selectedIndex property fixes it
2582 if ( !jQuery.support.optSelected ) {
2583 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2584 get: function( elem ) {
2585 var parent = elem.parentNode;
2586
2587 if ( parent ) {
2588 parent.selectedIndex;
2589
2590 // Make sure that it also works with optgroups, see #5701
2591 if ( parent.parentNode ) {
2592 parent.parentNode.selectedIndex;
2593 }
2594 }
2595 return null;
2596 }
2597 });
2598 }
2599
2600 // IE6/7 call enctype encoding
2601 if ( !jQuery.support.enctype ) {
2602 jQuery.propFix.enctype = "encoding";
2603 }
2604
2605 // Radios and checkboxes getter/setter
2606 if ( !jQuery.support.checkOn ) {
2607 jQuery.each([ "radio", "checkbox" ], function() {
2608 jQuery.valHooks[ this ] = {
2609 get: function( elem ) {
2610 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2611 return elem.getAttribute("value") === null ? "on" : elem.value;
2612 }
2613 };
2614 });
2615 }
2616 jQuery.each([ "radio", "checkbox" ], function() {
2617 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2618 set: function( elem, value ) {
2619 if ( jQuery.isArray( value ) ) {
2620 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2621 }
2622 }
2623 });
2624 });
2625 var rformElems = /^(?:textarea|input|select)$/i,
2626 rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/,
2627 rhoverHack = /(?:^|\s)hover(\.\S+|)\b/,
2628 rkeyEvent = /^key/,
2629 rmouseEvent = /^(?:mouse|contextmenu)|click/,
2630 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2631 hoverHack = function( events ) {
2632 return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
2633 };
2634
2635 /*
2636 * Helper functions for managing events -- not part of the public interface.
2637 * Props to Dean Edwards' addEvent library for many of the ideas.
2638 */
2639 jQuery.event = {
2640
2641 add: function( elem, types, handler, data, selector ) {
2642
2643 var elemData, eventHandle, events,
2644 t, tns, type, namespaces, handleObj,
2645 handleObjIn, handlers, special;
2646
2647 // Don't attach events to noData or text/comment nodes (allow plain objects tho)
2648 if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
2649 return;
2650 }
2651
2652 // Caller can pass in an object of custom data in lieu of the handler
2653 if ( handler.handler ) {
2654 handleObjIn = handler;
2655 handler = handleObjIn.handler;
2656 selector = handleObjIn.selector;
2657 }
2658
2659 // Make sure that the handler has a unique ID, used to find/remove it later
2660 if ( !handler.guid ) {
2661 handler.guid = jQuery.guid++;
2662 }
2663
2664 // Init the element's event structure and main handler, if this is the first
2665 events = elemData.events;
2666 if ( !events ) {
2667 elemData.events = events = {};
2668 }
2669 eventHandle = elemData.handle;
2670 if ( !eventHandle ) {
2671 elemData.handle = eventHandle = function( e ) {
2672 // Discard the second event of a jQuery.event.trigger() and
2673 // when an event is called after a page has unloaded
2674 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
2675 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2676 undefined;
2677 };
2678 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2679 eventHandle.elem = elem;
2680 }
2681
2682 // Handle multiple events separated by a space
2683 // jQuery(...).bind("mouseover mouseout", fn);
2684 types = jQuery.trim( hoverHack(types) ).split( " " );
2685 for ( t = 0; t < types.length; t++ ) {
2686
2687 tns = rtypenamespace.exec( types[t] ) || [];
2688 type = tns[1];
2689 namespaces = ( tns[2] || "" ).split( "." ).sort();
2690
2691 // If event changes its type, use the special event handlers for the changed type
2692 special = jQuery.event.special[ type ] || {};
2693
2694 // If selector defined, determine special event api type, otherwise given type
2695 type = ( selector ? special.delegateType : special.bindType ) || type;
2696
2697 // Update special based on newly reset type
2698 special = jQuery.event.special[ type ] || {};
2699
2700 // handleObj is passed to all event handlers
2701 handleObj = jQuery.extend({
2702 type: type,
2703 origType: tns[1],
2704 data: data,
2705 handler: handler,
2706 guid: handler.guid,
2707 selector: selector,
2708 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
2709 namespace: namespaces.join(".")
2710 }, handleObjIn );
2711
2712 // Init the event handler queue if we're the first
2713 handlers = events[ type ];
2714 if ( !handlers ) {
2715 handlers = events[ type ] = [];
2716 handlers.delegateCount = 0;
2717
2718 // Only use addEventListener/attachEvent if the special events handler returns false
2719 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2720 // Bind the global event handler to the element
2721 if ( elem.addEventListener ) {
2722 elem.addEventListener( type, eventHandle, false );
2723
2724 } else if ( elem.attachEvent ) {
2725 elem.attachEvent( "on" + type, eventHandle );
2726 }
2727 }
2728 }
2729
2730 if ( special.add ) {
2731 special.add.call( elem, handleObj );
2732
2733 if ( !handleObj.handler.guid ) {
2734 handleObj.handler.guid = handler.guid;
2735 }
2736 }
2737
2738 // Add to the element's handler list, delegates in front
2739 if ( selector ) {
2740 handlers.splice( handlers.delegateCount++, 0, handleObj );
2741 } else {
2742 handlers.push( handleObj );
2743 }
2744
2745 // Keep track of which events have ever been used, for event optimization
2746 jQuery.event.global[ type ] = true;
2747 }
2748
2749 // Nullify elem to prevent memory leaks in IE
2750 elem = null;
2751 },
2752
2753 global: {},
2754
2755 // Detach an event or set of events from an element
2756 remove: function( elem, types, handler, selector, mappedTypes ) {
2757
2758 var t, tns, type, origType, namespaces, origCount,
2759 j, events, special, eventType, handleObj,
2760 elemData = jQuery.hasData( elem ) && jQuery._data( elem );
2761
2762 if ( !elemData || !(events = elemData.events) ) {
2763 return;
2764 }
2765
2766 // Once for each type.namespace in types; type may be omitted
2767 types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
2768 for ( t = 0; t < types.length; t++ ) {
2769 tns = rtypenamespace.exec( types[t] ) || [];
2770 type = origType = tns[1];
2771 namespaces = tns[2];
2772
2773 // Unbind all events (on this namespace, if provided) for the element
2774 if ( !type ) {
2775 for ( type in events ) {
2776 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
2777 }
2778 continue;
2779 }
2780
2781 special = jQuery.event.special[ type ] || {};
2782 type = ( selector? special.delegateType : special.bindType ) || type;
2783 eventType = events[ type ] || [];
2784 origCount = eventType.length;
2785 namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
2786
2787 // Remove matching events
2788 for ( j = 0; j < eventType.length; j++ ) {
2789 handleObj = eventType[ j ];
2790
2791 if ( ( mappedTypes || origType === handleObj.origType ) &&
2792 ( !handler || handler.guid === handleObj.guid ) &&
2793 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
2794 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
2795 eventType.splice( j--, 1 );
2796
2797 if ( handleObj.selector ) {
2798 eventType.delegateCount--;
2799 }
2800 if ( special.remove ) {
2801 special.remove.call( elem, handleObj );
2802 }
2803 }
2804 }
2805
2806 // Remove generic event handler if we removed something and no more handlers exist
2807 // (avoids potential for endless recursion during removal of special event handlers)
2808 if ( eventType.length === 0 && origCount !== eventType.length ) {
2809 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
2810 jQuery.removeEvent( elem, type, elemData.handle );
2811 }
2812
2813 delete events[ type ];
2814 }
2815 }
2816
2817 // Remove the expando if it's no longer used
2818 if ( jQuery.isEmptyObject( events ) ) {
2819 delete elemData.handle;
2820
2821 // removeData also checks for emptiness and clears the expando if empty
2822 // so use it instead of delete
2823 jQuery.removeData( elem, "events", true );
2824 }
2825 },
2826
2827 // Events that are safe to short-circuit if no handlers are attached.
2828 // Native DOM events should not be added, they may have inline handlers.
2829 customEvent: {
2830 "getData": true,
2831 "setData": true,
2832 "changeData": true
2833 },
2834
2835 trigger: function( event, data, elem, onlyHandlers ) {
2836 // Don't do events on text and comment nodes
2837 if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
2838 return;
2839 }
2840
2841 // Event object or event type
2842 var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType,
2843 type = event.type || event,
2844 namespaces = [];
2845
2846 // focus/blur morphs to focusin/out; ensure we're not firing them right now
2847 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
2848 return;
2849 }
2850
2851 if ( type.indexOf( "!" ) >= 0 ) {
2852 // Exclusive events trigger only for the exact event (no namespaces)
2853 type = type.slice(0, -1);
2854 exclusive = true;
2855 }
2856
2857 if ( type.indexOf( "." ) >= 0 ) {
2858 // Namespaced trigger; create a regexp to match event type in handle()
2859 namespaces = type.split(".");
2860 type = namespaces.shift();
2861 namespaces.sort();
2862 }
2863
2864 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
2865 // No jQuery handlers for this event type, and it can't have inline handlers
2866 return;
2867 }
2868
2869 // Caller can pass in an Event, Object, or just an event type string
2870 event = typeof event === "object" ?
2871 // jQuery.Event object
2872 event[ jQuery.expando ] ? event :
2873 // Object literal
2874 new jQuery.Event( type, event ) :
2875 // Just the event type (string)
2876 new jQuery.Event( type );
2877
2878 event.type = type;
2879 event.isTrigger = true;
2880 event.exclusive = exclusive;
2881 event.namespace = namespaces.join( "." );
2882 event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
2883 ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
2884
2885 // Handle a global trigger
2886 if ( !elem ) {
2887
2888 // TODO: Stop taunting the data cache; remove global events and always attach to document
2889 cache = jQuery.cache;
2890 for ( i in cache ) {
2891 if ( cache[ i ].events && cache[ i ].events[ type ] ) {
2892 jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
2893 }
2894 }
2895 return;
2896 }
2897
2898 // Clean up the event in case it is being reused
2899 event.result = undefined;
2900 if ( !event.target ) {
2901 event.target = elem;
2902 }
2903
2904 // Clone any incoming data and prepend the event, creating the handler arg list
2905 data = data != null ? jQuery.makeArray( data ) : [];
2906 data.unshift( event );
2907
2908 // Allow special events to draw outside the lines
2909 special = jQuery.event.special[ type ] || {};
2910 if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
2911 return;
2912 }
2913
2914 // Determine event propagation path in advance, per W3C events spec (#9951)
2915 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
2916 eventPath = [[ elem, special.bindType || type ]];
2917 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
2918
2919 bubbleType = special.delegateType || type;
2920 cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
2921 for ( old = elem; cur; cur = cur.parentNode ) {
2922 eventPath.push([ cur, bubbleType ]);
2923 old = cur;
2924 }
2925
2926 // Only add window if we got to document (e.g., not plain obj or detached DOM)
2927 if ( old === (elem.ownerDocument || document) ) {
2928 eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
2929 }
2930 }
2931
2932 // Fire handlers on the event path
2933 for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
2934
2935 cur = eventPath[i][0];
2936 event.type = eventPath[i][1];
2937
2938 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
2939 if ( handle ) {
2940 handle.apply( cur, data );
2941 }
2942 // Note that this is a bare JS function and not a jQuery handler
2943 handle = ontype && cur[ ontype ];
2944 if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
2945 event.preventDefault();
2946 }
2947 }
2948 event.type = type;
2949
2950 // If nobody prevented the default action, do it now
2951 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
2952
2953 if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
2954 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
2955
2956 // Call a native DOM method on the target with the same name name as the event.
2957 // Can't use an .isFunction() check here because IE6/7 fails that test.
2958 // Don't do default actions on window, that's where global variables be (#6170)
2959 // IE<9 dies on focus/blur to hidden element (#1486)
2960 if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
2961
2962 // Don't re-trigger an onFOO event when we call its FOO() method
2963 old = elem[ ontype ];
2964
2965 if ( old ) {
2966 elem[ ontype ] = null;
2967 }
2968
2969 // Prevent re-triggering of the same event, since we already bubbled it above
2970 jQuery.event.triggered = type;
2971 elem[ type ]();
2972 jQuery.event.triggered = undefined;
2973
2974 if ( old ) {
2975 elem[ ontype ] = old;
2976 }
2977 }
2978 }
2979 }
2980
2981 return event.result;
2982 },
2983
2984 dispatch: function( event ) {
2985
2986 // Make a writable jQuery.Event from the native event object
2987 event = jQuery.event.fix( event || window.event );
2988
2989 var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related,
2990 handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
2991 delegateCount = handlers.delegateCount,
2992 args = core_slice.call( arguments ),
2993 run_all = !event.exclusive && !event.namespace,
2994 special = jQuery.event.special[ event.type ] || {},
2995 handlerQueue = [];
2996
2997 // Use the fix-ed jQuery.Event rather than the (read-only) native event
2998 args[0] = event;
2999 event.delegateTarget = this;
3000
3001 // Call the preDispatch hook for the mapped type, and let it bail if desired
3002 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
3003 return;
3004 }
3005
3006 // Determine handlers that should run if there are delegated events
3007 // Avoid non-left-click bubbling in Firefox (#3861)
3008 if ( delegateCount && !(event.button && event.type === "click") ) {
3009
3010 for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
3011
3012 // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)
3013 if ( cur.disabled !== true || event.type !== "click" ) {
3014 selMatch = {};
3015 matches = [];
3016 for ( i = 0; i < delegateCount; i++ ) {
3017 handleObj = handlers[ i ];
3018 sel = handleObj.selector;
3019
3020 if ( selMatch[ sel ] === undefined ) {
3021 selMatch[ sel ] = handleObj.needsContext ?
3022 jQuery( sel, this ).index( cur ) >= 0 :
3023 jQuery.find( sel, this, null, [ cur ] ).length;
3024 }
3025 if ( selMatch[ sel ] ) {
3026 matches.push( handleObj );
3027 }
3028 }
3029 if ( matches.length ) {
3030 handlerQueue.push({ elem: cur, matches: matches });
3031 }
3032 }
3033 }
3034 }
3035
3036 // Add the remaining (directly-bound) handlers
3037 if ( handlers.length > delegateCount ) {
3038 handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
3039 }
3040
3041 // Run delegates first; they may want to stop propagation beneath us
3042 for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
3043 matched = handlerQueue[ i ];
3044 event.currentTarget = matched.elem;
3045
3046 for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
3047 handleObj = matched.matches[ j ];
3048
3049 // Triggered event must either 1) be non-exclusive and have no namespace, or
3050 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3051 if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
3052
3053 event.data = handleObj.data;
3054 event.handleObj = handleObj;
3055
3056 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
3057 .apply( matched.elem, args );
3058
3059 if ( ret !== undefined ) {
3060 event.result = ret;
3061 if ( ret === false ) {
3062 event.preventDefault();
3063 event.stopPropagation();
3064 }
3065 }
3066 }
3067 }
3068 }
3069
3070 // Call the postDispatch hook for the mapped type
3071 if ( special.postDispatch ) {
3072 special.postDispatch.call( this, event );
3073 }
3074
3075 return event.result;
3076 },
3077
3078 // Includes some event props shared by KeyEvent and MouseEvent
3079 // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
3080 props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3081
3082 fixHooks: {},
3083
3084 keyHooks: {
3085 props: "char charCode key keyCode".split(" "),
3086 filter: function( event, original ) {
3087
3088 // Add which for key events
3089 if ( event.which == null ) {
3090 event.which = original.charCode != null ? original.charCode : original.keyCode;
3091 }
3092
3093 return event;
3094 }
3095 },
3096
3097 mouseHooks: {
3098 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3099 filter: function( event, original ) {
3100 var eventDoc, doc, body,
3101 button = original.button,
3102 fromElement = original.fromElement;
3103
3104 // Calculate pageX/Y if missing and clientX/Y available
3105 if ( event.pageX == null && original.clientX != null ) {
3106 eventDoc = event.target.ownerDocument || document;
3107 doc = eventDoc.documentElement;
3108 body = eventDoc.body;
3109
3110 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3111 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3112 }
3113
3114 // Add relatedTarget, if necessary
3115 if ( !event.relatedTarget && fromElement ) {
3116 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3117 }
3118
3119 // Add which for click: 1 === left; 2 === middle; 3 === right
3120 // Note: button is not normalized, so don't use it
3121 if ( !event.which && button !== undefined ) {
3122 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3123 }
3124
3125 return event;
3126 }
3127 },
3128
3129 fix: function( event ) {
3130 if ( event[ jQuery.expando ] ) {
3131 return event;
3132 }
3133
3134 // Create a writable copy of the event object and normalize some properties
3135 var i, prop,
3136 originalEvent = event,
3137 fixHook = jQuery.event.fixHooks[ event.type ] || {},
3138 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3139
3140 event = jQuery.Event( originalEvent );
3141
3142 for ( i = copy.length; i; ) {
3143 prop = copy[ --i ];
3144 event[ prop ] = originalEvent[ prop ];
3145 }
3146
3147 // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
3148 if ( !event.target ) {
3149 event.target = originalEvent.srcElement || document;
3150 }
3151
3152 // Target should not be a text node (#504, Safari)
3153 if ( event.target.nodeType === 3 ) {
3154 event.target = event.target.parentNode;
3155 }
3156
3157 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8)
3158 event.metaKey = !!event.metaKey;
3159
3160 return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
3161 },
3162
3163 special: {
3164 load: {
3165 // Prevent triggered image.load events from bubbling to window.load
3166 noBubble: true
3167 },
3168
3169 focus: {
3170 delegateType: "focusin"
3171 },
3172 blur: {
3173 delegateType: "focusout"
3174 },
3175
3176 beforeunload: {
3177 setup: function( data, namespaces, eventHandle ) {
3178 // We only want to do this special case on windows
3179 if ( jQuery.isWindow( this ) ) {
3180 this.onbeforeunload = eventHandle;
3181 }
3182 },
3183
3184 teardown: function( namespaces, eventHandle ) {
3185 if ( this.onbeforeunload === eventHandle ) {
3186 this.onbeforeunload = null;
3187 }
3188 }
3189 }
3190 },
3191
3192 simulate: function( type, elem, event, bubble ) {
3193 // Piggyback on a donor event to simulate a different one.
3194 // Fake originalEvent to avoid donor's stopPropagation, but if the
3195 // simulated event prevents default then we do the same on the donor.
3196 var e = jQuery.extend(
3197 new jQuery.Event(),
3198 event,
3199 { type: type,
3200 isSimulated: true,
3201 originalEvent: {}
3202 }
3203 );
3204 if ( bubble ) {
3205 jQuery.event.trigger( e, null, elem );
3206 } else {
3207 jQuery.event.dispatch.call( elem, e );
3208 }
3209 if ( e.isDefaultPrevented() ) {
3210 event.preventDefault();
3211 }
3212 }
3213 };
3214
3215 // Some plugins are using, but it's undocumented/deprecated and will be removed.
3216 // The 1.7 special event interface should provide all the hooks needed now.
3217 jQuery.event.handle = jQuery.event.dispatch;
3218
3219 jQuery.removeEvent = document.removeEventListener ?
3220 function( elem, type, handle ) {
3221 if ( elem.removeEventListener ) {
3222 elem.removeEventListener( type, handle, false );
3223 }
3224 } :
3225 function( elem, type, handle ) {
3226 var name = "on" + type;
3227
3228 if ( elem.detachEvent ) {
3229
3230 // #8545, #7054, preventing memory leaks for custom events in IE6-8
3231 // detachEvent needed property on element, by name of that event, to properly expose it to GC
3232 if ( typeof elem[ name ] === "undefined" ) {
3233 elem[ name ] = null;
3234 }
3235
3236 elem.detachEvent( name, handle );
3237 }
3238 };
3239
3240 jQuery.Event = function( src, props ) {
3241 // Allow instantiation without the 'new' keyword
3242 if ( !(this instanceof jQuery.Event) ) {
3243 return new jQuery.Event( src, props );
3244 }
3245
3246 // Event object
3247 if ( src && src.type ) {
3248 this.originalEvent = src;
3249 this.type = src.type;
3250
3251 // Events bubbling up the document may have been marked as prevented
3252 // by a handler lower down the tree; reflect the correct value.
3253 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3254 src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3255
3256 // Event type
3257 } else {
3258 this.type = src;
3259 }
3260
3261 // Put explicitly provided properties onto the event object
3262 if ( props ) {
3263 jQuery.extend( this, props );
3264 }
3265
3266 // Create a timestamp if incoming event doesn't have one
3267 this.timeStamp = src && src.timeStamp || jQuery.now();
3268
3269 // Mark it as fixed
3270 this[ jQuery.expando ] = true;
3271 };
3272
3273 function returnFalse() {
3274 return false;
3275 }
3276 function returnTrue() {
3277 return true;
3278 }
3279
3280 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3281 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3282 jQuery.Event.prototype = {
3283 preventDefault: function() {
3284 this.isDefaultPrevented = returnTrue;
3285
3286 var e = this.originalEvent;
3287 if ( !e ) {
3288 return;
3289 }
3290
3291 // if preventDefault exists run it on the original event
3292 if ( e.preventDefault ) {
3293 e.preventDefault();
3294
3295 // otherwise set the returnValue property of the original event to false (IE)
3296 } else {
3297 e.returnValue = false;
3298 }
3299 },
3300 stopPropagation: function() {
3301 this.isPropagationStopped = returnTrue;
3302
3303 var e = this.originalEvent;
3304 if ( !e ) {
3305 return;
3306 }
3307 // if stopPropagation exists run it on the original event
3308 if ( e.stopPropagation ) {
3309 e.stopPropagation();
3310 }
3311 // otherwise set the cancelBubble property of the original event to true (IE)
3312 e.cancelBubble = true;
3313 },
3314 stopImmediatePropagation: function() {
3315 this.isImmediatePropagationStopped = returnTrue;
3316 this.stopPropagation();
3317 },
3318 isDefaultPrevented: returnFalse,
3319 isPropagationStopped: returnFalse,
3320 isImmediatePropagationStopped: returnFalse
3321 };
3322
3323 // Create mouseenter/leave events using mouseover/out and event-time checks
3324 jQuery.each({
3325 mouseenter: "mouseover",
3326 mouseleave: "mouseout"
3327 }, function( orig, fix ) {
3328 jQuery.event.special[ orig ] = {
3329 delegateType: fix,
3330 bindType: fix,
3331
3332 handle: function( event ) {
3333 var ret,
3334 target = this,
3335 related = event.relatedTarget,
3336 handleObj = event.handleObj,
3337 selector = handleObj.selector;
3338
3339 // For mousenter/leave call the handler if related is outside the target.
3340 // NB: No relatedTarget if the mouse left/entered the browser window
3341 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3342 event.type = handleObj.origType;
3343 ret = handleObj.handler.apply( this, arguments );
3344 event.type = fix;
3345 }
3346 return ret;
3347 }
3348 };
3349 });
3350
3351 // IE submit delegation
3352 if ( !jQuery.support.submitBubbles ) {
3353
3354 jQuery.event.special.submit = {
3355 setup: function() {
3356 // Only need this for delegated form submit events
3357 if ( jQuery.nodeName( this, "form" ) ) {
3358 return false;
3359 }
3360
3361 // Lazy-add a submit handler when a descendant form may potentially be submitted
3362 jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
3363 // Node name check avoids a VML-related crash in IE (#9807)
3364 var elem = e.target,
3365 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
3366 if ( form && !jQuery._data( form, "_submit_attached" ) ) {
3367 jQuery.event.add( form, "submit._submit", function( event ) {
3368 event._submit_bubble = true;
3369 });
3370 jQuery._data( form, "_submit_attached", true );
3371 }
3372 });
3373 // return undefined since we don't need an event listener
3374 },
3375
3376 postDispatch: function( event ) {
3377 // If form was submitted by the user, bubble the event up the tree
3378 if ( event._submit_bubble ) {
3379 delete event._submit_bubble;
3380 if ( this.parentNode && !event.isTrigger ) {
3381 jQuery.event.simulate( "submit", this.parentNode, event, true );
3382 }
3383 }
3384 },
3385
3386 teardown: function() {
3387 // Only need this for delegated form submit events
3388 if ( jQuery.nodeName( this, "form" ) ) {
3389 return false;
3390 }
3391
3392 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
3393 jQuery.event.remove( this, "._submit" );
3394 }
3395 };
3396 }
3397
3398 // IE change delegation and checkbox/radio fix
3399 if ( !jQuery.support.changeBubbles ) {
3400
3401 jQuery.event.special.change = {
3402
3403 setup: function() {
3404
3405 if ( rformElems.test( this.nodeName ) ) {
3406 // IE doesn't fire change on a check/radio until blur; trigger it on click
3407 // after a propertychange. Eat the blur-change in special.change.handle.
3408 // This still fires onchange a second time for check/radio after blur.
3409 if ( this.type === "checkbox" || this.type === "radio" ) {
3410 jQuery.event.add( this, "propertychange._change", function( event ) {
3411 if ( event.originalEvent.propertyName === "checked" ) {
3412 this._just_changed = true;
3413 }
3414 });
3415 jQuery.event.add( this, "click._change", function( event ) {
3416 if ( this._just_changed && !event.isTrigger ) {
3417 this._just_changed = false;
3418 }
3419 // Allow triggered, simulated change events (#11500)
3420 jQuery.event.simulate( "change", this, event, true );
3421 });
3422 }
3423 return false;
3424 }
3425 // Delegated event; lazy-add a change handler on descendant inputs
3426 jQuery.event.add( this, "beforeactivate._change", function( e ) {
3427 var elem = e.target;
3428
3429 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) {
3430 jQuery.event.add( elem, "change._change", function( event ) {
3431 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
3432 jQuery.event.simulate( "change", this.parentNode, event, true );
3433 }
3434 });
3435 jQuery._data( elem, "_change_attached", true );
3436 }
3437 });
3438 },
3439
3440 handle: function( event ) {
3441 var elem = event.target;
3442
3443 // Swallow native change events from checkbox/radio, we already triggered them above
3444 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
3445 return event.handleObj.handler.apply( this, arguments );
3446 }
3447 },
3448
3449 teardown: function() {
3450 jQuery.event.remove( this, "._change" );
3451
3452 return !rformElems.test( this.nodeName );
3453 }
3454 };
3455 }
3456
3457 // Create "bubbling" focus and blur events
3458 if ( !jQuery.support.focusinBubbles ) {
3459 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
3460
3461 // Attach a single capturing handler while someone wants focusin/focusout
3462 var attaches = 0,
3463 handler = function( event ) {
3464 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
3465 };
3466
3467 jQuery.event.special[ fix ] = {
3468 setup: function() {
3469 if ( attaches++ === 0 ) {
3470 document.addEventListener( orig, handler, true );
3471 }
3472 },
3473 teardown: function() {
3474 if ( --attaches === 0 ) {
3475 document.removeEventListener( orig, handler, true );
3476 }
3477 }
3478 };
3479 });
3480 }
3481
3482 jQuery.fn.extend({
3483
3484 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
3485 var origFn, type;
3486
3487 // Types can be a map of types/handlers
3488 if ( typeof types === "object" ) {
3489 // ( types-Object, selector, data )
3490 if ( typeof selector !== "string" ) { // && selector != null
3491 // ( types-Object, data )
3492 data = data || selector;
3493 selector = undefined;
3494 }
3495 for ( type in types ) {
3496 this.on( type, selector, data, types[ type ], one );
3497 }
3498 return this;
3499 }
3500
3501 if ( data == null && fn == null ) {
3502 // ( types, fn )
3503 fn = selector;
3504 data = selector = undefined;
3505 } else if ( fn == null ) {
3506 if ( typeof selector === "string" ) {
3507 // ( types, selector, fn )
3508 fn = data;
3509 data = undefined;
3510 } else {
3511 // ( types, data, fn )
3512 fn = data;
3513 data = selector;
3514 selector = undefined;
3515 }
3516 }
3517 if ( fn === false ) {
3518 fn = returnFalse;
3519 } else if ( !fn ) {
3520 return this;
3521 }
3522
3523 if ( one === 1 ) {
3524 origFn = fn;
3525 fn = function( event ) {
3526 // Can use an empty set, since event contains the info
3527 jQuery().off( event );
3528 return origFn.apply( this, arguments );
3529 };
3530 // Use same guid so caller can remove using origFn
3531 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
3532 }
3533 return this.each( function() {
3534 jQuery.event.add( this, types, fn, data, selector );
3535 });
3536 },
3537 one: function( types, selector, data, fn ) {
3538 return this.on( types, selector, data, fn, 1 );
3539 },
3540 off: function( types, selector, fn ) {
3541 var handleObj, type;
3542 if ( types && types.preventDefault && types.handleObj ) {
3543 // ( event ) dispatched jQuery.Event
3544 handleObj = types.handleObj;
3545 jQuery( types.delegateTarget ).off(
3546 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
3547 handleObj.selector,
3548 handleObj.handler
3549 );
3550 return this;
3551 }
3552 if ( typeof types === "object" ) {
3553 // ( types-object [, selector] )
3554 for ( type in types ) {
3555 this.off( type, selector, types[ type ] );
3556 }
3557 return this;
3558 }
3559 if ( selector === false || typeof selector === "function" ) {
3560 // ( types [, fn] )
3561 fn = selector;
3562 selector = undefined;
3563 }
3564 if ( fn === false ) {
3565 fn = returnFalse;
3566 }
3567 return this.each(function() {
3568 jQuery.event.remove( this, types, fn, selector );
3569 });
3570 },
3571
3572 bind: function( types, data, fn ) {
3573 return this.on( types, null, data, fn );
3574 },
3575 unbind: function( types, fn ) {
3576 return this.off( types, null, fn );
3577 },
3578
3579 live: function( types, data, fn ) {
3580 jQuery( this.context ).on( types, this.selector, data, fn );
3581 return this;
3582 },
3583 die: function( types, fn ) {
3584 jQuery( this.context ).off( types, this.selector || "**", fn );
3585 return this;
3586 },
3587
3588 delegate: function( selector, types, data, fn ) {
3589 return this.on( types, selector, data, fn );
3590 },
3591 undelegate: function( selector, types, fn ) {
3592 // ( namespace ) or ( selector, types [, fn] )
3593 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3594 },
3595
3596 trigger: function( type, data ) {
3597 return this.each(function() {
3598 jQuery.event.trigger( type, data, this );
3599 });
3600 },
3601 triggerHandler: function( type, data ) {
3602 if ( this[0] ) {
3603 return jQuery.event.trigger( type, data, this[0], true );
3604 }
3605 },
3606
3607 toggle: function( fn ) {
3608 // Save reference to arguments for access in closure
3609 var args = arguments,
3610 guid = fn.guid || jQuery.guid++,
3611 i = 0,
3612 toggler = function( event ) {
3613 // Figure out which function to execute
3614 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
3615 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
3616
3617 // Make sure that clicks stop
3618 event.preventDefault();
3619
3620 // and execute the function
3621 return args[ lastToggle ].apply( this, arguments ) || false;
3622 };
3623
3624 // link all the functions, so any of them can unbind this click handler
3625 toggler.guid = guid;
3626 while ( i < args.length ) {
3627 args[ i++ ].guid = guid;
3628 }
3629
3630 return this.click( toggler );
3631 },
3632
3633 hover: function( fnOver, fnOut ) {
3634 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
3635 }
3636 });
3637
3638 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
3639 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
3640 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
3641
3642 // Handle event binding
3643 jQuery.fn[ name ] = function( data, fn ) {
3644 if ( fn == null ) {
3645 fn = data;
3646 data = null;
3647 }
3648
3649 return arguments.length > 0 ?
3650 this.on( name, null, data, fn ) :
3651 this.trigger( name );
3652 };
3653
3654 if ( rkeyEvent.test( name ) ) {
3655 jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
3656 }
3657
3658 if ( rmouseEvent.test( name ) ) {
3659 jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
3660 }
3661 });
3662 /*!
3663 * Sizzle CSS Selector Engine
3664 * Copyright 2012 jQuery Foundation and other contributors
3665 * Released under the MIT license
3666 * http://sizzlejs.com/
3667 */
3668 (function( window, undefined ) {
3669
3670 var cachedruns,
3671 assertGetIdNotName,
3672 Expr,
3673 getText,
3674 isXML,
3675 contains,
3676 compile,
3677 sortOrder,
3678 hasDuplicate,
3679 outermostContext,
3680
3681 baseHasDuplicate = true,
3682 strundefined = "undefined",
3683
3684 expando = ( "sizcache" + Math.random() ).replace( ".", "" ),
3685
3686 Token = String,
3687 document = window.document,
3688 docElem = document.documentElement,
3689 dirruns = 0,
3690 done = 0,
3691 pop = [].pop,
3692 push = [].push,
3693 slice = [].slice,
3694 // Use a stripped-down indexOf if a native one is unavailable
3695 indexOf = [].indexOf || function( elem ) {
3696 var i = 0,
3697 len = this.length;
3698 for ( ; i < len; i++ ) {
3699 if ( this[i] === elem ) {
3700 return i;
3701 }
3702 }
3703 return -1;
3704 },
3705
3706 // Augment a function for special use by Sizzle
3707 markFunction = function( fn, value ) {
3708 fn[ expando ] = value == null || value;
3709 return fn;
3710 },
3711
3712 createCache = function() {
3713 var cache = {},
3714 keys = [];
3715
3716 return markFunction(function( key, value ) {
3717 // Only keep the most recent entries
3718 if ( keys.push( key ) > Expr.cacheLength ) {
3719 delete cache[ keys.shift() ];
3720 }
3721
3722 // Retrieve with (key + " ") to avoid collision with native Object.prototype properties (see Issue #157)
3723 return (cache[ key + " " ] = value);
3724 }, cache );
3725 },
3726
3727 classCache = createCache(),
3728 tokenCache = createCache(),
3729 compilerCache = createCache(),
3730
3731 // Regex
3732
3733 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
3734 whitespace = "[\\x20\\t\\r\\n\\f]",
3735 // http://www.w3.org/TR/css3-syntax/#characters
3736 characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",
3737
3738 // Loosely modeled on CSS identifier characters
3739 // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors)
3740 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
3741 identifier = characterEncoding.replace( "w", "w#" ),
3742
3743 // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
3744 operators = "([*^$|!~]?=)",
3745 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
3746 "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
3747
3748 // Prefer arguments not in parens/brackets,
3749 // then attribute selectors and non-pseudos (denoted by :),
3750 // then anything else
3751 // These preferences are here to reduce the number of selectors
3752 // needing tokenize in the PSEUDO preFilter
3753 pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)",
3754
3755 // For matchExpr.POS and matchExpr.needsContext
3756 pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace +
3757 "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)",
3758
3759 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
3760 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
3761
3762 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
3763 rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
3764 rpseudo = new RegExp( pseudos ),
3765
3766 // Easily-parseable/retrievable ID or TAG or CLASS selectors
3767 rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,
3768
3769 rnot = /^:not/,
3770 rsibling = /[\x20\t\r\n\f]*[+~]/,
3771 rendsWithNot = /:not\($/,
3772
3773 rheader = /h\d/i,
3774 rinputs = /input|select|textarea|button/i,
3775
3776 rbackslash = /\\(?!\\)/g,
3777
3778 matchExpr = {
3779 "ID": new RegExp( "^#(" + characterEncoding + ")" ),
3780 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
3781 "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
3782 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
3783 "ATTR": new RegExp( "^" + attributes ),
3784 "PSEUDO": new RegExp( "^" + pseudos ),
3785 "POS": new RegExp( pos, "i" ),
3786 "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace +
3787 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
3788 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
3789 // For use in libraries implementing .is()
3790 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" )
3791 },
3792
3793 // Support
3794
3795 // Used for testing something on an element
3796 assert = function( fn ) {
3797 var div = document.createElement("div");
3798
3799 try {
3800 return fn( div );
3801 } catch (e) {
3802 return false;
3803 } finally {
3804 // release memory in IE
3805 div = null;
3806 }
3807 },
3808
3809 // Check if getElementsByTagName("*") returns only elements
3810 assertTagNameNoComments = assert(function( div ) {
3811 div.appendChild( document.createComment("") );
3812 return !div.getElementsByTagName("*").length;
3813 }),
3814
3815 // Check if getAttribute returns normalized href attributes
3816 assertHrefNotNormalized = assert(function( div ) {
3817 div.innerHTML = "<a href='#'></a>";
3818 return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
3819 div.firstChild.getAttribute("href") === "#";
3820 }),
3821
3822 // Check if attributes should be retrieved by attribute nodes
3823 assertAttributes = assert(function( div ) {
3824 div.innerHTML = "<select></select>";
3825 var type = typeof div.lastChild.getAttribute("multiple");
3826 // IE8 returns a string for some attributes even when not present
3827 return type !== "boolean" && type !== "string";
3828 }),
3829
3830 // Check if getElementsByClassName can be trusted
3831 assertUsableClassName = assert(function( div ) {
3832 // Opera can't find a second classname (in 9.6)
3833 div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
3834 if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
3835 return false;
3836 }
3837
3838 // Safari 3.2 caches class attributes and doesn't catch changes
3839 div.lastChild.className = "e";
3840 return div.getElementsByClassName("e").length === 2;
3841 }),
3842
3843 // Check if getElementById returns elements by name
3844 // Check if getElementsByName privileges form controls or returns elements by ID
3845 assertUsableName = assert(function( div ) {
3846 // Inject content
3847 div.id = expando + 0;
3848 div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
3849 docElem.insertBefore( div, docElem.firstChild );
3850
3851 // Test
3852 var pass = document.getElementsByName &&
3853 // buggy browsers will return fewer than the correct 2
3854 document.getElementsByName( expando ).length === 2 +
3855 // buggy browsers will return more than the correct 0
3856 document.getElementsByName( expando + 0 ).length;
3857 assertGetIdNotName = !document.getElementById( expando );
3858
3859 // Cleanup
3860 docElem.removeChild( div );
3861
3862 return pass;
3863 });
3864
3865 // If slice is not available, provide a backup
3866 try {
3867 slice.call( docElem.childNodes, 0 )[0].nodeType;
3868 } catch ( e ) {
3869 slice = function( i ) {
3870 var elem,
3871 results = [];
3872 for ( ; (elem = this[i]); i++ ) {
3873 results.push( elem );
3874 }
3875 return results;
3876 };
3877 }
3878
3879 function Sizzle( selector, context, results, seed ) {
3880 results = results || [];
3881 context = context || document;
3882 var match, elem, xml, m,
3883 nodeType = context.nodeType;
3884
3885 if ( !selector || typeof selector !== "string" ) {
3886 return results;
3887 }
3888
3889 if ( nodeType !== 1 && nodeType !== 9 ) {
3890 return [];
3891 }
3892
3893 xml = isXML( context );
3894
3895 if ( !xml && !seed ) {
3896 if ( (match = rquickExpr.exec( selector )) ) {
3897 // Speed-up: Sizzle("#ID")
3898 if ( (m = match[1]) ) {
3899 if ( nodeType === 9 ) {
3900 elem = context.getElementById( m );
3901 // Check parentNode to catch when Blackberry 4.6 returns
3902 // nodes that are no longer in the document #6963
3903 if ( elem && elem.parentNode ) {
3904 // Handle the case where IE, Opera, and Webkit return items
3905 // by name instead of ID
3906 if ( elem.id === m ) {
3907 results.push( elem );
3908 return results;
3909 }
3910 } else {
3911 return results;
3912 }
3913 } else {
3914 // Context is not a document
3915 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
3916 contains( context, elem ) && elem.id === m ) {
3917 results.push( elem );
3918 return results;
3919 }
3920 }
3921
3922 // Speed-up: Sizzle("TAG")
3923 } else if ( match[2] ) {
3924 push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
3925 return results;
3926
3927 // Speed-up: Sizzle(".CLASS")
3928 } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) {
3929 push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
3930 return results;
3931 }
3932 }
3933 }
3934
3935 // All others
3936 return select( selector.replace( rtrim, "$1" ), context, results, seed, xml );
3937 }
3938
3939 Sizzle.matches = function( expr, elements ) {
3940 return Sizzle( expr, null, null, elements );
3941 };
3942
3943 Sizzle.matchesSelector = function( elem, expr ) {
3944 return Sizzle( expr, null, null, [ elem ] ).length > 0;
3945 };
3946
3947 // Returns a function to use in pseudos for input types
3948 function createInputPseudo( type ) {
3949 return function( elem ) {
3950 var name = elem.nodeName.toLowerCase();
3951 return name === "input" && elem.type === type;
3952 };
3953 }
3954
3955 // Returns a function to use in pseudos for buttons
3956 function createButtonPseudo( type ) {
3957 return function( elem ) {
3958 var name = elem.nodeName.toLowerCase();
3959 return (name === "input" || name === "button") && elem.type === type;
3960 };
3961 }
3962
3963 // Returns a function to use in pseudos for positionals
3964 function createPositionalPseudo( fn ) {
3965 return markFunction(function( argument ) {
3966 argument = +argument;
3967 return markFunction(function( seed, matches ) {
3968 var j,
3969 matchIndexes = fn( [], seed.length, argument ),
3970 i = matchIndexes.length;
3971
3972 // Match elements found at the specified indexes
3973 while ( i-- ) {
3974 if ( seed[ (j = matchIndexes[i]) ] ) {
3975 seed[j] = !(matches[j] = seed[j]);
3976 }
3977 }
3978 });
3979 });
3980 }
3981
3982 /**
3983 * Utility function for retrieving the text value of an array of DOM nodes
3984 * @param {Array|Element} elem
3985 */
3986 getText = Sizzle.getText = function( elem ) {
3987 var node,
3988 ret = "",
3989 i = 0,
3990 nodeType = elem.nodeType;
3991
3992 if ( nodeType ) {
3993 if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
3994 // Use textContent for elements
3995 // innerText usage removed for consistency of new lines (see #11153)
3996 if ( typeof elem.textContent === "string" ) {
3997 return elem.textContent;
3998 } else {
3999 // Traverse its children
4000 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4001 ret += getText( elem );
4002 }
4003 }
4004 } else if ( nodeType === 3 || nodeType === 4 ) {
4005 return elem.nodeValue;
4006 }
4007 // Do not include comment or processing instruction nodes
4008 } else {
4009
4010 // If no nodeType, this is expected to be an array
4011 for ( ; (node = elem[i]); i++ ) {
4012 // Do not traverse comment nodes
4013 ret += getText( node );
4014 }
4015 }
4016 return ret;
4017 };
4018
4019 isXML = Sizzle.isXML = function( elem ) {
4020 // documentElement is verified for cases where it doesn't yet exist
4021 // (such as loading iframes in IE - #4833)
4022 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4023 return documentElement ? documentElement.nodeName !== "HTML" : false;
4024 };
4025
4026 // Element contains another
4027 contains = Sizzle.contains = docElem.contains ?
4028 function( a, b ) {
4029 var adown = a.nodeType === 9 ? a.documentElement : a,
4030 bup = b && b.parentNode;
4031 return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) );
4032 } :
4033 docElem.compareDocumentPosition ?
4034 function( a, b ) {
4035 return b && !!( a.compareDocumentPosition( b ) & 16 );
4036 } :
4037 function( a, b ) {
4038 while ( (b = b.parentNode) ) {
4039 if ( b === a ) {
4040 return true;
4041 }
4042 }
4043 return false;
4044 };
4045
4046 Sizzle.attr = function( elem, name ) {
4047 var val,
4048 xml = isXML( elem );
4049
4050 if ( !xml ) {
4051 name = name.toLowerCase();
4052 }
4053 if ( (val = Expr.attrHandle[ name ]) ) {
4054 return val( elem );
4055 }
4056 if ( xml || assertAttributes ) {
4057 return elem.getAttribute( name );
4058 }
4059 val = elem.getAttributeNode( name );
4060 return val ?
4061 typeof elem[ name ] === "boolean" ?
4062 elem[ name ] ? name : null :
4063 val.specified ? val.value : null :
4064 null;
4065 };
4066
4067 Expr = Sizzle.selectors = {
4068
4069 // Can be adjusted by the user
4070 cacheLength: 50,
4071
4072 createPseudo: markFunction,
4073
4074 match: matchExpr,
4075
4076 // IE6/7 return a modified href
4077 attrHandle: assertHrefNotNormalized ?
4078 {} :
4079 {
4080 "href": function( elem ) {
4081 return elem.getAttribute( "href", 2 );
4082 },
4083 "type": function( elem ) {
4084 return elem.getAttribute("type");
4085 }
4086 },
4087
4088 find: {
4089 "ID": assertGetIdNotName ?
4090 function( id, context, xml ) {
4091 if ( typeof context.getElementById !== strundefined && !xml ) {
4092 var m = context.getElementById( id );
4093 // Check parentNode to catch when Blackberry 4.6 returns
4094 // nodes that are no longer in the document #6963
4095 return m && m.parentNode ? [m] : [];
4096 }
4097 } :
4098 function( id, context, xml ) {
4099 if ( typeof context.getElementById !== strundefined && !xml ) {
4100 var m = context.getElementById( id );
4101
4102 return m ?
4103 m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
4104 [m] :
4105 undefined :
4106 [];
4107 }
4108 },
4109
4110 "TAG": assertTagNameNoComments ?
4111 function( tag, context ) {
4112 if ( typeof context.getElementsByTagName !== strundefined ) {
4113 return context.getElementsByTagName( tag );
4114 }
4115 } :
4116 function( tag, context ) {
4117 var results = context.getElementsByTagName( tag );
4118
4119 // Filter out possible comments
4120 if ( tag === "*" ) {
4121 var elem,
4122 tmp = [],
4123 i = 0;
4124
4125 for ( ; (elem = results[i]); i++ ) {
4126 if ( elem.nodeType === 1 ) {
4127 tmp.push( elem );
4128 }
4129 }
4130
4131 return tmp;
4132 }
4133 return results;
4134 },
4135
4136 "NAME": assertUsableName && function( tag, context ) {
4137 if ( typeof context.getElementsByName !== strundefined ) {
4138 return context.getElementsByName( name );
4139 }
4140 },
4141
4142 "CLASS": assertUsableClassName && function( className, context, xml ) {
4143 if ( typeof context.getElementsByClassName !== strundefined && !xml ) {
4144 return context.getElementsByClassName( className );
4145 }
4146 }
4147 },
4148
4149 relative: {
4150 ">": { dir: "parentNode", first: true },
4151 " ": { dir: "parentNode" },
4152 "+": { dir: "previousSibling", first: true },
4153 "~": { dir: "previousSibling" }
4154 },
4155
4156 preFilter: {
4157 "ATTR": function( match ) {
4158 match[1] = match[1].replace( rbackslash, "" );
4159
4160 // Move the given value to match[3] whether quoted or unquoted
4161 match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" );
4162
4163 if ( match[2] === "~=" ) {
4164 match[3] = " " + match[3] + " ";
4165 }
4166
4167 return match.slice( 0, 4 );
4168 },
4169
4170 "CHILD": function( match ) {
4171 /* matches from matchExpr["CHILD"]
4172 1 type (only|nth|...)
4173 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4174 3 xn-component of xn+y argument ([+-]?\d*n|)
4175 4 sign of xn-component
4176 5 x of xn-component
4177 6 sign of y-component
4178 7 y of y-component
4179 */
4180 match[1] = match[1].toLowerCase();
4181
4182 if ( match[1] === "nth" ) {
4183 // nth-child requires argument
4184 if ( !match[2] ) {
4185 Sizzle.error( match[0] );
4186 }
4187
4188 // numeric x and y parameters for Expr.filter.CHILD
4189 // remember that false/true cast respectively to 0/1
4190 match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) );
4191 match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" );
4192
4193 // other types prohibit arguments
4194 } else if ( match[2] ) {
4195 Sizzle.error( match[0] );
4196 }
4197
4198 return match;
4199 },
4200
4201 "PSEUDO": function( match ) {
4202 var unquoted, excess;
4203 if ( matchExpr["CHILD"].test( match[0] ) ) {
4204 return null;
4205 }
4206
4207 if ( match[3] ) {
4208 match[2] = match[3];
4209 } else if ( (unquoted = match[4]) ) {
4210 // Only check arguments that contain a pseudo
4211 if ( rpseudo.test(unquoted) &&
4212 // Get excess from tokenize (recursively)
4213 (excess = tokenize( unquoted, true )) &&
4214 // advance to the next closing parenthesis
4215 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
4216
4217 // excess is a negative index
4218 unquoted = unquoted.slice( 0, excess );
4219 match[0] = match[0].slice( 0, excess );
4220 }
4221 match[2] = unquoted;
4222 }
4223
4224 // Return only captures needed by the pseudo filter method (type and argument)
4225 return match.slice( 0, 3 );
4226 }
4227 },
4228
4229 filter: {
4230 "ID": assertGetIdNotName ?
4231 function( id ) {
4232 id = id.replace( rbackslash, "" );
4233 return function( elem ) {
4234 return elem.getAttribute("id") === id;
4235 };
4236 } :
4237 function( id ) {
4238 id = id.replace( rbackslash, "" );
4239 return function( elem ) {
4240 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
4241 return node && node.value === id;
4242 };
4243 },
4244
4245 "TAG": function( nodeName ) {
4246 if ( nodeName === "*" ) {
4247 return function() { return true; };
4248 }
4249 nodeName = nodeName.replace( rbackslash, "" ).toLowerCase();
4250
4251 return function( elem ) {
4252 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
4253 };
4254 },
4255
4256 "CLASS": function( className ) {
4257 var pattern = classCache[ expando ][ className + " " ];
4258
4259 return pattern ||
4260 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
4261 classCache( className, function( elem ) {
4262 return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
4263 });
4264 },
4265
4266 "ATTR": function( name, operator, check ) {
4267 return function( elem, context ) {
4268 var result = Sizzle.attr( elem, name );
4269
4270 if ( result == null ) {
4271 return operator === "!=";
4272 }
4273 if ( !operator ) {
4274 return true;
4275 }
4276
4277 result += "";
4278
4279 return operator === "=" ? result === check :
4280 operator === "!=" ? result !== check :
4281 operator === "^=" ? check && result.indexOf( check ) === 0 :
4282 operator === "*=" ? check && result.indexOf( check ) > -1 :
4283 operator === "$=" ? check && result.substr( result.length - check.length ) === check :
4284 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
4285 operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" :
4286 false;
4287 };
4288 },
4289
4290 "CHILD": function( type, argument, first, last ) {
4291
4292 if ( type === "nth" ) {
4293 return function( elem ) {
4294 var node, diff,
4295 parent = elem.parentNode;
4296
4297 if ( first === 1 && last === 0 ) {
4298 return true;
4299 }
4300
4301 if ( parent ) {
4302 diff = 0;
4303 for ( node = parent.firstChild; node; node = node.nextSibling ) {
4304 if ( node.nodeType === 1 ) {
4305 diff++;
4306 if ( elem === node ) {
4307 break;
4308 }
4309 }
4310 }
4311 }
4312
4313 // Incorporate the offset (or cast to NaN), then check against cycle size
4314 diff -= last;
4315 return diff === first || ( diff % first === 0 && diff / first >= 0 );
4316 };
4317 }
4318
4319 return function( elem ) {
4320 var node = elem;
4321
4322 switch ( type ) {
4323 case "only":
4324 case "first":
4325 while ( (node = node.previousSibling) ) {
4326 if ( node.nodeType === 1 ) {
4327 return false;
4328 }
4329 }
4330
4331 if ( type === "first" ) {
4332 return true;
4333 }
4334
4335 node = elem;
4336
4337 /* falls through */
4338 case "last":
4339 while ( (node = node.nextSibling) ) {
4340 if ( node.nodeType === 1 ) {
4341 return false;
4342 }
4343 }
4344
4345 return true;
4346 }
4347 };
4348 },
4349
4350 "PSEUDO": function( pseudo, argument ) {
4351 // pseudo-class names are case-insensitive
4352 // http://www.w3.org/TR/selectors/#pseudo-classes
4353 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
4354 // Remember that setFilters inherits from pseudos
4355 var args,
4356 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
4357 Sizzle.error( "unsupported pseudo: " + pseudo );
4358
4359 // The user may use createPseudo to indicate that
4360 // arguments are needed to create the filter function
4361 // just as Sizzle does
4362 if ( fn[ expando ] ) {
4363 return fn( argument );
4364 }
4365
4366 // But maintain support for old signatures
4367 if ( fn.length > 1 ) {
4368 args = [ pseudo, pseudo, "", argument ];
4369 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
4370 markFunction(function( seed, matches ) {
4371 var idx,
4372 matched = fn( seed, argument ),
4373 i = matched.length;
4374 while ( i-- ) {
4375 idx = indexOf.call( seed, matched[i] );
4376 seed[ idx ] = !( matches[ idx ] = matched[i] );
4377 }
4378 }) :
4379 function( elem ) {
4380 return fn( elem, 0, args );
4381 };
4382 }
4383
4384 return fn;
4385 }
4386 },
4387
4388 pseudos: {
4389 "not": markFunction(function( selector ) {
4390 // Trim the selector passed to compile
4391 // to avoid treating leading and trailing
4392 // spaces as combinators
4393 var input = [],
4394 results = [],
4395 matcher = compile( selector.replace( rtrim, "$1" ) );
4396
4397 return matcher[ expando ] ?
4398 markFunction(function( seed, matches, context, xml ) {
4399 var elem,
4400 unmatched = matcher( seed, null, xml, [] ),
4401 i = seed.length;
4402
4403 // Match elements unmatched by `matcher`
4404 while ( i-- ) {
4405 if ( (elem = unmatched[i]) ) {
4406 seed[i] = !(matches[i] = elem);
4407 }
4408 }
4409 }) :
4410 function( elem, context, xml ) {
4411 input[0] = elem;
4412 matcher( input, null, xml, results );
4413 return !results.pop();
4414 };
4415 }),
4416
4417 "has": markFunction(function( selector ) {
4418 return function( elem ) {
4419 return Sizzle( selector, elem ).length > 0;
4420 };
4421 }),
4422
4423 "contains": markFunction(function( text ) {
4424 return function( elem ) {
4425 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
4426 };
4427 }),
4428
4429 "enabled": function( elem ) {
4430 return elem.disabled === false;
4431 },
4432
4433 "disabled": function( elem ) {
4434 return elem.disabled === true;
4435 },
4436
4437 "checked": function( elem ) {
4438 // In CSS3, :checked should return both checked and selected elements
4439 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4440 var nodeName = elem.nodeName.toLowerCase();
4441 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
4442 },
4443
4444 "selected": function( elem ) {
4445 // Accessing this property makes selected-by-default
4446 // options in Safari work properly
4447 if ( elem.parentNode ) {
4448 elem.parentNode.selectedIndex;
4449 }
4450
4451 return elem.selected === true;
4452 },
4453
4454 "parent": function( elem ) {
4455 return !Expr.pseudos["empty"]( elem );
4456 },
4457
4458 "empty": function( elem ) {
4459 // http://www.w3.org/TR/selectors/#empty-pseudo
4460 // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
4461 // not comment, processing instructions, or others
4462 // Thanks to Diego Perini for the nodeName shortcut
4463 // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
4464 var nodeType;
4465 elem = elem.firstChild;
4466 while ( elem ) {
4467 if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) {
4468 return false;
4469 }
4470 elem = elem.nextSibling;
4471 }
4472 return true;
4473 },
4474
4475 "header": function( elem ) {
4476 return rheader.test( elem.nodeName );
4477 },
4478
4479 "text": function( elem ) {
4480 var type, attr;
4481 // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
4482 // use getAttribute instead to test this case
4483 return elem.nodeName.toLowerCase() === "input" &&
4484 (type = elem.type) === "text" &&
4485 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type );
4486 },
4487
4488 // Input types
4489 "radio": createInputPseudo("radio"),
4490 "checkbox": createInputPseudo("checkbox"),
4491 "file": createInputPseudo("file"),
4492 "password": createInputPseudo("password"),
4493 "image": createInputPseudo("image"),
4494
4495 "submit": createButtonPseudo("submit"),
4496 "reset": createButtonPseudo("reset"),
4497
4498 "button": function( elem ) {
4499 var name = elem.nodeName.toLowerCase();
4500 return name === "input" && elem.type === "button" || name === "button";
4501 },
4502
4503 "input": function( elem ) {
4504 return rinputs.test( elem.nodeName );
4505 },
4506
4507 "focus": function( elem ) {
4508 var doc = elem.ownerDocument;
4509 return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
4510 },
4511
4512 "active": function( elem ) {
4513 return elem === elem.ownerDocument.activeElement;
4514 },
4515
4516 // Positional types
4517 "first": createPositionalPseudo(function() {
4518 return [ 0 ];
4519 }),
4520
4521 "last": createPositionalPseudo(function( matchIndexes, length ) {
4522 return [ length - 1 ];
4523 }),
4524
4525 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
4526 return [ argument < 0 ? argument + length : argument ];
4527 }),
4528
4529 "even": createPositionalPseudo(function( matchIndexes, length ) {
4530 for ( var i = 0; i < length; i += 2 ) {
4531 matchIndexes.push( i );
4532 }
4533 return matchIndexes;
4534 }),
4535
4536 "odd": createPositionalPseudo(function( matchIndexes, length ) {
4537 for ( var i = 1; i < length; i += 2 ) {
4538 matchIndexes.push( i );
4539 }
4540 return matchIndexes;
4541 }),
4542
4543 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4544 for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) {
4545 matchIndexes.push( i );
4546 }
4547 return matchIndexes;
4548 }),
4549
4550 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4551 for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) {
4552 matchIndexes.push( i );
4553 }
4554 return matchIndexes;
4555 })
4556 }
4557 };
4558
4559 function siblingCheck( a, b, ret ) {
4560 if ( a === b ) {
4561 return ret;
4562 }
4563
4564 var cur = a.nextSibling;
4565
4566 while ( cur ) {
4567 if ( cur === b ) {
4568 return -1;
4569 }
4570
4571 cur = cur.nextSibling;
4572 }
4573
4574 return 1;
4575 }
4576
4577 sortOrder = docElem.compareDocumentPosition ?
4578 function( a, b ) {
4579 if ( a === b ) {
4580 hasDuplicate = true;
4581 return 0;
4582 }
4583
4584 return ( !a.compareDocumentPosition || !b.compareDocumentPosition ?
4585 a.compareDocumentPosition :
4586 a.compareDocumentPosition(b) & 4
4587 ) ? -1 : 1;
4588 } :
4589 function( a, b ) {
4590 // The nodes are identical, we can exit early
4591 if ( a === b ) {
4592 hasDuplicate = true;
4593 return 0;
4594
4595 // Fallback to using sourceIndex (in IE) if it's available on both nodes
4596 } else if ( a.sourceIndex && b.sourceIndex ) {
4597 return a.sourceIndex - b.sourceIndex;
4598 }
4599
4600 var al, bl,
4601 ap = [],
4602 bp = [],
4603 aup = a.parentNode,
4604 bup = b.parentNode,
4605 cur = aup;
4606
4607 // If the nodes are siblings (or identical) we can do a quick check
4608 if ( aup === bup ) {
4609 return siblingCheck( a, b );
4610
4611 // If no parents were found then the nodes are disconnected
4612 } else if ( !aup ) {
4613 return -1;
4614
4615 } else if ( !bup ) {
4616 return 1;
4617 }
4618
4619 // Otherwise they're somewhere else in the tree so we need
4620 // to build up a full list of the parentNodes for comparison
4621 while ( cur ) {
4622 ap.unshift( cur );
4623 cur = cur.parentNode;
4624 }
4625
4626 cur = bup;
4627
4628 while ( cur ) {
4629 bp.unshift( cur );
4630 cur = cur.parentNode;
4631 }
4632
4633 al = ap.length;
4634 bl = bp.length;
4635
4636 // Start walking down the tree looking for a discrepancy
4637 for ( var i = 0; i < al && i < bl; i++ ) {
4638 if ( ap[i] !== bp[i] ) {
4639 return siblingCheck( ap[i], bp[i] );
4640 }
4641 }
4642
4643 // We ended someplace up the tree so do a sibling check
4644 return i === al ?
4645 siblingCheck( a, bp[i], -1 ) :
4646 siblingCheck( ap[i], b, 1 );
4647 };
4648
4649 // Always assume the presence of duplicates if sort doesn't
4650 // pass them to our comparison function (as in Google Chrome).
4651 [0, 0].sort( sortOrder );
4652 baseHasDuplicate = !hasDuplicate;
4653
4654 // Document sorting and removing duplicates
4655 Sizzle.uniqueSort = function( results ) {
4656 var elem,
4657 duplicates = [],
4658 i = 1,
4659 j = 0;
4660
4661 hasDuplicate = baseHasDuplicate;
4662 results.sort( sortOrder );
4663
4664 if ( hasDuplicate ) {
4665 for ( ; (elem = results[i]); i++ ) {
4666 if ( elem === results[ i - 1 ] ) {
4667 j = duplicates.push( i );
4668 }
4669 }
4670 while ( j-- ) {
4671 results.splice( duplicates[ j ], 1 );
4672 }
4673 }
4674
4675 return results;
4676 };
4677
4678 Sizzle.error = function( msg ) {
4679 throw new Error( "Syntax error, unrecognized expression: " + msg );
4680 };
4681
4682 function tokenize( selector, parseOnly ) {
4683 var matched, match, tokens, type,
4684 soFar, groups, preFilters,
4685 cached = tokenCache[ expando ][ selector + " " ];
4686
4687 if ( cached ) {
4688 return parseOnly ? 0 : cached.slice( 0 );
4689 }
4690
4691 soFar = selector;
4692 groups = [];
4693 preFilters = Expr.preFilter;
4694
4695 while ( soFar ) {
4696
4697 // Comma and first run
4698 if ( !matched || (match = rcomma.exec( soFar )) ) {
4699 if ( match ) {
4700 // Don't consume trailing commas as valid
4701 soFar = soFar.slice( match[0].length ) || soFar;
4702 }
4703 groups.push( tokens = [] );
4704 }
4705
4706 matched = false;
4707
4708 // Combinators
4709 if ( (match = rcombinators.exec( soFar )) ) {
4710 tokens.push( matched = new Token( match.shift() ) );
4711 soFar = soFar.slice( matched.length );
4712
4713 // Cast descendant combinators to space
4714 matched.type = match[0].replace( rtrim, " " );
4715 }
4716
4717 // Filters
4718 for ( type in Expr.filter ) {
4719 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
4720 (match = preFilters[ type ]( match ))) ) {
4721
4722 tokens.push( matched = new Token( match.shift() ) );
4723 soFar = soFar.slice( matched.length );
4724 matched.type = type;
4725 matched.matches = match;
4726 }
4727 }
4728
4729 if ( !matched ) {
4730 break;
4731 }
4732 }
4733
4734 // Return the length of the invalid excess
4735 // if we're just parsing
4736 // Otherwise, throw an error or return tokens
4737 return parseOnly ?
4738 soFar.length :
4739 soFar ?
4740 Sizzle.error( selector ) :
4741 // Cache the tokens
4742 tokenCache( selector, groups ).slice( 0 );
4743 }
4744
4745 function addCombinator( matcher, combinator, base ) {
4746 var dir = combinator.dir,
4747 checkNonElements = base && combinator.dir === "parentNode",
4748 doneName = done++;
4749
4750 return combinator.first ?
4751 // Check against closest ancestor/preceding element
4752 function( elem, context, xml ) {
4753 while ( (elem = elem[ dir ]) ) {
4754 if ( checkNonElements || elem.nodeType === 1 ) {
4755 return matcher( elem, context, xml );
4756 }
4757 }
4758 } :
4759
4760 // Check against all ancestor/preceding elements
4761 function( elem, context, xml ) {
4762 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
4763 if ( !xml ) {
4764 var cache,
4765 dirkey = dirruns + " " + doneName + " ",
4766 cachedkey = dirkey + cachedruns;
4767 while ( (elem = elem[ dir ]) ) {
4768 if ( checkNonElements || elem.nodeType === 1 ) {
4769 if ( (cache = elem[ expando ]) === cachedkey ) {
4770 return elem.sizset;
4771 } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) {
4772 if ( elem.sizset ) {
4773 return elem;
4774 }
4775 } else {
4776 elem[ expando ] = cachedkey;
4777 if ( matcher( elem, context, xml ) ) {
4778 elem.sizset = true;
4779 return elem;
4780 }
4781 elem.sizset = false;
4782 }
4783 }
4784 }
4785 } else {
4786 while ( (elem = elem[ dir ]) ) {
4787 if ( checkNonElements || elem.nodeType === 1 ) {
4788 if ( matcher( elem, context, xml ) ) {
4789 return elem;
4790 }
4791 }
4792 }
4793 }
4794 };
4795 }
4796
4797 function elementMatcher( matchers ) {
4798 return matchers.length > 1 ?
4799 function( elem, context, xml ) {
4800 var i = matchers.length;
4801 while ( i-- ) {
4802 if ( !matchers[i]( elem, context, xml ) ) {
4803 return false;
4804 }
4805 }
4806 return true;
4807 } :
4808 matchers[0];
4809 }
4810
4811 function condense( unmatched, map, filter, context, xml ) {
4812 var elem,
4813 newUnmatched = [],
4814 i = 0,
4815 len = unmatched.length,
4816 mapped = map != null;
4817
4818 for ( ; i < len; i++ ) {
4819 if ( (elem = unmatched[i]) ) {
4820 if ( !filter || filter( elem, context, xml ) ) {
4821 newUnmatched.push( elem );
4822 if ( mapped ) {
4823 map.push( i );
4824 }
4825 }
4826 }
4827 }
4828
4829 return newUnmatched;
4830 }
4831
4832 function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
4833 if ( postFilter && !postFilter[ expando ] ) {
4834 postFilter = setMatcher( postFilter );
4835 }
4836 if ( postFinder && !postFinder[ expando ] ) {
4837 postFinder = setMatcher( postFinder, postSelector );
4838 }
4839 return markFunction(function( seed, results, context, xml ) {
4840 var temp, i, elem,
4841 preMap = [],
4842 postMap = [],
4843 preexisting = results.length,
4844
4845 // Get initial elements from seed or context
4846 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
4847
4848 // Prefilter to get matcher input, preserving a map for seed-results synchronization
4849 matcherIn = preFilter && ( seed || !selector ) ?
4850 condense( elems, preMap, preFilter, context, xml ) :
4851 elems,
4852
4853 matcherOut = matcher ?
4854 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
4855 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
4856
4857 // ...intermediate processing is necessary
4858 [] :
4859
4860 // ...otherwise use results directly
4861 results :
4862 matcherIn;
4863
4864 // Find primary matches
4865 if ( matcher ) {
4866 matcher( matcherIn, matcherOut, context, xml );
4867 }
4868
4869 // Apply postFilter
4870 if ( postFilter ) {
4871 temp = condense( matcherOut, postMap );
4872 postFilter( temp, [], context, xml );
4873
4874 // Un-match failing elements by moving them back to matcherIn
4875 i = temp.length;
4876 while ( i-- ) {
4877 if ( (elem = temp[i]) ) {
4878 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
4879 }
4880 }
4881 }
4882
4883 if ( seed ) {
4884 if ( postFinder || preFilter ) {
4885 if ( postFinder ) {
4886 // Get the final matcherOut by condensing this intermediate into postFinder contexts
4887 temp = [];
4888 i = matcherOut.length;
4889 while ( i-- ) {
4890 if ( (elem = matcherOut[i]) ) {
4891 // Restore matcherIn since elem is not yet a final match
4892 temp.push( (matcherIn[i] = elem) );
4893 }
4894 }
4895 postFinder( null, (matcherOut = []), temp, xml );
4896 }
4897
4898 // Move matched elements from seed to results to keep them synchronized
4899 i = matcherOut.length;
4900 while ( i-- ) {
4901 if ( (elem = matcherOut[i]) &&
4902 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
4903
4904 seed[temp] = !(results[temp] = elem);
4905 }
4906 }
4907 }
4908
4909 // Add elements to results, through postFinder if defined
4910 } else {
4911 matcherOut = condense(
4912 matcherOut === results ?
4913 matcherOut.splice( preexisting, matcherOut.length ) :
4914 matcherOut
4915 );
4916 if ( postFinder ) {
4917 postFinder( null, results, matcherOut, xml );
4918 } else {
4919 push.apply( results, matcherOut );
4920 }
4921 }
4922 });
4923 }
4924
4925 function matcherFromTokens( tokens ) {
4926 var checkContext, matcher, j,
4927 len = tokens.length,
4928 leadingRelative = Expr.relative[ tokens[0].type ],
4929 implicitRelative = leadingRelative || Expr.relative[" "],
4930 i = leadingRelative ? 1 : 0,
4931
4932 // The foundational matcher ensures that elements are reachable from top-level context(s)
4933 matchContext = addCombinator( function( elem ) {
4934 return elem === checkContext;
4935 }, implicitRelative, true ),
4936 matchAnyContext = addCombinator( function( elem ) {
4937 return indexOf.call( checkContext, elem ) > -1;
4938 }, implicitRelative, true ),
4939 matchers = [ function( elem, context, xml ) {
4940 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
4941 (checkContext = context).nodeType ?
4942 matchContext( elem, context, xml ) :
4943 matchAnyContext( elem, context, xml ) );
4944 } ];
4945
4946 for ( ; i < len; i++ ) {
4947 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
4948 matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
4949 } else {
4950 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
4951
4952 // Return special upon seeing a positional matcher
4953 if ( matcher[ expando ] ) {
4954 // Find the next relative operator (if any) for proper handling
4955 j = ++i;
4956 for ( ; j < len; j++ ) {
4957 if ( Expr.relative[ tokens[j].type ] ) {
4958 break;
4959 }
4960 }
4961 return setMatcher(
4962 i > 1 && elementMatcher( matchers ),
4963 i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ),
4964 matcher,
4965 i < j && matcherFromTokens( tokens.slice( i, j ) ),
4966 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
4967 j < len && tokens.join("")
4968 );
4969 }
4970 matchers.push( matcher );
4971 }
4972 }
4973
4974 return elementMatcher( matchers );
4975 }
4976
4977 function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
4978 var bySet = setMatchers.length > 0,
4979 byElement = elementMatchers.length > 0,
4980 superMatcher = function( seed, context, xml, results, expandContext ) {
4981 var elem, j, matcher,
4982 setMatched = [],
4983 matchedCount = 0,
4984 i = "0",
4985 unmatched = seed && [],
4986 outermost = expandContext != null,
4987 contextBackup = outermostContext,
4988 // We must always have either seed elements or context
4989 elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
4990 // Nested matchers should use non-integer dirruns
4991 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E);
4992
4993 if ( outermost ) {
4994 outermostContext = context !== document && context;
4995 cachedruns = superMatcher.el;
4996 }
4997
4998 // Add elements passing elementMatchers directly to results
4999 for ( ; (elem = elems[i]) != null; i++ ) {
5000 if ( byElement && elem ) {
5001 for ( j = 0; (matcher = elementMatchers[j]); j++ ) {
5002 if ( matcher( elem, context, xml ) ) {
5003 results.push( elem );
5004 break;
5005 }
5006 }
5007 if ( outermost ) {
5008 dirruns = dirrunsUnique;
5009 cachedruns = ++superMatcher.el;
5010 }
5011 }
5012
5013 // Track unmatched elements for set filters
5014 if ( bySet ) {
5015 // They will have gone through all possible matchers
5016 if ( (elem = !matcher && elem) ) {
5017 matchedCount--;
5018 }
5019
5020 // Lengthen the array for every element, matched or not
5021 if ( seed ) {
5022 unmatched.push( elem );
5023 }
5024 }
5025 }
5026
5027 // Apply set filters to unmatched elements
5028 matchedCount += i;
5029 if ( bySet && i !== matchedCount ) {
5030 for ( j = 0; (matcher = setMatchers[j]); j++ ) {
5031 matcher( unmatched, setMatched, context, xml );
5032 }
5033
5034 if ( seed ) {
5035 // Reintegrate element matches to eliminate the need for sorting
5036 if ( matchedCount > 0 ) {
5037 while ( i-- ) {
5038 if ( !(unmatched[i] || setMatched[i]) ) {
5039 setMatched[i] = pop.call( results );
5040 }
5041 }
5042 }
5043
5044 // Discard index placeholder values to get only actual matches
5045 setMatched = condense( setMatched );
5046 }
5047
5048 // Add matches to results
5049 push.apply( results, setMatched );
5050
5051 // Seedless set matches succeeding multiple successful matchers stipulate sorting
5052 if ( outermost && !seed && setMatched.length > 0 &&
5053 ( matchedCount + setMatchers.length ) > 1 ) {
5054
5055 Sizzle.uniqueSort( results );
5056 }
5057 }
5058
5059 // Override manipulation of globals by nested matchers
5060 if ( outermost ) {
5061 dirruns = dirrunsUnique;
5062 outermostContext = contextBackup;
5063 }
5064
5065 return unmatched;
5066 };
5067
5068 superMatcher.el = 0;
5069 return bySet ?
5070 markFunction( superMatcher ) :
5071 superMatcher;
5072 }
5073
5074 compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
5075 var i,
5076 setMatchers = [],
5077 elementMatchers = [],
5078 cached = compilerCache[ expando ][ selector + " " ];
5079
5080 if ( !cached ) {
5081 // Generate a function of recursive functions that can be used to check each element
5082 if ( !group ) {
5083 group = tokenize( selector );
5084 }
5085 i = group.length;
5086 while ( i-- ) {
5087 cached = matcherFromTokens( group[i] );
5088 if ( cached[ expando ] ) {
5089 setMatchers.push( cached );
5090 } else {
5091 elementMatchers.push( cached );
5092 }
5093 }
5094
5095 // Cache the compiled function
5096 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
5097 }
5098 return cached;
5099 };
5100
5101 function multipleContexts( selector, contexts, results ) {
5102 var i = 0,
5103 len = contexts.length;
5104 for ( ; i < len; i++ ) {
5105 Sizzle( selector, contexts[i], results );
5106 }
5107 return results;
5108 }
5109
5110 function select( selector, context, results, seed, xml ) {
5111 var i, tokens, token, type, find,
5112 match = tokenize( selector ),
5113 j = match.length;
5114
5115 if ( !seed ) {
5116 // Try to minimize operations if there is only one group
5117 if ( match.length === 1 ) {
5118
5119 // Take a shortcut and set the context if the root selector is an ID
5120 tokens = match[0] = match[0].slice( 0 );
5121 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
5122 context.nodeType === 9 && !xml &&
5123 Expr.relative[ tokens[1].type ] ) {
5124
5125 context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0];
5126 if ( !context ) {
5127 return results;
5128 }
5129
5130 selector = selector.slice( tokens.shift().length );
5131 }
5132
5133 // Fetch a seed set for right-to-left matching
5134 for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) {
5135 token = tokens[i];
5136
5137 // Abort if we hit a combinator
5138 if ( Expr.relative[ (type = token.type) ] ) {
5139 break;
5140 }
5141 if ( (find = Expr.find[ type ]) ) {
5142 // Search, expanding context for leading sibling combinators
5143 if ( (seed = find(
5144 token.matches[0].replace( rbackslash, "" ),
5145 rsibling.test( tokens[0].type ) && context.parentNode || context,
5146 xml
5147 )) ) {
5148
5149 // If seed is empty or no tokens remain, we can return early
5150 tokens.splice( i, 1 );
5151 selector = seed.length && tokens.join("");
5152 if ( !selector ) {
5153 push.apply( results, slice.call( seed, 0 ) );
5154 return results;
5155 }
5156
5157 break;
5158 }
5159 }
5160 }
5161 }
5162 }
5163
5164 // Compile and execute a filtering function
5165 // Provide `match` to avoid retokenization if we modified the selector above
5166 compile( selector, match )(
5167 seed,
5168 context,
5169 xml,
5170 results,
5171 rsibling.test( selector )
5172 );
5173 return results;
5174 }
5175
5176 if ( document.querySelectorAll ) {
5177 (function() {
5178 var disconnectedMatch,
5179 oldSelect = select,
5180 rescape = /'|\\/g,
5181 rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
5182
5183 // qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA
5184 // A support test would require too much code (would include document ready)
5185 rbuggyQSA = [ ":focus" ],
5186
5187 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
5188 // A support test would require too much code (would include document ready)
5189 // just skip matchesSelector for :active
5190 rbuggyMatches = [ ":active" ],
5191 matches = docElem.matchesSelector ||
5192 docElem.mozMatchesSelector ||
5193 docElem.webkitMatchesSelector ||
5194 docElem.oMatchesSelector ||
5195 docElem.msMatchesSelector;
5196
5197 // Build QSA regex
5198 // Regex strategy adopted from Diego Perini
5199 assert(function( div ) {
5200 // Select is set to empty string on purpose
5201 // This is to test IE's treatment of not explictly
5202 // setting a boolean content attribute,
5203 // since its presence should be enough
5204 // http://bugs.jquery.com/ticket/12359
5205 div.innerHTML = "<select><option selected=''></option></select>";
5206
5207 // IE8 - Some boolean attributes are not treated correctly
5208 if ( !div.querySelectorAll("[selected]").length ) {
5209 rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
5210 }
5211
5212 // Webkit/Opera - :checked should return selected option elements
5213 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
5214 // IE8 throws error here (do not put tests after this one)
5215 if ( !div.querySelectorAll(":checked").length ) {
5216 rbuggyQSA.push(":checked");
5217 }
5218 });
5219
5220 assert(function( div ) {
5221
5222 // Opera 10-12/IE9 - ^= $= *= and empty values
5223 // Should not select anything
5224 div.innerHTML = "<p test=''></p>";
5225 if ( div.querySelectorAll("[test^='']").length ) {
5226 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
5227 }
5228
5229 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
5230 // IE8 throws error here (do not put tests after this one)
5231 div.innerHTML = "<input type='hidden'/>";
5232 if ( !div.querySelectorAll(":enabled").length ) {
5233 rbuggyQSA.push(":enabled", ":disabled");
5234 }
5235 });
5236
5237 // rbuggyQSA always contains :focus, so no need for a length check
5238 rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") );
5239
5240 select = function( selector, context, results, seed, xml ) {
5241 // Only use querySelectorAll when not filtering,
5242 // when this is not xml,
5243 // and when no QSA bugs apply
5244 if ( !seed && !xml && !rbuggyQSA.test( selector ) ) {
5245 var groups, i,
5246 old = true,
5247 nid = expando,
5248 newContext = context,
5249 newSelector = context.nodeType === 9 && selector;
5250
5251 // qSA works strangely on Element-rooted queries
5252 // We can work around this by specifying an extra ID on the root
5253 // and working up from there (Thanks to Andrew Dupont for the technique)
5254 // IE 8 doesn't work on object elements
5255 if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
5256 groups = tokenize( selector );
5257
5258 if ( (old = context.getAttribute("id")) ) {
5259 nid = old.replace( rescape, "\\$&" );
5260 } else {
5261 context.setAttribute( "id", nid );
5262 }
5263 nid = "[id='" + nid + "'] ";
5264
5265 i = groups.length;
5266 while ( i-- ) {
5267 groups[i] = nid + groups[i].join("");
5268 }
5269 newContext = rsibling.test( selector ) && context.parentNode || context;
5270 newSelector = groups.join(",");
5271 }
5272
5273 if ( newSelector ) {
5274 try {
5275 push.apply( results, slice.call( newContext.querySelectorAll(
5276 newSelector
5277 ), 0 ) );
5278 return results;
5279 } catch(qsaError) {
5280 } finally {
5281 if ( !old ) {
5282 context.removeAttribute("id");
5283 }
5284 }
5285 }
5286 }
5287
5288 return oldSelect( selector, context, results, seed, xml );
5289 };
5290
5291 if ( matches ) {
5292 assert(function( div ) {
5293 // Check to see if it's possible to do matchesSelector
5294 // on a disconnected node (IE 9)
5295 disconnectedMatch = matches.call( div, "div" );
5296
5297 // This should fail with an exception
5298 // Gecko does not error, returns false instead
5299 try {
5300 matches.call( div, "[test!='']:sizzle" );
5301 rbuggyMatches.push( "!=", pseudos );
5302 } catch ( e ) {}
5303 });
5304
5305 // rbuggyMatches always contains :active and :focus, so no need for a length check
5306 rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") );
5307
5308 Sizzle.matchesSelector = function( elem, expr ) {
5309 // Make sure that attribute selectors are quoted
5310 expr = expr.replace( rattributeQuotes, "='$1']" );
5311
5312 // rbuggyMatches always contains :active, so no need for an existence check
5313 if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && !rbuggyQSA.test( expr ) ) {
5314 try {
5315 var ret = matches.call( elem, expr );
5316
5317 // IE 9's matchesSelector returns false on disconnected nodes
5318 if ( ret || disconnectedMatch ||
5319 // As well, disconnected nodes are said to be in a document
5320 // fragment in IE 9
5321 elem.document && elem.document.nodeType !== 11 ) {
5322 return ret;
5323 }
5324 } catch(e) {}
5325 }
5326
5327 return Sizzle( expr, null, null, [ elem ] ).length > 0;
5328 };
5329 }
5330 })();
5331 }
5332
5333 // Deprecated
5334 Expr.pseudos["nth"] = Expr.pseudos["eq"];
5335
5336 // Back-compat
5337 function setFilters() {}
5338 Expr.filters = setFilters.prototype = Expr.pseudos;
5339 Expr.setFilters = new setFilters();
5340
5341 // Override sizzle attribute retrieval
5342 Sizzle.attr = jQuery.attr;
5343 jQuery.find = Sizzle;
5344 jQuery.expr = Sizzle.selectors;
5345 jQuery.expr[":"] = jQuery.expr.pseudos;
5346 jQuery.unique = Sizzle.uniqueSort;
5347 jQuery.text = Sizzle.getText;
5348 jQuery.isXMLDoc = Sizzle.isXML;
5349 jQuery.contains = Sizzle.contains;
5350
5351
5352 })( window );
5353 var runtil = /Until$/,
5354 rparentsprev = /^(?:parents|prev(?:Until|All))/,
5355 isSimple = /^.[^:#\[\.,]*$/,
5356 rneedsContext = jQuery.expr.match.needsContext,
5357 // methods guaranteed to produce a unique set when starting from a unique set
5358 guaranteedUnique = {
5359 children: true,
5360 contents: true,
5361 next: true,
5362 prev: true
5363 };
5364
5365 jQuery.fn.extend({
5366 find: function( selector ) {
5367 var i, l, length, n, r, ret,
5368 self = this;
5369
5370 if ( typeof selector !== "string" ) {
5371 return jQuery( selector ).filter(function() {
5372 for ( i = 0, l = self.length; i < l; i++ ) {
5373 if ( jQuery.contains( self[ i ], this ) ) {
5374 return true;
5375 }
5376 }
5377 });
5378 }
5379
5380 ret = this.pushStack( "", "find", selector );
5381
5382 for ( i = 0, l = this.length; i < l; i++ ) {
5383 length = ret.length;
5384 jQuery.find( selector, this[i], ret );
5385
5386 if ( i > 0 ) {
5387 // Make sure that the results are unique
5388 for ( n = length; n < ret.length; n++ ) {
5389 for ( r = 0; r < length; r++ ) {
5390 if ( ret[r] === ret[n] ) {
5391 ret.splice(n--, 1);
5392 break;
5393 }
5394 }
5395 }
5396 }
5397 }
5398
5399 return ret;
5400 },
5401
5402 has: function( target ) {
5403 var i,
5404 targets = jQuery( target, this ),
5405 len = targets.length;
5406
5407 return this.filter(function() {
5408 for ( i = 0; i < len; i++ ) {
5409 if ( jQuery.contains( this, targets[i] ) ) {
5410 return true;
5411 }
5412 }
5413 });
5414 },
5415
5416 not: function( selector ) {
5417 return this.pushStack( winnow(this, selector, false), "not", selector);
5418 },
5419
5420 filter: function( selector ) {
5421 return this.pushStack( winnow(this, selector, true), "filter", selector );
5422 },
5423
5424 is: function( selector ) {
5425 return !!selector && (
5426 typeof selector === "string" ?
5427 // If this is a positional/relative selector, check membership in the returned set
5428 // so $("p:first").is("p:last") won't return true for a doc with two "p".
5429 rneedsContext.test( selector ) ?
5430 jQuery( selector, this.context ).index( this[0] ) >= 0 :
5431 jQuery.filter( selector, this ).length > 0 :
5432 this.filter( selector ).length > 0 );
5433 },
5434
5435 closest: function( selectors, context ) {
5436 var cur,
5437 i = 0,
5438 l = this.length,
5439 ret = [],
5440 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
5441 jQuery( selectors, context || this.context ) :
5442 0;
5443
5444 for ( ; i < l; i++ ) {
5445 cur = this[i];
5446
5447 while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
5448 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5449 ret.push( cur );
5450 break;
5451 }
5452 cur = cur.parentNode;
5453 }
5454 }
5455
5456 ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
5457
5458 return this.pushStack( ret, "closest", selectors );
5459 },
5460
5461 // Determine the position of an element within
5462 // the matched set of elements
5463 index: function( elem ) {
5464
5465 // No argument, return index in parent
5466 if ( !elem ) {
5467 return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
5468 }
5469
5470 // index in selector
5471 if ( typeof elem === "string" ) {
5472 return jQuery.inArray( this[0], jQuery( elem ) );
5473 }
5474
5475 // Locate the position of the desired element
5476 return jQuery.inArray(
5477 // If it receives a jQuery object, the first element is used
5478 elem.jquery ? elem[0] : elem, this );
5479 },
5480
5481 add: function( selector, context ) {
5482 var set = typeof selector === "string" ?
5483 jQuery( selector, context ) :
5484 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5485 all = jQuery.merge( this.get(), set );
5486
5487 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
5488 all :
5489 jQuery.unique( all ) );
5490 },
5491
5492 addBack: function( selector ) {
5493 return this.add( selector == null ?
5494 this.prevObject : this.prevObject.filter(selector)
5495 );
5496 }
5497 });
5498
5499 jQuery.fn.andSelf = jQuery.fn.addBack;
5500
5501 // A painfully simple check to see if an element is disconnected
5502 // from a document (should be improved, where feasible).
5503 function isDisconnected( node ) {
5504 return !node || !node.parentNode || node.parentNode.nodeType === 11;
5505 }
5506
5507 function sibling( cur, dir ) {
5508 do {
5509 cur = cur[ dir ];
5510 } while ( cur && cur.nodeType !== 1 );
5511
5512 return cur;
5513 }
5514
5515 jQuery.each({
5516 parent: function( elem ) {
5517 var parent = elem.parentNode;
5518 return parent && parent.nodeType !== 11 ? parent : null;
5519 },
5520 parents: function( elem ) {
5521 return jQuery.dir( elem, "parentNode" );
5522 },
5523 parentsUntil: function( elem, i, until ) {
5524 return jQuery.dir( elem, "parentNode", until );
5525 },
5526 next: function( elem ) {
5527 return sibling( elem, "nextSibling" );
5528 },
5529 prev: function( elem ) {
5530 return sibling( elem, "previousSibling" );
5531 },
5532 nextAll: function( elem ) {
5533 return jQuery.dir( elem, "nextSibling" );
5534 },
5535 prevAll: function( elem ) {
5536 return jQuery.dir( elem, "previousSibling" );
5537 },
5538 nextUntil: function( elem, i, until ) {
5539 return jQuery.dir( elem, "nextSibling", until );
5540 },
5541 prevUntil: function( elem, i, until ) {
5542 return jQuery.dir( elem, "previousSibling", until );
5543 },
5544 siblings: function( elem ) {
5545 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
5546 },
5547 children: function( elem ) {
5548 return jQuery.sibling( elem.firstChild );
5549 },
5550 contents: function( elem ) {
5551 return jQuery.nodeName( elem, "iframe" ) ?
5552 elem.contentDocument || elem.contentWindow.document :
5553 jQuery.merge( [], elem.childNodes );
5554 }
5555 }, function( name, fn ) {
5556 jQuery.fn[ name ] = function( until, selector ) {
5557 var ret = jQuery.map( this, fn, until );
5558
5559 if ( !runtil.test( name ) ) {
5560 selector = until;
5561 }
5562
5563 if ( selector && typeof selector === "string" ) {
5564 ret = jQuery.filter( selector, ret );
5565 }
5566
5567 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
5568
5569 if ( this.length > 1 && rparentsprev.test( name ) ) {
5570 ret = ret.reverse();
5571 }
5572
5573 return this.pushStack( ret, name, core_slice.call( arguments ).join(",") );
5574 };
5575 });
5576
5577 jQuery.extend({
5578 filter: function( expr, elems, not ) {
5579 if ( not ) {
5580 expr = ":not(" + expr + ")";
5581 }
5582
5583 return elems.length === 1 ?
5584 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
5585 jQuery.find.matches(expr, elems);
5586 },
5587
5588 dir: function( elem, dir, until ) {
5589 var matched = [],
5590 cur = elem[ dir ];
5591
5592 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5593 if ( cur.nodeType === 1 ) {
5594 matched.push( cur );
5595 }
5596 cur = cur[dir];
5597 }
5598 return matched;
5599 },
5600
5601 sibling: function( n, elem ) {
5602 var r = [];
5603
5604 for ( ; n; n = n.nextSibling ) {
5605 if ( n.nodeType === 1 && n !== elem ) {
5606 r.push( n );
5607 }
5608 }
5609
5610 return r;
5611 }
5612 });
5613
5614 // Implement the identical functionality for filter and not
5615 function winnow( elements, qualifier, keep ) {
5616
5617 // Can't pass null or undefined to indexOf in Firefox 4
5618 // Set to 0 to skip string check
5619 qualifier = qualifier || 0;
5620
5621 if ( jQuery.isFunction( qualifier ) ) {
5622 return jQuery.grep(elements, function( elem, i ) {
5623 var retVal = !!qualifier.call( elem, i, elem );
5624 return retVal === keep;
5625 });
5626
5627 } else if ( qualifier.nodeType ) {
5628 return jQuery.grep(elements, function( elem, i ) {
5629 return ( elem === qualifier ) === keep;
5630 });
5631
5632 } else if ( typeof qualifier === "string" ) {
5633 var filtered = jQuery.grep(elements, function( elem ) {
5634 return elem.nodeType === 1;
5635 });
5636
5637 if ( isSimple.test( qualifier ) ) {
5638 return jQuery.filter(qualifier, filtered, !keep);
5639 } else {
5640 qualifier = jQuery.filter( qualifier, filtered );
5641 }
5642 }
5643
5644 return jQuery.grep(elements, function( elem, i ) {
5645 return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
5646 });
5647 }
5648 function createSafeFragment( document ) {
5649 var list = nodeNames.split( "|" ),
5650 safeFrag = document.createDocumentFragment();
5651
5652 if ( safeFrag.createElement ) {
5653 while ( list.length ) {
5654 safeFrag.createElement(
5655 list.pop()
5656 );
5657 }
5658 }
5659 return safeFrag;
5660 }
5661
5662 var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5663 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5664 rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5665 rleadingWhitespace = /^\s+/,
5666 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5667 rtagName = /<([\w:]+)/,
5668 rtbody = /<tbody/i,
5669 rhtml = /<|&#?\w+;/,
5670 rnoInnerhtml = /<(?:script|style|link)/i,
5671 rnocache = /<(?:script|object|embed|option|style)/i,
5672 rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5673 rcheckableType = /^(?:checkbox|radio)$/,
5674 // checked="checked" or checked
5675 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5676 rscriptType = /\/(java|ecma)script/i,
5677 rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,
5678 wrapMap = {
5679 option: [ 1, "<select multiple='multiple'>", "</select>" ],
5680 legend: [ 1, "<fieldset>", "</fieldset>" ],
5681 thead: [ 1, "<table>", "</table>" ],
5682 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5683 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5684 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5685 area: [ 1, "<map>", "</map>" ],
5686 _default: [ 0, "", "" ]
5687 },
5688 safeFragment = createSafeFragment( document ),
5689 fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5690
5691 wrapMap.optgroup = wrapMap.option;
5692 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5693 wrapMap.th = wrapMap.td;
5694
5695 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5696 // unless wrapped in a div with non-breaking characters in front of it.
5697 if ( !jQuery.support.htmlSerialize ) {
5698 wrapMap._default = [ 1, "X<div>", "</div>" ];
5699 }
5700
5701 jQuery.fn.extend({
5702 text: function( value ) {
5703 return jQuery.access( this, function( value ) {
5704 return value === undefined ?
5705 jQuery.text( this ) :
5706 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5707 }, null, value, arguments.length );
5708 },
5709
5710 wrapAll: function( html ) {
5711 if ( jQuery.isFunction( html ) ) {
5712 return this.each(function(i) {
5713 jQuery(this).wrapAll( html.call(this, i) );
5714 });
5715 }
5716
5717 if ( this[0] ) {
5718 // The elements to wrap the target around
5719 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
5720
5721 if ( this[0].parentNode ) {
5722 wrap.insertBefore( this[0] );
5723 }
5724
5725 wrap.map(function() {
5726 var elem = this;
5727
5728 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
5729 elem = elem.firstChild;
5730 }
5731
5732 return elem;
5733 }).append( this );
5734 }
5735
5736 return this;
5737 },
5738
5739 wrapInner: function( html ) {
5740 if ( jQuery.isFunction( html ) ) {
5741 return this.each(function(i) {
5742 jQuery(this).wrapInner( html.call(this, i) );
5743 });
5744 }
5745
5746 return this.each(function() {
5747 var self = jQuery( this ),
5748 contents = self.contents();
5749
5750 if ( contents.length ) {
5751 contents.wrapAll( html );
5752
5753 } else {
5754 self.append( html );
5755 }
5756 });
5757 },
5758
5759 wrap: function( html ) {
5760 var isFunction = jQuery.isFunction( html );
5761
5762 return this.each(function(i) {
5763 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
5764 });
5765 },
5766
5767 unwrap: function() {
5768 return this.parent().each(function() {
5769 if ( !jQuery.nodeName( this, "body" ) ) {
5770 jQuery( this ).replaceWith( this.childNodes );
5771 }
5772 }).end();
5773 },
5774
5775 append: function() {
5776 return this.domManip(arguments, true, function( elem ) {
5777 if ( this.nodeType === 1 || this.nodeType === 11 ) {
5778 this.appendChild( elem );
5779 }
5780 });
5781 },
5782
5783 prepend: function() {
5784 return this.domManip(arguments, true, function( elem ) {
5785 if ( this.nodeType === 1 || this.nodeType === 11 ) {
5786 this.insertBefore( elem, this.firstChild );
5787 }
5788 });
5789 },
5790
5791 before: function() {
5792 if ( !isDisconnected( this[0] ) ) {
5793 return this.domManip(arguments, false, function( elem ) {
5794 this.parentNode.insertBefore( elem, this );
5795 });
5796 }
5797
5798 if ( arguments.length ) {
5799 var set = jQuery.clean( arguments );
5800 return this.pushStack( jQuery.merge( set, this ), "before", this.selector );
5801 }
5802 },
5803
5804 after: function() {
5805 if ( !isDisconnected( this[0] ) ) {
5806 return this.domManip(arguments, false, function( elem ) {
5807 this.parentNode.insertBefore( elem, this.nextSibling );
5808 });
5809 }
5810
5811 if ( arguments.length ) {
5812 var set = jQuery.clean( arguments );
5813 return this.pushStack( jQuery.merge( this, set ), "after", this.selector );
5814 }
5815 },
5816
5817 // keepData is for internal use only--do not document
5818 remove: function( selector, keepData ) {
5819 var elem,
5820 i = 0;
5821
5822 for ( ; (elem = this[i]) != null; i++ ) {
5823 if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
5824 if ( !keepData && elem.nodeType === 1 ) {
5825 jQuery.cleanData( elem.getElementsByTagName("*") );
5826 jQuery.cleanData( [ elem ] );
5827 }
5828
5829 if ( elem.parentNode ) {
5830 elem.parentNode.removeChild( elem );
5831 }
5832 }
5833 }
5834
5835 return this;
5836 },
5837
5838 empty: function() {
5839 var elem,
5840 i = 0;
5841
5842 for ( ; (elem = this[i]) != null; i++ ) {
5843 // Remove element nodes and prevent memory leaks
5844 if ( elem.nodeType === 1 ) {
5845 jQuery.cleanData( elem.getElementsByTagName("*") );
5846 }
5847
5848 // Remove any remaining nodes
5849 while ( elem.firstChild ) {
5850 elem.removeChild( elem.firstChild );
5851 }
5852 }
5853
5854 return this;
5855 },
5856
5857 clone: function( dataAndEvents, deepDataAndEvents ) {
5858 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
5859 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
5860
5861 return this.map( function () {
5862 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
5863 });
5864 },
5865
5866 html: function( value ) {
5867 return jQuery.access( this, function( value ) {
5868 var elem = this[0] || {},
5869 i = 0,
5870 l = this.length;
5871
5872 if ( value === undefined ) {
5873 return elem.nodeType === 1 ?
5874 elem.innerHTML.replace( rinlinejQuery, "" ) :
5875 undefined;
5876 }
5877
5878 // See if we can take a shortcut and just use innerHTML
5879 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
5880 ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
5881 ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
5882 !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
5883
5884 value = value.replace( rxhtmlTag, "<$1></$2>" );
5885
5886 try {
5887 for (; i < l; i++ ) {
5888 // Remove element nodes and prevent memory leaks
5889 elem = this[i] || {};
5890 if ( elem.nodeType === 1 ) {
5891 jQuery.cleanData( elem.getElementsByTagName( "*" ) );
5892 elem.innerHTML = value;
5893 }
5894 }
5895
5896 elem = 0;
5897
5898 // If using innerHTML throws an exception, use the fallback method
5899 } catch(e) {}
5900 }
5901
5902 if ( elem ) {
5903 this.empty().append( value );
5904 }
5905 }, null, value, arguments.length );
5906 },
5907
5908 replaceWith: function( value ) {
5909 if ( !isDisconnected( this[0] ) ) {
5910 // Make sure that the elements are removed from the DOM before they are inserted
5911 // this can help fix replacing a parent with child elements
5912 if ( jQuery.isFunction( value ) ) {
5913 return this.each(function(i) {
5914 var self = jQuery(this), old = self.html();
5915 self.replaceWith( value.call( this, i, old ) );
5916 });
5917 }
5918
5919 if ( typeof value !== "string" ) {
5920 value = jQuery( value ).detach();
5921 }
5922
5923 return this.each(function() {
5924 var next = this.nextSibling,
5925 parent = this.parentNode;
5926
5927 jQuery( this ).remove();
5928
5929 if ( next ) {
5930 jQuery(next).before( value );
5931 } else {
5932 jQuery(parent).append( value );
5933 }
5934 });
5935 }
5936
5937 return this.length ?
5938 this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
5939 this;
5940 },
5941
5942 detach: function( selector ) {
5943 return this.remove( selector, true );
5944 },
5945
5946 domManip: function( args, table, callback ) {
5947
5948 // Flatten any nested arrays
5949 args = [].concat.apply( [], args );
5950
5951 var results, first, fragment, iNoClone,
5952 i = 0,
5953 value = args[0],
5954 scripts = [],
5955 l = this.length;
5956
5957 // We can't cloneNode fragments that contain checked, in WebKit
5958 if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) {
5959 return this.each(function() {
5960 jQuery(this).domManip( args, table, callback );
5961 });
5962 }
5963
5964 if ( jQuery.isFunction(value) ) {
5965 return this.each(function(i) {
5966 var self = jQuery(this);
5967 args[0] = value.call( this, i, table ? self.html() : undefined );
5968 self.domManip( args, table, callback );
5969 });
5970 }
5971
5972 if ( this[0] ) {
5973 results = jQuery.buildFragment( args, this, scripts );
5974 fragment = results.fragment;
5975 first = fragment.firstChild;
5976
5977 if ( fragment.childNodes.length === 1 ) {
5978 fragment = first;
5979 }
5980
5981 if ( first ) {
5982 table = table && jQuery.nodeName( first, "tr" );
5983
5984 // Use the original fragment for the last item instead of the first because it can end up
5985 // being emptied incorrectly in certain situations (#8070).
5986 // Fragments from the fragment cache must always be cloned and never used in place.
5987 for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) {
5988 callback.call(
5989 table && jQuery.nodeName( this[i], "table" ) ?
5990 findOrAppend( this[i], "tbody" ) :
5991 this[i],
5992 i === iNoClone ?
5993 fragment :
5994 jQuery.clone( fragment, true, true )
5995 );
5996 }
5997 }
5998
5999 // Fix #11809: Avoid leaking memory
6000 fragment = first = null;
6001
6002 if ( scripts.length ) {
6003 jQuery.each( scripts, function( i, elem ) {
6004 if ( elem.src ) {
6005 if ( jQuery.ajax ) {
6006 jQuery.ajax({
6007 url: elem.src,
6008 type: "GET",
6009 dataType: "script",
6010 async: false,
6011 global: false,
6012 "throws": true
6013 });
6014 } else {
6015 jQuery.error("no ajax");
6016 }
6017 } else {
6018 jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) );
6019 }
6020
6021 if ( elem.parentNode ) {
6022 elem.parentNode.removeChild( elem );
6023 }
6024 });
6025 }
6026 }
6027
6028 return this;
6029 }
6030 });
6031
6032 function findOrAppend( elem, tag ) {
6033 return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
6034 }
6035
6036 function cloneCopyEvent( src, dest ) {
6037
6038 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6039 return;
6040 }
6041
6042 var type, i, l,
6043 oldData = jQuery._data( src ),
6044 curData = jQuery._data( dest, oldData ),
6045 events = oldData.events;
6046
6047 if ( events ) {
6048 delete curData.handle;
6049 curData.events = {};
6050
6051 for ( type in events ) {
6052 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6053 jQuery.event.add( dest, type, events[ type ][ i ] );
6054 }
6055 }
6056 }
6057
6058 // make the cloned public data object a copy from the original
6059 if ( curData.data ) {
6060 curData.data = jQuery.extend( {}, curData.data );
6061 }
6062 }
6063
6064 function cloneFixAttributes( src, dest ) {
6065 var nodeName;
6066
6067 // We do not need to do anything for non-Elements
6068 if ( dest.nodeType !== 1 ) {
6069 return;
6070 }
6071
6072 // clearAttributes removes the attributes, which we don't want,
6073 // but also removes the attachEvent events, which we *do* want
6074 if ( dest.clearAttributes ) {
6075 dest.clearAttributes();
6076 }
6077
6078 // mergeAttributes, in contrast, only merges back on the
6079 // original attributes, not the events
6080 if ( dest.mergeAttributes ) {
6081 dest.mergeAttributes( src );
6082 }
6083
6084 nodeName = dest.nodeName.toLowerCase();
6085
6086 if ( nodeName === "object" ) {
6087 // IE6-10 improperly clones children of object elements using classid.
6088 // IE10 throws NoModificationAllowedError if parent is null, #12132.
6089 if ( dest.parentNode ) {
6090 dest.outerHTML = src.outerHTML;
6091 }
6092
6093 // This path appears unavoidable for IE9. When cloning an object
6094 // element in IE9, the outerHTML strategy above is not sufficient.
6095 // If the src has innerHTML and the destination does not,
6096 // copy the src.innerHTML into the dest.innerHTML. #10324
6097 if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) {
6098 dest.innerHTML = src.innerHTML;
6099 }
6100
6101 } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
6102 // IE6-8 fails to persist the checked state of a cloned checkbox
6103 // or radio button. Worse, IE6-7 fail to give the cloned element
6104 // a checked appearance if the defaultChecked value isn't also set
6105
6106 dest.defaultChecked = dest.checked = src.checked;
6107
6108 // IE6-7 get confused and end up setting the value of a cloned
6109 // checkbox/radio button to an empty string instead of "on"
6110 if ( dest.value !== src.value ) {
6111 dest.value = src.value;
6112 }
6113
6114 // IE6-8 fails to return the selected option to the default selected
6115 // state when cloning options
6116 } else if ( nodeName === "option" ) {
6117 dest.selected = src.defaultSelected;
6118
6119 // IE6-8 fails to set the defaultValue to the correct value when
6120 // cloning other types of input fields
6121 } else if ( nodeName === "input" || nodeName === "textarea" ) {
6122 dest.defaultValue = src.defaultValue;
6123
6124 // IE blanks contents when cloning scripts
6125 } else if ( nodeName === "script" && dest.text !== src.text ) {
6126 dest.text = src.text;
6127 }
6128
6129 // Event data gets referenced instead of copied if the expando
6130 // gets copied too
6131 dest.removeAttribute( jQuery.expando );
6132 }
6133
6134 jQuery.buildFragment = function( args, context, scripts ) {
6135 var fragment, cacheable, cachehit,
6136 first = args[ 0 ];
6137
6138 // Set context from what may come in as undefined or a jQuery collection or a node
6139 // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 &
6140 // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception
6141 context = context || document;
6142 context = !context.nodeType && context[0] || context;
6143 context = context.ownerDocument || context;
6144
6145 // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
6146 // Cloning options loses the selected state, so don't cache them
6147 // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
6148 // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
6149 // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
6150 if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document &&
6151 first.charAt(0) === "<" && !rnocache.test( first ) &&
6152 (jQuery.support.checkClone || !rchecked.test( first )) &&
6153 (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
6154
6155 // Mark cacheable and look for a hit
6156 cacheable = true;
6157 fragment = jQuery.fragments[ first ];
6158 cachehit = fragment !== undefined;
6159 }
6160
6161 if ( !fragment ) {
6162 fragment = context.createDocumentFragment();
6163 jQuery.clean( args, context, fragment, scripts );
6164
6165 // Update the cache, but only store false
6166 // unless this is a second parsing of the same content
6167 if ( cacheable ) {
6168 jQuery.fragments[ first ] = cachehit && fragment;
6169 }
6170 }
6171
6172 return { fragment: fragment, cacheable: cacheable };
6173 };
6174
6175 jQuery.fragments = {};
6176
6177 jQuery.each({
6178 appendTo: "append",
6179 prependTo: "prepend",
6180 insertBefore: "before",
6181 insertAfter: "after",
6182 replaceAll: "replaceWith"
6183 }, function( name, original ) {
6184 jQuery.fn[ name ] = function( selector ) {
6185 var elems,
6186 i = 0,
6187 ret = [],
6188 insert = jQuery( selector ),
6189 l = insert.length,
6190 parent = this.length === 1 && this[0].parentNode;
6191
6192 if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) {
6193 insert[ original ]( this[0] );
6194 return this;
6195 } else {
6196 for ( ; i < l; i++ ) {
6197 elems = ( i > 0 ? this.clone(true) : this ).get();
6198 jQuery( insert[i] )[ original ]( elems );
6199 ret = ret.concat( elems );
6200 }
6201
6202 return this.pushStack( ret, name, insert.selector );
6203 }
6204 };
6205 });
6206
6207 function getAll( elem ) {
6208 if ( typeof elem.getElementsByTagName !== "undefined" ) {
6209 return elem.getElementsByTagName( "*" );
6210
6211 } else if ( typeof elem.querySelectorAll !== "undefined" ) {
6212 return elem.querySelectorAll( "*" );
6213
6214 } else {
6215 return [];
6216 }
6217 }
6218
6219 // Used in clean, fixes the defaultChecked property
6220 function fixDefaultChecked( elem ) {
6221 if ( rcheckableType.test( elem.type ) ) {
6222 elem.defaultChecked = elem.checked;
6223 }
6224 }
6225
6226 jQuery.extend({
6227 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6228 var srcElements,
6229 destElements,
6230 i,
6231 clone;
6232
6233 if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6234 clone = elem.cloneNode( true );
6235
6236 // IE<=8 does not properly clone detached, unknown element nodes
6237 } else {
6238 fragmentDiv.innerHTML = elem.outerHTML;
6239 fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6240 }
6241
6242 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6243 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6244 // IE copies events bound via attachEvent when using cloneNode.
6245 // Calling detachEvent on the clone will also remove the events
6246 // from the original. In order to get around this, we use some
6247 // proprietary methods to clear the events. Thanks to MooTools
6248 // guys for this hotness.
6249
6250 cloneFixAttributes( elem, clone );
6251
6252 // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
6253 srcElements = getAll( elem );
6254 destElements = getAll( clone );
6255
6256 // Weird iteration because IE will replace the length property
6257 // with an element if you are cloning the body and one of the
6258 // elements on the page has a name or id of "length"
6259 for ( i = 0; srcElements[i]; ++i ) {
6260 // Ensure that the destination node is not null; Fixes #9587
6261 if ( destElements[i] ) {
6262 cloneFixAttributes( srcElements[i], destElements[i] );
6263 }
6264 }
6265 }
6266
6267 // Copy the events from the original to the clone
6268 if ( dataAndEvents ) {
6269 cloneCopyEvent( elem, clone );
6270
6271 if ( deepDataAndEvents ) {
6272 srcElements = getAll( elem );
6273 destElements = getAll( clone );
6274
6275 for ( i = 0; srcElements[i]; ++i ) {
6276 cloneCopyEvent( srcElements[i], destElements[i] );
6277 }
6278 }
6279 }
6280
6281 srcElements = destElements = null;
6282
6283 // Return the cloned set
6284 return clone;
6285 },
6286
6287 clean: function( elems, context, fragment, scripts ) {
6288 var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags,
6289 safe = context === document && safeFragment,
6290 ret = [];
6291
6292 // Ensure that context is a document
6293 if ( !context || typeof context.createDocumentFragment === "undefined" ) {
6294 context = document;
6295 }
6296
6297 // Use the already-created safe fragment if context permits
6298 for ( i = 0; (elem = elems[i]) != null; i++ ) {
6299 if ( typeof elem === "number" ) {
6300 elem += "";
6301 }
6302
6303 if ( !elem ) {
6304 continue;
6305 }
6306
6307 // Convert html string into DOM nodes
6308 if ( typeof elem === "string" ) {
6309 if ( !rhtml.test( elem ) ) {
6310 elem = context.createTextNode( elem );
6311 } else {
6312 // Ensure a safe container in which to render the html
6313 safe = safe || createSafeFragment( context );
6314 div = context.createElement("div");
6315 safe.appendChild( div );
6316
6317 // Fix "XHTML"-style tags in all browsers
6318 elem = elem.replace(rxhtmlTag, "<$1></$2>");
6319
6320 // Go to html and back, then peel off extra wrappers
6321 tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
6322 wrap = wrapMap[ tag ] || wrapMap._default;
6323 depth = wrap[0];
6324 div.innerHTML = wrap[1] + elem + wrap[2];
6325
6326 // Move to the right depth
6327 while ( depth-- ) {
6328 div = div.lastChild;
6329 }
6330
6331 // Remove IE's autoinserted <tbody> from table fragments
6332 if ( !jQuery.support.tbody ) {
6333
6334 // String was a <table>, *may* have spurious <tbody>
6335 hasBody = rtbody.test(elem);
6336 tbody = tag === "table" && !hasBody ?
6337 div.firstChild && div.firstChild.childNodes :
6338
6339 // String was a bare <thead> or <tfoot>
6340 wrap[1] === "<table>" && !hasBody ?
6341 div.childNodes :
6342 [];
6343
6344 for ( j = tbody.length - 1; j >= 0 ; --j ) {
6345 if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
6346 tbody[ j ].parentNode.removeChild( tbody[ j ] );
6347 }
6348 }
6349 }
6350
6351 // IE completely kills leading whitespace when innerHTML is used
6352 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6353 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
6354 }
6355
6356 elem = div.childNodes;
6357
6358 // Take out of fragment container (we need a fresh div each time)
6359 div.parentNode.removeChild( div );
6360 }
6361 }
6362
6363 if ( elem.nodeType ) {
6364 ret.push( elem );
6365 } else {
6366 jQuery.merge( ret, elem );
6367 }
6368 }
6369
6370 // Fix #11356: Clear elements from safeFragment
6371 if ( div ) {
6372 elem = div = safe = null;
6373 }
6374
6375 // Reset defaultChecked for any radios and checkboxes
6376 // about to be appended to the DOM in IE 6/7 (#8060)
6377 if ( !jQuery.support.appendChecked ) {
6378 for ( i = 0; (elem = ret[i]) != null; i++ ) {
6379 if ( jQuery.nodeName( elem, "input" ) ) {
6380 fixDefaultChecked( elem );
6381 } else if ( typeof elem.getElementsByTagName !== "undefined" ) {
6382 jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
6383 }
6384 }
6385 }
6386
6387 // Append elements to a provided document fragment
6388 if ( fragment ) {
6389 // Special handling of each script element
6390 handleScript = function( elem ) {
6391 // Check if we consider it executable
6392 if ( !elem.type || rscriptType.test( elem.type ) ) {
6393 // Detach the script and store it in the scripts array (if provided) or the fragment
6394 // Return truthy to indicate that it has been handled
6395 return scripts ?
6396 scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
6397 fragment.appendChild( elem );
6398 }
6399 };
6400
6401 for ( i = 0; (elem = ret[i]) != null; i++ ) {
6402 // Check if we're done after handling an executable script
6403 if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
6404 // Append to fragment and handle embedded scripts
6405 fragment.appendChild( elem );
6406 if ( typeof elem.getElementsByTagName !== "undefined" ) {
6407 // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
6408 jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
6409
6410 // Splice the scripts into ret after their former ancestor and advance our index beyond them
6411 ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
6412 i += jsTags.length;
6413 }
6414 }
6415 }
6416 }
6417
6418 return ret;
6419 },
6420
6421 cleanData: function( elems, /* internal */ acceptData ) {
6422 var data, id, elem, type,
6423 i = 0,
6424 internalKey = jQuery.expando,
6425 cache = jQuery.cache,
6426 deleteExpando = jQuery.support.deleteExpando,
6427 special = jQuery.event.special;
6428
6429 for ( ; (elem = elems[i]) != null; i++ ) {
6430
6431 if ( acceptData || jQuery.acceptData( elem ) ) {
6432
6433 id = elem[ internalKey ];
6434 data = id && cache[ id ];
6435
6436 if ( data ) {
6437 if ( data.events ) {
6438 for ( type in data.events ) {
6439 if ( special[ type ] ) {
6440 jQuery.event.remove( elem, type );
6441
6442 // This is a shortcut to avoid jQuery.event.remove's overhead
6443 } else {
6444 jQuery.removeEvent( elem, type, data.handle );
6445 }
6446 }
6447 }
6448
6449 // Remove cache only if it was not already removed by jQuery.event.remove
6450 if ( cache[ id ] ) {
6451
6452 delete cache[ id ];
6453
6454 // IE does not allow us to delete expando properties from nodes,
6455 // nor does it have a removeAttribute function on Document nodes;
6456 // we must handle all of these cases
6457 if ( deleteExpando ) {
6458 delete elem[ internalKey ];
6459
6460 } else if ( elem.removeAttribute ) {
6461 elem.removeAttribute( internalKey );
6462
6463 } else {
6464 elem[ internalKey ] = null;
6465 }
6466
6467 jQuery.deletedIds.push( id );
6468 }
6469 }
6470 }
6471 }
6472 }
6473 });
6474 // Limit scope pollution from any deprecated API
6475 (function() {
6476
6477 var matched, browser;
6478
6479 // Use of jQuery.browser is frowned upon.
6480 // More details: http://api.jquery.com/jQuery.browser
6481 // jQuery.uaMatch maintained for back-compat
6482 jQuery.uaMatch = function( ua ) {
6483 ua = ua.toLowerCase();
6484
6485 var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
6486 /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
6487 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
6488 /(msie) ([\w.]+)/.exec( ua ) ||
6489 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
6490 [];
6491
6492 return {
6493 browser: match[ 1 ] || "",
6494 version: match[ 2 ] || "0"
6495 };
6496 };
6497
6498 matched = jQuery.uaMatch( navigator.userAgent );
6499 browser = {};
6500
6501 if ( matched.browser ) {
6502 browser[ matched.browser ] = true;
6503 browser.version = matched.version;
6504 }
6505
6506 // Chrome is Webkit, but Webkit is also Safari.
6507 if ( browser.chrome ) {
6508 browser.webkit = true;
6509 } else if ( browser.webkit ) {
6510 browser.safari = true;
6511 }
6512
6513 jQuery.browser = browser;
6514
6515 jQuery.sub = function() {
6516 function jQuerySub( selector, context ) {
6517 return new jQuerySub.fn.init( selector, context );
6518 }
6519 jQuery.extend( true, jQuerySub, this );
6520 jQuerySub.superclass = this;
6521 jQuerySub.fn = jQuerySub.prototype = this();
6522 jQuerySub.fn.constructor = jQuerySub;
6523 jQuerySub.sub = this.sub;
6524 jQuerySub.fn.init = function init( selector, context ) {
6525 if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
6526 context = jQuerySub( context );
6527 }
6528
6529 return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
6530 };
6531 jQuerySub.fn.init.prototype = jQuerySub.fn;
6532 var rootjQuerySub = jQuerySub(document);
6533 return jQuerySub;
6534 };
6535
6536 })();
6537 var curCSS, iframe, iframeDoc,
6538 ralpha = /alpha\([^)]*\)/i,
6539 ropacity = /opacity=([^)]*)/,
6540 rposition = /^(top|right|bottom|left)$/,
6541 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6542 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6543 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6544 rmargin = /^margin/,
6545 rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
6546 rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
6547 rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ),
6548 elemdisplay = { BODY: "block" },
6549
6550 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6551 cssNormalTransform = {
6552 letterSpacing: 0,
6553 fontWeight: 400
6554 },
6555
6556 cssExpand = [ "Top", "Right", "Bottom", "Left" ],
6557 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
6558
6559 eventsToggle = jQuery.fn.toggle;
6560
6561 // return a css property mapped to a potentially vendor prefixed property
6562 function vendorPropName( style, name ) {
6563
6564 // shortcut for names that are not vendor prefixed
6565 if ( name in style ) {
6566 return name;
6567 }
6568
6569 // check for vendor prefixed names
6570 var capName = name.charAt(0).toUpperCase() + name.slice(1),
6571 origName = name,
6572 i = cssPrefixes.length;
6573
6574 while ( i-- ) {
6575 name = cssPrefixes[ i ] + capName;
6576 if ( name in style ) {
6577 return name;
6578 }
6579 }
6580
6581 return origName;
6582 }
6583
6584 function isHidden( elem, el ) {
6585 elem = el || elem;
6586 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
6587 }
6588
6589 function showHide( elements, show ) {
6590 var elem, display,
6591 values = [],
6592 index = 0,
6593 length = elements.length;
6594
6595 for ( ; index < length; index++ ) {
6596 elem = elements[ index ];
6597 if ( !elem.style ) {
6598 continue;
6599 }
6600 values[ index ] = jQuery._data( elem, "olddisplay" );
6601 if ( show ) {
6602 // Reset the inline display of this element to learn if it is
6603 // being hidden by cascaded rules or not
6604 if ( !values[ index ] && elem.style.display === "none" ) {
6605 elem.style.display = "";
6606 }
6607
6608 // Set elements which have been overridden with display: none
6609 // in a stylesheet to whatever the default browser style is
6610 // for such an element
6611 if ( elem.style.display === "" && isHidden( elem ) ) {
6612 values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
6613 }
6614 } else {
6615 display = curCSS( elem, "display" );
6616
6617 if ( !values[ index ] && display !== "none" ) {
6618 jQuery._data( elem, "olddisplay", display );
6619 }
6620 }
6621 }
6622
6623 // Set the display of most of the elements in a second loop
6624 // to avoid the constant reflow
6625 for ( index = 0; index < length; index++ ) {
6626 elem = elements[ index ];
6627 if ( !elem.style ) {
6628 continue;
6629 }
6630 if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6631 elem.style.display = show ? values[ index ] || "" : "none";
6632 }
6633 }
6634
6635 return elements;
6636 }
6637
6638 jQuery.fn.extend({
6639 css: function( name, value ) {
6640 return jQuery.access( this, function( elem, name, value ) {
6641 return value !== undefined ?
6642 jQuery.style( elem, name, value ) :
6643 jQuery.css( elem, name );
6644 }, name, value, arguments.length > 1 );
6645 },
6646 show: function() {
6647 return showHide( this, true );
6648 },
6649 hide: function() {
6650 return showHide( this );
6651 },
6652 toggle: function( state, fn2 ) {
6653 var bool = typeof state === "boolean";
6654
6655 if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) {
6656 return eventsToggle.apply( this, arguments );
6657 }
6658
6659 return this.each(function() {
6660 if ( bool ? state : isHidden( this ) ) {
6661 jQuery( this ).show();
6662 } else {
6663 jQuery( this ).hide();
6664 }
6665 });
6666 }
6667 });
6668
6669 jQuery.extend({
6670 // Add in style property hooks for overriding the default
6671 // behavior of getting and setting a style property
6672 cssHooks: {
6673 opacity: {
6674 get: function( elem, computed ) {
6675 if ( computed ) {
6676 // We should always get a number back from opacity
6677 var ret = curCSS( elem, "opacity" );
6678 return ret === "" ? "1" : ret;
6679
6680 }
6681 }
6682 }
6683 },
6684
6685 // Exclude the following css properties to add px
6686 cssNumber: {
6687 "fillOpacity": true,
6688 "fontWeight": true,
6689 "lineHeight": true,
6690 "opacity": true,
6691 "orphans": true,
6692 "widows": true,
6693 "zIndex": true,
6694 "zoom": true
6695 },
6696
6697 // Add in properties whose names you wish to fix before
6698 // setting or getting the value
6699 cssProps: {
6700 // normalize float css property
6701 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6702 },
6703
6704 // Get and set the style property on a DOM Node
6705 style: function( elem, name, value, extra ) {
6706 // Don't set styles on text and comment nodes
6707 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6708 return;
6709 }
6710
6711 // Make sure that we're working with the right name
6712 var ret, type, hooks,
6713 origName = jQuery.camelCase( name ),
6714 style = elem.style;
6715
6716 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6717
6718 // gets hook for the prefixed version
6719 // followed by the unprefixed version
6720 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6721
6722 // Check if we're setting a value
6723 if ( value !== undefined ) {
6724 type = typeof value;
6725
6726 // convert relative number strings (+= or -=) to relative numbers. #7345
6727 if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6728 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6729 // Fixes bug #9237
6730 type = "number";
6731 }
6732
6733 // Make sure that NaN and null values aren't set. See: #7116
6734 if ( value == null || type === "number" && isNaN( value ) ) {
6735 return;
6736 }
6737
6738 // If a number was passed in, add 'px' to the (except for certain CSS properties)
6739 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6740 value += "px";
6741 }
6742
6743 // If a hook was provided, use that value, otherwise just set the specified value
6744 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6745 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6746 // Fixes bug #5509
6747 try {
6748 style[ name ] = value;
6749 } catch(e) {}
6750 }
6751
6752 } else {
6753 // If a hook was provided get the non-computed value from there
6754 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6755 return ret;
6756 }
6757
6758 // Otherwise just get the value from the style object
6759 return style[ name ];
6760 }
6761 },
6762
6763 css: function( elem, name, numeric, extra ) {
6764 var val, num, hooks,
6765 origName = jQuery.camelCase( name );
6766
6767 // Make sure that we're working with the right name
6768 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6769
6770 // gets hook for the prefixed version
6771 // followed by the unprefixed version
6772 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6773
6774 // If a hook was provided get the computed value from there
6775 if ( hooks && "get" in hooks ) {
6776 val = hooks.get( elem, true, extra );
6777 }
6778
6779 // Otherwise, if a way to get the computed value exists, use that
6780 if ( val === undefined ) {
6781 val = curCSS( elem, name );
6782 }
6783
6784 //convert "normal" to computed value
6785 if ( val === "normal" && name in cssNormalTransform ) {
6786 val = cssNormalTransform[ name ];
6787 }
6788
6789 // Return, converting to number if forced or a qualifier was provided and val looks numeric
6790 if ( numeric || extra !== undefined ) {
6791 num = parseFloat( val );
6792 return numeric || jQuery.isNumeric( num ) ? num || 0 : val;
6793 }
6794 return val;
6795 },
6796
6797 // A method for quickly swapping in/out CSS properties to get correct calculations
6798 swap: function( elem, options, callback ) {
6799 var ret, name,
6800 old = {};
6801
6802 // Remember the old values, and insert the new ones
6803 for ( name in options ) {
6804 old[ name ] = elem.style[ name ];
6805 elem.style[ name ] = options[ name ];
6806 }
6807
6808 ret = callback.call( elem );
6809
6810 // Revert the old values
6811 for ( name in options ) {
6812 elem.style[ name ] = old[ name ];
6813 }
6814
6815 return ret;
6816 }
6817 });
6818
6819 // NOTE: To any future maintainer, we've window.getComputedStyle
6820 // because jsdom on node.js will break without it.
6821 if ( window.getComputedStyle ) {
6822 curCSS = function( elem, name ) {
6823 var ret, width, minWidth, maxWidth,
6824 computed = window.getComputedStyle( elem, null ),
6825 style = elem.style;
6826
6827 if ( computed ) {
6828
6829 // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6830 ret = computed.getPropertyValue( name ) || computed[ name ];
6831
6832 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6833 ret = jQuery.style( elem, name );
6834 }
6835
6836 // A tribute to the "awesome hack by Dean Edwards"
6837 // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6838 // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6839 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6840 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6841 width = style.width;
6842 minWidth = style.minWidth;
6843 maxWidth = style.maxWidth;
6844
6845 style.minWidth = style.maxWidth = style.width = ret;
6846 ret = computed.width;
6847
6848 style.width = width;
6849 style.minWidth = minWidth;
6850 style.maxWidth = maxWidth;
6851 }
6852 }
6853
6854 return ret;
6855 };
6856 } else if ( document.documentElement.currentStyle ) {
6857 curCSS = function( elem, name ) {
6858 var left, rsLeft,
6859 ret = elem.currentStyle && elem.currentStyle[ name ],
6860 style = elem.style;
6861
6862 // Avoid setting ret to empty string here
6863 // so we don't default to auto
6864 if ( ret == null && style && style[ name ] ) {
6865 ret = style[ name ];
6866 }
6867
6868 // From the awesome hack by Dean Edwards
6869 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6870
6871 // If we're not dealing with a regular pixel number
6872 // but a number that has a weird ending, we need to convert it to pixels
6873 // but not position css attributes, as those are proportional to the parent element instead
6874 // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
6875 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
6876
6877 // Remember the original values
6878 left = style.left;
6879 rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
6880
6881 // Put in the new values to get a computed value out
6882 if ( rsLeft ) {
6883 elem.runtimeStyle.left = elem.currentStyle.left;
6884 }
6885 style.left = name === "fontSize" ? "1em" : ret;
6886 ret = style.pixelLeft + "px";
6887
6888 // Revert the changed values
6889 style.left = left;
6890 if ( rsLeft ) {
6891 elem.runtimeStyle.left = rsLeft;
6892 }
6893 }
6894
6895 return ret === "" ? "auto" : ret;
6896 };
6897 }
6898
6899 function setPositiveNumber( elem, value, subtract ) {
6900 var matches = rnumsplit.exec( value );
6901 return matches ?
6902 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
6903 value;
6904 }
6905
6906 function augmentWidthOrHeight( elem, name, extra, isBorderBox ) {
6907 var i = extra === ( isBorderBox ? "border" : "content" ) ?
6908 // If we already have the right measurement, avoid augmentation
6909 4 :
6910 // Otherwise initialize for horizontal or vertical properties
6911 name === "width" ? 1 : 0,
6912
6913 val = 0;
6914
6915 for ( ; i < 4; i += 2 ) {
6916 // both box models exclude margin, so add it if we want it
6917 if ( extra === "margin" ) {
6918 // we use jQuery.css instead of curCSS here
6919 // because of the reliableMarginRight CSS hook!
6920 val += jQuery.css( elem, extra + cssExpand[ i ], true );
6921 }
6922
6923 // From this point on we use curCSS for maximum performance (relevant in animations)
6924 if ( isBorderBox ) {
6925 // border-box includes padding, so remove it if we want content
6926 if ( extra === "content" ) {
6927 val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
6928 }
6929
6930 // at this point, extra isn't border nor margin, so remove border
6931 if ( extra !== "margin" ) {
6932 val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
6933 }
6934 } else {
6935 // at this point, extra isn't content, so add padding
6936 val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0;
6937
6938 // at this point, extra isn't content nor padding, so add border
6939 if ( extra !== "padding" ) {
6940 val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0;
6941 }
6942 }
6943 }
6944
6945 return val;
6946 }
6947
6948 function getWidthOrHeight( elem, name, extra ) {
6949
6950 // Start with offset property, which is equivalent to the border-box value
6951 var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
6952 valueIsBorderBox = true,
6953 isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box";
6954
6955 // some non-html elements return undefined for offsetWidth, so check for null/undefined
6956 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
6957 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
6958 if ( val <= 0 || val == null ) {
6959 // Fall back to computed then uncomputed css if necessary
6960 val = curCSS( elem, name );
6961 if ( val < 0 || val == null ) {
6962 val = elem.style[ name ];
6963 }
6964
6965 // Computed unit is not pixels. Stop here and return.
6966 if ( rnumnonpx.test(val) ) {
6967 return val;
6968 }
6969
6970 // we need the check for style in case a browser which returns unreliable values
6971 // for getComputedStyle silently falls back to the reliable elem.style
6972 valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
6973
6974 // Normalize "", auto, and prepare for extra
6975 val = parseFloat( val ) || 0;
6976 }
6977
6978 // use the active box-sizing model to add/subtract irrelevant styles
6979 return ( val +
6980 augmentWidthOrHeight(
6981 elem,
6982 name,
6983 extra || ( isBorderBox ? "border" : "content" ),
6984 valueIsBorderBox
6985 )
6986 ) + "px";
6987 }
6988
6989
6990 // Try to determine the default display value of an element
6991 function css_defaultDisplay( nodeName ) {
6992 if ( elemdisplay[ nodeName ] ) {
6993 return elemdisplay[ nodeName ];
6994 }
6995
6996 var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ),
6997 display = elem.css("display");
6998 elem.remove();
6999
7000 // If the simple way fails,
7001 // get element's real default display by attaching it to a temp iframe
7002 if ( display === "none" || display === "" ) {
7003 // Use the already-created iframe if possible
7004 iframe = document.body.appendChild(
7005 iframe || jQuery.extend( document.createElement("iframe"), {
7006 frameBorder: 0,
7007 width: 0,
7008 height: 0
7009 })
7010 );
7011
7012 // Create a cacheable copy of the iframe document on first call.
7013 // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
7014 // document to it; WebKit & Firefox won't allow reusing the iframe document.
7015 if ( !iframeDoc || !iframe.createElement ) {
7016 iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
7017 iframeDoc.write("<!doctype html><html><body>");
7018 iframeDoc.close();
7019 }
7020
7021 elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) );
7022
7023 display = curCSS( elem, "display" );
7024 document.body.removeChild( iframe );
7025 }
7026
7027 // Store the correct default display
7028 elemdisplay[ nodeName ] = display;
7029
7030 return display;
7031 }
7032
7033 jQuery.each([ "height", "width" ], function( i, name ) {
7034 jQuery.cssHooks[ name ] = {
7035 get: function( elem, computed, extra ) {
7036 if ( computed ) {
7037 // certain elements can have dimension info if we invisibly show them
7038 // however, it must have a current display style that would benefit from this
7039 if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) {
7040 return jQuery.swap( elem, cssShow, function() {
7041 return getWidthOrHeight( elem, name, extra );
7042 });
7043 } else {
7044 return getWidthOrHeight( elem, name, extra );
7045 }
7046 }
7047 },
7048
7049 set: function( elem, value, extra ) {
7050 return setPositiveNumber( elem, value, extra ?
7051 augmentWidthOrHeight(
7052 elem,
7053 name,
7054 extra,
7055 jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"
7056 ) : 0
7057 );
7058 }
7059 };
7060 });
7061
7062 if ( !jQuery.support.opacity ) {
7063 jQuery.cssHooks.opacity = {
7064 get: function( elem, computed ) {
7065 // IE uses filters for opacity
7066 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7067 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7068 computed ? "1" : "";
7069 },
7070
7071 set: function( elem, value ) {
7072 var style = elem.style,
7073 currentStyle = elem.currentStyle,
7074 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7075 filter = currentStyle && currentStyle.filter || style.filter || "";
7076
7077 // IE has trouble with opacity if it does not have layout
7078 // Force it by setting the zoom level
7079 style.zoom = 1;
7080
7081 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7082 if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7083 style.removeAttribute ) {
7084
7085 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7086 // if "filter:" is present at all, clearType is disabled, we want to avoid this
7087 // style.removeAttribute is IE Only, but so apparently is this code path...
7088 style.removeAttribute( "filter" );
7089
7090 // if there there is no filter style applied in a css rule, we are done
7091 if ( currentStyle && !currentStyle.filter ) {
7092 return;
7093 }
7094 }
7095
7096 // otherwise, set new filter values
7097 style.filter = ralpha.test( filter ) ?
7098 filter.replace( ralpha, opacity ) :
7099 filter + " " + opacity;
7100 }
7101 };
7102 }
7103
7104 // These hooks cannot be added until DOM ready because the support test
7105 // for it is not run until after DOM ready
7106 jQuery(function() {
7107 if ( !jQuery.support.reliableMarginRight ) {
7108 jQuery.cssHooks.marginRight = {
7109 get: function( elem, computed ) {
7110 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7111 // Work around by temporarily setting element display to inline-block
7112 return jQuery.swap( elem, { "display": "inline-block" }, function() {
7113 if ( computed ) {
7114 return curCSS( elem, "marginRight" );
7115 }
7116 });
7117 }
7118 };
7119 }
7120
7121 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
7122 // getComputedStyle returns percent when specified for top/left/bottom/right
7123 // rather than make the css module depend on the offset module, we just check for it here
7124 if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
7125 jQuery.each( [ "top", "left" ], function( i, prop ) {
7126 jQuery.cssHooks[ prop ] = {
7127 get: function( elem, computed ) {
7128 if ( computed ) {
7129 var ret = curCSS( elem, prop );
7130 // if curCSS returns percentage, fallback to offset
7131 return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret;
7132 }
7133 }
7134 };
7135 });
7136 }
7137
7138 });
7139
7140 if ( jQuery.expr && jQuery.expr.filters ) {
7141 jQuery.expr.filters.hidden = function( elem ) {
7142 return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none");
7143 };
7144
7145 jQuery.expr.filters.visible = function( elem ) {
7146 return !jQuery.expr.filters.hidden( elem );
7147 };
7148 }
7149
7150 // These hooks are used by animate to expand properties
7151 jQuery.each({
7152 margin: "",
7153 padding: "",
7154 border: "Width"
7155 }, function( prefix, suffix ) {
7156 jQuery.cssHooks[ prefix + suffix ] = {
7157 expand: function( value ) {
7158 var i,
7159
7160 // assumes a single number if not a string
7161 parts = typeof value === "string" ? value.split(" ") : [ value ],
7162 expanded = {};
7163
7164 for ( i = 0; i < 4; i++ ) {
7165 expanded[ prefix + cssExpand[ i ] + suffix ] =
7166 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7167 }
7168
7169 return expanded;
7170 }
7171 };
7172
7173 if ( !rmargin.test( prefix ) ) {
7174 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7175 }
7176 });
7177 var r20 = /%20/g,
7178 rbracket = /\[\]$/,
7179 rCRLF = /\r?\n/g,
7180 rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
7181 rselectTextarea = /^(?:select|textarea)/i;
7182
7183 jQuery.fn.extend({
7184 serialize: function() {
7185 return jQuery.param( this.serializeArray() );
7186 },
7187 serializeArray: function() {
7188 return this.map(function(){
7189 return this.elements ? jQuery.makeArray( this.elements ) : this;
7190 })
7191 .filter(function(){
7192 return this.name && !this.disabled &&
7193 ( this.checked || rselectTextarea.test( this.nodeName ) ||
7194 rinput.test( this.type ) );
7195 })
7196 .map(function( i, elem ){
7197 var val = jQuery( this ).val();
7198
7199 return val == null ?
7200 null :
7201 jQuery.isArray( val ) ?
7202 jQuery.map( val, function( val, i ){
7203 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7204 }) :
7205 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7206 }).get();
7207 }
7208 });
7209
7210 //Serialize an array of form elements or a set of
7211 //key/values into a query string
7212 jQuery.param = function( a, traditional ) {
7213 var prefix,
7214 s = [],
7215 add = function( key, value ) {
7216 // If value is a function, invoke it and return its value
7217 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
7218 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7219 };
7220
7221 // Set traditional to true for jQuery <= 1.3.2 behavior.
7222 if ( traditional === undefined ) {
7223 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
7224 }
7225
7226 // If an array was passed in, assume that it is an array of form elements.
7227 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7228 // Serialize the form elements
7229 jQuery.each( a, function() {
7230 add( this.name, this.value );
7231 });
7232
7233 } else {
7234 // If traditional, encode the "old" way (the way 1.3.2 or older
7235 // did it), otherwise encode params recursively.
7236 for ( prefix in a ) {
7237 buildParams( prefix, a[ prefix ], traditional, add );
7238 }
7239 }
7240
7241 // Return the resulting serialization
7242 return s.join( "&" ).replace( r20, "+" );
7243 };
7244
7245 function buildParams( prefix, obj, traditional, add ) {
7246 var name;
7247
7248 if ( jQuery.isArray( obj ) ) {
7249 // Serialize array item.
7250 jQuery.each( obj, function( i, v ) {
7251 if ( traditional || rbracket.test( prefix ) ) {
7252 // Treat each array item as a scalar.
7253 add( prefix, v );
7254
7255 } else {
7256 // If array item is non-scalar (array or object), encode its
7257 // numeric index to resolve deserialization ambiguity issues.
7258 // Note that rack (as of 1.0.0) can't currently deserialize
7259 // nested arrays properly, and attempting to do so may cause
7260 // a server error. Possible fixes are to modify rack's
7261 // deserialization algorithm or to provide an option or flag
7262 // to force array serialization to be shallow.
7263 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
7264 }
7265 });
7266
7267 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
7268 // Serialize object item.
7269 for ( name in obj ) {
7270 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7271 }
7272
7273 } else {
7274 // Serialize scalar item.
7275 add( prefix, obj );
7276 }
7277 }
7278 var
7279 // Document location
7280 ajaxLocParts,
7281 ajaxLocation,
7282
7283 rhash = /#.*$/,
7284 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7285 // #7653, #8125, #8152: local protocol detection
7286 rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
7287 rnoContent = /^(?:GET|HEAD)$/,
7288 rprotocol = /^\/\//,
7289 rquery = /\?/,
7290 rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
7291 rts = /([?&])_=[^&]*/,
7292 rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
7293
7294 // Keep a copy of the old load method
7295 _load = jQuery.fn.load,
7296
7297 /* Prefilters
7298 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7299 * 2) These are called:
7300 * - BEFORE asking for a transport
7301 * - AFTER param serialization (s.data is a string if s.processData is true)
7302 * 3) key is the dataType
7303 * 4) the catchall symbol "*" can be used
7304 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7305 */
7306 prefilters = {},
7307
7308 /* Transports bindings
7309 * 1) key is the dataType
7310 * 2) the catchall symbol "*" can be used
7311 * 3) selection will start with transport dataType and THEN go to "*" if needed
7312 */
7313 transports = {},
7314
7315 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7316 allTypes = ["*/"] + ["*"];
7317
7318 // #8138, IE may throw an exception when accessing
7319 // a field from window.location if document.domain has been set
7320 try {
7321 ajaxLocation = location.href;
7322 } catch( e ) {
7323 // Use the href attribute of an A element
7324 // since IE will modify it given document.location
7325 ajaxLocation = document.createElement( "a" );
7326 ajaxLocation.href = "";
7327 ajaxLocation = ajaxLocation.href;
7328 }
7329
7330 // Segment location into parts
7331 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7332
7333 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7334 function addToPrefiltersOrTransports( structure ) {
7335
7336 // dataTypeExpression is optional and defaults to "*"
7337 return function( dataTypeExpression, func ) {
7338
7339 if ( typeof dataTypeExpression !== "string" ) {
7340 func = dataTypeExpression;
7341 dataTypeExpression = "*";
7342 }
7343
7344 var dataType, list, placeBefore,
7345 dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),
7346 i = 0,
7347 length = dataTypes.length;
7348
7349 if ( jQuery.isFunction( func ) ) {
7350 // For each dataType in the dataTypeExpression
7351 for ( ; i < length; i++ ) {
7352 dataType = dataTypes[ i ];
7353 // We control if we're asked to add before
7354 // any existing element
7355 placeBefore = /^\+/.test( dataType );
7356 if ( placeBefore ) {
7357 dataType = dataType.substr( 1 ) || "*";
7358 }
7359 list = structure[ dataType ] = structure[ dataType ] || [];
7360 // then we add to the structure accordingly
7361 list[ placeBefore ? "unshift" : "push" ]( func );
7362 }
7363 }
7364 };
7365 }
7366
7367 // Base inspection function for prefilters and transports
7368 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
7369 dataType /* internal */, inspected /* internal */ ) {
7370
7371 dataType = dataType || options.dataTypes[ 0 ];
7372 inspected = inspected || {};
7373
7374 inspected[ dataType ] = true;
7375
7376 var selection,
7377 list = structure[ dataType ],
7378 i = 0,
7379 length = list ? list.length : 0,
7380 executeOnly = ( structure === prefilters );
7381
7382 for ( ; i < length && ( executeOnly || !selection ); i++ ) {
7383 selection = list[ i ]( options, originalOptions, jqXHR );
7384 // If we got redirected to another dataType
7385 // we try there if executing only and not done already
7386 if ( typeof selection === "string" ) {
7387 if ( !executeOnly || inspected[ selection ] ) {
7388 selection = undefined;
7389 } else {
7390 options.dataTypes.unshift( selection );
7391 selection = inspectPrefiltersOrTransports(
7392 structure, options, originalOptions, jqXHR, selection, inspected );
7393 }
7394 }
7395 }
7396 // If we're only executing or nothing was selected
7397 // we try the catchall dataType if not done already
7398 if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
7399 selection = inspectPrefiltersOrTransports(
7400 structure, options, originalOptions, jqXHR, "*", inspected );
7401 }
7402 // unnecessary when only executing (prefilters)
7403 // but it'll be ignored by the caller in that case
7404 return selection;
7405 }
7406
7407 // A special extend for ajax options
7408 // that takes "flat" options (not to be deep extended)
7409 // Fixes #9887
7410 function ajaxExtend( target, src ) {
7411 var key, deep,
7412 flatOptions = jQuery.ajaxSettings.flatOptions || {};
7413 for ( key in src ) {
7414 if ( src[ key ] !== undefined ) {
7415 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
7416 }
7417 }
7418 if ( deep ) {
7419 jQuery.extend( true, target, deep );
7420 }
7421 }
7422
7423 jQuery.fn.load = function( url, params, callback ) {
7424 if ( typeof url !== "string" && _load ) {
7425 return _load.apply( this, arguments );
7426 }
7427
7428 // Don't do a request if no elements are being requested
7429 if ( !this.length ) {
7430 return this;
7431 }
7432
7433 var selector, type, response,
7434 self = this,
7435 off = url.indexOf(" ");
7436
7437 if ( off >= 0 ) {
7438 selector = url.slice( off, url.length );
7439 url = url.slice( 0, off );
7440 }
7441
7442 // If it's a function
7443 if ( jQuery.isFunction( params ) ) {
7444
7445 // We assume that it's the callback
7446 callback = params;
7447 params = undefined;
7448
7449 // Otherwise, build a param string
7450 } else if ( params && typeof params === "object" ) {
7451 type = "POST";
7452 }
7453
7454 // Request the remote document
7455 jQuery.ajax({
7456 url: url,
7457
7458 // if "type" variable is undefined, then "GET" method will be used
7459 type: type,
7460 dataType: "html",
7461 data: params,
7462 complete: function( jqXHR, status ) {
7463 if ( callback ) {
7464 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
7465 }
7466 }
7467 }).done(function( responseText ) {
7468
7469 // Save response for use in complete callback
7470 response = arguments;
7471
7472 // See if a selector was specified
7473 self.html( selector ?
7474
7475 // Create a dummy div to hold the results
7476 jQuery("<div>")
7477
7478 // inject the contents of the document in, removing the scripts
7479 // to avoid any 'Permission Denied' errors in IE
7480 .append( responseText.replace( rscript, "" ) )
7481
7482 // Locate the specified elements
7483 .find( selector ) :
7484
7485 // If not, just inject the full result
7486 responseText );
7487
7488 });
7489
7490 return this;
7491 };
7492
7493 // Attach a bunch of functions for handling common AJAX events
7494 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
7495 jQuery.fn[ o ] = function( f ){
7496 return this.on( o, f );
7497 };
7498 });
7499
7500 jQuery.each( [ "get", "post" ], function( i, method ) {
7501 jQuery[ method ] = function( url, data, callback, type ) {
7502 // shift arguments if data argument was omitted
7503 if ( jQuery.isFunction( data ) ) {
7504 type = type || callback;
7505 callback = data;
7506 data = undefined;
7507 }
7508
7509 return jQuery.ajax({
7510 type: method,
7511 url: url,
7512 data: data,
7513 success: callback,
7514 dataType: type
7515 });
7516 };
7517 });
7518
7519 jQuery.extend({
7520
7521 getScript: function( url, callback ) {
7522 return jQuery.get( url, undefined, callback, "script" );
7523 },
7524
7525 getJSON: function( url, data, callback ) {
7526 return jQuery.get( url, data, callback, "json" );
7527 },
7528
7529 // Creates a full fledged settings object into target
7530 // with both ajaxSettings and settings fields.
7531 // If target is omitted, writes into ajaxSettings.
7532 ajaxSetup: function( target, settings ) {
7533 if ( settings ) {
7534 // Building a settings object
7535 ajaxExtend( target, jQuery.ajaxSettings );
7536 } else {
7537 // Extending ajaxSettings
7538 settings = target;
7539 target = jQuery.ajaxSettings;
7540 }
7541 ajaxExtend( target, settings );
7542 return target;
7543 },
7544
7545 ajaxSettings: {
7546 url: ajaxLocation,
7547 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7548 global: true,
7549 type: "GET",
7550 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7551 processData: true,
7552 async: true,
7553 /*
7554 timeout: 0,
7555 data: null,
7556 dataType: null,
7557 username: null,
7558 password: null,
7559 cache: null,
7560 throws: false,
7561 traditional: false,
7562 headers: {},
7563 */
7564
7565 accepts: {
7566 xml: "application/xml, text/xml",
7567 html: "text/html",
7568 text: "text/plain",
7569 json: "application/json, text/javascript",
7570 "*": allTypes
7571 },
7572
7573 contents: {
7574 xml: /xml/,
7575 html: /html/,
7576 json: /json/
7577 },
7578
7579 responseFields: {
7580 xml: "responseXML",
7581 text: "responseText"
7582 },
7583
7584 // List of data converters
7585 // 1) key format is "source_type destination_type" (a single space in-between)
7586 // 2) the catchall symbol "*" can be used for source_type
7587 converters: {
7588
7589 // Convert anything to text
7590 "* text": window.String,
7591
7592 // Text to html (true = no transformation)
7593 "text html": true,
7594
7595 // Evaluate text as a json expression
7596 "text json": jQuery.parseJSON,
7597
7598 // Parse text as xml
7599 "text xml": jQuery.parseXML
7600 },
7601
7602 // For options that shouldn't be deep extended:
7603 // you can add your own custom options here if
7604 // and when you create one that shouldn't be
7605 // deep extended (see ajaxExtend)
7606 flatOptions: {
7607 context: true,
7608 url: true
7609 }
7610 },
7611
7612 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7613 ajaxTransport: addToPrefiltersOrTransports( transports ),
7614
7615 // Main method
7616 ajax: function( url, options ) {
7617
7618 // If url is an object, simulate pre-1.5 signature
7619 if ( typeof url === "object" ) {
7620 options = url;
7621 url = undefined;
7622 }
7623
7624 // Force options to be an object
7625 options = options || {};
7626
7627 var // ifModified key
7628 ifModifiedKey,
7629 // Response headers
7630 responseHeadersString,
7631 responseHeaders,
7632 // transport
7633 transport,
7634 // timeout handle
7635 timeoutTimer,
7636 // Cross-domain detection vars
7637 parts,
7638 // To know if global events are to be dispatched
7639 fireGlobals,
7640 // Loop variable
7641 i,
7642 // Create the final options object
7643 s = jQuery.ajaxSetup( {}, options ),
7644 // Callbacks context
7645 callbackContext = s.context || s,
7646 // Context for global events
7647 // It's the callbackContext if one was provided in the options
7648 // and if it's a DOM node or a jQuery collection
7649 globalEventContext = callbackContext !== s &&
7650 ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
7651 jQuery( callbackContext ) : jQuery.event,
7652 // Deferreds
7653 deferred = jQuery.Deferred(),
7654 completeDeferred = jQuery.Callbacks( "once memory" ),
7655 // Status-dependent callbacks
7656 statusCode = s.statusCode || {},
7657 // Headers (they are sent all at once)
7658 requestHeaders = {},
7659 requestHeadersNames = {},
7660 // The jqXHR state
7661 state = 0,
7662 // Default abort message
7663 strAbort = "canceled",
7664 // Fake xhr
7665 jqXHR = {
7666
7667 readyState: 0,
7668
7669 // Caches the header
7670 setRequestHeader: function( name, value ) {
7671 if ( !state ) {
7672 var lname = name.toLowerCase();
7673 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7674 requestHeaders[ name ] = value;
7675 }
7676 return this;
7677 },
7678
7679 // Raw string
7680 getAllResponseHeaders: function() {
7681 return state === 2 ? responseHeadersString : null;
7682 },
7683
7684 // Builds headers hashtable if needed
7685 getResponseHeader: function( key ) {
7686 var match;
7687 if ( state === 2 ) {
7688 if ( !responseHeaders ) {
7689 responseHeaders = {};
7690 while( ( match = rheaders.exec( responseHeadersString ) ) ) {
7691 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7692 }
7693 }
7694 match = responseHeaders[ key.toLowerCase() ];
7695 }
7696 return match === undefined ? null : match;
7697 },
7698
7699 // Overrides response content-type header
7700 overrideMimeType: function( type ) {
7701 if ( !state ) {
7702 s.mimeType = type;
7703 }
7704 return this;
7705 },
7706
7707 // Cancel the request
7708 abort: function( statusText ) {
7709 statusText = statusText || strAbort;
7710 if ( transport ) {
7711 transport.abort( statusText );
7712 }
7713 done( 0, statusText );
7714 return this;
7715 }
7716 };
7717
7718 // Callback for when everything is done
7719 // It is defined here because jslint complains if it is declared
7720 // at the end of the function (which would be more logical and readable)
7721 function done( status, nativeStatusText, responses, headers ) {
7722 var isSuccess, success, error, response, modified,
7723 statusText = nativeStatusText;
7724
7725 // Called once
7726 if ( state === 2 ) {
7727 return;
7728 }
7729
7730 // State is "done" now
7731 state = 2;
7732
7733 // Clear timeout if it exists
7734 if ( timeoutTimer ) {
7735 clearTimeout( timeoutTimer );
7736 }
7737
7738 // Dereference transport for early garbage collection
7739 // (no matter how long the jqXHR object will be used)
7740 transport = undefined;
7741
7742 // Cache response headers
7743 responseHeadersString = headers || "";
7744
7745 // Set readyState
7746 jqXHR.readyState = status > 0 ? 4 : 0;
7747
7748 // Get response data
7749 if ( responses ) {
7750 response = ajaxHandleResponses( s, jqXHR, responses );
7751 }
7752
7753 // If successful, handle type chaining
7754 if ( status >= 200 && status < 300 || status === 304 ) {
7755
7756 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7757 if ( s.ifModified ) {
7758
7759 modified = jqXHR.getResponseHeader("Last-Modified");
7760 if ( modified ) {
7761 jQuery.lastModified[ ifModifiedKey ] = modified;
7762 }
7763 modified = jqXHR.getResponseHeader("Etag");
7764 if ( modified ) {
7765 jQuery.etag[ ifModifiedKey ] = modified;
7766 }
7767 }
7768
7769 // If not modified
7770 if ( status === 304 ) {
7771
7772 statusText = "notmodified";
7773 isSuccess = true;
7774
7775 // If we have data
7776 } else {
7777
7778 isSuccess = ajaxConvert( s, response );
7779 statusText = isSuccess.state;
7780 success = isSuccess.data;
7781 error = isSuccess.error;
7782 isSuccess = !error;
7783 }
7784 } else {
7785 // We extract error from statusText
7786 // then normalize statusText and status for non-aborts
7787 error = statusText;
7788 if ( !statusText || status ) {
7789 statusText = "error";
7790 if ( status < 0 ) {
7791 status = 0;
7792 }
7793 }
7794 }
7795
7796 // Set data for the fake xhr object
7797 jqXHR.status = status;
7798 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
7799
7800 // Success/Error
7801 if ( isSuccess ) {
7802 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
7803 } else {
7804 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
7805 }
7806
7807 // Status-dependent callbacks
7808 jqXHR.statusCode( statusCode );
7809 statusCode = undefined;
7810
7811 if ( fireGlobals ) {
7812 globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
7813 [ jqXHR, s, isSuccess ? success : error ] );
7814 }
7815
7816 // Complete
7817 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
7818
7819 if ( fireGlobals ) {
7820 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
7821 // Handle the global AJAX counter
7822 if ( !( --jQuery.active ) ) {
7823 jQuery.event.trigger( "ajaxStop" );
7824 }
7825 }
7826 }
7827
7828 // Attach deferreds
7829 deferred.promise( jqXHR );
7830 jqXHR.success = jqXHR.done;
7831 jqXHR.error = jqXHR.fail;
7832 jqXHR.complete = completeDeferred.add;
7833
7834 // Status-dependent callbacks
7835 jqXHR.statusCode = function( map ) {
7836 if ( map ) {
7837 var tmp;
7838 if ( state < 2 ) {
7839 for ( tmp in map ) {
7840 statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
7841 }
7842 } else {
7843 tmp = map[ jqXHR.status ];
7844 jqXHR.always( tmp );
7845 }
7846 }
7847 return this;
7848 };
7849
7850 // Remove hash character (#7531: and string promotion)
7851 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7852 // We also use the url parameter if available
7853 s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7854
7855 // Extract dataTypes list
7856 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace );
7857
7858 // A cross-domain request is in order when we have a protocol:host:port mismatch
7859 if ( s.crossDomain == null ) {
7860 parts = rurl.exec( s.url.toLowerCase() );
7861 s.crossDomain = !!( parts &&
7862 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
7863 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7864 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7865 );
7866 }
7867
7868 // Convert data if not already a string
7869 if ( s.data && s.processData && typeof s.data !== "string" ) {
7870 s.data = jQuery.param( s.data, s.traditional );
7871 }
7872
7873 // Apply prefilters
7874 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7875
7876 // If request was aborted inside a prefilter, stop there
7877 if ( state === 2 ) {
7878 return jqXHR;
7879 }
7880
7881 // We can fire global events as of now if asked to
7882 fireGlobals = s.global;
7883
7884 // Uppercase the type
7885 s.type = s.type.toUpperCase();
7886
7887 // Determine if request has content
7888 s.hasContent = !rnoContent.test( s.type );
7889
7890 // Watch for a new set of requests
7891 if ( fireGlobals && jQuery.active++ === 0 ) {
7892 jQuery.event.trigger( "ajaxStart" );
7893 }
7894
7895 // More options handling for requests with no content
7896 if ( !s.hasContent ) {
7897
7898 // If data is available, append data to url
7899 if ( s.data ) {
7900 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
7901 // #9682: remove data so that it's not used in an eventual retry
7902 delete s.data;
7903 }
7904
7905 // Get ifModifiedKey before adding the anti-cache parameter
7906 ifModifiedKey = s.url;
7907
7908 // Add anti-cache in url if needed
7909 if ( s.cache === false ) {
7910
7911 var ts = jQuery.now(),
7912 // try replacing _= if it is there
7913 ret = s.url.replace( rts, "$1_=" + ts );
7914
7915 // if nothing was replaced, add timestamp to the end
7916 s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
7917 }
7918 }
7919
7920 // Set the correct header, if data is being sent
7921 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7922 jqXHR.setRequestHeader( "Content-Type", s.contentType );
7923 }
7924
7925 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7926 if ( s.ifModified ) {
7927 ifModifiedKey = ifModifiedKey || s.url;
7928 if ( jQuery.lastModified[ ifModifiedKey ] ) {
7929 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
7930 }
7931 if ( jQuery.etag[ ifModifiedKey ] ) {
7932 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
7933 }
7934 }
7935
7936 // Set the Accepts header for the server, depending on the dataType
7937 jqXHR.setRequestHeader(
7938 "Accept",
7939 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7940 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
7941 s.accepts[ "*" ]
7942 );
7943
7944 // Check for headers option
7945 for ( i in s.headers ) {
7946 jqXHR.setRequestHeader( i, s.headers[ i ] );
7947 }
7948
7949 // Allow custom headers/mimetypes and early abort
7950 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7951 // Abort if not done already and return
7952 return jqXHR.abort();
7953
7954 }
7955
7956 // aborting is no longer a cancellation
7957 strAbort = "abort";
7958
7959 // Install callbacks on deferreds
7960 for ( i in { success: 1, error: 1, complete: 1 } ) {
7961 jqXHR[ i ]( s[ i ] );
7962 }
7963
7964 // Get transport
7965 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
7966
7967 // If no transport, we auto-abort
7968 if ( !transport ) {
7969 done( -1, "No Transport" );
7970 } else {
7971 jqXHR.readyState = 1;
7972 // Send global event
7973 if ( fireGlobals ) {
7974 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
7975 }
7976 // Timeout
7977 if ( s.async && s.timeout > 0 ) {
7978 timeoutTimer = setTimeout( function(){
7979 jqXHR.abort( "timeout" );
7980 }, s.timeout );
7981 }
7982
7983 try {
7984 state = 1;
7985 transport.send( requestHeaders, done );
7986 } catch (e) {
7987 // Propagate exception as error if not done
7988 if ( state < 2 ) {
7989 done( -1, e );
7990 // Simply rethrow otherwise
7991 } else {
7992 throw e;
7993 }
7994 }
7995 }
7996
7997 return jqXHR;
7998 },
7999
8000 // Counter for holding the number of active queries
8001 active: 0,
8002
8003 // Last-Modified header cache for next request
8004 lastModified: {},
8005 etag: {}
8006
8007 });
8008
8009 /* Handles responses to an ajax request:
8010 * - sets all responseXXX fields accordingly
8011 * - finds the right dataType (mediates between content-type and expected dataType)
8012 * - returns the corresponding response
8013 */
8014 function ajaxHandleResponses( s, jqXHR, responses ) {
8015
8016 var ct, type, finalDataType, firstDataType,
8017 contents = s.contents,
8018 dataTypes = s.dataTypes,
8019 responseFields = s.responseFields;
8020
8021 // Fill responseXXX fields
8022 for ( type in responseFields ) {
8023 if ( type in responses ) {
8024 jqXHR[ responseFields[type] ] = responses[ type ];
8025 }
8026 }
8027
8028 // Remove auto dataType and get content-type in the process
8029 while( dataTypes[ 0 ] === "*" ) {
8030 dataTypes.shift();
8031 if ( ct === undefined ) {
8032 ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
8033 }
8034 }
8035
8036 // Check if we're dealing with a known content-type
8037 if ( ct ) {
8038 for ( type in contents ) {
8039 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8040 dataTypes.unshift( type );
8041 break;
8042 }
8043 }
8044 }
8045
8046 // Check to see if we have a response for the expected dataType
8047 if ( dataTypes[ 0 ] in responses ) {
8048 finalDataType = dataTypes[ 0 ];
8049 } else {
8050 // Try convertible dataTypes
8051 for ( type in responses ) {
8052 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8053 finalDataType = type;
8054 break;
8055 }
8056 if ( !firstDataType ) {
8057 firstDataType = type;
8058 }
8059 }
8060 // Or just use first one
8061 finalDataType = finalDataType || firstDataType;
8062 }
8063
8064 // If we found a dataType
8065 // We add the dataType to the list if needed
8066 // and return the corresponding response
8067 if ( finalDataType ) {
8068 if ( finalDataType !== dataTypes[ 0 ] ) {
8069 dataTypes.unshift( finalDataType );
8070 }
8071 return responses[ finalDataType ];
8072 }
8073 }
8074
8075 // Chain conversions given the request and the original response
8076 function ajaxConvert( s, response ) {
8077
8078 var conv, conv2, current, tmp,
8079 // Work with a copy of dataTypes in case we need to modify it for conversion
8080 dataTypes = s.dataTypes.slice(),
8081 prev = dataTypes[ 0 ],
8082 converters = {},
8083 i = 0;
8084
8085 // Apply the dataFilter if provided
8086 if ( s.dataFilter ) {
8087 response = s.dataFilter( response, s.dataType );
8088 }
8089
8090 // Create converters map with lowercased keys
8091 if ( dataTypes[ 1 ] ) {
8092 for ( conv in s.converters ) {
8093 converters[ conv.toLowerCase() ] = s.converters[ conv ];
8094 }
8095 }
8096
8097 // Convert to each sequential dataType, tolerating list modification
8098 for ( ; (current = dataTypes[++i]); ) {
8099
8100 // There's only work to do if current dataType is non-auto
8101 if ( current !== "*" ) {
8102
8103 // Convert response if prev dataType is non-auto and differs from current
8104 if ( prev !== "*" && prev !== current ) {
8105
8106 // Seek a direct converter
8107 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8108
8109 // If none found, seek a pair
8110 if ( !conv ) {
8111 for ( conv2 in converters ) {
8112
8113 // If conv2 outputs current
8114 tmp = conv2.split(" ");
8115 if ( tmp[ 1 ] === current ) {
8116
8117 // If prev can be converted to accepted input
8118 conv = converters[ prev + " " + tmp[ 0 ] ] ||
8119 converters[ "* " + tmp[ 0 ] ];
8120 if ( conv ) {
8121 // Condense equivalence converters
8122 if ( conv === true ) {
8123 conv = converters[ conv2 ];
8124
8125 // Otherwise, insert the intermediate dataType
8126 } else if ( converters[ conv2 ] !== true ) {
8127 current = tmp[ 0 ];
8128 dataTypes.splice( i--, 0, current );
8129 }
8130
8131 break;
8132 }
8133 }
8134 }
8135 }
8136
8137 // Apply converter (if not an equivalence)
8138 if ( conv !== true ) {
8139
8140 // Unless errors are allowed to bubble, catch and return them
8141 if ( conv && s["throws"] ) {
8142 response = conv( response );
8143 } else {
8144 try {
8145 response = conv( response );
8146 } catch ( e ) {
8147 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8148 }
8149 }
8150 }
8151 }
8152
8153 // Update prev for next iteration
8154 prev = current;
8155 }
8156 }
8157
8158 return { state: "success", data: response };
8159 }
8160 var oldCallbacks = [],
8161 rquestion = /\?/,
8162 rjsonp = /(=)\?(?=&|$)|\?\?/,
8163 nonce = jQuery.now();
8164
8165 // Default jsonp settings
8166 jQuery.ajaxSetup({
8167 jsonp: "callback",
8168 jsonpCallback: function() {
8169 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
8170 this[ callback ] = true;
8171 return callback;
8172 }
8173 });
8174
8175 // Detect, normalize options and install callbacks for jsonp requests
8176 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8177
8178 var callbackName, overwritten, responseContainer,
8179 data = s.data,
8180 url = s.url,
8181 hasCallback = s.jsonp !== false,
8182 replaceInUrl = hasCallback && rjsonp.test( url ),
8183 replaceInData = hasCallback && !replaceInUrl && typeof data === "string" &&
8184 !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") &&
8185 rjsonp.test( data );
8186
8187 // Handle iff the expected data type is "jsonp" or we have a parameter to set
8188 if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) {
8189
8190 // Get callback name, remembering preexisting value associated with it
8191 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8192 s.jsonpCallback() :
8193 s.jsonpCallback;
8194 overwritten = window[ callbackName ];
8195
8196 // Insert callback into url or form data
8197 if ( replaceInUrl ) {
8198 s.url = url.replace( rjsonp, "$1" + callbackName );
8199 } else if ( replaceInData ) {
8200 s.data = data.replace( rjsonp, "$1" + callbackName );
8201 } else if ( hasCallback ) {
8202 s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8203 }
8204
8205 // Use data converter to retrieve json after script execution
8206 s.converters["script json"] = function() {
8207 if ( !responseContainer ) {
8208 jQuery.error( callbackName + " was not called" );
8209 }
8210 return responseContainer[ 0 ];
8211 };
8212
8213 // force json dataType
8214 s.dataTypes[ 0 ] = "json";
8215
8216 // Install callback
8217 window[ callbackName ] = function() {
8218 responseContainer = arguments;
8219 };
8220
8221 // Clean-up function (fires after converters)
8222 jqXHR.always(function() {
8223 // Restore preexisting value
8224 window[ callbackName ] = overwritten;
8225
8226 // Save back as free
8227 if ( s[ callbackName ] ) {
8228 // make sure that re-using the options doesn't screw things around
8229 s.jsonpCallback = originalSettings.jsonpCallback;
8230
8231 // save the callback name for future use
8232 oldCallbacks.push( callbackName );
8233 }
8234
8235 // Call if it was a function and we have a response
8236 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8237 overwritten( responseContainer[ 0 ] );
8238 }
8239
8240 responseContainer = overwritten = undefined;
8241 });
8242
8243 // Delegate to script
8244 return "script";
8245 }
8246 });
8247 // Install script dataType
8248 jQuery.ajaxSetup({
8249 accepts: {
8250 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8251 },
8252 contents: {
8253 script: /javascript|ecmascript/
8254 },
8255 converters: {
8256 "text script": function( text ) {
8257 jQuery.globalEval( text );
8258 return text;
8259 }
8260 }
8261 });
8262
8263 // Handle cache's special case and global
8264 jQuery.ajaxPrefilter( "script", function( s ) {
8265 if ( s.cache === undefined ) {
8266 s.cache = false;
8267 }
8268 if ( s.crossDomain ) {
8269 s.type = "GET";
8270 s.global = false;
8271 }
8272 });
8273
8274 // Bind script tag hack transport
8275 jQuery.ajaxTransport( "script", function(s) {
8276
8277 // This transport only deals with cross domain requests
8278 if ( s.crossDomain ) {
8279
8280 var script,
8281 head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
8282
8283 return {
8284
8285 send: function( _, callback ) {
8286
8287 script = document.createElement( "script" );
8288
8289 script.async = "async";
8290
8291 if ( s.scriptCharset ) {
8292 script.charset = s.scriptCharset;
8293 }
8294
8295 script.src = s.url;
8296
8297 // Attach handlers for all browsers
8298 script.onload = script.onreadystatechange = function( _, isAbort ) {
8299
8300 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8301
8302 // Handle memory leak in IE
8303 script.onload = script.onreadystatechange = null;
8304
8305 // Remove the script
8306 if ( head && script.parentNode ) {
8307 head.removeChild( script );
8308 }
8309
8310 // Dereference the script
8311 script = undefined;
8312
8313 // Callback if not abort
8314 if ( !isAbort ) {
8315 callback( 200, "success" );
8316 }
8317 }
8318 };
8319 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
8320 // This arises when a base node is used (#2709 and #4378).
8321 head.insertBefore( script, head.firstChild );
8322 },
8323
8324 abort: function() {
8325 if ( script ) {
8326 script.onload( 0, 1 );
8327 }
8328 }
8329 };
8330 }
8331 });
8332 var xhrCallbacks,
8333 // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8334 xhrOnUnloadAbort = window.ActiveXObject ? function() {
8335 // Abort all pending requests
8336 for ( var key in xhrCallbacks ) {
8337 xhrCallbacks[ key ]( 0, 1 );
8338 }
8339 } : false,
8340 xhrId = 0;
8341
8342 // Functions to create xhrs
8343 function createStandardXHR() {
8344 try {
8345 return new window.XMLHttpRequest();
8346 } catch( e ) {}
8347 }
8348
8349 function createActiveXHR() {
8350 try {
8351 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
8352 } catch( e ) {}
8353 }
8354
8355 // Create the request object
8356 // (This is still attached to ajaxSettings for backward compatibility)
8357 jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8358 /* Microsoft failed to properly
8359 * implement the XMLHttpRequest in IE7 (can't request local files),
8360 * so we use the ActiveXObject when it is available
8361 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8362 * we need a fallback.
8363 */
8364 function() {
8365 return !this.isLocal && createStandardXHR() || createActiveXHR();
8366 } :
8367 // For all other browsers, use the standard XMLHttpRequest object
8368 createStandardXHR;
8369
8370 // Determine support properties
8371 (function( xhr ) {
8372 jQuery.extend( jQuery.support, {
8373 ajax: !!xhr,
8374 cors: !!xhr && ( "withCredentials" in xhr )
8375 });
8376 })( jQuery.ajaxSettings.xhr() );
8377
8378 // Create transport if the browser can provide an xhr
8379 if ( jQuery.support.ajax ) {
8380
8381 jQuery.ajaxTransport(function( s ) {
8382 // Cross domain only allowed if supported through XMLHttpRequest
8383 if ( !s.crossDomain || jQuery.support.cors ) {
8384
8385 var callback;
8386
8387 return {
8388 send: function( headers, complete ) {
8389
8390 // Get a new xhr
8391 var handle, i,
8392 xhr = s.xhr();
8393
8394 // Open the socket
8395 // Passing null username, generates a login popup on Opera (#2865)
8396 if ( s.username ) {
8397 xhr.open( s.type, s.url, s.async, s.username, s.password );
8398 } else {
8399 xhr.open( s.type, s.url, s.async );
8400 }
8401
8402 // Apply custom fields if provided
8403 if ( s.xhrFields ) {
8404 for ( i in s.xhrFields ) {
8405 xhr[ i ] = s.xhrFields[ i ];
8406 }
8407 }
8408
8409 // Override mime type if needed
8410 if ( s.mimeType && xhr.overrideMimeType ) {
8411 xhr.overrideMimeType( s.mimeType );
8412 }
8413
8414 // X-Requested-With header
8415 // For cross-domain requests, seeing as conditions for a preflight are
8416 // akin to a jigsaw puzzle, we simply never set it to be sure.
8417 // (it can always be set on a per-request basis or even using ajaxSetup)
8418 // For same-domain requests, won't change header if already provided.
8419 if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8420 headers[ "X-Requested-With" ] = "XMLHttpRequest";
8421 }
8422
8423 // Need an extra try/catch for cross domain requests in Firefox 3
8424 try {
8425 for ( i in headers ) {
8426 xhr.setRequestHeader( i, headers[ i ] );
8427 }
8428 } catch( _ ) {}
8429
8430 // Do send the request
8431 // This may raise an exception which is actually
8432 // handled in jQuery.ajax (so no try/catch here)
8433 xhr.send( ( s.hasContent && s.data ) || null );
8434
8435 // Listener
8436 callback = function( _, isAbort ) {
8437
8438 var status,
8439 statusText,
8440 responseHeaders,
8441 responses,
8442 xml;
8443
8444 // Firefox throws exceptions when accessing properties
8445 // of an xhr when a network error occurred
8446 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8447 try {
8448
8449 // Was never called and is aborted or complete
8450 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8451
8452 // Only called once
8453 callback = undefined;
8454
8455 // Do not keep as active anymore
8456 if ( handle ) {
8457 xhr.onreadystatechange = jQuery.noop;
8458 if ( xhrOnUnloadAbort ) {
8459 delete xhrCallbacks[ handle ];
8460 }
8461 }
8462
8463 // If it's an abort
8464 if ( isAbort ) {
8465 // Abort it manually if needed
8466 if ( xhr.readyState !== 4 ) {
8467 xhr.abort();
8468 }
8469 } else {
8470 status = xhr.status;
8471 responseHeaders = xhr.getAllResponseHeaders();
8472 responses = {};
8473 xml = xhr.responseXML;
8474
8475 // Construct response list
8476 if ( xml && xml.documentElement /* #4958 */ ) {
8477 responses.xml = xml;
8478 }
8479
8480 // When requesting binary data, IE6-9 will throw an exception
8481 // on any attempt to access responseText (#11426)
8482 try {
8483 responses.text = xhr.responseText;
8484 } catch( e ) {
8485 }
8486
8487 // Firefox throws an exception when accessing
8488 // statusText for faulty cross-domain requests
8489 try {
8490 statusText = xhr.statusText;
8491 } catch( e ) {
8492 // We normalize with Webkit giving an empty statusText
8493 statusText = "";
8494 }
8495
8496 // Filter status for non standard behaviors
8497
8498 // If the request is local and we have data: assume a success
8499 // (success with no data won't get notified, that's the best we
8500 // can do given current implementations)
8501 if ( !status && s.isLocal && !s.crossDomain ) {
8502 status = responses.text ? 200 : 404;
8503 // IE - #1450: sometimes returns 1223 when it should be 204
8504 } else if ( status === 1223 ) {
8505 status = 204;
8506 }
8507 }
8508 }
8509 } catch( firefoxAccessException ) {
8510 if ( !isAbort ) {
8511 complete( -1, firefoxAccessException );
8512 }
8513 }
8514
8515 // Call complete if needed
8516 if ( responses ) {
8517 complete( status, statusText, responses, responseHeaders );
8518 }
8519 };
8520
8521 if ( !s.async ) {
8522 // if we're in sync mode we fire the callback
8523 callback();
8524 } else if ( xhr.readyState === 4 ) {
8525 // (IE6 & IE7) if it's in cache and has been
8526 // retrieved directly we need to fire the callback
8527 setTimeout( callback, 0 );
8528 } else {
8529 handle = ++xhrId;
8530 if ( xhrOnUnloadAbort ) {
8531 // Create the active xhrs callbacks list if needed
8532 // and attach the unload handler
8533 if ( !xhrCallbacks ) {
8534 xhrCallbacks = {};
8535 jQuery( window ).unload( xhrOnUnloadAbort );
8536 }
8537 // Add to list of active xhrs callbacks
8538 xhrCallbacks[ handle ] = callback;
8539 }
8540 xhr.onreadystatechange = callback;
8541 }
8542 },
8543
8544 abort: function() {
8545 if ( callback ) {
8546 callback(0,1);
8547 }
8548 }
8549 };
8550 }
8551 });
8552 }
8553 var fxNow, timerId,
8554 rfxtypes = /^(?:toggle|show|hide)$/,
8555 rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
8556 rrun = /queueHooks$/,
8557 animationPrefilters = [ defaultPrefilter ],
8558 tweeners = {
8559 "*": [function( prop, value ) {
8560 var end, unit,
8561 tween = this.createTween( prop, value ),
8562 parts = rfxnum.exec( value ),
8563 target = tween.cur(),
8564 start = +target || 0,
8565 scale = 1,
8566 maxIterations = 20;
8567
8568 if ( parts ) {
8569 end = +parts[2];
8570 unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8571
8572 // We need to compute starting value
8573 if ( unit !== "px" && start ) {
8574 // Iteratively approximate from a nonzero starting point
8575 // Prefer the current property, because this process will be trivial if it uses the same units
8576 // Fallback to end or a simple constant
8577 start = jQuery.css( tween.elem, prop, true ) || end || 1;
8578
8579 do {
8580 // If previous iteration zeroed out, double until we get *something*
8581 // Use a string for doubling factor so we don't accidentally see scale as unchanged below
8582 scale = scale || ".5";
8583
8584 // Adjust and apply
8585 start = start / scale;
8586 jQuery.style( tween.elem, prop, start + unit );
8587
8588 // Update scale, tolerating zero or NaN from tween.cur()
8589 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8590 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8591 }
8592
8593 tween.unit = unit;
8594 tween.start = start;
8595 // If a +=/-= token was provided, we're doing a relative animation
8596 tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
8597 }
8598 return tween;
8599 }]
8600 };
8601
8602 // Animations created synchronously will run synchronously
8603 function createFxNow() {
8604 setTimeout(function() {
8605 fxNow = undefined;
8606 }, 0 );
8607 return ( fxNow = jQuery.now() );
8608 }
8609
8610 function createTweens( animation, props ) {
8611 jQuery.each( props, function( prop, value ) {
8612 var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8613 index = 0,
8614 length = collection.length;
8615 for ( ; index < length; index++ ) {
8616 if ( collection[ index ].call( animation, prop, value ) ) {
8617
8618 // we're done with this property
8619 return;
8620 }
8621 }
8622 });
8623 }
8624
8625 function Animation( elem, properties, options ) {
8626 var result,
8627 index = 0,
8628 tweenerIndex = 0,
8629 length = animationPrefilters.length,
8630 deferred = jQuery.Deferred().always( function() {
8631 // don't match elem in the :animated selector
8632 delete tick.elem;
8633 }),
8634 tick = function() {
8635 var currentTime = fxNow || createFxNow(),
8636 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8637 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8638 temp = remaining / animation.duration || 0,
8639 percent = 1 - temp,
8640 index = 0,
8641 length = animation.tweens.length;
8642
8643 for ( ; index < length ; index++ ) {
8644 animation.tweens[ index ].run( percent );
8645 }
8646
8647 deferred.notifyWith( elem, [ animation, percent, remaining ]);
8648
8649 if ( percent < 1 && length ) {
8650 return remaining;
8651 } else {
8652 deferred.resolveWith( elem, [ animation ] );
8653 return false;
8654 }
8655 },
8656 animation = deferred.promise({
8657 elem: elem,
8658 props: jQuery.extend( {}, properties ),
8659 opts: jQuery.extend( true, { specialEasing: {} }, options ),
8660 originalProperties: properties,
8661 originalOptions: options,
8662 startTime: fxNow || createFxNow(),
8663 duration: options.duration,
8664 tweens: [],
8665 createTween: function( prop, end, easing ) {
8666 var tween = jQuery.Tween( elem, animation.opts, prop, end,
8667 animation.opts.specialEasing[ prop ] || animation.opts.easing );
8668 animation.tweens.push( tween );
8669 return tween;
8670 },
8671 stop: function( gotoEnd ) {
8672 var index = 0,
8673 // if we are going to the end, we want to run all the tweens
8674 // otherwise we skip this part
8675 length = gotoEnd ? animation.tweens.length : 0;
8676
8677 for ( ; index < length ; index++ ) {
8678 animation.tweens[ index ].run( 1 );
8679 }
8680
8681 // resolve when we played the last frame
8682 // otherwise, reject
8683 if ( gotoEnd ) {
8684 deferred.resolveWith( elem, [ animation, gotoEnd ] );
8685 } else {
8686 deferred.rejectWith( elem, [ animation, gotoEnd ] );
8687 }
8688 return this;
8689 }
8690 }),
8691 props = animation.props;
8692
8693 propFilter( props, animation.opts.specialEasing );
8694
8695 for ( ; index < length ; index++ ) {
8696 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
8697 if ( result ) {
8698 return result;
8699 }
8700 }
8701
8702 createTweens( animation, props );
8703
8704 if ( jQuery.isFunction( animation.opts.start ) ) {
8705 animation.opts.start.call( elem, animation );
8706 }
8707
8708 jQuery.fx.timer(
8709 jQuery.extend( tick, {
8710 anim: animation,
8711 queue: animation.opts.queue,
8712 elem: elem
8713 })
8714 );
8715
8716 // attach callbacks from options
8717 return animation.progress( animation.opts.progress )
8718 .done( animation.opts.done, animation.opts.complete )
8719 .fail( animation.opts.fail )
8720 .always( animation.opts.always );
8721 }
8722
8723 function propFilter( props, specialEasing ) {
8724 var index, name, easing, value, hooks;
8725
8726 // camelCase, specialEasing and expand cssHook pass
8727 for ( index in props ) {
8728 name = jQuery.camelCase( index );
8729 easing = specialEasing[ name ];
8730 value = props[ index ];
8731 if ( jQuery.isArray( value ) ) {
8732 easing = value[ 1 ];
8733 value = props[ index ] = value[ 0 ];
8734 }
8735
8736 if ( index !== name ) {
8737 props[ name ] = value;
8738 delete props[ index ];
8739 }
8740
8741 hooks = jQuery.cssHooks[ name ];
8742 if ( hooks && "expand" in hooks ) {
8743 value = hooks.expand( value );
8744 delete props[ name ];
8745
8746 // not quite $.extend, this wont overwrite keys already present.
8747 // also - reusing 'index' from above because we have the correct "name"
8748 for ( index in value ) {
8749 if ( !( index in props ) ) {
8750 props[ index ] = value[ index ];
8751 specialEasing[ index ] = easing;
8752 }
8753 }
8754 } else {
8755 specialEasing[ name ] = easing;
8756 }
8757 }
8758 }
8759
8760 jQuery.Animation = jQuery.extend( Animation, {
8761
8762 tweener: function( props, callback ) {
8763 if ( jQuery.isFunction( props ) ) {
8764 callback = props;
8765 props = [ "*" ];
8766 } else {
8767 props = props.split(" ");
8768 }
8769
8770 var prop,
8771 index = 0,
8772 length = props.length;
8773
8774 for ( ; index < length ; index++ ) {
8775 prop = props[ index ];
8776 tweeners[ prop ] = tweeners[ prop ] || [];
8777 tweeners[ prop ].unshift( callback );
8778 }
8779 },
8780
8781 prefilter: function( callback, prepend ) {
8782 if ( prepend ) {
8783 animationPrefilters.unshift( callback );
8784 } else {
8785 animationPrefilters.push( callback );
8786 }
8787 }
8788 });
8789
8790 function defaultPrefilter( elem, props, opts ) {
8791 var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire,
8792 anim = this,
8793 style = elem.style,
8794 orig = {},
8795 handled = [],
8796 hidden = elem.nodeType && isHidden( elem );
8797
8798 // handle queue: false promises
8799 if ( !opts.queue ) {
8800 hooks = jQuery._queueHooks( elem, "fx" );
8801 if ( hooks.unqueued == null ) {
8802 hooks.unqueued = 0;
8803 oldfire = hooks.empty.fire;
8804 hooks.empty.fire = function() {
8805 if ( !hooks.unqueued ) {
8806 oldfire();
8807 }
8808 };
8809 }
8810 hooks.unqueued++;
8811
8812 anim.always(function() {
8813 // doing this makes sure that the complete handler will be called
8814 // before this completes
8815 anim.always(function() {
8816 hooks.unqueued--;
8817 if ( !jQuery.queue( elem, "fx" ).length ) {
8818 hooks.empty.fire();
8819 }
8820 });
8821 });
8822 }
8823
8824 // height/width overflow pass
8825 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
8826 // Make sure that nothing sneaks out
8827 // Record all 3 overflow attributes because IE does not
8828 // change the overflow attribute when overflowX and
8829 // overflowY are set to the same value
8830 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
8831
8832 // Set display property to inline-block for height/width
8833 // animations on inline elements that are having width/height animated
8834 if ( jQuery.css( elem, "display" ) === "inline" &&
8835 jQuery.css( elem, "float" ) === "none" ) {
8836
8837 // inline-level elements accept inline-block;
8838 // block-level elements need to be inline with layout
8839 if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
8840 style.display = "inline-block";
8841
8842 } else {
8843 style.zoom = 1;
8844 }
8845 }
8846 }
8847
8848 if ( opts.overflow ) {
8849 style.overflow = "hidden";
8850 if ( !jQuery.support.shrinkWrapBlocks ) {
8851 anim.done(function() {
8852 style.overflow = opts.overflow[ 0 ];
8853 style.overflowX = opts.overflow[ 1 ];
8854 style.overflowY = opts.overflow[ 2 ];
8855 });
8856 }
8857 }
8858
8859
8860 // show/hide pass
8861 for ( index in props ) {
8862 value = props[ index ];
8863 if ( rfxtypes.exec( value ) ) {
8864 delete props[ index ];
8865 toggle = toggle || value === "toggle";
8866 if ( value === ( hidden ? "hide" : "show" ) ) {
8867 continue;
8868 }
8869 handled.push( index );
8870 }
8871 }
8872
8873 length = handled.length;
8874 if ( length ) {
8875 dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
8876 if ( "hidden" in dataShow ) {
8877 hidden = dataShow.hidden;
8878 }
8879
8880 // store state if its toggle - enables .stop().toggle() to "reverse"
8881 if ( toggle ) {
8882 dataShow.hidden = !hidden;
8883 }
8884 if ( hidden ) {
8885 jQuery( elem ).show();
8886 } else {
8887 anim.done(function() {
8888 jQuery( elem ).hide();
8889 });
8890 }
8891 anim.done(function() {
8892 var prop;
8893 jQuery.removeData( elem, "fxshow", true );
8894 for ( prop in orig ) {
8895 jQuery.style( elem, prop, orig[ prop ] );
8896 }
8897 });
8898 for ( index = 0 ; index < length ; index++ ) {
8899 prop = handled[ index ];
8900 tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
8901 orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
8902
8903 if ( !( prop in dataShow ) ) {
8904 dataShow[ prop ] = tween.start;
8905 if ( hidden ) {
8906 tween.end = tween.start;
8907 tween.start = prop === "width" || prop === "height" ? 1 : 0;
8908 }
8909 }
8910 }
8911 }
8912 }
8913
8914 function Tween( elem, options, prop, end, easing ) {
8915 return new Tween.prototype.init( elem, options, prop, end, easing );
8916 }
8917 jQuery.Tween = Tween;
8918
8919 Tween.prototype = {
8920 constructor: Tween,
8921 init: function( elem, options, prop, end, easing, unit ) {
8922 this.elem = elem;
8923 this.prop = prop;
8924 this.easing = easing || "swing";
8925 this.options = options;
8926 this.start = this.now = this.cur();
8927 this.end = end;
8928 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8929 },
8930 cur: function() {
8931 var hooks = Tween.propHooks[ this.prop ];
8932
8933 return hooks && hooks.get ?
8934 hooks.get( this ) :
8935 Tween.propHooks._default.get( this );
8936 },
8937 run: function( percent ) {
8938 var eased,
8939 hooks = Tween.propHooks[ this.prop ];
8940
8941 if ( this.options.duration ) {
8942 this.pos = eased = jQuery.easing[ this.easing ](
8943 percent, this.options.duration * percent, 0, 1, this.options.duration
8944 );
8945 } else {
8946 this.pos = eased = percent;
8947 }
8948 this.now = ( this.end - this.start ) * eased + this.start;
8949
8950 if ( this.options.step ) {
8951 this.options.step.call( this.elem, this.now, this );
8952 }
8953
8954 if ( hooks && hooks.set ) {
8955 hooks.set( this );
8956 } else {
8957 Tween.propHooks._default.set( this );
8958 }
8959 return this;
8960 }
8961 };
8962
8963 Tween.prototype.init.prototype = Tween.prototype;
8964
8965 Tween.propHooks = {
8966 _default: {
8967 get: function( tween ) {
8968 var result;
8969
8970 if ( tween.elem[ tween.prop ] != null &&
8971 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
8972 return tween.elem[ tween.prop ];
8973 }
8974
8975 // passing any value as a 4th parameter to .css will automatically
8976 // attempt a parseFloat and fallback to a string if the parse fails
8977 // so, simple values such as "10px" are parsed to Float.
8978 // complex values such as "rotate(1rad)" are returned as is.
8979 result = jQuery.css( tween.elem, tween.prop, false, "" );
8980 // Empty strings, null, undefined and "auto" are converted to 0.
8981 return !result || result === "auto" ? 0 : result;
8982 },
8983 set: function( tween ) {
8984 // use step hook for back compat - use cssHook if its there - use .style if its
8985 // available and use plain properties where available
8986 if ( jQuery.fx.step[ tween.prop ] ) {
8987 jQuery.fx.step[ tween.prop ]( tween );
8988 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
8989 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
8990 } else {
8991 tween.elem[ tween.prop ] = tween.now;
8992 }
8993 }
8994 }
8995 };
8996
8997 // Remove in 2.0 - this supports IE8's panic based approach
8998 // to setting things on disconnected nodes
8999
9000 Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
9001 set: function( tween ) {
9002 if ( tween.elem.nodeType && tween.elem.parentNode ) {
9003 tween.elem[ tween.prop ] = tween.now;
9004 }
9005 }
9006 };
9007
9008 jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9009 var cssFn = jQuery.fn[ name ];
9010 jQuery.fn[ name ] = function( speed, easing, callback ) {
9011 return speed == null || typeof speed === "boolean" ||
9012 // special check for .toggle( handler, handler, ... )
9013 ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ?
9014 cssFn.apply( this, arguments ) :
9015 this.animate( genFx( name, true ), speed, easing, callback );
9016 };
9017 });
9018
9019 jQuery.fn.extend({
9020 fadeTo: function( speed, to, easing, callback ) {
9021
9022 // show any hidden elements after setting opacity to 0
9023 return this.filter( isHidden ).css( "opacity", 0 ).show()
9024
9025 // animate to the value specified
9026 .end().animate({ opacity: to }, speed, easing, callback );
9027 },
9028 animate: function( prop, speed, easing, callback ) {
9029 var empty = jQuery.isEmptyObject( prop ),
9030 optall = jQuery.speed( speed, easing, callback ),
9031 doAnimation = function() {
9032 // Operate on a copy of prop so per-property easing won't be lost
9033 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9034
9035 // Empty animations resolve immediately
9036 if ( empty ) {
9037 anim.stop( true );
9038 }
9039 };
9040
9041 return empty || optall.queue === false ?
9042 this.each( doAnimation ) :
9043 this.queue( optall.queue, doAnimation );
9044 },
9045 stop: function( type, clearQueue, gotoEnd ) {
9046 var stopQueue = function( hooks ) {
9047 var stop = hooks.stop;
9048 delete hooks.stop;
9049 stop( gotoEnd );
9050 };
9051
9052 if ( typeof type !== "string" ) {
9053 gotoEnd = clearQueue;
9054 clearQueue = type;
9055 type = undefined;
9056 }
9057 if ( clearQueue && type !== false ) {
9058 this.queue( type || "fx", [] );
9059 }
9060
9061 return this.each(function() {
9062 var dequeue = true,
9063 index = type != null && type + "queueHooks",
9064 timers = jQuery.timers,
9065 data = jQuery._data( this );
9066
9067 if ( index ) {
9068 if ( data[ index ] && data[ index ].stop ) {
9069 stopQueue( data[ index ] );
9070 }
9071 } else {
9072 for ( index in data ) {
9073 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9074 stopQueue( data[ index ] );
9075 }
9076 }
9077 }
9078
9079 for ( index = timers.length; index--; ) {
9080 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9081 timers[ index ].anim.stop( gotoEnd );
9082 dequeue = false;
9083 timers.splice( index, 1 );
9084 }
9085 }
9086
9087 // start the next in the queue if the last step wasn't forced
9088 // timers currently will call their complete callbacks, which will dequeue
9089 // but only if they were gotoEnd
9090 if ( dequeue || !gotoEnd ) {
9091 jQuery.dequeue( this, type );
9092 }
9093 });
9094 }
9095 });
9096
9097 // Generate parameters to create a standard animation
9098 function genFx( type, includeWidth ) {
9099 var which,
9100 attrs = { height: type },
9101 i = 0;
9102
9103 // if we include width, step value is 1 to do all cssExpand values,
9104 // if we don't include width, step value is 2 to skip over Left and Right
9105 includeWidth = includeWidth? 1 : 0;
9106 for( ; i < 4 ; i += 2 - includeWidth ) {
9107 which = cssExpand[ i ];
9108 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
9109 }
9110
9111 if ( includeWidth ) {
9112 attrs.opacity = attrs.width = type;
9113 }
9114
9115 return attrs;
9116 }
9117
9118 // Generate shortcuts for custom animations
9119 jQuery.each({
9120 slideDown: genFx("show"),
9121 slideUp: genFx("hide"),
9122 slideToggle: genFx("toggle"),
9123 fadeIn: { opacity: "show" },
9124 fadeOut: { opacity: "hide" },
9125 fadeToggle: { opacity: "toggle" }
9126 }, function( name, props ) {
9127 jQuery.fn[ name ] = function( speed, easing, callback ) {
9128 return this.animate( props, speed, easing, callback );
9129 };
9130 });
9131
9132 jQuery.speed = function( speed, easing, fn ) {
9133 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9134 complete: fn || !fn && easing ||
9135 jQuery.isFunction( speed ) && speed,
9136 duration: speed,
9137 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9138 };
9139
9140 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9141 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9142
9143 // normalize opt.queue - true/undefined/null -> "fx"
9144 if ( opt.queue == null || opt.queue === true ) {
9145 opt.queue = "fx";
9146 }
9147
9148 // Queueing
9149 opt.old = opt.complete;
9150
9151 opt.complete = function() {
9152 if ( jQuery.isFunction( opt.old ) ) {
9153 opt.old.call( this );
9154 }
9155
9156 if ( opt.queue ) {
9157 jQuery.dequeue( this, opt.queue );
9158 }
9159 };
9160
9161 return opt;
9162 };
9163
9164 jQuery.easing = {
9165 linear: function( p ) {
9166 return p;
9167 },
9168 swing: function( p ) {
9169 return 0.5 - Math.cos( p*Math.PI ) / 2;
9170 }
9171 };
9172
9173 jQuery.timers = [];
9174 jQuery.fx = Tween.prototype.init;
9175 jQuery.fx.tick = function() {
9176 var timer,
9177 timers = jQuery.timers,
9178 i = 0;
9179
9180 fxNow = jQuery.now();
9181
9182 for ( ; i < timers.length; i++ ) {
9183 timer = timers[ i ];
9184 // Checks the timer has not already been removed
9185 if ( !timer() && timers[ i ] === timer ) {
9186 timers.splice( i--, 1 );
9187 }
9188 }
9189
9190 if ( !timers.length ) {
9191 jQuery.fx.stop();
9192 }
9193 fxNow = undefined;
9194 };
9195
9196 jQuery.fx.timer = function( timer ) {
9197 if ( timer() && jQuery.timers.push( timer ) && !timerId ) {
9198 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9199 }
9200 };
9201
9202 jQuery.fx.interval = 13;
9203
9204 jQuery.fx.stop = function() {
9205 clearInterval( timerId );
9206 timerId = null;
9207 };
9208
9209 jQuery.fx.speeds = {
9210 slow: 600,
9211 fast: 200,
9212 // Default speed
9213 _default: 400
9214 };
9215
9216 // Back Compat <1.8 extension point
9217 jQuery.fx.step = {};
9218
9219 if ( jQuery.expr && jQuery.expr.filters ) {
9220 jQuery.expr.filters.animated = function( elem ) {
9221 return jQuery.grep(jQuery.timers, function( fn ) {
9222 return elem === fn.elem;
9223 }).length;
9224 };
9225 }
9226 var rroot = /^(?:body|html)$/i;
9227
9228 jQuery.fn.offset = function( options ) {
9229 if ( arguments.length ) {
9230 return options === undefined ?
9231 this :
9232 this.each(function( i ) {
9233 jQuery.offset.setOffset( this, options, i );
9234 });
9235 }
9236
9237 var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft,
9238 box = { top: 0, left: 0 },
9239 elem = this[ 0 ],
9240 doc = elem && elem.ownerDocument;
9241
9242 if ( !doc ) {
9243 return;
9244 }
9245
9246 if ( (body = doc.body) === elem ) {
9247 return jQuery.offset.bodyOffset( elem );
9248 }
9249
9250 docElem = doc.documentElement;
9251
9252 // Make sure it's not a disconnected DOM node
9253 if ( !jQuery.contains( docElem, elem ) ) {
9254 return box;
9255 }
9256
9257 // If we don't have gBCR, just use 0,0 rather than error
9258 // BlackBerry 5, iOS 3 (original iPhone)
9259 if ( typeof elem.getBoundingClientRect !== "undefined" ) {
9260 box = elem.getBoundingClientRect();
9261 }
9262 win = getWindow( doc );
9263 clientTop = docElem.clientTop || body.clientTop || 0;
9264 clientLeft = docElem.clientLeft || body.clientLeft || 0;
9265 scrollTop = win.pageYOffset || docElem.scrollTop;
9266 scrollLeft = win.pageXOffset || docElem.scrollLeft;
9267 return {
9268 top: box.top + scrollTop - clientTop,
9269 left: box.left + scrollLeft - clientLeft
9270 };
9271 };
9272
9273 jQuery.offset = {
9274
9275 bodyOffset: function( body ) {
9276 var top = body.offsetTop,
9277 left = body.offsetLeft;
9278
9279 if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
9280 top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
9281 left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
9282 }
9283
9284 return { top: top, left: left };
9285 },
9286
9287 setOffset: function( elem, options, i ) {
9288 var position = jQuery.css( elem, "position" );
9289
9290 // set position first, in-case top/left are set even on static elem
9291 if ( position === "static" ) {
9292 elem.style.position = "relative";
9293 }
9294
9295 var curElem = jQuery( elem ),
9296 curOffset = curElem.offset(),
9297 curCSSTop = jQuery.css( elem, "top" ),
9298 curCSSLeft = jQuery.css( elem, "left" ),
9299 calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9300 props = {}, curPosition = {}, curTop, curLeft;
9301
9302 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9303 if ( calculatePosition ) {
9304 curPosition = curElem.position();
9305 curTop = curPosition.top;
9306 curLeft = curPosition.left;
9307 } else {
9308 curTop = parseFloat( curCSSTop ) || 0;
9309 curLeft = parseFloat( curCSSLeft ) || 0;
9310 }
9311
9312 if ( jQuery.isFunction( options ) ) {
9313 options = options.call( elem, i, curOffset );
9314 }
9315
9316 if ( options.top != null ) {
9317 props.top = ( options.top - curOffset.top ) + curTop;
9318 }
9319 if ( options.left != null ) {
9320 props.left = ( options.left - curOffset.left ) + curLeft;
9321 }
9322
9323 if ( "using" in options ) {
9324 options.using.call( elem, props );
9325 } else {
9326 curElem.css( props );
9327 }
9328 }
9329 };
9330
9331
9332 jQuery.fn.extend({
9333
9334 position: function() {
9335 if ( !this[0] ) {
9336 return;
9337 }
9338
9339 var elem = this[0],
9340
9341 // Get *real* offsetParent
9342 offsetParent = this.offsetParent(),
9343
9344 // Get correct offsets
9345 offset = this.offset(),
9346 parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
9347
9348 // Subtract element margins
9349 // note: when an element has margin: auto the offsetLeft and marginLeft
9350 // are the same in Safari causing offset.left to incorrectly be 0
9351 offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
9352 offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
9353
9354 // Add offsetParent borders
9355 parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
9356 parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
9357
9358 // Subtract the two offsets
9359 return {
9360 top: offset.top - parentOffset.top,
9361 left: offset.left - parentOffset.left
9362 };
9363 },
9364
9365 offsetParent: function() {
9366 return this.map(function() {
9367 var offsetParent = this.offsetParent || document.body;
9368 while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
9369 offsetParent = offsetParent.offsetParent;
9370 }
9371 return offsetParent || document.body;
9372 });
9373 }
9374 });
9375
9376
9377 // Create scrollLeft and scrollTop methods
9378 jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
9379 var top = /Y/.test( prop );
9380
9381 jQuery.fn[ method ] = function( val ) {
9382 return jQuery.access( this, function( elem, method, val ) {
9383 var win = getWindow( elem );
9384
9385 if ( val === undefined ) {
9386 return win ? (prop in win) ? win[ prop ] :
9387 win.document.documentElement[ method ] :
9388 elem[ method ];
9389 }
9390
9391 if ( win ) {
9392 win.scrollTo(
9393 !top ? val : jQuery( win ).scrollLeft(),
9394 top ? val : jQuery( win ).scrollTop()
9395 );
9396
9397 } else {
9398 elem[ method ] = val;
9399 }
9400 }, method, val, arguments.length, null );
9401 };
9402 });
9403
9404 function getWindow( elem ) {
9405 return jQuery.isWindow( elem ) ?
9406 elem :
9407 elem.nodeType === 9 ?
9408 elem.defaultView || elem.parentWindow :
9409 false;
9410 }
9411 // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9412 jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9413 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9414 // margin is only for outerHeight, outerWidth
9415 jQuery.fn[ funcName ] = function( margin, value ) {
9416 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9417 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9418
9419 return jQuery.access( this, function( elem, type, value ) {
9420 var doc;
9421
9422 if ( jQuery.isWindow( elem ) ) {
9423 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9424 // isn't a whole lot we can do. See pull request at this URL for discussion:
9425 // https://github.com/jquery/jquery/pull/764
9426 return elem.document.documentElement[ "client" + name ];
9427 }
9428
9429 // Get document width or height
9430 if ( elem.nodeType === 9 ) {
9431 doc = elem.documentElement;
9432
9433 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
9434 // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
9435 return Math.max(
9436 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9437 elem.body[ "offset" + name ], doc[ "offset" + name ],
9438 doc[ "client" + name ]
9439 );
9440 }
9441
9442 return value === undefined ?
9443 // Get width or height on the element, requesting but not forcing parseFloat
9444 jQuery.css( elem, type, value, extra ) :
9445
9446 // Set width or height on the element
9447 jQuery.style( elem, type, value, extra );
9448 }, type, chainable ? margin : undefined, chainable, null );
9449 };
9450 });
9451 });
9452 // Expose jQuery to the global object
9453 window.jQuery = window.$ = jQuery;
9454
9455 // Expose jQuery as an AMD module, but only for AMD loaders that
9456 // understand the issues with loading multiple versions of jQuery
9457 // in a page that all might call define(). The loader will indicate
9458 // they have special allowances for multiple jQuery versions by
9459 // specifying define.amd.jQuery = true. Register as a named module,
9460 // since jQuery can be concatenated with other files that may use define,
9461 // but not use a proper concatenation script that understands anonymous
9462 // AMD modules. A named AMD is safest and most robust way to register.
9463 // Lowercase jquery is used because AMD module names are derived from
9464 // file names, and jQuery is normally delivered in a lowercase file name.
9465 // Do this after creating the global so that if an AMD module wants to call
9466 // noConflict to hide this version of jQuery, it will work.
9467 if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9468 define( "jquery", [], function () { return jQuery; } );
9469 }
9470
9471 })( window );
+0
-4
faraday/server/www/script/jquery.tablesorter.min.js less more
0
1 (function($){$.extend({tablesorter:new
2 function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",cssChildRow:"expand-child",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,sortLocaleCompare:true,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'/\.|\,/g',onRenderHeader:null,selectorHeaders:'thead th',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}if(table.tBodies.length==0)return;var rows=table.tBodies[0].rows;if(rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,rows,-1,i);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,rows,rowIndex,cellIndex){var l=parsers.length,node=false,nodeValue=false,keepLooking=true;while(nodeValue==''&&keepLooking){rowIndex++;if(rows[rowIndex]){node=getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex);nodeValue=trimAndGetNodeText(table.config,node);if(table.config.debug){log('Checking if value was empty on row:'+rowIndex);}}else{keepLooking=false;}}for(var i=1;i<l;i++){if(parsers[i].is(nodeValue,table,node)){return parsers[i];}}return parsers[0];}function getNodeFromRowAndCellIndex(rows,rowIndex,cellIndex){return rows[rowIndex].cells[cellIndex];}function trimAndGetNodeText(config,node){return $.trim(getElementText(config,node));}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=$(table.tBodies[0].rows[i]),cols=[];if(c.hasClass(table.config.cssChildRow)){cache.row[cache.row.length-1]=cache.row[cache.row.length-1].add(c);continue;}cache.row.push(c);for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c[0].cells[j]),table,c[0].cells[j]));}cols.push(cache.normalized.length);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){var text="";if(!node)return"";if(!config.supportsTextContent)config.supportsTextContent=node.textContent||false;if(config.textExtraction=="simple"){if(config.supportsTextContent){text=node.textContent;}else{if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){text=node.childNodes[0].innerHTML;}else{text=node.innerHTML;}}}else{if(typeof(config.textExtraction)=="function"){text=config.textExtraction(node);}else{text=$(node).text();}}return text;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){var pos=n[i][checkCell];rows.push(r[pos]);if(!table.config.appender){var l=r[pos].length;for(var j=0;j<l;j++){tableBody[0].appendChild(r[pos][j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false;var header_index=computeTableHeaderCellIndexes(table);$tableHeaders=$(table.config.selectorHeaders,table).each(function(index){this.column=header_index[this.parentNode.rowIndex+"-"+this.cellIndex];this.order=formatSortingOrder(table.config.sortInitialOrder);this.count=this.order;if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(checkHeaderOptionsSortingLocked(table,index))this.order=this.lockedOrder=checkHeaderOptionsSortingLocked(table,index);if(!this.sortDisabled){var $th=$(this).addClass(table.config.cssHeader);if(table.config.onRenderHeader)table.config.onRenderHeader.apply($th);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function computeTableHeaderCellIndexes(t){var matrix=[];var lookup={};var thead=t.getElementsByTagName('THEAD')[0];var trs=thead.getElementsByTagName('TR');for(var i=0;i<trs.length;i++){var cells=trs[i].cells;for(var j=0;j<cells.length;j++){var c=cells[j];var rowIndex=c.parentNode.rowIndex;var cellId=rowIndex+"-"+c.cellIndex;var rowSpan=c.rowSpan||1;var colSpan=c.colSpan||1
3 var firstAvailCol;if(typeof(matrix[rowIndex])=="undefined"){matrix[rowIndex]=[];}for(var k=0;k<matrix[rowIndex].length+1;k++){if(typeof(matrix[rowIndex][k])=="undefined"){firstAvailCol=k;break;}}lookup[cellId]=firstAvailCol;for(var k=rowIndex;k<rowIndex+rowSpan;k++){if(typeof(matrix[k])=="undefined"){matrix[k]=[];}var matrixrow=matrix[k];for(var l=firstAvailCol;l<firstAvailCol+colSpan;l++){matrixrow[l]="x";}}}}return lookup;}function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function checkHeaderOptionsSortingLocked(table,i){if((table.config.headers[i])&&(table.config.headers[i].lockedOrder))return table.config.headers[i].lockedOrder;return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){return(v.toLowerCase()=="desc")?1:0;}else{return(v==1)?1:0;}}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(table.config.parsers[c].type=="text")?((order==0)?makeSortFunction("text","asc",c):makeSortFunction("text","desc",c)):((order==0)?makeSortFunction("numeric","asc",c):makeSortFunction("numeric","desc",c));var e="e"+i;dynamicExp+="var "+e+" = "+s;dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";if(table.config.debug){benchmark("Evaling expression:"+dynamicExp,new Date());}eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function makeSortFunction(type,direction,index){var a="a["+index+"]",b="b["+index+"]";if(type=='text'&&direction=='asc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+a+" < "+b+") ? -1 : 1 )));";}else if(type=='text'&&direction=='desc'){return"("+a+" == "+b+" ? 0 : ("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : ("+b+" < "+a+") ? -1 : 1 )));";}else if(type=='numeric'&&direction=='asc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+a+" - "+b+"));";}else if(type=='numeric'&&direction=='desc'){return"("+a+" === null && "+b+" === null) ? 0 :("+a+" === null ? Number.POSITIVE_INFINITY : ("+b+" === null ? Number.NEGATIVE_INFINITY : "+b+" - "+a+"));";}};function makeSortText(i){return"((a["+i+"] < b["+i+"]) ? -1 : ((a["+i+"] > b["+i+"]) ? 1 : 0));";};function makeSortTextDesc(i){return"((b["+i+"] < a["+i+"]) ? -1 : ((b["+i+"] > a["+i+"]) ? 1 : 0));";};function makeSortNumeric(i){return"a["+i+"]-b["+i+"];";};function makeSortNumericDesc(i){return"b["+i+"]-a["+i+"];";};function sortText(a,b){if(table.config.sortLocaleCompare)return a.localeCompare(b);return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){if(table.config.sortLocaleCompare)return b.localeCompare(a);return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$.data(this,"tablesorter",config);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){$this.trigger("sortStart");var $cell=$(this);var i=this.column;this.order=this.count++%2;if(this.lockedOrder)this.order=this.lockedOrder;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){var me=this;setTimeout(function(){me.config.parsers=buildParserCache(me,$headers);cache=buildCache(me);},1);}).bind("updateCell",function(e,cell){var config=this.config;var pos=[(cell.parentNode.rowIndex-1),cell.cellIndex];cache.normalized[pos[0]][pos[1]]=config.parsers[pos[1]].format(getElementText(config,cell),cell);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){return/^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g,'')));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLocaleLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}var $tr,row=-1,odd;$("tr:visible",table.tBodies[0]).each(function(i){$tr=$(this);if(!$tr.hasClass(table.config.cssChildRow))row++;odd=(row%2==0);$tr.removeClass(table.config.widgetZebra.css[odd?0:1]).addClass(table.config.widgetZebra.css[odd?1:0])});if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
+0
-6
faraday/server/www/script/jquery.ui.tabs.min.js less more
0 /*! jQuery UI - v1.10.4 - 2014-05-12
1 * http://jqueryui.com
2 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.tabs.js
3 * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */
4
5 (function(t,e){function n(e,n){var r,s,o,a=e.nodeName.toLowerCase();return"area"===a?(r=e.parentNode,s=r.name,e.href&&s&&"map"===r.nodeName.toLowerCase()?(o=t("img[usemap=#"+s+"]")[0],!!o&&i(o)):!1):(/input|select|textarea|button|object/.test(a)?!e.disabled:"a"===a?e.href||n:n)&&i(e)}function i(e){return t.expr.filters.visible(e)&&!t(e).parents().addBack().filter(function(){return"hidden"===t.css(this,"visibility")}).length}var r=0,s=/^ui-id-\d+$/;t.ui=t.ui||{},t.extend(t.ui,{version:"1.10.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),t.fn.extend({focus:function(e){return function(n,i){return"number"==typeof n?this.each(function(){var e=this;setTimeout(function(){t(e).focus(),i&&i.call(e)},n)}):e.apply(this,arguments)}}(t.fn.focus),scrollParent:function(){var e;return e=t.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(t.css(this,"position"))&&/(auto|scroll)/.test(t.css(this,"overflow")+t.css(this,"overflow-y")+t.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(t.css(this,"overflow")+t.css(this,"overflow-y")+t.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!e.length?t(document):e},zIndex:function(n){if(n!==e)return this.css("zIndex",n);if(this.length)for(var i,r,s=t(this[0]);s.length&&s[0]!==document;){if(i=s.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(r=parseInt(s.css("zIndex"),10),!isNaN(r)&&0!==r))return r;s=s.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++r)})},removeUniqueId:function(){return this.each(function(){s.test(this.id)&&t(this).removeAttr("id")})}}),t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(n){return!!t.data(n,e)}}):function(e,n,i){return!!t.data(e,i[3])},focusable:function(e){return n(e,!isNaN(t.attr(e,"tabindex")))},tabbable:function(e){var i=t.attr(e,"tabindex"),r=isNaN(i);return(r||i>=0)&&n(e,!r)}}),t("<a>").outerWidth(1).jquery||t.each(["Width","Height"],function(n,i){function r(e,n,i,r){return t.each(s,function(){n-=parseFloat(t.css(e,"padding"+this))||0,i&&(n-=parseFloat(t.css(e,"border"+this+"Width"))||0),r&&(n-=parseFloat(t.css(e,"margin"+this))||0)}),n}var s="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(n){return n===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,r(this,n)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,r(this,e,!0,n)+"px")})}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(t.fn.removeData=function(e){return function(n){return arguments.length?e.call(this,t.camelCase(n)):e.call(this)}}(t.fn.removeData)),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),t.support.selectstart="onselectstart"in document.createElement("div"),t.fn.extend({disableSelection:function(){return this.bind((t.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(t){t.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),t.extend(t.ui,{plugin:{add:function(e,n,i){var r,s=t.ui[e].prototype;for(r in i)s.plugins[r]=s.plugins[r]||[],s.plugins[r].push([n,i[r]])},call:function(t,e,n){var i,r=t.plugins[e];if(r&&t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType)for(i=0;r.length>i;i++)t.options[r[i][0]]&&r[i][1].apply(t.element,n)}},hasScroll:function(e,n){if("hidden"===t(e).css("overflow"))return!1;var i=n&&"left"===n?"scrollLeft":"scrollTop",r=!1;return e[i]>0?!0:(e[i]=1,r=e[i]>0,e[i]=0,r)}})})(jQuery);(function(t,e){var i=0,s=Array.prototype.slice,n=t.cleanData;t.cleanData=function(e){for(var i,s=0;null!=(i=e[s]);s++)try{t(i).triggerHandler("remove")}catch(o){}n(e)},t.widget=function(i,s,n){var o,r,h,a,l={},c=i.split(".")[0];i=i.split(".")[1],o=c+"-"+i,n||(n=s,s=t.Widget),t.expr[":"][o.toLowerCase()]=function(e){return!!t.data(e,o)},t[c]=t[c]||{},r=t[c][i],h=t[c][i]=function(t,i){return this._createWidget?(arguments.length&&this._createWidget(t,i),e):new h(t,i)},t.extend(h,r,{version:n.version,_proto:t.extend({},n),_childConstructors:[]}),a=new s,a.options=t.widget.extend({},a.options),t.each(n,function(i,n){return t.isFunction(n)?(l[i]=function(){var t=function(){return s.prototype[i].apply(this,arguments)},e=function(t){return s.prototype[i].apply(this,t)};return function(){var i,s=this._super,o=this._superApply;return this._super=t,this._superApply=e,i=n.apply(this,arguments),this._super=s,this._superApply=o,i}}(),e):(l[i]=n,e)}),h.prototype=t.widget.extend(a,{widgetEventPrefix:r?a.widgetEventPrefix||i:i},l,{constructor:h,namespace:c,widgetName:i,widgetFullName:o}),r?(t.each(r._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,h,i._proto)}),delete r._childConstructors):s._childConstructors.push(h),t.widget.bridge(i,h)},t.widget.extend=function(i){for(var n,o,r=s.call(arguments,1),h=0,a=r.length;a>h;h++)for(n in r[h])o=r[h][n],r[h].hasOwnProperty(n)&&o!==e&&(i[n]=t.isPlainObject(o)?t.isPlainObject(i[n])?t.widget.extend({},i[n],o):t.widget.extend({},o):o);return i},t.widget.bridge=function(i,n){var o=n.prototype.widgetFullName||i;t.fn[i]=function(r){var h="string"==typeof r,a=s.call(arguments,1),l=this;return r=!h&&a.length?t.widget.extend.apply(null,[r].concat(a)):r,h?this.each(function(){var s,n=t.data(this,o);return n?t.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,a),s!==n&&s!==e?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):e):t.error("no such method '"+r+"' for "+i+" widget instance"):t.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var e=t.data(this,o);e?e.option(r||{})._init():t.data(this,o,new n(r,this))}),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this.bindings=t(),this.hoverable=t(),this.focusable=t(),s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(i,s){var n,o,r,h=i;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof i)if(h={},n=i.split("."),i=n.shift(),n.length){for(o=h[i]=t.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)o[n[r]]=o[n[r]]||{},o=o[n[r]];if(i=n.pop(),1===arguments.length)return o[i]===e?null:o[i];o[i]=s}else{if(1===arguments.length)return this.options[i]===e?null:this.options[i];h[i]=s}return this._setOptions(h),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!e).attr("aria-disabled",e),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var o,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=o=t(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,o=this.widget()),t.each(n,function(n,h){function a(){return i||r.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof h?r[h]:h).apply(r,arguments):e}"string"!=typeof h&&(a.guid=h.guid=h.guid||a.guid||t.guid++);var l=n.match(/^(\w+)\s*(.*)$/),c=l[1]+r.eventNamespace,u=l[2];u?o.delegate(u,c,a):s.bind(c,a)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(e).undelegate(e)},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,s){var n,o,r=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var r,h=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),r=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),r&&t.effects&&t.effects.effect[h]?s[e](n):h!==e&&s[h]?s[h](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}})})(jQuery);(function(t,e){function i(){return++n}function s(t){return t=t.cloneNode(!1),t.hash.length>1&&decodeURIComponent(t.href.replace(a,""))===decodeURIComponent(location.href.replace(a,""))}var n=0,a=/#.*$/;t.widget("ui.tabs",{version:"1.10.4",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.each(function(s,a){return t(a).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),a=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:a=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;default:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,a),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDisabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var a,o,r,h=t(n).uniqueId().attr("id"),l=t(n).closest("li"),c=l.attr("aria-controls");s(n)?(a=n.hash,o=e.element.find(e._sanitizeSelector(a))):(r=e._tabId(l),a="#"+r,o=e.element.find(a),o.length||(o=e._createPanel(r),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),c&&l.data("ui-tabs-aria-controls",c),l.attr({"aria-controls":a.substring(1),"aria-labelledby":h}),o.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?t():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):t(),c={oldTab:s,oldPanel:l,newTab:r?t():a,newPanel:h};e.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",e,c)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?t():a,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),e),this._toggle(e,c))},_toggle:function(e,i){function s(){a.running=!1,a._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.options.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,a=this.tabs.eq(e),o=a.find(".ui-tabs-anchor"),r=this._getPanelForTab(a),h={tab:a,panel:r};s(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(a.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),a.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href"),beforeSend:function(e,a){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:a},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})})(jQuery);
+0
-3195
faraday/server/www/script/moment.js less more
0 //! moment.js
1 //! version : 2.10.6
2 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
3 //! license : MIT
4 //! momentjs.com
5
6 (function (global, factory) {
7 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
8 typeof define === 'function' && define.amd ? define(factory) :
9 global.moment = factory()
10 }(this, function () { 'use strict';
11
12 var hookCallback;
13
14 function utils_hooks__hooks () {
15 return hookCallback.apply(null, arguments);
16 }
17
18 // This is done to register the method called with moment()
19 // without creating circular dependencies.
20 function setHookCallback (callback) {
21 hookCallback = callback;
22 }
23
24 function isArray(input) {
25 return Object.prototype.toString.call(input) === '[object Array]';
26 }
27
28 function isDate(input) {
29 return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
30 }
31
32 function map(arr, fn) {
33 var res = [], i;
34 for (i = 0; i < arr.length; ++i) {
35 res.push(fn(arr[i], i));
36 }
37 return res;
38 }
39
40 function hasOwnProp(a, b) {
41 return Object.prototype.hasOwnProperty.call(a, b);
42 }
43
44 function extend(a, b) {
45 for (var i in b) {
46 if (hasOwnProp(b, i)) {
47 a[i] = b[i];
48 }
49 }
50
51 if (hasOwnProp(b, 'toString')) {
52 a.toString = b.toString;
53 }
54
55 if (hasOwnProp(b, 'valueOf')) {
56 a.valueOf = b.valueOf;
57 }
58
59 return a;
60 }
61
62 function create_utc__createUTC (input, format, locale, strict) {
63 return createLocalOrUTC(input, format, locale, strict, true).utc();
64 }
65
66 function defaultParsingFlags() {
67 // We need to deep clone this object.
68 return {
69 empty : false,
70 unusedTokens : [],
71 unusedInput : [],
72 overflow : -2,
73 charsLeftOver : 0,
74 nullInput : false,
75 invalidMonth : null,
76 invalidFormat : false,
77 userInvalidated : false,
78 iso : false
79 };
80 }
81
82 function getParsingFlags(m) {
83 if (m._pf == null) {
84 m._pf = defaultParsingFlags();
85 }
86 return m._pf;
87 }
88
89 function valid__isValid(m) {
90 if (m._isValid == null) {
91 var flags = getParsingFlags(m);
92 m._isValid = !isNaN(m._d.getTime()) &&
93 flags.overflow < 0 &&
94 !flags.empty &&
95 !flags.invalidMonth &&
96 !flags.invalidWeekday &&
97 !flags.nullInput &&
98 !flags.invalidFormat &&
99 !flags.userInvalidated;
100
101 if (m._strict) {
102 m._isValid = m._isValid &&
103 flags.charsLeftOver === 0 &&
104 flags.unusedTokens.length === 0 &&
105 flags.bigHour === undefined;
106 }
107 }
108 return m._isValid;
109 }
110
111 function valid__createInvalid (flags) {
112 var m = create_utc__createUTC(NaN);
113 if (flags != null) {
114 extend(getParsingFlags(m), flags);
115 }
116 else {
117 getParsingFlags(m).userInvalidated = true;
118 }
119
120 return m;
121 }
122
123 var momentProperties = utils_hooks__hooks.momentProperties = [];
124
125 function copyConfig(to, from) {
126 var i, prop, val;
127
128 if (typeof from._isAMomentObject !== 'undefined') {
129 to._isAMomentObject = from._isAMomentObject;
130 }
131 if (typeof from._i !== 'undefined') {
132 to._i = from._i;
133 }
134 if (typeof from._f !== 'undefined') {
135 to._f = from._f;
136 }
137 if (typeof from._l !== 'undefined') {
138 to._l = from._l;
139 }
140 if (typeof from._strict !== 'undefined') {
141 to._strict = from._strict;
142 }
143 if (typeof from._tzm !== 'undefined') {
144 to._tzm = from._tzm;
145 }
146 if (typeof from._isUTC !== 'undefined') {
147 to._isUTC = from._isUTC;
148 }
149 if (typeof from._offset !== 'undefined') {
150 to._offset = from._offset;
151 }
152 if (typeof from._pf !== 'undefined') {
153 to._pf = getParsingFlags(from);
154 }
155 if (typeof from._locale !== 'undefined') {
156 to._locale = from._locale;
157 }
158
159 if (momentProperties.length > 0) {
160 for (i in momentProperties) {
161 prop = momentProperties[i];
162 val = from[prop];
163 if (typeof val !== 'undefined') {
164 to[prop] = val;
165 }
166 }
167 }
168
169 return to;
170 }
171
172 var updateInProgress = false;
173
174 // Moment prototype object
175 function Moment(config) {
176 copyConfig(this, config);
177 this._d = new Date(config._d != null ? config._d.getTime() : NaN);
178 // Prevent infinite loop in case updateOffset creates new moment
179 // objects.
180 if (updateInProgress === false) {
181 updateInProgress = true;
182 utils_hooks__hooks.updateOffset(this);
183 updateInProgress = false;
184 }
185 }
186
187 function isMoment (obj) {
188 return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
189 }
190
191 function absFloor (number) {
192 if (number < 0) {
193 return Math.ceil(number);
194 } else {
195 return Math.floor(number);
196 }
197 }
198
199 function toInt(argumentForCoercion) {
200 var coercedNumber = +argumentForCoercion,
201 value = 0;
202
203 if (coercedNumber !== 0 && isFinite(coercedNumber)) {
204 value = absFloor(coercedNumber);
205 }
206
207 return value;
208 }
209
210 function compareArrays(array1, array2, dontConvert) {
211 var len = Math.min(array1.length, array2.length),
212 lengthDiff = Math.abs(array1.length - array2.length),
213 diffs = 0,
214 i;
215 for (i = 0; i < len; i++) {
216 if ((dontConvert && array1[i] !== array2[i]) ||
217 (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
218 diffs++;
219 }
220 }
221 return diffs + lengthDiff;
222 }
223
224 function Locale() {
225 }
226
227 var locales = {};
228 var globalLocale;
229
230 function normalizeLocale(key) {
231 return key ? key.toLowerCase().replace('_', '-') : key;
232 }
233
234 // pick the locale from the array
235 // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
236 // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
237 function chooseLocale(names) {
238 var i = 0, j, next, locale, split;
239
240 while (i < names.length) {
241 split = normalizeLocale(names[i]).split('-');
242 j = split.length;
243 next = normalizeLocale(names[i + 1]);
244 next = next ? next.split('-') : null;
245 while (j > 0) {
246 locale = loadLocale(split.slice(0, j).join('-'));
247 if (locale) {
248 return locale;
249 }
250 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
251 //the next array item is better than a shallower substring of this one
252 break;
253 }
254 j--;
255 }
256 i++;
257 }
258 return null;
259 }
260
261 function loadLocale(name) {
262 var oldLocale = null;
263 // TODO: Find a better way to register and load all the locales in Node
264 if (!locales[name] && typeof module !== 'undefined' &&
265 module && module.exports) {
266 try {
267 oldLocale = globalLocale._abbr;
268 require('./locale/' + name);
269 // because defineLocale currently also sets the global locale, we
270 // want to undo that for lazy loaded locales
271 locale_locales__getSetGlobalLocale(oldLocale);
272 } catch (e) { }
273 }
274 return locales[name];
275 }
276
277 // This function will load locale and then set the global locale. If
278 // no arguments are passed in, it will simply return the current global
279 // locale key.
280 function locale_locales__getSetGlobalLocale (key, values) {
281 var data;
282 if (key) {
283 if (typeof values === 'undefined') {
284 data = locale_locales__getLocale(key);
285 }
286 else {
287 data = defineLocale(key, values);
288 }
289
290 if (data) {
291 // moment.duration._locale = moment._locale = data;
292 globalLocale = data;
293 }
294 }
295
296 return globalLocale._abbr;
297 }
298
299 function defineLocale (name, values) {
300 if (values !== null) {
301 values.abbr = name;
302 locales[name] = locales[name] || new Locale();
303 locales[name].set(values);
304
305 // backwards compat for now: also set the locale
306 locale_locales__getSetGlobalLocale(name);
307
308 return locales[name];
309 } else {
310 // useful for testing
311 delete locales[name];
312 return null;
313 }
314 }
315
316 // returns locale data
317 function locale_locales__getLocale (key) {
318 var locale;
319
320 if (key && key._locale && key._locale._abbr) {
321 key = key._locale._abbr;
322 }
323
324 if (!key) {
325 return globalLocale;
326 }
327
328 if (!isArray(key)) {
329 //short-circuit everything else
330 locale = loadLocale(key);
331 if (locale) {
332 return locale;
333 }
334 key = [key];
335 }
336
337 return chooseLocale(key);
338 }
339
340 var aliases = {};
341
342 function addUnitAlias (unit, shorthand) {
343 var lowerCase = unit.toLowerCase();
344 aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
345 }
346
347 function normalizeUnits(units) {
348 return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
349 }
350
351 function normalizeObjectUnits(inputObject) {
352 var normalizedInput = {},
353 normalizedProp,
354 prop;
355
356 for (prop in inputObject) {
357 if (hasOwnProp(inputObject, prop)) {
358 normalizedProp = normalizeUnits(prop);
359 if (normalizedProp) {
360 normalizedInput[normalizedProp] = inputObject[prop];
361 }
362 }
363 }
364
365 return normalizedInput;
366 }
367
368 function makeGetSet (unit, keepTime) {
369 return function (value) {
370 if (value != null) {
371 get_set__set(this, unit, value);
372 utils_hooks__hooks.updateOffset(this, keepTime);
373 return this;
374 } else {
375 return get_set__get(this, unit);
376 }
377 };
378 }
379
380 function get_set__get (mom, unit) {
381 return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();
382 }
383
384 function get_set__set (mom, unit, value) {
385 return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
386 }
387
388 // MOMENTS
389
390 function getSet (units, value) {
391 var unit;
392 if (typeof units === 'object') {
393 for (unit in units) {
394 this.set(unit, units[unit]);
395 }
396 } else {
397 units = normalizeUnits(units);
398 if (typeof this[units] === 'function') {
399 return this[units](value);
400 }
401 }
402 return this;
403 }
404
405 function zeroFill(number, targetLength, forceSign) {
406 var absNumber = '' + Math.abs(number),
407 zerosToFill = targetLength - absNumber.length,
408 sign = number >= 0;
409 return (sign ? (forceSign ? '+' : '') : '-') +
410 Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
411 }
412
413 var formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
414
415 var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
416
417 var formatFunctions = {};
418
419 var formatTokenFunctions = {};
420
421 // token: 'M'
422 // padded: ['MM', 2]
423 // ordinal: 'Mo'
424 // callback: function () { this.month() + 1 }
425 function addFormatToken (token, padded, ordinal, callback) {
426 var func = callback;
427 if (typeof callback === 'string') {
428 func = function () {
429 return this[callback]();
430 };
431 }
432 if (token) {
433 formatTokenFunctions[token] = func;
434 }
435 if (padded) {
436 formatTokenFunctions[padded[0]] = function () {
437 return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
438 };
439 }
440 if (ordinal) {
441 formatTokenFunctions[ordinal] = function () {
442 return this.localeData().ordinal(func.apply(this, arguments), token);
443 };
444 }
445 }
446
447 function removeFormattingTokens(input) {
448 if (input.match(/\[[\s\S]/)) {
449 return input.replace(/^\[|\]$/g, '');
450 }
451 return input.replace(/\\/g, '');
452 }
453
454 function makeFormatFunction(format) {
455 var array = format.match(formattingTokens), i, length;
456
457 for (i = 0, length = array.length; i < length; i++) {
458 if (formatTokenFunctions[array[i]]) {
459 array[i] = formatTokenFunctions[array[i]];
460 } else {
461 array[i] = removeFormattingTokens(array[i]);
462 }
463 }
464
465 return function (mom) {
466 var output = '';
467 for (i = 0; i < length; i++) {
468 output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
469 }
470 return output;
471 };
472 }
473
474 // format date using native date object
475 function formatMoment(m, format) {
476 if (!m.isValid()) {
477 return m.localeData().invalidDate();
478 }
479
480 format = expandFormat(format, m.localeData());
481 formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
482
483 return formatFunctions[format](m);
484 }
485
486 function expandFormat(format, locale) {
487 var i = 5;
488
489 function replaceLongDateFormatTokens(input) {
490 return locale.longDateFormat(input) || input;
491 }
492
493 localFormattingTokens.lastIndex = 0;
494 while (i >= 0 && localFormattingTokens.test(format)) {
495 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
496 localFormattingTokens.lastIndex = 0;
497 i -= 1;
498 }
499
500 return format;
501 }
502
503 var match1 = /\d/; // 0 - 9
504 var match2 = /\d\d/; // 00 - 99
505 var match3 = /\d{3}/; // 000 - 999
506 var match4 = /\d{4}/; // 0000 - 9999
507 var match6 = /[+-]?\d{6}/; // -999999 - 999999
508 var match1to2 = /\d\d?/; // 0 - 99
509 var match1to3 = /\d{1,3}/; // 0 - 999
510 var match1to4 = /\d{1,4}/; // 0 - 9999
511 var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
512
513 var matchUnsigned = /\d+/; // 0 - inf
514 var matchSigned = /[+-]?\d+/; // -inf - inf
515
516 var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
517
518 var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
519
520 // any word (or two) characters or numbers including two/three word month in arabic.
521 var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
522
523 var regexes = {};
524
525 function isFunction (sth) {
526 // https://github.com/moment/moment/issues/2325
527 return typeof sth === 'function' &&
528 Object.prototype.toString.call(sth) === '[object Function]';
529 }
530
531
532 function addRegexToken (token, regex, strictRegex) {
533 regexes[token] = isFunction(regex) ? regex : function (isStrict) {
534 return (isStrict && strictRegex) ? strictRegex : regex;
535 };
536 }
537
538 function getParseRegexForToken (token, config) {
539 if (!hasOwnProp(regexes, token)) {
540 return new RegExp(unescapeFormat(token));
541 }
542
543 return regexes[token](config._strict, config._locale);
544 }
545
546 // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
547 function unescapeFormat(s) {
548 return s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
549 return p1 || p2 || p3 || p4;
550 }).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
551 }
552
553 var tokens = {};
554
555 function addParseToken (token, callback) {
556 var i, func = callback;
557 if (typeof token === 'string') {
558 token = [token];
559 }
560 if (typeof callback === 'number') {
561 func = function (input, array) {
562 array[callback] = toInt(input);
563 };
564 }
565 for (i = 0; i < token.length; i++) {
566 tokens[token[i]] = func;
567 }
568 }
569
570 function addWeekParseToken (token, callback) {
571 addParseToken(token, function (input, array, config, token) {
572 config._w = config._w || {};
573 callback(input, config._w, config, token);
574 });
575 }
576
577 function addTimeToArrayFromToken(token, input, config) {
578 if (input != null && hasOwnProp(tokens, token)) {
579 tokens[token](input, config._a, config, token);
580 }
581 }
582
583 var YEAR = 0;
584 var MONTH = 1;
585 var DATE = 2;
586 var HOUR = 3;
587 var MINUTE = 4;
588 var SECOND = 5;
589 var MILLISECOND = 6;
590
591 function daysInMonth(year, month) {
592 return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
593 }
594
595 // FORMATTING
596
597 addFormatToken('M', ['MM', 2], 'Mo', function () {
598 return this.month() + 1;
599 });
600
601 addFormatToken('MMM', 0, 0, function (format) {
602 return this.localeData().monthsShort(this, format);
603 });
604
605 addFormatToken('MMMM', 0, 0, function (format) {
606 return this.localeData().months(this, format);
607 });
608
609 // ALIASES
610
611 addUnitAlias('month', 'M');
612
613 // PARSING
614
615 addRegexToken('M', match1to2);
616 addRegexToken('MM', match1to2, match2);
617 addRegexToken('MMM', matchWord);
618 addRegexToken('MMMM', matchWord);
619
620 addParseToken(['M', 'MM'], function (input, array) {
621 array[MONTH] = toInt(input) - 1;
622 });
623
624 addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
625 var month = config._locale.monthsParse(input, token, config._strict);
626 // if we didn't find a month name, mark the date as invalid.
627 if (month != null) {
628 array[MONTH] = month;
629 } else {
630 getParsingFlags(config).invalidMonth = input;
631 }
632 });
633
634 // LOCALES
635
636 var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
637 function localeMonths (m) {
638 return this._months[m.month()];
639 }
640
641 var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
642 function localeMonthsShort (m) {
643 return this._monthsShort[m.month()];
644 }
645
646 function localeMonthsParse (monthName, format, strict) {
647 var i, mom, regex;
648
649 if (!this._monthsParse) {
650 this._monthsParse = [];
651 this._longMonthsParse = [];
652 this._shortMonthsParse = [];
653 }
654
655 for (i = 0; i < 12; i++) {
656 // make the regex if we don't have it already
657 mom = create_utc__createUTC([2000, i]);
658 if (strict && !this._longMonthsParse[i]) {
659 this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
660 this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
661 }
662 if (!strict && !this._monthsParse[i]) {
663 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
664 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
665 }
666 // test the regex
667 if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
668 return i;
669 } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
670 return i;
671 } else if (!strict && this._monthsParse[i].test(monthName)) {
672 return i;
673 }
674 }
675 }
676
677 // MOMENTS
678
679 function setMonth (mom, value) {
680 var dayOfMonth;
681
682 // TODO: Move this out of here!
683 if (typeof value === 'string') {
684 value = mom.localeData().monthsParse(value);
685 // TODO: Another silent failure?
686 if (typeof value !== 'number') {
687 return mom;
688 }
689 }
690
691 dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
692 mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
693 return mom;
694 }
695
696 function getSetMonth (value) {
697 if (value != null) {
698 setMonth(this, value);
699 utils_hooks__hooks.updateOffset(this, true);
700 return this;
701 } else {
702 return get_set__get(this, 'Month');
703 }
704 }
705
706 function getDaysInMonth () {
707 return daysInMonth(this.year(), this.month());
708 }
709
710 function checkOverflow (m) {
711 var overflow;
712 var a = m._a;
713
714 if (a && getParsingFlags(m).overflow === -2) {
715 overflow =
716 a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
717 a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
718 a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
719 a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
720 a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
721 a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
722 -1;
723
724 if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
725 overflow = DATE;
726 }
727
728 getParsingFlags(m).overflow = overflow;
729 }
730
731 return m;
732 }
733
734 function warn(msg) {
735 if (utils_hooks__hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) {
736 console.warn('Deprecation warning: ' + msg);
737 }
738 }
739
740 function deprecate(msg, fn) {
741 var firstTime = true;
742
743 return extend(function () {
744 if (firstTime) {
745 warn(msg + '\n' + (new Error()).stack);
746 firstTime = false;
747 }
748 return fn.apply(this, arguments);
749 }, fn);
750 }
751
752 var deprecations = {};
753
754 function deprecateSimple(name, msg) {
755 if (!deprecations[name]) {
756 warn(msg);
757 deprecations[name] = true;
758 }
759 }
760
761 utils_hooks__hooks.suppressDeprecationWarnings = false;
762
763 var from_string__isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
764
765 var isoDates = [
766 ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/],
767 ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/],
768 ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/],
769 ['GGGG-[W]WW', /\d{4}-W\d{2}/],
770 ['YYYY-DDD', /\d{4}-\d{3}/]
771 ];
772
773 // iso time formats and regexes
774 var isoTimes = [
775 ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/],
776 ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
777 ['HH:mm', /(T| )\d\d:\d\d/],
778 ['HH', /(T| )\d\d/]
779 ];
780
781 var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
782
783 // date from iso format
784 function configFromISO(config) {
785 var i, l,
786 string = config._i,
787 match = from_string__isoRegex.exec(string);
788
789 if (match) {
790 getParsingFlags(config).iso = true;
791 for (i = 0, l = isoDates.length; i < l; i++) {
792 if (isoDates[i][1].exec(string)) {
793 config._f = isoDates[i][0];
794 break;
795 }
796 }
797 for (i = 0, l = isoTimes.length; i < l; i++) {
798 if (isoTimes[i][1].exec(string)) {
799 // match[6] should be 'T' or space
800 config._f += (match[6] || ' ') + isoTimes[i][0];
801 break;
802 }
803 }
804 if (string.match(matchOffset)) {
805 config._f += 'Z';
806 }
807 configFromStringAndFormat(config);
808 } else {
809 config._isValid = false;
810 }
811 }
812
813 // date from iso format or fallback
814 function configFromString(config) {
815 var matched = aspNetJsonRegex.exec(config._i);
816
817 if (matched !== null) {
818 config._d = new Date(+matched[1]);
819 return;
820 }
821
822 configFromISO(config);
823 if (config._isValid === false) {
824 delete config._isValid;
825 utils_hooks__hooks.createFromInputFallback(config);
826 }
827 }
828
829 utils_hooks__hooks.createFromInputFallback = deprecate(
830 'moment construction falls back to js Date. This is ' +
831 'discouraged and will be removed in upcoming major ' +
832 'release. Please refer to ' +
833 'https://github.com/moment/moment/issues/1407 for more info.',
834 function (config) {
835 config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
836 }
837 );
838
839 function createDate (y, m, d, h, M, s, ms) {
840 //can't just apply() to create a date:
841 //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
842 var date = new Date(y, m, d, h, M, s, ms);
843
844 //the date constructor doesn't accept years < 1970
845 if (y < 1970) {
846 date.setFullYear(y);
847 }
848 return date;
849 }
850
851 function createUTCDate (y) {
852 var date = new Date(Date.UTC.apply(null, arguments));
853 if (y < 1970) {
854 date.setUTCFullYear(y);
855 }
856 return date;
857 }
858
859 addFormatToken(0, ['YY', 2], 0, function () {
860 return this.year() % 100;
861 });
862
863 addFormatToken(0, ['YYYY', 4], 0, 'year');
864 addFormatToken(0, ['YYYYY', 5], 0, 'year');
865 addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
866
867 // ALIASES
868
869 addUnitAlias('year', 'y');
870
871 // PARSING
872
873 addRegexToken('Y', matchSigned);
874 addRegexToken('YY', match1to2, match2);
875 addRegexToken('YYYY', match1to4, match4);
876 addRegexToken('YYYYY', match1to6, match6);
877 addRegexToken('YYYYYY', match1to6, match6);
878
879 addParseToken(['YYYYY', 'YYYYYY'], YEAR);
880 addParseToken('YYYY', function (input, array) {
881 array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
882 });
883 addParseToken('YY', function (input, array) {
884 array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
885 });
886
887 // HELPERS
888
889 function daysInYear(year) {
890 return isLeapYear(year) ? 366 : 365;
891 }
892
893 function isLeapYear(year) {
894 return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
895 }
896
897 // HOOKS
898
899 utils_hooks__hooks.parseTwoDigitYear = function (input) {
900 return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
901 };
902
903 // MOMENTS
904
905 var getSetYear = makeGetSet('FullYear', false);
906
907 function getIsLeapYear () {
908 return isLeapYear(this.year());
909 }
910
911 addFormatToken('w', ['ww', 2], 'wo', 'week');
912 addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
913
914 // ALIASES
915
916 addUnitAlias('week', 'w');
917 addUnitAlias('isoWeek', 'W');
918
919 // PARSING
920
921 addRegexToken('w', match1to2);
922 addRegexToken('ww', match1to2, match2);
923 addRegexToken('W', match1to2);
924 addRegexToken('WW', match1to2, match2);
925
926 addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
927 week[token.substr(0, 1)] = toInt(input);
928 });
929
930 // HELPERS
931
932 // firstDayOfWeek 0 = sun, 6 = sat
933 // the day of the week that starts the week
934 // (usually sunday or monday)
935 // firstDayOfWeekOfYear 0 = sun, 6 = sat
936 // the first week is the week that contains the first
937 // of this day of the week
938 // (eg. ISO weeks use thursday (4))
939 function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
940 var end = firstDayOfWeekOfYear - firstDayOfWeek,
941 daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
942 adjustedMoment;
943
944
945 if (daysToDayOfWeek > end) {
946 daysToDayOfWeek -= 7;
947 }
948
949 if (daysToDayOfWeek < end - 7) {
950 daysToDayOfWeek += 7;
951 }
952
953 adjustedMoment = local__createLocal(mom).add(daysToDayOfWeek, 'd');
954 return {
955 week: Math.ceil(adjustedMoment.dayOfYear() / 7),
956 year: adjustedMoment.year()
957 };
958 }
959
960 // LOCALES
961
962 function localeWeek (mom) {
963 return weekOfYear(mom, this._week.dow, this._week.doy).week;
964 }
965
966 var defaultLocaleWeek = {
967 dow : 0, // Sunday is the first day of the week.
968 doy : 6 // The week that contains Jan 1st is the first week of the year.
969 };
970
971 function localeFirstDayOfWeek () {
972 return this._week.dow;
973 }
974
975 function localeFirstDayOfYear () {
976 return this._week.doy;
977 }
978
979 // MOMENTS
980
981 function getSetWeek (input) {
982 var week = this.localeData().week(this);
983 return input == null ? week : this.add((input - week) * 7, 'd');
984 }
985
986 function getSetISOWeek (input) {
987 var week = weekOfYear(this, 1, 4).week;
988 return input == null ? week : this.add((input - week) * 7, 'd');
989 }
990
991 addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
992
993 // ALIASES
994
995 addUnitAlias('dayOfYear', 'DDD');
996
997 // PARSING
998
999 addRegexToken('DDD', match1to3);
1000 addRegexToken('DDDD', match3);
1001 addParseToken(['DDD', 'DDDD'], function (input, array, config) {
1002 config._dayOfYear = toInt(input);
1003 });
1004
1005 // HELPERS
1006
1007 //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1008 function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
1009 var week1Jan = 6 + firstDayOfWeek - firstDayOfWeekOfYear, janX = createUTCDate(year, 0, 1 + week1Jan), d = janX.getUTCDay(), dayOfYear;
1010 if (d < firstDayOfWeek) {
1011 d += 7;
1012 }
1013
1014 weekday = weekday != null ? 1 * weekday : firstDayOfWeek;
1015
1016 dayOfYear = 1 + week1Jan + 7 * (week - 1) - d + weekday;
1017
1018 return {
1019 year: dayOfYear > 0 ? year : year - 1,
1020 dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
1021 };
1022 }
1023
1024 // MOMENTS
1025
1026 function getSetDayOfYear (input) {
1027 var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
1028 return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
1029 }
1030
1031 // Pick the first defined of two or three arguments.
1032 function defaults(a, b, c) {
1033 if (a != null) {
1034 return a;
1035 }
1036 if (b != null) {
1037 return b;
1038 }
1039 return c;
1040 }
1041
1042 function currentDateArray(config) {
1043 var now = new Date();
1044 if (config._useUTC) {
1045 return [now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()];
1046 }
1047 return [now.getFullYear(), now.getMonth(), now.getDate()];
1048 }
1049
1050 // convert an array to a date.
1051 // the array should mirror the parameters below
1052 // note: all values past the year are optional and will default to the lowest possible value.
1053 // [year, month, day , hour, minute, second, millisecond]
1054 function configFromArray (config) {
1055 var i, date, input = [], currentDate, yearToUse;
1056
1057 if (config._d) {
1058 return;
1059 }
1060
1061 currentDate = currentDateArray(config);
1062
1063 //compute day of the year from weeks and weekdays
1064 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
1065 dayOfYearFromWeekInfo(config);
1066 }
1067
1068 //if the day of the year is set, figure out what it is
1069 if (config._dayOfYear) {
1070 yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
1071
1072 if (config._dayOfYear > daysInYear(yearToUse)) {
1073 getParsingFlags(config)._overflowDayOfYear = true;
1074 }
1075
1076 date = createUTCDate(yearToUse, 0, config._dayOfYear);
1077 config._a[MONTH] = date.getUTCMonth();
1078 config._a[DATE] = date.getUTCDate();
1079 }
1080
1081 // Default to current date.
1082 // * if no year, month, day of month are given, default to today
1083 // * if day of month is given, default month and year
1084 // * if month is given, default only year
1085 // * if year is given, don't default anything
1086 for (i = 0; i < 3 && config._a[i] == null; ++i) {
1087 config._a[i] = input[i] = currentDate[i];
1088 }
1089
1090 // Zero out whatever was not defaulted, including time
1091 for (; i < 7; i++) {
1092 config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
1093 }
1094
1095 // Check for 24:00:00.000
1096 if (config._a[HOUR] === 24 &&
1097 config._a[MINUTE] === 0 &&
1098 config._a[SECOND] === 0 &&
1099 config._a[MILLISECOND] === 0) {
1100 config._nextDay = true;
1101 config._a[HOUR] = 0;
1102 }
1103
1104 config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
1105 // Apply timezone offset from input. The actual utcOffset can be changed
1106 // with parseZone.
1107 if (config._tzm != null) {
1108 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
1109 }
1110
1111 if (config._nextDay) {
1112 config._a[HOUR] = 24;
1113 }
1114 }
1115
1116 function dayOfYearFromWeekInfo(config) {
1117 var w, weekYear, week, weekday, dow, doy, temp;
1118
1119 w = config._w;
1120 if (w.GG != null || w.W != null || w.E != null) {
1121 dow = 1;
1122 doy = 4;
1123
1124 // TODO: We need to take the current isoWeekYear, but that depends on
1125 // how we interpret now (local, utc, fixed offset). So create
1126 // a now version of current config (take local/utc/offset flags, and
1127 // create now).
1128 weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
1129 week = defaults(w.W, 1);
1130 weekday = defaults(w.E, 1);
1131 } else {
1132 dow = config._locale._week.dow;
1133 doy = config._locale._week.doy;
1134
1135 weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
1136 week = defaults(w.w, 1);
1137
1138 if (w.d != null) {
1139 // weekday -- low day numbers are considered next week
1140 weekday = w.d;
1141 if (weekday < dow) {
1142 ++week;
1143 }
1144 } else if (w.e != null) {
1145 // local weekday -- counting starts from begining of week
1146 weekday = w.e + dow;
1147 } else {
1148 // default to begining of week
1149 weekday = dow;
1150 }
1151 }
1152 temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);
1153
1154 config._a[YEAR] = temp.year;
1155 config._dayOfYear = temp.dayOfYear;
1156 }
1157
1158 utils_hooks__hooks.ISO_8601 = function () {};
1159
1160 // date from string and format string
1161 function configFromStringAndFormat(config) {
1162 // TODO: Move this to another part of the creation flow to prevent circular deps
1163 if (config._f === utils_hooks__hooks.ISO_8601) {
1164 configFromISO(config);
1165 return;
1166 }
1167
1168 config._a = [];
1169 getParsingFlags(config).empty = true;
1170
1171 // This array is used to make a Date, either with `new Date` or `Date.UTC`
1172 var string = '' + config._i,
1173 i, parsedInput, tokens, token, skipped,
1174 stringLength = string.length,
1175 totalParsedInputLength = 0;
1176
1177 tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
1178
1179 for (i = 0; i < tokens.length; i++) {
1180 token = tokens[i];
1181 parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
1182 if (parsedInput) {
1183 skipped = string.substr(0, string.indexOf(parsedInput));
1184 if (skipped.length > 0) {
1185 getParsingFlags(config).unusedInput.push(skipped);
1186 }
1187 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
1188 totalParsedInputLength += parsedInput.length;
1189 }
1190 // don't parse if it's not a known token
1191 if (formatTokenFunctions[token]) {
1192 if (parsedInput) {
1193 getParsingFlags(config).empty = false;
1194 }
1195 else {
1196 getParsingFlags(config).unusedTokens.push(token);
1197 }
1198 addTimeToArrayFromToken(token, parsedInput, config);
1199 }
1200 else if (config._strict && !parsedInput) {
1201 getParsingFlags(config).unusedTokens.push(token);
1202 }
1203 }
1204
1205 // add remaining unparsed input length to the string
1206 getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
1207 if (string.length > 0) {
1208 getParsingFlags(config).unusedInput.push(string);
1209 }
1210
1211 // clear _12h flag if hour is <= 12
1212 if (getParsingFlags(config).bigHour === true &&
1213 config._a[HOUR] <= 12 &&
1214 config._a[HOUR] > 0) {
1215 getParsingFlags(config).bigHour = undefined;
1216 }
1217 // handle meridiem
1218 config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
1219
1220 configFromArray(config);
1221 checkOverflow(config);
1222 }
1223
1224
1225 function meridiemFixWrap (locale, hour, meridiem) {
1226 var isPm;
1227
1228 if (meridiem == null) {
1229 // nothing to do
1230 return hour;
1231 }
1232 if (locale.meridiemHour != null) {
1233 return locale.meridiemHour(hour, meridiem);
1234 } else if (locale.isPM != null) {
1235 // Fallback
1236 isPm = locale.isPM(meridiem);
1237 if (isPm && hour < 12) {
1238 hour += 12;
1239 }
1240 if (!isPm && hour === 12) {
1241 hour = 0;
1242 }
1243 return hour;
1244 } else {
1245 // this is not supposed to happen
1246 return hour;
1247 }
1248 }
1249
1250 function configFromStringAndArray(config) {
1251 var tempConfig,
1252 bestMoment,
1253
1254 scoreToBeat,
1255 i,
1256 currentScore;
1257
1258 if (config._f.length === 0) {
1259 getParsingFlags(config).invalidFormat = true;
1260 config._d = new Date(NaN);
1261 return;
1262 }
1263
1264 for (i = 0; i < config._f.length; i++) {
1265 currentScore = 0;
1266 tempConfig = copyConfig({}, config);
1267 if (config._useUTC != null) {
1268 tempConfig._useUTC = config._useUTC;
1269 }
1270 tempConfig._f = config._f[i];
1271 configFromStringAndFormat(tempConfig);
1272
1273 if (!valid__isValid(tempConfig)) {
1274 continue;
1275 }
1276
1277 // if there is any input that was not parsed add a penalty for that format
1278 currentScore += getParsingFlags(tempConfig).charsLeftOver;
1279
1280 //or tokens
1281 currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
1282
1283 getParsingFlags(tempConfig).score = currentScore;
1284
1285 if (scoreToBeat == null || currentScore < scoreToBeat) {
1286 scoreToBeat = currentScore;
1287 bestMoment = tempConfig;
1288 }
1289 }
1290
1291 extend(config, bestMoment || tempConfig);
1292 }
1293
1294 function configFromObject(config) {
1295 if (config._d) {
1296 return;
1297 }
1298
1299 var i = normalizeObjectUnits(config._i);
1300 config._a = [i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond];
1301
1302 configFromArray(config);
1303 }
1304
1305 function createFromConfig (config) {
1306 var res = new Moment(checkOverflow(prepareConfig(config)));
1307 if (res._nextDay) {
1308 // Adding is smart enough around DST
1309 res.add(1, 'd');
1310 res._nextDay = undefined;
1311 }
1312
1313 return res;
1314 }
1315
1316 function prepareConfig (config) {
1317 var input = config._i,
1318 format = config._f;
1319
1320 config._locale = config._locale || locale_locales__getLocale(config._l);
1321
1322 if (input === null || (format === undefined && input === '')) {
1323 return valid__createInvalid({nullInput: true});
1324 }
1325
1326 if (typeof input === 'string') {
1327 config._i = input = config._locale.preparse(input);
1328 }
1329
1330 if (isMoment(input)) {
1331 return new Moment(checkOverflow(input));
1332 } else if (isArray(format)) {
1333 configFromStringAndArray(config);
1334 } else if (format) {
1335 configFromStringAndFormat(config);
1336 } else if (isDate(input)) {
1337 config._d = input;
1338 } else {
1339 configFromInput(config);
1340 }
1341
1342 return config;
1343 }
1344
1345 function configFromInput(config) {
1346 var input = config._i;
1347 if (input === undefined) {
1348 config._d = new Date();
1349 } else if (isDate(input)) {
1350 config._d = new Date(+input);
1351 } else if (typeof input === 'string') {
1352 configFromString(config);
1353 } else if (isArray(input)) {
1354 config._a = map(input.slice(0), function (obj) {
1355 return parseInt(obj, 10);
1356 });
1357 configFromArray(config);
1358 } else if (typeof(input) === 'object') {
1359 configFromObject(config);
1360 } else if (typeof(input) === 'number') {
1361 // from milliseconds
1362 config._d = new Date(input);
1363 } else {
1364 utils_hooks__hooks.createFromInputFallback(config);
1365 }
1366 }
1367
1368 function createLocalOrUTC (input, format, locale, strict, isUTC) {
1369 var c = {};
1370
1371 if (typeof(locale) === 'boolean') {
1372 strict = locale;
1373 locale = undefined;
1374 }
1375 // object construction must be done this way.
1376 // https://github.com/moment/moment/issues/1423
1377 c._isAMomentObject = true;
1378 c._useUTC = c._isUTC = isUTC;
1379 c._l = locale;
1380 c._i = input;
1381 c._f = format;
1382 c._strict = strict;
1383
1384 return createFromConfig(c);
1385 }
1386
1387 function local__createLocal (input, format, locale, strict) {
1388 return createLocalOrUTC(input, format, locale, strict, false);
1389 }
1390
1391 var prototypeMin = deprecate(
1392 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
1393 function () {
1394 var other = local__createLocal.apply(null, arguments);
1395 return other < this ? this : other;
1396 }
1397 );
1398
1399 var prototypeMax = deprecate(
1400 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
1401 function () {
1402 var other = local__createLocal.apply(null, arguments);
1403 return other > this ? this : other;
1404 }
1405 );
1406
1407 // Pick a moment m from moments so that m[fn](other) is true for all
1408 // other. This relies on the function fn to be transitive.
1409 //
1410 // moments should either be an array of moment objects or an array, whose
1411 // first element is an array of moment objects.
1412 function pickBy(fn, moments) {
1413 var res, i;
1414 if (moments.length === 1 && isArray(moments[0])) {
1415 moments = moments[0];
1416 }
1417 if (!moments.length) {
1418 return local__createLocal();
1419 }
1420 res = moments[0];
1421 for (i = 1; i < moments.length; ++i) {
1422 if (!moments[i].isValid() || moments[i][fn](res)) {
1423 res = moments[i];
1424 }
1425 }
1426 return res;
1427 }
1428
1429 // TODO: Use [].sort instead?
1430 function min () {
1431 var args = [].slice.call(arguments, 0);
1432
1433 return pickBy('isBefore', args);
1434 }
1435
1436 function max () {
1437 var args = [].slice.call(arguments, 0);
1438
1439 return pickBy('isAfter', args);
1440 }
1441
1442 function Duration (duration) {
1443 var normalizedInput = normalizeObjectUnits(duration),
1444 years = normalizedInput.year || 0,
1445 quarters = normalizedInput.quarter || 0,
1446 months = normalizedInput.month || 0,
1447 weeks = normalizedInput.week || 0,
1448 days = normalizedInput.day || 0,
1449 hours = normalizedInput.hour || 0,
1450 minutes = normalizedInput.minute || 0,
1451 seconds = normalizedInput.second || 0,
1452 milliseconds = normalizedInput.millisecond || 0;
1453
1454 // representation for dateAddRemove
1455 this._milliseconds = +milliseconds +
1456 seconds * 1e3 + // 1000
1457 minutes * 6e4 + // 1000 * 60
1458 hours * 36e5; // 1000 * 60 * 60
1459 // Because of dateAddRemove treats 24 hours as different from a
1460 // day when working around DST, we need to store them separately
1461 this._days = +days +
1462 weeks * 7;
1463 // It is impossible translate months into days without knowing
1464 // which months you are are talking about, so we have to store
1465 // it separately.
1466 this._months = +months +
1467 quarters * 3 +
1468 years * 12;
1469
1470 this._data = {};
1471
1472 this._locale = locale_locales__getLocale();
1473
1474 this._bubble();
1475 }
1476
1477 function isDuration (obj) {
1478 return obj instanceof Duration;
1479 }
1480
1481 function offset (token, separator) {
1482 addFormatToken(token, 0, 0, function () {
1483 var offset = this.utcOffset();
1484 var sign = '+';
1485 if (offset < 0) {
1486 offset = -offset;
1487 sign = '-';
1488 }
1489 return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
1490 });
1491 }
1492
1493 offset('Z', ':');
1494 offset('ZZ', '');
1495
1496 // PARSING
1497
1498 addRegexToken('Z', matchOffset);
1499 addRegexToken('ZZ', matchOffset);
1500 addParseToken(['Z', 'ZZ'], function (input, array, config) {
1501 config._useUTC = true;
1502 config._tzm = offsetFromString(input);
1503 });
1504
1505 // HELPERS
1506
1507 // timezone chunker
1508 // '+10:00' > ['10', '00']
1509 // '-1530' > ['-15', '30']
1510 var chunkOffset = /([\+\-]|\d\d)/gi;
1511
1512 function offsetFromString(string) {
1513 var matches = ((string || '').match(matchOffset) || []);
1514 var chunk = matches[matches.length - 1] || [];
1515 var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
1516 var minutes = +(parts[1] * 60) + toInt(parts[2]);
1517
1518 return parts[0] === '+' ? minutes : -minutes;
1519 }
1520
1521 // Return a moment from input, that is local/utc/zone equivalent to model.
1522 function cloneWithOffset(input, model) {
1523 var res, diff;
1524 if (model._isUTC) {
1525 res = model.clone();
1526 diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res);
1527 // Use low-level api, because this fn is low-level api.
1528 res._d.setTime(+res._d + diff);
1529 utils_hooks__hooks.updateOffset(res, false);
1530 return res;
1531 } else {
1532 return local__createLocal(input).local();
1533 }
1534 }
1535
1536 function getDateOffset (m) {
1537 // On Firefox.24 Date#getTimezoneOffset returns a floating point.
1538 // https://github.com/moment/moment/pull/1871
1539 return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
1540 }
1541
1542 // HOOKS
1543
1544 // This function will be called whenever a moment is mutated.
1545 // It is intended to keep the offset in sync with the timezone.
1546 utils_hooks__hooks.updateOffset = function () {};
1547
1548 // MOMENTS
1549
1550 // keepLocalTime = true means only change the timezone, without
1551 // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
1552 // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
1553 // +0200, so we adjust the time as needed, to be valid.
1554 //
1555 // Keeping the time actually adds/subtracts (one hour)
1556 // from the actual represented time. That is why we call updateOffset
1557 // a second time. In case it wants us to change the offset again
1558 // _changeInProgress == true case, then we have to adjust, because
1559 // there is no such time in the given timezone.
1560 function getSetOffset (input, keepLocalTime) {
1561 var offset = this._offset || 0,
1562 localAdjust;
1563 if (input != null) {
1564 if (typeof input === 'string') {
1565 input = offsetFromString(input);
1566 }
1567 if (Math.abs(input) < 16) {
1568 input = input * 60;
1569 }
1570 if (!this._isUTC && keepLocalTime) {
1571 localAdjust = getDateOffset(this);
1572 }
1573 this._offset = input;
1574 this._isUTC = true;
1575 if (localAdjust != null) {
1576 this.add(localAdjust, 'm');
1577 }
1578 if (offset !== input) {
1579 if (!keepLocalTime || this._changeInProgress) {
1580 add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
1581 } else if (!this._changeInProgress) {
1582 this._changeInProgress = true;
1583 utils_hooks__hooks.updateOffset(this, true);
1584 this._changeInProgress = null;
1585 }
1586 }
1587 return this;
1588 } else {
1589 return this._isUTC ? offset : getDateOffset(this);
1590 }
1591 }
1592
1593 function getSetZone (input, keepLocalTime) {
1594 if (input != null) {
1595 if (typeof input !== 'string') {
1596 input = -input;
1597 }
1598
1599 this.utcOffset(input, keepLocalTime);
1600
1601 return this;
1602 } else {
1603 return -this.utcOffset();
1604 }
1605 }
1606
1607 function setOffsetToUTC (keepLocalTime) {
1608 return this.utcOffset(0, keepLocalTime);
1609 }
1610
1611 function setOffsetToLocal (keepLocalTime) {
1612 if (this._isUTC) {
1613 this.utcOffset(0, keepLocalTime);
1614 this._isUTC = false;
1615
1616 if (keepLocalTime) {
1617 this.subtract(getDateOffset(this), 'm');
1618 }
1619 }
1620 return this;
1621 }
1622
1623 function setOffsetToParsedOffset () {
1624 if (this._tzm) {
1625 this.utcOffset(this._tzm);
1626 } else if (typeof this._i === 'string') {
1627 this.utcOffset(offsetFromString(this._i));
1628 }
1629 return this;
1630 }
1631
1632 function hasAlignedHourOffset (input) {
1633 input = input ? local__createLocal(input).utcOffset() : 0;
1634
1635 return (this.utcOffset() - input) % 60 === 0;
1636 }
1637
1638 function isDaylightSavingTime () {
1639 return (
1640 this.utcOffset() > this.clone().month(0).utcOffset() ||
1641 this.utcOffset() > this.clone().month(5).utcOffset()
1642 );
1643 }
1644
1645 function isDaylightSavingTimeShifted () {
1646 if (typeof this._isDSTShifted !== 'undefined') {
1647 return this._isDSTShifted;
1648 }
1649
1650 var c = {};
1651
1652 copyConfig(c, this);
1653 c = prepareConfig(c);
1654
1655 if (c._a) {
1656 var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
1657 this._isDSTShifted = this.isValid() &&
1658 compareArrays(c._a, other.toArray()) > 0;
1659 } else {
1660 this._isDSTShifted = false;
1661 }
1662
1663 return this._isDSTShifted;
1664 }
1665
1666 function isLocal () {
1667 return !this._isUTC;
1668 }
1669
1670 function isUtcOffset () {
1671 return this._isUTC;
1672 }
1673
1674 function isUtc () {
1675 return this._isUTC && this._offset === 0;
1676 }
1677
1678 var aspNetRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/;
1679
1680 // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
1681 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
1682 var create__isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;
1683
1684 function create__createDuration (input, key) {
1685 var duration = input,
1686 // matching against regexp is expensive, do it on demand
1687 match = null,
1688 sign,
1689 ret,
1690 diffRes;
1691
1692 if (isDuration(input)) {
1693 duration = {
1694 ms : input._milliseconds,
1695 d : input._days,
1696 M : input._months
1697 };
1698 } else if (typeof input === 'number') {
1699 duration = {};
1700 if (key) {
1701 duration[key] = input;
1702 } else {
1703 duration.milliseconds = input;
1704 }
1705 } else if (!!(match = aspNetRegex.exec(input))) {
1706 sign = (match[1] === '-') ? -1 : 1;
1707 duration = {
1708 y : 0,
1709 d : toInt(match[DATE]) * sign,
1710 h : toInt(match[HOUR]) * sign,
1711 m : toInt(match[MINUTE]) * sign,
1712 s : toInt(match[SECOND]) * sign,
1713 ms : toInt(match[MILLISECOND]) * sign
1714 };
1715 } else if (!!(match = create__isoRegex.exec(input))) {
1716 sign = (match[1] === '-') ? -1 : 1;
1717 duration = {
1718 y : parseIso(match[2], sign),
1719 M : parseIso(match[3], sign),
1720 d : parseIso(match[4], sign),
1721 h : parseIso(match[5], sign),
1722 m : parseIso(match[6], sign),
1723 s : parseIso(match[7], sign),
1724 w : parseIso(match[8], sign)
1725 };
1726 } else if (duration == null) {// checks for null or undefined
1727 duration = {};
1728 } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
1729 diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
1730
1731 duration = {};
1732 duration.ms = diffRes.milliseconds;
1733 duration.M = diffRes.months;
1734 }
1735
1736 ret = new Duration(duration);
1737
1738 if (isDuration(input) && hasOwnProp(input, '_locale')) {
1739 ret._locale = input._locale;
1740 }
1741
1742 return ret;
1743 }
1744
1745 create__createDuration.fn = Duration.prototype;
1746
1747 function parseIso (inp, sign) {
1748 // We'd normally use ~~inp for this, but unfortunately it also
1749 // converts floats to ints.
1750 // inp may be undefined, so careful calling replace on it.
1751 var res = inp && parseFloat(inp.replace(',', '.'));
1752 // apply sign while we're at it
1753 return (isNaN(res) ? 0 : res) * sign;
1754 }
1755
1756 function positiveMomentsDifference(base, other) {
1757 var res = {milliseconds: 0, months: 0};
1758
1759 res.months = other.month() - base.month() +
1760 (other.year() - base.year()) * 12;
1761 if (base.clone().add(res.months, 'M').isAfter(other)) {
1762 --res.months;
1763 }
1764
1765 res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
1766
1767 return res;
1768 }
1769
1770 function momentsDifference(base, other) {
1771 var res;
1772 other = cloneWithOffset(other, base);
1773 if (base.isBefore(other)) {
1774 res = positiveMomentsDifference(base, other);
1775 } else {
1776 res = positiveMomentsDifference(other, base);
1777 res.milliseconds = -res.milliseconds;
1778 res.months = -res.months;
1779 }
1780
1781 return res;
1782 }
1783
1784 function createAdder(direction, name) {
1785 return function (val, period) {
1786 var dur, tmp;
1787 //invert the arguments, but complain about it
1788 if (period !== null && !isNaN(+period)) {
1789 deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
1790 tmp = val; val = period; period = tmp;
1791 }
1792
1793 val = typeof val === 'string' ? +val : val;
1794 dur = create__createDuration(val, period);
1795 add_subtract__addSubtract(this, dur, direction);
1796 return this;
1797 };
1798 }
1799
1800 function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
1801 var milliseconds = duration._milliseconds,
1802 days = duration._days,
1803 months = duration._months;
1804 updateOffset = updateOffset == null ? true : updateOffset;
1805
1806 if (milliseconds) {
1807 mom._d.setTime(+mom._d + milliseconds * isAdding);
1808 }
1809 if (days) {
1810 get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
1811 }
1812 if (months) {
1813 setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
1814 }
1815 if (updateOffset) {
1816 utils_hooks__hooks.updateOffset(mom, days || months);
1817 }
1818 }
1819
1820 var add_subtract__add = createAdder(1, 'add');
1821 var add_subtract__subtract = createAdder(-1, 'subtract');
1822
1823 function moment_calendar__calendar (time, formats) {
1824 // We want to compare the start of today, vs this.
1825 // Getting start-of-today depends on whether we're local/utc/offset or not.
1826 var now = time || local__createLocal(),
1827 sod = cloneWithOffset(now, this).startOf('day'),
1828 diff = this.diff(sod, 'days', true),
1829 format = diff < -6 ? 'sameElse' :
1830 diff < -1 ? 'lastWeek' :
1831 diff < 0 ? 'lastDay' :
1832 diff < 1 ? 'sameDay' :
1833 diff < 2 ? 'nextDay' :
1834 diff < 7 ? 'nextWeek' : 'sameElse';
1835 return this.format(formats && formats[format] || this.localeData().calendar(format, this, local__createLocal(now)));
1836 }
1837
1838 function clone () {
1839 return new Moment(this);
1840 }
1841
1842 function isAfter (input, units) {
1843 var inputMs;
1844 units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
1845 if (units === 'millisecond') {
1846 input = isMoment(input) ? input : local__createLocal(input);
1847 return +this > +input;
1848 } else {
1849 inputMs = isMoment(input) ? +input : +local__createLocal(input);
1850 return inputMs < +this.clone().startOf(units);
1851 }
1852 }
1853
1854 function isBefore (input, units) {
1855 var inputMs;
1856 units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
1857 if (units === 'millisecond') {
1858 input = isMoment(input) ? input : local__createLocal(input);
1859 return +this < +input;
1860 } else {
1861 inputMs = isMoment(input) ? +input : +local__createLocal(input);
1862 return +this.clone().endOf(units) < inputMs;
1863 }
1864 }
1865
1866 function isBetween (from, to, units) {
1867 return this.isAfter(from, units) && this.isBefore(to, units);
1868 }
1869
1870 function isSame (input, units) {
1871 var inputMs;
1872 units = normalizeUnits(units || 'millisecond');
1873 if (units === 'millisecond') {
1874 input = isMoment(input) ? input : local__createLocal(input);
1875 return +this === +input;
1876 } else {
1877 inputMs = +local__createLocal(input);
1878 return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
1879 }
1880 }
1881
1882 function diff (input, units, asFloat) {
1883 var that = cloneWithOffset(input, this),
1884 zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4,
1885 delta, output;
1886
1887 units = normalizeUnits(units);
1888
1889 if (units === 'year' || units === 'month' || units === 'quarter') {
1890 output = monthDiff(this, that);
1891 if (units === 'quarter') {
1892 output = output / 3;
1893 } else if (units === 'year') {
1894 output = output / 12;
1895 }
1896 } else {
1897 delta = this - that;
1898 output = units === 'second' ? delta / 1e3 : // 1000
1899 units === 'minute' ? delta / 6e4 : // 1000 * 60
1900 units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
1901 units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
1902 units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
1903 delta;
1904 }
1905 return asFloat ? output : absFloor(output);
1906 }
1907
1908 function monthDiff (a, b) {
1909 // difference in months
1910 var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
1911 // b is in (anchor - 1 month, anchor + 1 month)
1912 anchor = a.clone().add(wholeMonthDiff, 'months'),
1913 anchor2, adjust;
1914
1915 if (b - anchor < 0) {
1916 anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
1917 // linear across the month
1918 adjust = (b - anchor) / (anchor - anchor2);
1919 } else {
1920 anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
1921 // linear across the month
1922 adjust = (b - anchor) / (anchor2 - anchor);
1923 }
1924
1925 return -(wholeMonthDiff + adjust);
1926 }
1927
1928 utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
1929
1930 function toString () {
1931 return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
1932 }
1933
1934 function moment_format__toISOString () {
1935 var m = this.clone().utc();
1936 if (0 < m.year() && m.year() <= 9999) {
1937 if ('function' === typeof Date.prototype.toISOString) {
1938 // native implementation is ~50x faster, use it when we can
1939 return this.toDate().toISOString();
1940 } else {
1941 return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1942 }
1943 } else {
1944 return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1945 }
1946 }
1947
1948 function format (inputString) {
1949 var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat);
1950 return this.localeData().postformat(output);
1951 }
1952
1953 function from (time, withoutSuffix) {
1954 if (!this.isValid()) {
1955 return this.localeData().invalidDate();
1956 }
1957 return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
1958 }
1959
1960 function fromNow (withoutSuffix) {
1961 return this.from(local__createLocal(), withoutSuffix);
1962 }
1963
1964 function to (time, withoutSuffix) {
1965 if (!this.isValid()) {
1966 return this.localeData().invalidDate();
1967 }
1968 return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
1969 }
1970
1971 function toNow (withoutSuffix) {
1972 return this.to(local__createLocal(), withoutSuffix);
1973 }
1974
1975 function locale (key) {
1976 var newLocaleData;
1977
1978 if (key === undefined) {
1979 return this._locale._abbr;
1980 } else {
1981 newLocaleData = locale_locales__getLocale(key);
1982 if (newLocaleData != null) {
1983 this._locale = newLocaleData;
1984 }
1985 return this;
1986 }
1987 }
1988
1989 var lang = deprecate(
1990 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
1991 function (key) {
1992 if (key === undefined) {
1993 return this.localeData();
1994 } else {
1995 return this.locale(key);
1996 }
1997 }
1998 );
1999
2000 function localeData () {
2001 return this._locale;
2002 }
2003
2004 function startOf (units) {
2005 units = normalizeUnits(units);
2006 // the following switch intentionally omits break keywords
2007 // to utilize falling through the cases.
2008 switch (units) {
2009 case 'year':
2010 this.month(0);
2011 /* falls through */
2012 case 'quarter':
2013 case 'month':
2014 this.date(1);
2015 /* falls through */
2016 case 'week':
2017 case 'isoWeek':
2018 case 'day':
2019 this.hours(0);
2020 /* falls through */
2021 case 'hour':
2022 this.minutes(0);
2023 /* falls through */
2024 case 'minute':
2025 this.seconds(0);
2026 /* falls through */
2027 case 'second':
2028 this.milliseconds(0);
2029 }
2030
2031 // weeks are a special case
2032 if (units === 'week') {
2033 this.weekday(0);
2034 }
2035 if (units === 'isoWeek') {
2036 this.isoWeekday(1);
2037 }
2038
2039 // quarters are also special
2040 if (units === 'quarter') {
2041 this.month(Math.floor(this.month() / 3) * 3);
2042 }
2043
2044 return this;
2045 }
2046
2047 function endOf (units) {
2048 units = normalizeUnits(units);
2049 if (units === undefined || units === 'millisecond') {
2050 return this;
2051 }
2052 return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
2053 }
2054
2055 function to_type__valueOf () {
2056 return +this._d - ((this._offset || 0) * 60000);
2057 }
2058
2059 function unix () {
2060 return Math.floor(+this / 1000);
2061 }
2062
2063 function toDate () {
2064 return this._offset ? new Date(+this) : this._d;
2065 }
2066
2067 function toArray () {
2068 var m = this;
2069 return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
2070 }
2071
2072 function toObject () {
2073 var m = this;
2074 return {
2075 years: m.year(),
2076 months: m.month(),
2077 date: m.date(),
2078 hours: m.hours(),
2079 minutes: m.minutes(),
2080 seconds: m.seconds(),
2081 milliseconds: m.milliseconds()
2082 };
2083 }
2084
2085 function moment_valid__isValid () {
2086 return valid__isValid(this);
2087 }
2088
2089 function parsingFlags () {
2090 return extend({}, getParsingFlags(this));
2091 }
2092
2093 function invalidAt () {
2094 return getParsingFlags(this).overflow;
2095 }
2096
2097 addFormatToken(0, ['gg', 2], 0, function () {
2098 return this.weekYear() % 100;
2099 });
2100
2101 addFormatToken(0, ['GG', 2], 0, function () {
2102 return this.isoWeekYear() % 100;
2103 });
2104
2105 function addWeekYearFormatToken (token, getter) {
2106 addFormatToken(0, [token, token.length], 0, getter);
2107 }
2108
2109 addWeekYearFormatToken('gggg', 'weekYear');
2110 addWeekYearFormatToken('ggggg', 'weekYear');
2111 addWeekYearFormatToken('GGGG', 'isoWeekYear');
2112 addWeekYearFormatToken('GGGGG', 'isoWeekYear');
2113
2114 // ALIASES
2115
2116 addUnitAlias('weekYear', 'gg');
2117 addUnitAlias('isoWeekYear', 'GG');
2118
2119 // PARSING
2120
2121 addRegexToken('G', matchSigned);
2122 addRegexToken('g', matchSigned);
2123 addRegexToken('GG', match1to2, match2);
2124 addRegexToken('gg', match1to2, match2);
2125 addRegexToken('GGGG', match1to4, match4);
2126 addRegexToken('gggg', match1to4, match4);
2127 addRegexToken('GGGGG', match1to6, match6);
2128 addRegexToken('ggggg', match1to6, match6);
2129
2130 addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
2131 week[token.substr(0, 2)] = toInt(input);
2132 });
2133
2134 addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
2135 week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
2136 });
2137
2138 // HELPERS
2139
2140 function weeksInYear(year, dow, doy) {
2141 return weekOfYear(local__createLocal([year, 11, 31 + dow - doy]), dow, doy).week;
2142 }
2143
2144 // MOMENTS
2145
2146 function getSetWeekYear (input) {
2147 var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;
2148 return input == null ? year : this.add((input - year), 'y');
2149 }
2150
2151 function getSetISOWeekYear (input) {
2152 var year = weekOfYear(this, 1, 4).year;
2153 return input == null ? year : this.add((input - year), 'y');
2154 }
2155
2156 function getISOWeeksInYear () {
2157 return weeksInYear(this.year(), 1, 4);
2158 }
2159
2160 function getWeeksInYear () {
2161 var weekInfo = this.localeData()._week;
2162 return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
2163 }
2164
2165 addFormatToken('Q', 0, 0, 'quarter');
2166
2167 // ALIASES
2168
2169 addUnitAlias('quarter', 'Q');
2170
2171 // PARSING
2172
2173 addRegexToken('Q', match1);
2174 addParseToken('Q', function (input, array) {
2175 array[MONTH] = (toInt(input) - 1) * 3;
2176 });
2177
2178 // MOMENTS
2179
2180 function getSetQuarter (input) {
2181 return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
2182 }
2183
2184 addFormatToken('D', ['DD', 2], 'Do', 'date');
2185
2186 // ALIASES
2187
2188 addUnitAlias('date', 'D');
2189
2190 // PARSING
2191
2192 addRegexToken('D', match1to2);
2193 addRegexToken('DD', match1to2, match2);
2194 addRegexToken('Do', function (isStrict, locale) {
2195 return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
2196 });
2197
2198 addParseToken(['D', 'DD'], DATE);
2199 addParseToken('Do', function (input, array) {
2200 array[DATE] = toInt(input.match(match1to2)[0], 10);
2201 });
2202
2203 // MOMENTS
2204
2205 var getSetDayOfMonth = makeGetSet('Date', true);
2206
2207 addFormatToken('d', 0, 'do', 'day');
2208
2209 addFormatToken('dd', 0, 0, function (format) {
2210 return this.localeData().weekdaysMin(this, format);
2211 });
2212
2213 addFormatToken('ddd', 0, 0, function (format) {
2214 return this.localeData().weekdaysShort(this, format);
2215 });
2216
2217 addFormatToken('dddd', 0, 0, function (format) {
2218 return this.localeData().weekdays(this, format);
2219 });
2220
2221 addFormatToken('e', 0, 0, 'weekday');
2222 addFormatToken('E', 0, 0, 'isoWeekday');
2223
2224 // ALIASES
2225
2226 addUnitAlias('day', 'd');
2227 addUnitAlias('weekday', 'e');
2228 addUnitAlias('isoWeekday', 'E');
2229
2230 // PARSING
2231
2232 addRegexToken('d', match1to2);
2233 addRegexToken('e', match1to2);
2234 addRegexToken('E', match1to2);
2235 addRegexToken('dd', matchWord);
2236 addRegexToken('ddd', matchWord);
2237 addRegexToken('dddd', matchWord);
2238
2239 addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config) {
2240 var weekday = config._locale.weekdaysParse(input);
2241 // if we didn't get a weekday name, mark the date as invalid
2242 if (weekday != null) {
2243 week.d = weekday;
2244 } else {
2245 getParsingFlags(config).invalidWeekday = input;
2246 }
2247 });
2248
2249 addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
2250 week[token] = toInt(input);
2251 });
2252
2253 // HELPERS
2254
2255 function parseWeekday(input, locale) {
2256 if (typeof input !== 'string') {
2257 return input;
2258 }
2259
2260 if (!isNaN(input)) {
2261 return parseInt(input, 10);
2262 }
2263
2264 input = locale.weekdaysParse(input);
2265 if (typeof input === 'number') {
2266 return input;
2267 }
2268
2269 return null;
2270 }
2271
2272 // LOCALES
2273
2274 var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
2275 function localeWeekdays (m) {
2276 return this._weekdays[m.day()];
2277 }
2278
2279 var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
2280 function localeWeekdaysShort (m) {
2281 return this._weekdaysShort[m.day()];
2282 }
2283
2284 var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
2285 function localeWeekdaysMin (m) {
2286 return this._weekdaysMin[m.day()];
2287 }
2288
2289 function localeWeekdaysParse (weekdayName) {
2290 var i, mom, regex;
2291
2292 this._weekdaysParse = this._weekdaysParse || [];
2293
2294 for (i = 0; i < 7; i++) {
2295 // make the regex if we don't have it already
2296 if (!this._weekdaysParse[i]) {
2297 mom = local__createLocal([2000, 1]).day(i);
2298 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
2299 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
2300 }
2301 // test the regex
2302 if (this._weekdaysParse[i].test(weekdayName)) {
2303 return i;
2304 }
2305 }
2306 }
2307
2308 // MOMENTS
2309
2310 function getSetDayOfWeek (input) {
2311 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
2312 if (input != null) {
2313 input = parseWeekday(input, this.localeData());
2314 return this.add(input - day, 'd');
2315 } else {
2316 return day;
2317 }
2318 }
2319
2320 function getSetLocaleDayOfWeek (input) {
2321 var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
2322 return input == null ? weekday : this.add(input - weekday, 'd');
2323 }
2324
2325 function getSetISODayOfWeek (input) {
2326 // behaves the same as moment#day except
2327 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
2328 // as a setter, sunday should belong to the previous week.
2329 return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
2330 }
2331
2332 addFormatToken('H', ['HH', 2], 0, 'hour');
2333 addFormatToken('h', ['hh', 2], 0, function () {
2334 return this.hours() % 12 || 12;
2335 });
2336
2337 function meridiem (token, lowercase) {
2338 addFormatToken(token, 0, 0, function () {
2339 return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
2340 });
2341 }
2342
2343 meridiem('a', true);
2344 meridiem('A', false);
2345
2346 // ALIASES
2347
2348 addUnitAlias('hour', 'h');
2349
2350 // PARSING
2351
2352 function matchMeridiem (isStrict, locale) {
2353 return locale._meridiemParse;
2354 }
2355
2356 addRegexToken('a', matchMeridiem);
2357 addRegexToken('A', matchMeridiem);
2358 addRegexToken('H', match1to2);
2359 addRegexToken('h', match1to2);
2360 addRegexToken('HH', match1to2, match2);
2361 addRegexToken('hh', match1to2, match2);
2362
2363 addParseToken(['H', 'HH'], HOUR);
2364 addParseToken(['a', 'A'], function (input, array, config) {
2365 config._isPm = config._locale.isPM(input);
2366 config._meridiem = input;
2367 });
2368 addParseToken(['h', 'hh'], function (input, array, config) {
2369 array[HOUR] = toInt(input);
2370 getParsingFlags(config).bigHour = true;
2371 });
2372
2373 // LOCALES
2374
2375 function localeIsPM (input) {
2376 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
2377 // Using charAt should be more compatible.
2378 return ((input + '').toLowerCase().charAt(0) === 'p');
2379 }
2380
2381 var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
2382 function localeMeridiem (hours, minutes, isLower) {
2383 if (hours > 11) {
2384 return isLower ? 'pm' : 'PM';
2385 } else {
2386 return isLower ? 'am' : 'AM';
2387 }
2388 }
2389
2390
2391 // MOMENTS
2392
2393 // Setting the hour should keep the time, because the user explicitly
2394 // specified which hour he wants. So trying to maintain the same hour (in
2395 // a new timezone) makes sense. Adding/subtracting hours does not follow
2396 // this rule.
2397 var getSetHour = makeGetSet('Hours', true);
2398
2399 addFormatToken('m', ['mm', 2], 0, 'minute');
2400
2401 // ALIASES
2402
2403 addUnitAlias('minute', 'm');
2404
2405 // PARSING
2406
2407 addRegexToken('m', match1to2);
2408 addRegexToken('mm', match1to2, match2);
2409 addParseToken(['m', 'mm'], MINUTE);
2410
2411 // MOMENTS
2412
2413 var getSetMinute = makeGetSet('Minutes', false);
2414
2415 addFormatToken('s', ['ss', 2], 0, 'second');
2416
2417 // ALIASES
2418
2419 addUnitAlias('second', 's');
2420
2421 // PARSING
2422
2423 addRegexToken('s', match1to2);
2424 addRegexToken('ss', match1to2, match2);
2425 addParseToken(['s', 'ss'], SECOND);
2426
2427 // MOMENTS
2428
2429 var getSetSecond = makeGetSet('Seconds', false);
2430
2431 addFormatToken('S', 0, 0, function () {
2432 return ~~(this.millisecond() / 100);
2433 });
2434
2435 addFormatToken(0, ['SS', 2], 0, function () {
2436 return ~~(this.millisecond() / 10);
2437 });
2438
2439 addFormatToken(0, ['SSS', 3], 0, 'millisecond');
2440 addFormatToken(0, ['SSSS', 4], 0, function () {
2441 return this.millisecond() * 10;
2442 });
2443 addFormatToken(0, ['SSSSS', 5], 0, function () {
2444 return this.millisecond() * 100;
2445 });
2446 addFormatToken(0, ['SSSSSS', 6], 0, function () {
2447 return this.millisecond() * 1000;
2448 });
2449 addFormatToken(0, ['SSSSSSS', 7], 0, function () {
2450 return this.millisecond() * 10000;
2451 });
2452 addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
2453 return this.millisecond() * 100000;
2454 });
2455 addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
2456 return this.millisecond() * 1000000;
2457 });
2458
2459
2460 // ALIASES
2461
2462 addUnitAlias('millisecond', 'ms');
2463
2464 // PARSING
2465
2466 addRegexToken('S', match1to3, match1);
2467 addRegexToken('SS', match1to3, match2);
2468 addRegexToken('SSS', match1to3, match3);
2469
2470 var token;
2471 for (token = 'SSSS'; token.length <= 9; token += 'S') {
2472 addRegexToken(token, matchUnsigned);
2473 }
2474
2475 function parseMs(input, array) {
2476 array[MILLISECOND] = toInt(('0.' + input) * 1000);
2477 }
2478
2479 for (token = 'S'; token.length <= 9; token += 'S') {
2480 addParseToken(token, parseMs);
2481 }
2482 // MOMENTS
2483
2484 var getSetMillisecond = makeGetSet('Milliseconds', false);
2485
2486 addFormatToken('z', 0, 0, 'zoneAbbr');
2487 addFormatToken('zz', 0, 0, 'zoneName');
2488
2489 // MOMENTS
2490
2491 function getZoneAbbr () {
2492 return this._isUTC ? 'UTC' : '';
2493 }
2494
2495 function getZoneName () {
2496 return this._isUTC ? 'Coordinated Universal Time' : '';
2497 }
2498
2499 var momentPrototype__proto = Moment.prototype;
2500
2501 momentPrototype__proto.add = add_subtract__add;
2502 momentPrototype__proto.calendar = moment_calendar__calendar;
2503 momentPrototype__proto.clone = clone;
2504 momentPrototype__proto.diff = diff;
2505 momentPrototype__proto.endOf = endOf;
2506 momentPrototype__proto.format = format;
2507 momentPrototype__proto.from = from;
2508 momentPrototype__proto.fromNow = fromNow;
2509 momentPrototype__proto.to = to;
2510 momentPrototype__proto.toNow = toNow;
2511 momentPrototype__proto.get = getSet;
2512 momentPrototype__proto.invalidAt = invalidAt;
2513 momentPrototype__proto.isAfter = isAfter;
2514 momentPrototype__proto.isBefore = isBefore;
2515 momentPrototype__proto.isBetween = isBetween;
2516 momentPrototype__proto.isSame = isSame;
2517 momentPrototype__proto.isValid = moment_valid__isValid;
2518 momentPrototype__proto.lang = lang;
2519 momentPrototype__proto.locale = locale;
2520 momentPrototype__proto.localeData = localeData;
2521 momentPrototype__proto.max = prototypeMax;
2522 momentPrototype__proto.min = prototypeMin;
2523 momentPrototype__proto.parsingFlags = parsingFlags;
2524 momentPrototype__proto.set = getSet;
2525 momentPrototype__proto.startOf = startOf;
2526 momentPrototype__proto.subtract = add_subtract__subtract;
2527 momentPrototype__proto.toArray = toArray;
2528 momentPrototype__proto.toObject = toObject;
2529 momentPrototype__proto.toDate = toDate;
2530 momentPrototype__proto.toISOString = moment_format__toISOString;
2531 momentPrototype__proto.toJSON = moment_format__toISOString;
2532 momentPrototype__proto.toString = toString;
2533 momentPrototype__proto.unix = unix;
2534 momentPrototype__proto.valueOf = to_type__valueOf;
2535
2536 // Year
2537 momentPrototype__proto.year = getSetYear;
2538 momentPrototype__proto.isLeapYear = getIsLeapYear;
2539
2540 // Week Year
2541 momentPrototype__proto.weekYear = getSetWeekYear;
2542 momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
2543
2544 // Quarter
2545 momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
2546
2547 // Month
2548 momentPrototype__proto.month = getSetMonth;
2549 momentPrototype__proto.daysInMonth = getDaysInMonth;
2550
2551 // Week
2552 momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek;
2553 momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek;
2554 momentPrototype__proto.weeksInYear = getWeeksInYear;
2555 momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
2556
2557 // Day
2558 momentPrototype__proto.date = getSetDayOfMonth;
2559 momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek;
2560 momentPrototype__proto.weekday = getSetLocaleDayOfWeek;
2561 momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
2562 momentPrototype__proto.dayOfYear = getSetDayOfYear;
2563
2564 // Hour
2565 momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
2566
2567 // Minute
2568 momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
2569
2570 // Second
2571 momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
2572
2573 // Millisecond
2574 momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
2575
2576 // Offset
2577 momentPrototype__proto.utcOffset = getSetOffset;
2578 momentPrototype__proto.utc = setOffsetToUTC;
2579 momentPrototype__proto.local = setOffsetToLocal;
2580 momentPrototype__proto.parseZone = setOffsetToParsedOffset;
2581 momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
2582 momentPrototype__proto.isDST = isDaylightSavingTime;
2583 momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted;
2584 momentPrototype__proto.isLocal = isLocal;
2585 momentPrototype__proto.isUtcOffset = isUtcOffset;
2586 momentPrototype__proto.isUtc = isUtc;
2587 momentPrototype__proto.isUTC = isUtc;
2588
2589 // Timezone
2590 momentPrototype__proto.zoneAbbr = getZoneAbbr;
2591 momentPrototype__proto.zoneName = getZoneName;
2592
2593 // Deprecations
2594 momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
2595 momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
2596 momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
2597 momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
2598
2599 var momentPrototype = momentPrototype__proto;
2600
2601 function moment__createUnix (input) {
2602 return local__createLocal(input * 1000);
2603 }
2604
2605 function moment__createInZone () {
2606 return local__createLocal.apply(null, arguments).parseZone();
2607 }
2608
2609 var defaultCalendar = {
2610 sameDay : '[Today at] LT',
2611 nextDay : '[Tomorrow at] LT',
2612 nextWeek : 'dddd [at] LT',
2613 lastDay : '[Yesterday at] LT',
2614 lastWeek : '[Last] dddd [at] LT',
2615 sameElse : 'L'
2616 };
2617
2618 function locale_calendar__calendar (key, mom, now) {
2619 var output = this._calendar[key];
2620 return typeof output === 'function' ? output.call(mom, now) : output;
2621 }
2622
2623 var defaultLongDateFormat = {
2624 LTS : 'h:mm:ss A',
2625 LT : 'h:mm A',
2626 L : 'MM/DD/YYYY',
2627 LL : 'MMMM D, YYYY',
2628 LLL : 'MMMM D, YYYY h:mm A',
2629 LLLL : 'dddd, MMMM D, YYYY h:mm A'
2630 };
2631
2632 function longDateFormat (key) {
2633 var format = this._longDateFormat[key],
2634 formatUpper = this._longDateFormat[key.toUpperCase()];
2635
2636 if (format || !formatUpper) {
2637 return format;
2638 }
2639
2640 this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
2641 return val.slice(1);
2642 });
2643
2644 return this._longDateFormat[key];
2645 }
2646
2647 var defaultInvalidDate = 'Invalid date';
2648
2649 function invalidDate () {
2650 return this._invalidDate;
2651 }
2652
2653 var defaultOrdinal = '%d';
2654 var defaultOrdinalParse = /\d{1,2}/;
2655
2656 function ordinal (number) {
2657 return this._ordinal.replace('%d', number);
2658 }
2659
2660 function preParsePostFormat (string) {
2661 return string;
2662 }
2663
2664 var defaultRelativeTime = {
2665 future : 'in %s',
2666 past : '%s ago',
2667 s : 'a few seconds',
2668 m : 'a minute',
2669 mm : '%d minutes',
2670 h : 'an hour',
2671 hh : '%d hours',
2672 d : 'a day',
2673 dd : '%d days',
2674 M : 'a month',
2675 MM : '%d months',
2676 y : 'a year',
2677 yy : '%d years'
2678 };
2679
2680 function relative__relativeTime (number, withoutSuffix, string, isFuture) {
2681 var output = this._relativeTime[string];
2682 return (typeof output === 'function') ?
2683 output(number, withoutSuffix, string, isFuture) :
2684 output.replace(/%d/i, number);
2685 }
2686
2687 function pastFuture (diff, output) {
2688 var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
2689 return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
2690 }
2691
2692 function locale_set__set (config) {
2693 var prop, i;
2694 for (i in config) {
2695 prop = config[i];
2696 if (typeof prop === 'function') {
2697 this[i] = prop;
2698 } else {
2699 this['_' + i] = prop;
2700 }
2701 }
2702 // Lenient ordinal parsing accepts just a number in addition to
2703 // number + (possibly) stuff coming from _ordinalParseLenient.
2704 this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
2705 }
2706
2707 var prototype__proto = Locale.prototype;
2708
2709 prototype__proto._calendar = defaultCalendar;
2710 prototype__proto.calendar = locale_calendar__calendar;
2711 prototype__proto._longDateFormat = defaultLongDateFormat;
2712 prototype__proto.longDateFormat = longDateFormat;
2713 prototype__proto._invalidDate = defaultInvalidDate;
2714 prototype__proto.invalidDate = invalidDate;
2715 prototype__proto._ordinal = defaultOrdinal;
2716 prototype__proto.ordinal = ordinal;
2717 prototype__proto._ordinalParse = defaultOrdinalParse;
2718 prototype__proto.preparse = preParsePostFormat;
2719 prototype__proto.postformat = preParsePostFormat;
2720 prototype__proto._relativeTime = defaultRelativeTime;
2721 prototype__proto.relativeTime = relative__relativeTime;
2722 prototype__proto.pastFuture = pastFuture;
2723 prototype__proto.set = locale_set__set;
2724
2725 // Month
2726 prototype__proto.months = localeMonths;
2727 prototype__proto._months = defaultLocaleMonths;
2728 prototype__proto.monthsShort = localeMonthsShort;
2729 prototype__proto._monthsShort = defaultLocaleMonthsShort;
2730 prototype__proto.monthsParse = localeMonthsParse;
2731
2732 // Week
2733 prototype__proto.week = localeWeek;
2734 prototype__proto._week = defaultLocaleWeek;
2735 prototype__proto.firstDayOfYear = localeFirstDayOfYear;
2736 prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
2737
2738 // Day of Week
2739 prototype__proto.weekdays = localeWeekdays;
2740 prototype__proto._weekdays = defaultLocaleWeekdays;
2741 prototype__proto.weekdaysMin = localeWeekdaysMin;
2742 prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin;
2743 prototype__proto.weekdaysShort = localeWeekdaysShort;
2744 prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
2745 prototype__proto.weekdaysParse = localeWeekdaysParse;
2746
2747 // Hours
2748 prototype__proto.isPM = localeIsPM;
2749 prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
2750 prototype__proto.meridiem = localeMeridiem;
2751
2752 function lists__get (format, index, field, setter) {
2753 var locale = locale_locales__getLocale();
2754 var utc = create_utc__createUTC().set(setter, index);
2755 return locale[field](utc, format);
2756 }
2757
2758 function list (format, index, field, count, setter) {
2759 if (typeof format === 'number') {
2760 index = format;
2761 format = undefined;
2762 }
2763
2764 format = format || '';
2765
2766 if (index != null) {
2767 return lists__get(format, index, field, setter);
2768 }
2769
2770 var i;
2771 var out = [];
2772 for (i = 0; i < count; i++) {
2773 out[i] = lists__get(format, i, field, setter);
2774 }
2775 return out;
2776 }
2777
2778 function lists__listMonths (format, index) {
2779 return list(format, index, 'months', 12, 'month');
2780 }
2781
2782 function lists__listMonthsShort (format, index) {
2783 return list(format, index, 'monthsShort', 12, 'month');
2784 }
2785
2786 function lists__listWeekdays (format, index) {
2787 return list(format, index, 'weekdays', 7, 'day');
2788 }
2789
2790 function lists__listWeekdaysShort (format, index) {
2791 return list(format, index, 'weekdaysShort', 7, 'day');
2792 }
2793
2794 function lists__listWeekdaysMin (format, index) {
2795 return list(format, index, 'weekdaysMin', 7, 'day');
2796 }
2797
2798 locale_locales__getSetGlobalLocale('en', {
2799 ordinalParse: /\d{1,2}(th|st|nd|rd)/,
2800 ordinal : function (number) {
2801 var b = number % 10,
2802 output = (toInt(number % 100 / 10) === 1) ? 'th' :
2803 (b === 1) ? 'st' :
2804 (b === 2) ? 'nd' :
2805 (b === 3) ? 'rd' : 'th';
2806 return number + output;
2807 }
2808 });
2809
2810 // Side effect imports
2811 utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
2812 utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);
2813
2814 var mathAbs = Math.abs;
2815
2816 function duration_abs__abs () {
2817 var data = this._data;
2818
2819 this._milliseconds = mathAbs(this._milliseconds);
2820 this._days = mathAbs(this._days);
2821 this._months = mathAbs(this._months);
2822
2823 data.milliseconds = mathAbs(data.milliseconds);
2824 data.seconds = mathAbs(data.seconds);
2825 data.minutes = mathAbs(data.minutes);
2826 data.hours = mathAbs(data.hours);
2827 data.months = mathAbs(data.months);
2828 data.years = mathAbs(data.years);
2829
2830 return this;
2831 }
2832
2833 function duration_add_subtract__addSubtract (duration, input, value, direction) {
2834 var other = create__createDuration(input, value);
2835
2836 duration._milliseconds += direction * other._milliseconds;
2837 duration._days += direction * other._days;
2838 duration._months += direction * other._months;
2839
2840 return duration._bubble();
2841 }
2842
2843 // supports only 2.0-style add(1, 's') or add(duration)
2844 function duration_add_subtract__add (input, value) {
2845 return duration_add_subtract__addSubtract(this, input, value, 1);
2846 }
2847
2848 // supports only 2.0-style subtract(1, 's') or subtract(duration)
2849 function duration_add_subtract__subtract (input, value) {
2850 return duration_add_subtract__addSubtract(this, input, value, -1);
2851 }
2852
2853 function absCeil (number) {
2854 if (number < 0) {
2855 return Math.floor(number);
2856 } else {
2857 return Math.ceil(number);
2858 }
2859 }
2860
2861 function bubble () {
2862 var milliseconds = this._milliseconds;
2863 var days = this._days;
2864 var months = this._months;
2865 var data = this._data;
2866 var seconds, minutes, hours, years, monthsFromDays;
2867
2868 // if we have a mix of positive and negative values, bubble down first
2869 // check: https://github.com/moment/moment/issues/2166
2870 if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
2871 (milliseconds <= 0 && days <= 0 && months <= 0))) {
2872 milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
2873 days = 0;
2874 months = 0;
2875 }
2876
2877 // The following code bubbles up values, see the tests for
2878 // examples of what that means.
2879 data.milliseconds = milliseconds % 1000;
2880
2881 seconds = absFloor(milliseconds / 1000);
2882 data.seconds = seconds % 60;
2883
2884 minutes = absFloor(seconds / 60);
2885 data.minutes = minutes % 60;
2886
2887 hours = absFloor(minutes / 60);
2888 data.hours = hours % 24;
2889
2890 days += absFloor(hours / 24);
2891
2892 // convert days to months
2893 monthsFromDays = absFloor(daysToMonths(days));
2894 months += monthsFromDays;
2895 days -= absCeil(monthsToDays(monthsFromDays));
2896
2897 // 12 months -> 1 year
2898 years = absFloor(months / 12);
2899 months %= 12;
2900
2901 data.days = days;
2902 data.months = months;
2903 data.years = years;
2904
2905 return this;
2906 }
2907
2908 function daysToMonths (days) {
2909 // 400 years have 146097 days (taking into account leap year rules)
2910 // 400 years have 12 months === 4800
2911 return days * 4800 / 146097;
2912 }
2913
2914 function monthsToDays (months) {
2915 // the reverse of daysToMonths
2916 return months * 146097 / 4800;
2917 }
2918
2919 function as (units) {
2920 var days;
2921 var months;
2922 var milliseconds = this._milliseconds;
2923
2924 units = normalizeUnits(units);
2925
2926 if (units === 'month' || units === 'year') {
2927 days = this._days + milliseconds / 864e5;
2928 months = this._months + daysToMonths(days);
2929 return units === 'month' ? months : months / 12;
2930 } else {
2931 // handle milliseconds separately because of floating point math errors (issue #1867)
2932 days = this._days + Math.round(monthsToDays(this._months));
2933 switch (units) {
2934 case 'week' : return days / 7 + milliseconds / 6048e5;
2935 case 'day' : return days + milliseconds / 864e5;
2936 case 'hour' : return days * 24 + milliseconds / 36e5;
2937 case 'minute' : return days * 1440 + milliseconds / 6e4;
2938 case 'second' : return days * 86400 + milliseconds / 1000;
2939 // Math.floor prevents floating point math errors here
2940 case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
2941 default: throw new Error('Unknown unit ' + units);
2942 }
2943 }
2944 }
2945
2946 // TODO: Use this.as('ms')?
2947 function duration_as__valueOf () {
2948 return (
2949 this._milliseconds +
2950 this._days * 864e5 +
2951 (this._months % 12) * 2592e6 +
2952 toInt(this._months / 12) * 31536e6
2953 );
2954 }
2955
2956 function makeAs (alias) {
2957 return function () {
2958 return this.as(alias);
2959 };
2960 }
2961
2962 var asMilliseconds = makeAs('ms');
2963 var asSeconds = makeAs('s');
2964 var asMinutes = makeAs('m');
2965 var asHours = makeAs('h');
2966 var asDays = makeAs('d');
2967 var asWeeks = makeAs('w');
2968 var asMonths = makeAs('M');
2969 var asYears = makeAs('y');
2970
2971 function duration_get__get (units) {
2972 units = normalizeUnits(units);
2973 return this[units + 's']();
2974 }
2975
2976 function makeGetter(name) {
2977 return function () {
2978 return this._data[name];
2979 };
2980 }
2981
2982 var milliseconds = makeGetter('milliseconds');
2983 var seconds = makeGetter('seconds');
2984 var minutes = makeGetter('minutes');
2985 var hours = makeGetter('hours');
2986 var days = makeGetter('days');
2987 var months = makeGetter('months');
2988 var years = makeGetter('years');
2989
2990 function weeks () {
2991 return absFloor(this.days() / 7);
2992 }
2993
2994 var round = Math.round;
2995 var thresholds = {
2996 s: 45, // seconds to minute
2997 m: 45, // minutes to hour
2998 h: 22, // hours to day
2999 d: 26, // days to month
3000 M: 11 // months to year
3001 };
3002
3003 // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
3004 function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
3005 return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
3006 }
3007
3008 function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
3009 var duration = create__createDuration(posNegDuration).abs();
3010 var seconds = round(duration.as('s'));
3011 var minutes = round(duration.as('m'));
3012 var hours = round(duration.as('h'));
3013 var days = round(duration.as('d'));
3014 var months = round(duration.as('M'));
3015 var years = round(duration.as('y'));
3016
3017 var a = seconds < thresholds.s && ['s', seconds] ||
3018 minutes === 1 && ['m'] ||
3019 minutes < thresholds.m && ['mm', minutes] ||
3020 hours === 1 && ['h'] ||
3021 hours < thresholds.h && ['hh', hours] ||
3022 days === 1 && ['d'] ||
3023 days < thresholds.d && ['dd', days] ||
3024 months === 1 && ['M'] ||
3025 months < thresholds.M && ['MM', months] ||
3026 years === 1 && ['y'] || ['yy', years];
3027
3028 a[2] = withoutSuffix;
3029 a[3] = +posNegDuration > 0;
3030 a[4] = locale;
3031 return substituteTimeAgo.apply(null, a);
3032 }
3033
3034 // This function allows you to set a threshold for relative time strings
3035 function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
3036 if (thresholds[threshold] === undefined) {
3037 return false;
3038 }
3039 if (limit === undefined) {
3040 return thresholds[threshold];
3041 }
3042 thresholds[threshold] = limit;
3043 return true;
3044 }
3045
3046 function humanize (withSuffix) {
3047 var locale = this.localeData();
3048 var output = duration_humanize__relativeTime(this, !withSuffix, locale);
3049
3050 if (withSuffix) {
3051 output = locale.pastFuture(+this, output);
3052 }
3053
3054 return locale.postformat(output);
3055 }
3056
3057 var iso_string__abs = Math.abs;
3058
3059 function iso_string__toISOString() {
3060 // for ISO strings we do not use the normal bubbling rules:
3061 // * milliseconds bubble up until they become hours
3062 // * days do not bubble at all
3063 // * months bubble up until they become years
3064 // This is because there is no context-free conversion between hours and days
3065 // (think of clock changes)
3066 // and also not between days and months (28-31 days per month)
3067 var seconds = iso_string__abs(this._milliseconds) / 1000;
3068 var days = iso_string__abs(this._days);
3069 var months = iso_string__abs(this._months);
3070 var minutes, hours, years;
3071
3072 // 3600 seconds -> 60 minutes -> 1 hour
3073 minutes = absFloor(seconds / 60);
3074 hours = absFloor(minutes / 60);
3075 seconds %= 60;
3076 minutes %= 60;
3077
3078 // 12 months -> 1 year
3079 years = absFloor(months / 12);
3080 months %= 12;
3081
3082
3083 // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
3084 var Y = years;
3085 var M = months;
3086 var D = days;
3087 var h = hours;
3088 var m = minutes;
3089 var s = seconds;
3090 var total = this.asSeconds();
3091
3092 if (!total) {
3093 // this is the same as C#'s (Noda) and python (isodate)...
3094 // but not other JS (goog.date)
3095 return 'P0D';
3096 }
3097
3098 return (total < 0 ? '-' : '') +
3099 'P' +
3100 (Y ? Y + 'Y' : '') +
3101 (M ? M + 'M' : '') +
3102 (D ? D + 'D' : '') +
3103 ((h || m || s) ? 'T' : '') +
3104 (h ? h + 'H' : '') +
3105 (m ? m + 'M' : '') +
3106 (s ? s + 'S' : '');
3107 }
3108
3109 var duration_prototype__proto = Duration.prototype;
3110
3111 duration_prototype__proto.abs = duration_abs__abs;
3112 duration_prototype__proto.add = duration_add_subtract__add;
3113 duration_prototype__proto.subtract = duration_add_subtract__subtract;
3114 duration_prototype__proto.as = as;
3115 duration_prototype__proto.asMilliseconds = asMilliseconds;
3116 duration_prototype__proto.asSeconds = asSeconds;
3117 duration_prototype__proto.asMinutes = asMinutes;
3118 duration_prototype__proto.asHours = asHours;
3119 duration_prototype__proto.asDays = asDays;
3120 duration_prototype__proto.asWeeks = asWeeks;
3121 duration_prototype__proto.asMonths = asMonths;
3122 duration_prototype__proto.asYears = asYears;
3123 duration_prototype__proto.valueOf = duration_as__valueOf;
3124 duration_prototype__proto._bubble = bubble;
3125 duration_prototype__proto.get = duration_get__get;
3126 duration_prototype__proto.milliseconds = milliseconds;
3127 duration_prototype__proto.seconds = seconds;
3128 duration_prototype__proto.minutes = minutes;
3129 duration_prototype__proto.hours = hours;
3130 duration_prototype__proto.days = days;
3131 duration_prototype__proto.weeks = weeks;
3132 duration_prototype__proto.months = months;
3133 duration_prototype__proto.years = years;
3134 duration_prototype__proto.humanize = humanize;
3135 duration_prototype__proto.toISOString = iso_string__toISOString;
3136 duration_prototype__proto.toString = iso_string__toISOString;
3137 duration_prototype__proto.toJSON = iso_string__toISOString;
3138 duration_prototype__proto.locale = locale;
3139 duration_prototype__proto.localeData = localeData;
3140
3141 // Deprecations
3142 duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
3143 duration_prototype__proto.lang = lang;
3144
3145 // Side effect imports
3146
3147 addFormatToken('X', 0, 0, 'unix');
3148 addFormatToken('x', 0, 0, 'valueOf');
3149
3150 // PARSING
3151
3152 addRegexToken('x', matchSigned);
3153 addRegexToken('X', matchTimestamp);
3154 addParseToken('X', function (input, array, config) {
3155 config._d = new Date(parseFloat(input, 10) * 1000);
3156 });
3157 addParseToken('x', function (input, array, config) {
3158 config._d = new Date(toInt(input));
3159 });
3160
3161 // Side effect imports
3162
3163
3164 utils_hooks__hooks.version = '2.10.6';
3165
3166 setHookCallback(local__createLocal);
3167
3168 utils_hooks__hooks.fn = momentPrototype;
3169 utils_hooks__hooks.min = min;
3170 utils_hooks__hooks.max = max;
3171 utils_hooks__hooks.utc = create_utc__createUTC;
3172 utils_hooks__hooks.unix = moment__createUnix;
3173 utils_hooks__hooks.months = lists__listMonths;
3174 utils_hooks__hooks.isDate = isDate;
3175 utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale;
3176 utils_hooks__hooks.invalid = valid__createInvalid;
3177 utils_hooks__hooks.duration = create__createDuration;
3178 utils_hooks__hooks.isMoment = isMoment;
3179 utils_hooks__hooks.weekdays = lists__listWeekdays;
3180 utils_hooks__hooks.parseZone = moment__createInZone;
3181 utils_hooks__hooks.localeData = locale_locales__getLocale;
3182 utils_hooks__hooks.isDuration = isDuration;
3183 utils_hooks__hooks.monthsShort = lists__listMonthsShort;
3184 utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin;
3185 utils_hooks__hooks.defineLocale = defineLocale;
3186 utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort;
3187 utils_hooks__hooks.normalizeUnits = normalizeUnits;
3188 utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
3189
3190 var _moment = utils_hooks__hooks;
3191
3192 return _moment;
3193
3194 }));
+0
-7
faraday/server/www/script/moment.min.js less more
0 //! moment.js
1 //! version : 2.10.6
2 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
3 //! license : MIT
4 //! momentjs.com
5 !function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Hc.apply(null,arguments)}function b(a){Hc=a}function c(a){return"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function f(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function g(a,b){for(var c in b)f(b,c)&&(a[c]=b[c]);return f(b,"toString")&&(a.toString=b.toString),f(b,"valueOf")&&(a.valueOf=b.valueOf),a}function h(a,b,c,d){return Ca(a,b,c,d,!0).utc()}function i(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function j(a){return null==a._pf&&(a._pf=i()),a._pf}function k(a){if(null==a._isValid){var b=j(a);a._isValid=!(isNaN(a._d.getTime())||!(b.overflow<0)||b.empty||b.invalidMonth||b.invalidWeekday||b.nullInput||b.invalidFormat||b.userInvalidated),a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function l(a){var b=h(NaN);return null!=a?g(j(b),a):j(b).userInvalidated=!0,b}function m(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=j(b)),"undefined"!=typeof b._locale&&(a._locale=b._locale),Jc.length>0)for(c in Jc)d=Jc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function n(b){m(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),Kc===!1&&(Kc=!0,a.updateOffset(this),Kc=!1)}function o(a){return a instanceof n||null!=a&&null!=a._isAMomentObject}function p(a){return 0>a?Math.ceil(a):Math.floor(a)}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=p(b)),c}function r(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function s(){}function t(a){return a?a.toLowerCase().replace("_","-"):a}function u(a){for(var b,c,d,e,f=0;f<a.length;){for(e=t(a[f]).split("-"),b=e.length,c=t(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=v(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&r(e,c,!0)>=b-1)break;b--}f++}return null}function v(a){var b=null;if(!Lc[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Ic._abbr,require("./locale/"+a),w(b)}catch(c){}return Lc[a]}function w(a,b){var c;return a&&(c="undefined"==typeof b?y(a):x(a,b),c&&(Ic=c)),Ic._abbr}function x(a,b){return null!==b?(b.abbr=a,Lc[a]=Lc[a]||new s,Lc[a].set(b),w(a),Lc[a]):(delete Lc[a],null)}function y(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Ic;if(!c(a)){if(b=v(a))return b;a=[a]}return u(a)}function z(a,b){var c=a.toLowerCase();Mc[c]=Mc[c+"s"]=Mc[b]=a}function A(a){return"string"==typeof a?Mc[a]||Mc[a.toLowerCase()]:void 0}function B(a){var b,c,d={};for(c in a)f(a,c)&&(b=A(c),b&&(d[b]=a[c]));return d}function C(b,c){return function(d){return null!=d?(E(this,b,d),a.updateOffset(this,c),this):D(this,b)}}function D(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function E(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function F(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=A(a),"function"==typeof this[a])return this[a](b);return this}function G(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function H(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Qc[a]=e),b&&(Qc[b[0]]=function(){return G(e.apply(this,arguments),b[1],b[2])}),c&&(Qc[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function I(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function J(a){var b,c,d=a.match(Nc);for(b=0,c=d.length;c>b;b++)Qc[d[b]]?d[b]=Qc[d[b]]:d[b]=I(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function K(a,b){return a.isValid()?(b=L(b,a.localeData()),Pc[b]=Pc[b]||J(b),Pc[b](a)):a.localeData().invalidDate()}function L(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Oc.lastIndex=0;d>=0&&Oc.test(a);)a=a.replace(Oc,c),Oc.lastIndex=0,d-=1;return a}function M(a){return"function"==typeof a&&"[object Function]"===Object.prototype.toString.call(a)}function N(a,b,c){dd[a]=M(b)?b:function(a){return a&&c?c:b}}function O(a,b){return f(dd,a)?dd[a](b._strict,b._locale):new RegExp(P(a))}function P(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=q(a)}),c=0;c<a.length;c++)ed[a[c]]=d}function R(a,b){Q(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function S(a,b,c){null!=b&&f(ed,a)&&ed[a](b,c._a,c,a)}function T(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function U(a){return this._months[a.month()]}function V(a){return this._monthsShort[a.month()]}function W(a,b,c){var d,e,f;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function X(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),T(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function Y(b){return null!=b?(X(this,b),a.updateOffset(this,!0),this):D(this,"Month")}function Z(){return T(this.year(),this.month())}function $(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[gd]<0||c[gd]>11?gd:c[hd]<1||c[hd]>T(c[fd],c[gd])?hd:c[id]<0||c[id]>24||24===c[id]&&(0!==c[jd]||0!==c[kd]||0!==c[ld])?id:c[jd]<0||c[jd]>59?jd:c[kd]<0||c[kd]>59?kd:c[ld]<0||c[ld]>999?ld:-1,j(a)._overflowDayOfYear&&(fd>b||b>hd)&&(b=hd),j(a).overflow=b),a}function _(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function aa(a,b){var c=!0;return g(function(){return c&&(_(a+"\n"+(new Error).stack),c=!1),b.apply(this,arguments)},b)}function ba(a,b){od[a]||(_(b),od[a]=!0)}function ca(a){var b,c,d=a._i,e=pd.exec(d);if(e){for(j(a).iso=!0,b=0,c=qd.length;c>b;b++)if(qd[b][1].exec(d)){a._f=qd[b][0];break}for(b=0,c=rd.length;c>b;b++)if(rd[b][1].exec(d)){a._f+=(e[6]||" ")+rd[b][0];break}d.match(ad)&&(a._f+="Z"),va(a)}else a._isValid=!1}function da(b){var c=sd.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(ca(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ea(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function fa(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function ga(a){return ha(a)?366:365}function ha(a){return a%4===0&&a%100!==0||a%400===0}function ia(){return ha(this.year())}function ja(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=Da(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ka(a){return ja(a,this._week.dow,this._week.doy).week}function la(){return this._week.dow}function ma(){return this._week.doy}function na(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function oa(a){var b=ja(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function pa(a,b,c,d,e){var f,g=6+e-d,h=fa(a,0,1+g),i=h.getUTCDay();return e>i&&(i+=7),c=null!=c?1*c:e,f=1+g+7*(b-1)-i+c,{year:f>0?a:a-1,dayOfYear:f>0?f:ga(a-1)+f}}function qa(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function ra(a,b,c){return null!=a?a:null!=b?b:c}function sa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function ta(a){var b,c,d,e,f=[];if(!a._d){for(d=sa(a),a._w&&null==a._a[hd]&&null==a._a[gd]&&ua(a),a._dayOfYear&&(e=ra(a._a[fd],d[fd]),a._dayOfYear>ga(e)&&(j(a)._overflowDayOfYear=!0),c=fa(e,0,a._dayOfYear),a._a[gd]=c.getUTCMonth(),a._a[hd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[id]&&0===a._a[jd]&&0===a._a[kd]&&0===a._a[ld]&&(a._nextDay=!0,a._a[id]=0),a._d=(a._useUTC?fa:ea).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[id]=24)}}function ua(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ra(b.GG,a._a[fd],ja(Da(),1,4).year),d=ra(b.W,1),e=ra(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ra(b.gg,a._a[fd],ja(Da(),f,g).year),d=ra(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=pa(c,d,e,g,f),a._a[fd]=h.year,a._dayOfYear=h.dayOfYear}function va(b){if(b._f===a.ISO_8601)return void ca(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=L(b._f,b._locale).match(Nc)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(O(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),Qc[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),S(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[id]<=12&&b._a[id]>0&&(j(b).bigHour=void 0),b._a[id]=wa(b._locale,b._a[id],b._meridiem),ta(b),$(b)}function wa(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function xa(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=m({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],va(b),k(b)&&(f+=j(b).charsLeftOver,f+=10*j(b).unusedTokens.length,j(b).score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function ya(a){if(!a._d){var b=B(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],ta(a)}}function za(a){var b=new n($(Aa(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Aa(a){var b=a._i,e=a._f;return a._locale=a._locale||y(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),o(b)?new n($(b)):(c(e)?xa(a):e?va(a):d(b)?a._d=b:Ba(a),a))}function Ba(b){var f=b._i;void 0===f?b._d=new Date:d(f)?b._d=new Date(+f):"string"==typeof f?da(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),ta(b)):"object"==typeof f?ya(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ca(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,za(f)}function Da(a,b,c,d){return Ca(a,b,c,d,!1)}function Ea(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Da();for(d=b[0],e=1;e<b.length;++e)(!b[e].isValid()||b[e][a](d))&&(d=b[e]);return d}function Fa(){var a=[].slice.call(arguments,0);return Ea("isBefore",a)}function Ga(){var a=[].slice.call(arguments,0);return Ea("isAfter",a)}function Ha(a){var b=B(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=y(),this._bubble()}function Ia(a){return a instanceof Ha}function Ja(a,b){H(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+G(~~(a/60),2)+b+G(~~a%60,2)})}function Ka(a){var b=(a||"").match(ad)||[],c=b[b.length-1]||[],d=(c+"").match(xd)||["-",0,0],e=+(60*d[1])+q(d[2]);return"+"===d[0]?e:-e}function La(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(o(b)||d(b)?+b:+Da(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Da(b).local()}function Ma(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Na(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ka(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ma(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?bb(this,Ya(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ma(this)}function Oa(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Pa(a){return this.utcOffset(0,a)}function Qa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ma(this),"m")),this}function Ra(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ka(this._i)),this}function Sa(a){return a=a?Da(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Ta(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ua(){if("undefined"!=typeof this._isDSTShifted)return this._isDSTShifted;var a={};if(m(a,this),a=Aa(a),a._a){var b=a._isUTC?h(a._a):Da(a._a);this._isDSTShifted=this.isValid()&&r(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Va(){return!this._isUTC}function Wa(){return this._isUTC}function Xa(){return this._isUTC&&0===this._offset}function Ya(a,b){var c,d,e,g=a,h=null;return Ia(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=yd.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:q(h[hd])*c,h:q(h[id])*c,m:q(h[jd])*c,s:q(h[kd])*c,ms:q(h[ld])*c}):(h=zd.exec(a))?(c="-"===h[1]?-1:1,g={y:Za(h[2],c),M:Za(h[3],c),d:Za(h[4],c),h:Za(h[5],c),m:Za(h[6],c),s:Za(h[7],c),w:Za(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=_a(Da(g.from),Da(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Ha(g),Ia(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function Za(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function $a(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function _a(a,b){var c;return b=La(b,a),a.isBefore(b)?c=$a(a,b):(c=$a(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function ab(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(ba(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ya(c,d),bb(this,e,a),this}}function bb(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&E(b,"Date",D(b,"Date")+g*d),h&&X(b,D(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function cb(a,b){var c=a||Da(),d=La(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse";return this.format(b&&b[f]||this.localeData().calendar(f,this,Da(c)))}function db(){return new n(this)}function eb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+this>+a):(c=o(a)?+a:+Da(a),c<+this.clone().startOf(b))}function fb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+a>+this):(c=o(a)?+a:+Da(a),+this.clone().endOf(b)<c)}function gb(a,b,c){return this.isAfter(a,c)&&this.isBefore(b,c)}function hb(a,b){var c;return b=A(b||"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+this===+a):(c=+Da(a),+this.clone().startOf(b)<=c&&c<=+this.clone().endOf(b))}function ib(a,b,c){var d,e,f=La(a,this),g=6e4*(f.utcOffset()-this.utcOffset());return b=A(b),"year"===b||"month"===b||"quarter"===b?(e=jb(this,f),"quarter"===b?e/=3:"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:p(e)}function jb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function kb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function lb(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?"function"==typeof Date.prototype.toISOString?this.toDate().toISOString():K(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):K(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function mb(b){var c=K(this,b||a.defaultFormat);return this.localeData().postformat(c)}function nb(a,b){return this.isValid()?Ya({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function ob(a){return this.from(Da(),a)}function pb(a,b){return this.isValid()?Ya({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function qb(a){return this.to(Da(),a)}function rb(a){var b;return void 0===a?this._locale._abbr:(b=y(a),null!=b&&(this._locale=b),this)}function sb(){return this._locale}function tb(a){switch(a=A(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function ub(a){return a=A(a),void 0===a||"millisecond"===a?this:this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms")}function vb(){return+this._d-6e4*(this._offset||0)}function wb(){return Math.floor(+this/1e3)}function xb(){return this._offset?new Date(+this):this._d}function yb(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function zb(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function Ab(){return k(this)}function Bb(){return g({},j(this))}function Cb(){return j(this).overflow}function Db(a,b){H(0,[a,a.length],0,b)}function Eb(a,b,c){return ja(Da([a,11,31+b-c]),b,c).week}function Fb(a){var b=ja(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")}function Gb(a){var b=ja(this,1,4).year;return null==a?b:this.add(a-b,"y")}function Hb(){return Eb(this.year(),1,4)}function Ib(){var a=this.localeData()._week;return Eb(this.year(),a.dow,a.doy)}function Jb(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}function Kb(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function Lb(a){return this._weekdays[a.day()]}function Mb(a){return this._weekdaysShort[a.day()]}function Nb(a){return this._weekdaysMin[a.day()]}function Ob(a){var b,c,d;for(this._weekdaysParse=this._weekdaysParse||[],b=0;7>b;b++)if(this._weekdaysParse[b]||(c=Da([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Pb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Kb(a,this.localeData()),this.add(a-b,"d")):b}function Qb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Rb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Sb(a,b){H(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Tb(a,b){return b._meridiemParse}function Ub(a){return"p"===(a+"").toLowerCase().charAt(0)}function Vb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wb(a,b){b[ld]=q(1e3*("0."+a))}function Xb(){return this._isUTC?"UTC":""}function Yb(){return this._isUTC?"Coordinated Universal Time":""}function Zb(a){return Da(1e3*a)}function $b(){return Da.apply(null,arguments).parseZone()}function _b(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function bc(){return this._invalidDate}function cc(a){return this._ordinal.replace("%d",a)}function dc(a){return a}function ec(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function gc(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function hc(a,b,c,d){var e=y(),f=h().set(d,b);return e[c](f,a)}function ic(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return hc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=hc(a,f,c,e);return g}function jc(a,b){return ic(a,b,"months",12,"month")}function kc(a,b){return ic(a,b,"monthsShort",12,"month")}function lc(a,b){return ic(a,b,"weekdays",7,"day")}function mc(a,b){return ic(a,b,"weekdaysShort",7,"day")}function nc(a,b){return ic(a,b,"weekdaysMin",7,"day")}function oc(){var a=this._data;return this._milliseconds=Wd(this._milliseconds),this._days=Wd(this._days),this._months=Wd(this._months),a.milliseconds=Wd(a.milliseconds),a.seconds=Wd(a.seconds),a.minutes=Wd(a.minutes),a.hours=Wd(a.hours),a.months=Wd(a.months),a.years=Wd(a.years),this}function pc(a,b,c,d){var e=Ya(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function qc(a,b){return pc(this,a,b,1)}function rc(a,b){return pc(this,a,b,-1)}function sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*sc(vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=p(f/1e3),i.seconds=a%60,b=p(a/60),i.minutes=b%60,c=p(b/60),i.hours=c%24,g+=p(c/24),e=p(uc(g)),h+=e,g-=sc(vc(e)),d=p(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function uc(a){return 4800*a/146097}function vc(a){return 146097*a/4800}function wc(a){var b,c,d=this._milliseconds;if(a=A(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*q(this._months/12)}function yc(a){return function(){return this.as(a)}}function zc(a){return a=A(a),this[a+"s"]()}function Ac(a){return function(){return this._data[a]}}function Bc(){return p(this.days()/7)}function Cc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function Dc(a,b,c){var d=Ya(a).abs(),e=ke(d.as("s")),f=ke(d.as("m")),g=ke(d.as("h")),h=ke(d.as("d")),i=ke(d.as("M")),j=ke(d.as("y")),k=e<le.s&&["s",e]||1===f&&["m"]||f<le.m&&["mm",f]||1===g&&["h"]||g<le.h&&["hh",g]||1===h&&["d"]||h<le.d&&["dd",h]||1===i&&["M"]||i<le.M&&["MM",i]||1===j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,Cc.apply(null,k)}function Ec(a,b){return void 0===le[a]?!1:void 0===b?le[a]:(le[a]=b,!0)}function Fc(a){var b=this.localeData(),c=Dc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Gc(){var a,b,c,d=me(this._milliseconds)/1e3,e=me(this._days),f=me(this._months);a=p(d/60),b=p(a/60),d%=60,a%=60,c=p(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var Hc,Ic,Jc=a.momentProperties=[],Kc=!1,Lc={},Mc={},Nc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Oc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Pc={},Qc={},Rc=/\d/,Sc=/\d\d/,Tc=/\d{3}/,Uc=/\d{4}/,Vc=/[+-]?\d{6}/,Wc=/\d\d?/,Xc=/\d{1,3}/,Yc=/\d{1,4}/,Zc=/[+-]?\d{1,6}/,$c=/\d+/,_c=/[+-]?\d+/,ad=/Z|[+-]\d\d:?\d\d/gi,bd=/[+-]?\d+(\.\d{1,3})?/,cd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,dd={},ed={},fd=0,gd=1,hd=2,id=3,jd=4,kd=5,ld=6;H("M",["MM",2],"Mo",function(){return this.month()+1}),H("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),H("MMMM",0,0,function(a){return this.localeData().months(this,a)}),z("month","M"),N("M",Wc),N("MM",Wc,Sc),N("MMM",cd),N("MMMM",cd),Q(["M","MM"],function(a,b){b[gd]=q(a)-1}),Q(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[gd]=e:j(c).invalidMonth=a});var md="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),nd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),od={};a.suppressDeprecationWarnings=!1;var pd=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,qd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],rd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],sd=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=aa("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),H(0,["YY",2],0,function(){return this.year()%100}),H(0,["YYYY",4],0,"year"),H(0,["YYYYY",5],0,"year"),H(0,["YYYYYY",6,!0],0,"year"),z("year","y"),N("Y",_c),N("YY",Wc,Sc),N("YYYY",Yc,Uc),N("YYYYY",Zc,Vc),N("YYYYYY",Zc,Vc),Q(["YYYYY","YYYYYY"],fd),Q("YYYY",function(b,c){c[fd]=2===b.length?a.parseTwoDigitYear(b):q(b)}),Q("YY",function(b,c){c[fd]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return q(a)+(q(a)>68?1900:2e3)};var td=C("FullYear",!1);H("w",["ww",2],"wo","week"),H("W",["WW",2],"Wo","isoWeek"),z("week","w"),z("isoWeek","W"),N("w",Wc),N("ww",Wc,Sc),N("W",Wc),N("WW",Wc,Sc),R(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=q(a)});var ud={dow:0,doy:6};H("DDD",["DDDD",3],"DDDo","dayOfYear"),z("dayOfYear","DDD"),N("DDD",Xc),N("DDDD",Tc),Q(["DDD","DDDD"],function(a,b,c){c._dayOfYear=q(a)}),a.ISO_8601=function(){};var vd=aa("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return this>a?this:a}),wd=aa("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return a>this?this:a});Ja("Z",":"),Ja("ZZ",""),N("Z",ad),N("ZZ",ad),Q(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ka(a)});var xd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var yd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,zd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ya.fn=Ha.prototype;var Ad=ab(1,"add"),Bd=ab(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var Cd=aa("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});H(0,["gg",2],0,function(){return this.weekYear()%100}),H(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Db("gggg","weekYear"),Db("ggggg","weekYear"),Db("GGGG","isoWeekYear"),Db("GGGGG","isoWeekYear"),z("weekYear","gg"),z("isoWeekYear","GG"),N("G",_c),N("g",_c),N("GG",Wc,Sc),N("gg",Wc,Sc),N("GGGG",Yc,Uc),N("gggg",Yc,Uc),N("GGGGG",Zc,Vc),N("ggggg",Zc,Vc),R(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=q(a)}),R(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),H("Q",0,0,"quarter"),z("quarter","Q"),N("Q",Rc),Q("Q",function(a,b){b[gd]=3*(q(a)-1)}),H("D",["DD",2],"Do","date"),z("date","D"),N("D",Wc),N("DD",Wc,Sc),N("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),Q(["D","DD"],hd),Q("Do",function(a,b){b[hd]=q(a.match(Wc)[0],10)});var Dd=C("Date",!0);H("d",0,"do","day"),H("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),H("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),H("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),H("e",0,0,"weekday"),H("E",0,0,"isoWeekday"),z("day","d"),z("weekday","e"),z("isoWeekday","E"),N("d",Wc),N("e",Wc),N("E",Wc),N("dd",cd),N("ddd",cd),N("dddd",cd),R(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:j(c).invalidWeekday=a}),R(["d","e","E"],function(a,b,c,d){b[d]=q(a)});var Ed="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Fd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Gd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");H("H",["HH",2],0,"hour"),H("h",["hh",2],0,function(){return this.hours()%12||12}),Sb("a",!0),Sb("A",!1),z("hour","h"),N("a",Tb),N("A",Tb),N("H",Wc),N("h",Wc),N("HH",Wc,Sc),N("hh",Wc,Sc),Q(["H","HH"],id),Q(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),Q(["h","hh"],function(a,b,c){b[id]=q(a),j(c).bigHour=!0});var Hd=/[ap]\.?m?\.?/i,Id=C("Hours",!0);H("m",["mm",2],0,"minute"),z("minute","m"),N("m",Wc),N("mm",Wc,Sc),Q(["m","mm"],jd);var Jd=C("Minutes",!1);H("s",["ss",2],0,"second"),z("second","s"),N("s",Wc),N("ss",Wc,Sc),Q(["s","ss"],kd);var Kd=C("Seconds",!1);H("S",0,0,function(){return~~(this.millisecond()/100)}),H(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,function(){return 10*this.millisecond()}),H(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),H(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),H(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),H(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),H(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),z("millisecond","ms"),N("S",Xc,Rc),N("SS",Xc,Sc),N("SSS",Xc,Tc);var Ld;for(Ld="SSSS";Ld.length<=9;Ld+="S")N(Ld,$c);for(Ld="S";Ld.length<=9;Ld+="S")Q(Ld,Wb);var Md=C("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var Nd=n.prototype;Nd.add=Ad,Nd.calendar=cb,Nd.clone=db,Nd.diff=ib,Nd.endOf=ub,Nd.format=mb,Nd.from=nb,Nd.fromNow=ob,Nd.to=pb,Nd.toNow=qb,Nd.get=F,Nd.invalidAt=Cb,Nd.isAfter=eb,Nd.isBefore=fb,Nd.isBetween=gb,Nd.isSame=hb,Nd.isValid=Ab,Nd.lang=Cd,Nd.locale=rb,Nd.localeData=sb,Nd.max=wd,Nd.min=vd,Nd.parsingFlags=Bb,Nd.set=F,Nd.startOf=tb,Nd.subtract=Bd,Nd.toArray=yb,Nd.toObject=zb,Nd.toDate=xb,Nd.toISOString=lb,Nd.toJSON=lb,Nd.toString=kb,Nd.unix=wb,Nd.valueOf=vb,Nd.year=td,Nd.isLeapYear=ia,Nd.weekYear=Fb,Nd.isoWeekYear=Gb,Nd.quarter=Nd.quarters=Jb,Nd.month=Y,Nd.daysInMonth=Z,Nd.week=Nd.weeks=na,Nd.isoWeek=Nd.isoWeeks=oa,Nd.weeksInYear=Ib,Nd.isoWeeksInYear=Hb,Nd.date=Dd,Nd.day=Nd.days=Pb,Nd.weekday=Qb,Nd.isoWeekday=Rb,Nd.dayOfYear=qa,Nd.hour=Nd.hours=Id,Nd.minute=Nd.minutes=Jd,Nd.second=Nd.seconds=Kd,
6 Nd.millisecond=Nd.milliseconds=Md,Nd.utcOffset=Na,Nd.utc=Pa,Nd.local=Qa,Nd.parseZone=Ra,Nd.hasAlignedHourOffset=Sa,Nd.isDST=Ta,Nd.isDSTShifted=Ua,Nd.isLocal=Va,Nd.isUtcOffset=Wa,Nd.isUtc=Xa,Nd.isUTC=Xa,Nd.zoneAbbr=Xb,Nd.zoneName=Yb,Nd.dates=aa("dates accessor is deprecated. Use date instead.",Dd),Nd.months=aa("months accessor is deprecated. Use month instead",Y),Nd.years=aa("years accessor is deprecated. Use year instead",td),Nd.zone=aa("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Oa);var Od=Nd,Pd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Qd={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Rd="Invalid date",Sd="%d",Td=/\d{1,2}/,Ud={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Vd=s.prototype;Vd._calendar=Pd,Vd.calendar=_b,Vd._longDateFormat=Qd,Vd.longDateFormat=ac,Vd._invalidDate=Rd,Vd.invalidDate=bc,Vd._ordinal=Sd,Vd.ordinal=cc,Vd._ordinalParse=Td,Vd.preparse=dc,Vd.postformat=dc,Vd._relativeTime=Ud,Vd.relativeTime=ec,Vd.pastFuture=fc,Vd.set=gc,Vd.months=U,Vd._months=md,Vd.monthsShort=V,Vd._monthsShort=nd,Vd.monthsParse=W,Vd.week=ka,Vd._week=ud,Vd.firstDayOfYear=ma,Vd.firstDayOfWeek=la,Vd.weekdays=Lb,Vd._weekdays=Ed,Vd.weekdaysMin=Nb,Vd._weekdaysMin=Gd,Vd.weekdaysShort=Mb,Vd._weekdaysShort=Fd,Vd.weekdaysParse=Ob,Vd.isPM=Ub,Vd._meridiemParse=Hd,Vd.meridiem=Vb,w("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=aa("moment.lang is deprecated. Use moment.locale instead.",w),a.langData=aa("moment.langData is deprecated. Use moment.localeData instead.",y);var Wd=Math.abs,Xd=yc("ms"),Yd=yc("s"),Zd=yc("m"),$d=yc("h"),_d=yc("d"),ae=yc("w"),be=yc("M"),ce=yc("y"),de=Ac("milliseconds"),ee=Ac("seconds"),fe=Ac("minutes"),ge=Ac("hours"),he=Ac("days"),ie=Ac("months"),je=Ac("years"),ke=Math.round,le={s:45,m:45,h:22,d:26,M:11},me=Math.abs,ne=Ha.prototype;ne.abs=oc,ne.add=qc,ne.subtract=rc,ne.as=wc,ne.asMilliseconds=Xd,ne.asSeconds=Yd,ne.asMinutes=Zd,ne.asHours=$d,ne.asDays=_d,ne.asWeeks=ae,ne.asMonths=be,ne.asYears=ce,ne.valueOf=xc,ne._bubble=tc,ne.get=zc,ne.milliseconds=de,ne.seconds=ee,ne.minutes=fe,ne.hours=ge,ne.days=he,ne.weeks=Bc,ne.months=ie,ne.years=je,ne.humanize=Fc,ne.toISOString=Gc,ne.toString=Gc,ne.toJSON=Gc,ne.locale=rb,ne.localeData=sb,ne.toIsoString=aa("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Gc),ne.lang=Cd,H("X",0,0,"unix"),H("x",0,0,"valueOf"),N("x",_c),N("X",bd),Q("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),Q("x",function(a,b,c){c._d=new Date(q(a))}),a.version="2.10.6",b(Da),a.fn=Od,a.min=Fa,a.max=Ga,a.utc=h,a.unix=Zb,a.months=jc,a.isDate=d,a.locale=w,a.invalid=l,a.duration=Ya,a.isMoment=o,a.weekdays=lc,a.parseZone=$b,a.localeData=y,a.isDuration=Ia,a.monthsShort=kc,a.weekdaysMin=nc,a.defineLocale=x,a.weekdaysShort=mc,a.normalizeUnits=A,a.relativeTimeThreshold=Ec;var oe=a;return oe});
+0
-1021
faraday/server/www/script/mousetrap.js less more
0 /*global define:false */
1 /**
2 * Copyright 2015 Craig Campbell
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Mousetrap is a simple keyboard shortcut library for Javascript with
17 * no external dependencies
18 *
19 * @version 1.5.2
20 * @url craig.is/killing/mice
21 */
22 (function(window, document, undefined) {
23
24 /**
25 * mapping of special keycodes to their corresponding keys
26 *
27 * everything in this dictionary cannot use keypress events
28 * so it has to be here to map to the correct keycodes for
29 * keyup/keydown events
30 *
31 * @type {Object}
32 */
33 var _MAP = {
34 8: 'backspace',
35 9: 'tab',
36 13: 'enter',
37 16: 'shift',
38 17: 'ctrl',
39 18: 'alt',
40 20: 'capslock',
41 27: 'esc',
42 32: 'space',
43 33: 'pageup',
44 34: 'pagedown',
45 35: 'end',
46 36: 'home',
47 37: 'left',
48 38: 'up',
49 39: 'right',
50 40: 'down',
51 45: 'ins',
52 46: 'del',
53 91: 'meta',
54 93: 'meta',
55 224: 'meta'
56 };
57
58 /**
59 * mapping for special characters so they can support
60 *
61 * this dictionary is only used incase you want to bind a
62 * keyup or keydown event to one of these keys
63 *
64 * @type {Object}
65 */
66 var _KEYCODE_MAP = {
67 106: '*',
68 107: '+',
69 109: '-',
70 110: '.',
71 111 : '/',
72 186: ';',
73 187: '=',
74 188: ',',
75 189: '-',
76 190: '.',
77 191: '/',
78 192: '`',
79 219: '[',
80 220: '\\',
81 221: ']',
82 222: '\''
83 };
84
85 /**
86 * this is a mapping of keys that require shift on a US keypad
87 * back to the non shift equivelents
88 *
89 * this is so you can use keyup events with these keys
90 *
91 * note that this will only work reliably on US keyboards
92 *
93 * @type {Object}
94 */
95 var _SHIFT_MAP = {
96 '~': '`',
97 '!': '1',
98 '@': '2',
99 '#': '3',
100 '$': '4',
101 '%': '5',
102 '^': '6',
103 '&': '7',
104 '*': '8',
105 '(': '9',
106 ')': '0',
107 '_': '-',
108 '+': '=',
109 ':': ';',
110 '\"': '\'',
111 '<': ',',
112 '>': '.',
113 '?': '/',
114 '|': '\\'
115 };
116
117 /**
118 * this is a list of special strings you can use to map
119 * to modifier keys when you specify your keyboard shortcuts
120 *
121 * @type {Object}
122 */
123 var _SPECIAL_ALIASES = {
124 'option': 'alt',
125 'command': 'meta',
126 'return': 'enter',
127 'escape': 'esc',
128 'plus': '+',
129 'mod': /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'meta' : 'ctrl'
130 };
131
132 /**
133 * variable to store the flipped version of _MAP from above
134 * needed to check if we should use keypress or not when no action
135 * is specified
136 *
137 * @type {Object|undefined}
138 */
139 var _REVERSE_MAP;
140
141 /**
142 * loop through the f keys, f1 to f19 and add them to the map
143 * programatically
144 */
145 for (var i = 1; i < 20; ++i) {
146 _MAP[111 + i] = 'f' + i;
147 }
148
149 /**
150 * loop through to map numbers on the numeric keypad
151 */
152 for (i = 0; i <= 9; ++i) {
153 _MAP[i + 96] = i;
154 }
155
156 /**
157 * cross browser add event method
158 *
159 * @param {Element|HTMLDocument} object
160 * @param {string} type
161 * @param {Function} callback
162 * @returns void
163 */
164 function _addEvent(object, type, callback) {
165 if (object.addEventListener) {
166 object.addEventListener(type, callback, false);
167 return;
168 }
169
170 object.attachEvent('on' + type, callback);
171 }
172
173 /**
174 * takes the event and returns the key character
175 *
176 * @param {Event} e
177 * @return {string}
178 */
179 function _characterFromEvent(e) {
180
181 // for keypress events we should return the character as is
182 if (e.type == 'keypress') {
183 var character = String.fromCharCode(e.which);
184
185 // if the shift key is not pressed then it is safe to assume
186 // that we want the character to be lowercase. this means if
187 // you accidentally have caps lock on then your key bindings
188 // will continue to work
189 //
190 // the only side effect that might not be desired is if you
191 // bind something like 'A' cause you want to trigger an
192 // event when capital A is pressed caps lock will no longer
193 // trigger the event. shift+a will though.
194 if (!e.shiftKey) {
195 character = character.toLowerCase();
196 }
197
198 return character;
199 }
200
201 // for non keypress events the special maps are needed
202 if (_MAP[e.which]) {
203 return _MAP[e.which];
204 }
205
206 if (_KEYCODE_MAP[e.which]) {
207 return _KEYCODE_MAP[e.which];
208 }
209
210 // if it is not in the special map
211
212 // with keydown and keyup events the character seems to always
213 // come in as an uppercase character whether you are pressing shift
214 // or not. we should make sure it is always lowercase for comparisons
215 return String.fromCharCode(e.which).toLowerCase();
216 }
217
218 /**
219 * checks if two arrays are equal
220 *
221 * @param {Array} modifiers1
222 * @param {Array} modifiers2
223 * @returns {boolean}
224 */
225 function _modifiersMatch(modifiers1, modifiers2) {
226 return modifiers1.sort().join(',') === modifiers2.sort().join(',');
227 }
228
229 /**
230 * takes a key event and figures out what the modifiers are
231 *
232 * @param {Event} e
233 * @returns {Array}
234 */
235 function _eventModifiers(e) {
236 var modifiers = [];
237
238 if (e.shiftKey) {
239 modifiers.push('shift');
240 }
241
242 if (e.altKey) {
243 modifiers.push('alt');
244 }
245
246 if (e.ctrlKey) {
247 modifiers.push('ctrl');
248 }
249
250 if (e.metaKey) {
251 modifiers.push('meta');
252 }
253
254 return modifiers;
255 }
256
257 /**
258 * prevents default for this event
259 *
260 * @param {Event} e
261 * @returns void
262 */
263 function _preventDefault(e) {
264 if (e.preventDefault) {
265 e.preventDefault();
266 return;
267 }
268
269 e.returnValue = false;
270 }
271
272 /**
273 * stops propogation for this event
274 *
275 * @param {Event} e
276 * @returns void
277 */
278 function _stopPropagation(e) {
279 if (e.stopPropagation) {
280 e.stopPropagation();
281 return;
282 }
283
284 e.cancelBubble = true;
285 }
286
287 /**
288 * determines if the keycode specified is a modifier key or not
289 *
290 * @param {string} key
291 * @returns {boolean}
292 */
293 function _isModifier(key) {
294 return key == 'shift' || key == 'ctrl' || key == 'alt' || key == 'meta';
295 }
296
297 /**
298 * reverses the map lookup so that we can look for specific keys
299 * to see what can and can't use keypress
300 *
301 * @return {Object}
302 */
303 function _getReverseMap() {
304 if (!_REVERSE_MAP) {
305 _REVERSE_MAP = {};
306 for (var key in _MAP) {
307
308 // pull out the numeric keypad from here cause keypress should
309 // be able to detect the keys from the character
310 if (key > 95 && key < 112) {
311 continue;
312 }
313
314 if (_MAP.hasOwnProperty(key)) {
315 _REVERSE_MAP[_MAP[key]] = key;
316 }
317 }
318 }
319 return _REVERSE_MAP;
320 }
321
322 /**
323 * picks the best action based on the key combination
324 *
325 * @param {string} key - character for key
326 * @param {Array} modifiers
327 * @param {string=} action passed in
328 */
329 function _pickBestAction(key, modifiers, action) {
330
331 // if no action was picked in we should try to pick the one
332 // that we think would work best for this key
333 if (!action) {
334 action = _getReverseMap()[key] ? 'keydown' : 'keypress';
335 }
336
337 // modifier keys don't work as expected with keypress,
338 // switch to keydown
339 if (action == 'keypress' && modifiers.length) {
340 action = 'keydown';
341 }
342
343 return action;
344 }
345
346 /**
347 * Converts from a string key combination to an array
348 *
349 * @param {string} combination like "command+shift+l"
350 * @return {Array}
351 */
352 function _keysFromString(combination) {
353 if (combination === '+') {
354 return ['+'];
355 }
356
357 combination = combination.replace(/\+{2}/g, '+plus');
358 return combination.split('+');
359 }
360
361 /**
362 * Gets info for a specific key combination
363 *
364 * @param {string} combination key combination ("command+s" or "a" or "*")
365 * @param {string=} action
366 * @returns {Object}
367 */
368 function _getKeyInfo(combination, action) {
369 var keys;
370 var key;
371 var i;
372 var modifiers = [];
373
374 // take the keys from this pattern and figure out what the actual
375 // pattern is all about
376 keys = _keysFromString(combination);
377
378 for (i = 0; i < keys.length; ++i) {
379 key = keys[i];
380
381 // normalize key names
382 if (_SPECIAL_ALIASES[key]) {
383 key = _SPECIAL_ALIASES[key];
384 }
385
386 // if this is not a keypress event then we should
387 // be smart about using shift keys
388 // this will only work for US keyboards however
389 if (action && action != 'keypress' && _SHIFT_MAP[key]) {
390 key = _SHIFT_MAP[key];
391 modifiers.push('shift');
392 }
393
394 // if this key is a modifier then add it to the list of modifiers
395 if (_isModifier(key)) {
396 modifiers.push(key);
397 }
398 }
399
400 // depending on what the key combination is
401 // we will try to pick the best event for it
402 action = _pickBestAction(key, modifiers, action);
403
404 return {
405 key: key,
406 modifiers: modifiers,
407 action: action
408 };
409 }
410
411 function _belongsTo(element, ancestor) {
412 if (element === document) {
413 return false;
414 }
415
416 if (element === ancestor) {
417 return true;
418 }
419
420 return _belongsTo(element.parentNode, ancestor);
421 }
422
423 function Mousetrap(targetElement) {
424 var self = this;
425
426 targetElement = targetElement || document;
427
428 if (!(self instanceof Mousetrap)) {
429 return new Mousetrap(targetElement);
430 }
431
432 /**
433 * element to attach key events to
434 *
435 * @type {Element}
436 */
437 self.target = targetElement;
438
439 /**
440 * a list of all the callbacks setup via Mousetrap.bind()
441 *
442 * @type {Object}
443 */
444 self._callbacks = {};
445
446 /**
447 * direct map of string combinations to callbacks used for trigger()
448 *
449 * @type {Object}
450 */
451 self._directMap = {};
452
453 /**
454 * keeps track of what level each sequence is at since multiple
455 * sequences can start out with the same sequence
456 *
457 * @type {Object}
458 */
459 var _sequenceLevels = {};
460
461 /**
462 * variable to store the setTimeout call
463 *
464 * @type {null|number}
465 */
466 var _resetTimer;
467
468 /**
469 * temporary state where we will ignore the next keyup
470 *
471 * @type {boolean|string}
472 */
473 var _ignoreNextKeyup = false;
474
475 /**
476 * temporary state where we will ignore the next keypress
477 *
478 * @type {boolean}
479 */
480 var _ignoreNextKeypress = false;
481
482 /**
483 * are we currently inside of a sequence?
484 * type of action ("keyup" or "keydown" or "keypress") or false
485 *
486 * @type {boolean|string}
487 */
488 var _nextExpectedAction = false;
489
490 /**
491 * resets all sequence counters except for the ones passed in
492 *
493 * @param {Object} doNotReset
494 * @returns void
495 */
496 function _resetSequences(doNotReset) {
497 doNotReset = doNotReset || {};
498
499 var activeSequences = false,
500 key;
501
502 for (key in _sequenceLevels) {
503 if (doNotReset[key]) {
504 activeSequences = true;
505 continue;
506 }
507 _sequenceLevels[key] = 0;
508 }
509
510 if (!activeSequences) {
511 _nextExpectedAction = false;
512 }
513 }
514
515 /**
516 * finds all callbacks that match based on the keycode, modifiers,
517 * and action
518 *
519 * @param {string} character
520 * @param {Array} modifiers
521 * @param {Event|Object} e
522 * @param {string=} sequenceName - name of the sequence we are looking for
523 * @param {string=} combination
524 * @param {number=} level
525 * @returns {Array}
526 */
527 function _getMatches(character, modifiers, e, sequenceName, combination, level) {
528 var i;
529 var callback;
530 var matches = [];
531 var action = e.type;
532
533 // if there are no events related to this keycode
534 if (!self._callbacks[character]) {
535 return [];
536 }
537
538 // if a modifier key is coming up on its own we should allow it
539 if (action == 'keyup' && _isModifier(character)) {
540 modifiers = [character];
541 }
542
543 // loop through all callbacks for the key that was pressed
544 // and see if any of them match
545 for (i = 0; i < self._callbacks[character].length; ++i) {
546 callback = self._callbacks[character][i];
547
548 // if a sequence name is not specified, but this is a sequence at
549 // the wrong level then move onto the next match
550 if (!sequenceName && callback.seq && _sequenceLevels[callback.seq] != callback.level) {
551 continue;
552 }
553
554 // if the action we are looking for doesn't match the action we got
555 // then we should keep going
556 if (action != callback.action) {
557 continue;
558 }
559
560 // if this is a keypress event and the meta key and control key
561 // are not pressed that means that we need to only look at the
562 // character, otherwise check the modifiers as well
563 //
564 // chrome will not fire a keypress if meta or control is down
565 // safari will fire a keypress if meta or meta+shift is down
566 // firefox will fire a keypress if meta or control is down
567 if ((action == 'keypress' && !e.metaKey && !e.ctrlKey) || _modifiersMatch(modifiers, callback.modifiers)) {
568
569 // when you bind a combination or sequence a second time it
570 // should overwrite the first one. if a sequenceName or
571 // combination is specified in this call it does just that
572 //
573 // @todo make deleting its own method?
574 var deleteCombo = !sequenceName && callback.combo == combination;
575 var deleteSequence = sequenceName && callback.seq == sequenceName && callback.level == level;
576 if (deleteCombo || deleteSequence) {
577 self._callbacks[character].splice(i, 1);
578 }
579
580 matches.push(callback);
581 }
582 }
583
584 return matches;
585 }
586
587 /**
588 * actually calls the callback function
589 *
590 * if your callback function returns false this will use the jquery
591 * convention - prevent default and stop propogation on the event
592 *
593 * @param {Function} callback
594 * @param {Event} e
595 * @returns void
596 */
597 function _fireCallback(callback, e, combo, sequence) {
598
599 // if this event should not happen stop here
600 if (self.stopCallback(e, e.target || e.srcElement, combo, sequence)) {
601 return;
602 }
603
604 if (callback(e, combo) === false) {
605 _preventDefault(e);
606 _stopPropagation(e);
607 }
608 }
609
610 /**
611 * handles a character key event
612 *
613 * @param {string} character
614 * @param {Array} modifiers
615 * @param {Event} e
616 * @returns void
617 */
618 self._handleKey = function(character, modifiers, e) {
619 var callbacks = _getMatches(character, modifiers, e);
620 var i;
621 var doNotReset = {};
622 var maxLevel = 0;
623 var processedSequenceCallback = false;
624
625 // Calculate the maxLevel for sequences so we can only execute the longest callback sequence
626 for (i = 0; i < callbacks.length; ++i) {
627 if (callbacks[i].seq) {
628 maxLevel = Math.max(maxLevel, callbacks[i].level);
629 }
630 }
631
632 // loop through matching callbacks for this key event
633 for (i = 0; i < callbacks.length; ++i) {
634
635 // fire for all sequence callbacks
636 // this is because if for example you have multiple sequences
637 // bound such as "g i" and "g t" they both need to fire the
638 // callback for matching g cause otherwise you can only ever
639 // match the first one
640 if (callbacks[i].seq) {
641
642 // only fire callbacks for the maxLevel to prevent
643 // subsequences from also firing
644 //
645 // for example 'a option b' should not cause 'option b' to fire
646 // even though 'option b' is part of the other sequence
647 //
648 // any sequences that do not match here will be discarded
649 // below by the _resetSequences call
650 if (callbacks[i].level != maxLevel) {
651 continue;
652 }
653
654 processedSequenceCallback = true;
655
656 // keep a list of which sequences were matches for later
657 doNotReset[callbacks[i].seq] = 1;
658 _fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);
659 continue;
660 }
661
662 // if there were no sequence matches but we are still here
663 // that means this is a regular match so we should fire that
664 if (!processedSequenceCallback) {
665 _fireCallback(callbacks[i].callback, e, callbacks[i].combo);
666 }
667 }
668
669 // if the key you pressed matches the type of sequence without
670 // being a modifier (ie "keyup" or "keypress") then we should
671 // reset all sequences that were not matched by this event
672 //
673 // this is so, for example, if you have the sequence "h a t" and you
674 // type "h e a r t" it does not match. in this case the "e" will
675 // cause the sequence to reset
676 //
677 // modifier keys are ignored because you can have a sequence
678 // that contains modifiers such as "enter ctrl+space" and in most
679 // cases the modifier key will be pressed before the next key
680 //
681 // also if you have a sequence such as "ctrl+b a" then pressing the
682 // "b" key will trigger a "keypress" and a "keydown"
683 //
684 // the "keydown" is expected when there is a modifier, but the
685 // "keypress" ends up matching the _nextExpectedAction since it occurs
686 // after and that causes the sequence to reset
687 //
688 // we ignore keypresses in a sequence that directly follow a keydown
689 // for the same character
690 var ignoreThisKeypress = e.type == 'keypress' && _ignoreNextKeypress;
691 if (e.type == _nextExpectedAction && !_isModifier(character) && !ignoreThisKeypress) {
692 _resetSequences(doNotReset);
693 }
694
695 _ignoreNextKeypress = processedSequenceCallback && e.type == 'keydown';
696 };
697
698 /**
699 * handles a keydown event
700 *
701 * @param {Event} e
702 * @returns void
703 */
704 function _handleKeyEvent(e) {
705
706 // normalize e.which for key events
707 // @see http://stackoverflow.com/questions/4285627/javascript-keycode-vs-charcode-utter-confusion
708 if (typeof e.which !== 'number') {
709 e.which = e.keyCode;
710 }
711
712 var character = _characterFromEvent(e);
713
714 // no character found then stop
715 if (!character) {
716 return;
717 }
718
719 // need to use === for the character check because the character can be 0
720 if (e.type == 'keyup' && _ignoreNextKeyup === character) {
721 _ignoreNextKeyup = false;
722 return;
723 }
724
725 self.handleKey(character, _eventModifiers(e), e);
726 }
727
728 /**
729 * called to set a 1 second timeout on the specified sequence
730 *
731 * this is so after each key press in the sequence you have 1 second
732 * to press the next key before you have to start over
733 *
734 * @returns void
735 */
736 function _resetSequenceTimer() {
737 clearTimeout(_resetTimer);
738 _resetTimer = setTimeout(_resetSequences, 1000);
739 }
740
741 /**
742 * binds a key sequence to an event
743 *
744 * @param {string} combo - combo specified in bind call
745 * @param {Array} keys
746 * @param {Function} callback
747 * @param {string=} action
748 * @returns void
749 */
750 function _bindSequence(combo, keys, callback, action) {
751
752 // start off by adding a sequence level record for this combination
753 // and setting the level to 0
754 _sequenceLevels[combo] = 0;
755
756 /**
757 * callback to increase the sequence level for this sequence and reset
758 * all other sequences that were active
759 *
760 * @param {string} nextAction
761 * @returns {Function}
762 */
763 function _increaseSequence(nextAction) {
764 return function() {
765 _nextExpectedAction = nextAction;
766 ++_sequenceLevels[combo];
767 _resetSequenceTimer();
768 };
769 }
770
771 /**
772 * wraps the specified callback inside of another function in order
773 * to reset all sequence counters as soon as this sequence is done
774 *
775 * @param {Event} e
776 * @returns void
777 */
778 function _callbackAndReset(e) {
779 _fireCallback(callback, e, combo);
780
781 // we should ignore the next key up if the action is key down
782 // or keypress. this is so if you finish a sequence and
783 // release the key the final key will not trigger a keyup
784 if (action !== 'keyup') {
785 _ignoreNextKeyup = _characterFromEvent(e);
786 }
787
788 // weird race condition if a sequence ends with the key
789 // another sequence begins with
790 setTimeout(_resetSequences, 10);
791 }
792
793 // loop through keys one at a time and bind the appropriate callback
794 // function. for any key leading up to the final one it should
795 // increase the sequence. after the final, it should reset all sequences
796 //
797 // if an action is specified in the original bind call then that will
798 // be used throughout. otherwise we will pass the action that the
799 // next key in the sequence should match. this allows a sequence
800 // to mix and match keypress and keydown events depending on which
801 // ones are better suited to the key provided
802 for (var i = 0; i < keys.length; ++i) {
803 var isFinal = i + 1 === keys.length;
804 var wrappedCallback = isFinal ? _callbackAndReset : _increaseSequence(action || _getKeyInfo(keys[i + 1]).action);
805 _bindSingle(keys[i], wrappedCallback, action, combo, i);
806 }
807 }
808
809 /**
810 * binds a single keyboard combination
811 *
812 * @param {string} combination
813 * @param {Function} callback
814 * @param {string=} action
815 * @param {string=} sequenceName - name of sequence if part of sequence
816 * @param {number=} level - what part of the sequence the command is
817 * @returns void
818 */
819 function _bindSingle(combination, callback, action, sequenceName, level) {
820
821 // store a direct mapped reference for use with Mousetrap.trigger
822 self._directMap[combination + ':' + action] = callback;
823
824 // make sure multiple spaces in a row become a single space
825 combination = combination.replace(/\s+/g, ' ');
826
827 var sequence = combination.split(' ');
828 var info;
829
830 // if this pattern is a sequence of keys then run through this method
831 // to reprocess each pattern one key at a time
832 if (sequence.length > 1) {
833 _bindSequence(combination, sequence, callback, action);
834 return;
835 }
836
837 info = _getKeyInfo(combination, action);
838
839 // make sure to initialize array if this is the first time
840 // a callback is added for this key
841 self._callbacks[info.key] = self._callbacks[info.key] || [];
842
843 // remove an existing match if there is one
844 _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);
845
846 // add this call back to the array
847 // if it is a sequence put it at the beginning
848 // if not put it at the end
849 //
850 // this is important because the way these are processed expects
851 // the sequence ones to come first
852 self._callbacks[info.key][sequenceName ? 'unshift' : 'push']({
853 callback: callback,
854 modifiers: info.modifiers,
855 action: info.action,
856 seq: sequenceName,
857 level: level,
858 combo: combination
859 });
860 }
861
862 /**
863 * binds multiple combinations to the same callback
864 *
865 * @param {Array} combinations
866 * @param {Function} callback
867 * @param {string|undefined} action
868 * @returns void
869 */
870 self._bindMultiple = function(combinations, callback, action) {
871 for (var i = 0; i < combinations.length; ++i) {
872 _bindSingle(combinations[i], callback, action);
873 }
874 };
875
876 // start!
877 _addEvent(targetElement, 'keypress', _handleKeyEvent);
878 _addEvent(targetElement, 'keydown', _handleKeyEvent);
879 _addEvent(targetElement, 'keyup', _handleKeyEvent);
880 }
881
882 /**
883 * binds an event to mousetrap
884 *
885 * can be a single key, a combination of keys separated with +,
886 * an array of keys, or a sequence of keys separated by spaces
887 *
888 * be sure to list the modifier keys first to make sure that the
889 * correct key ends up getting bound (the last key in the pattern)
890 *
891 * @param {string|Array} keys
892 * @param {Function} callback
893 * @param {string=} action - 'keypress', 'keydown', or 'keyup'
894 * @returns void
895 */
896 Mousetrap.prototype.bind = function(keys, callback, action) {
897 var self = this;
898 keys = keys instanceof Array ? keys : [keys];
899 self._bindMultiple.call(self, keys, callback, action);
900 return self;
901 };
902
903 /**
904 * unbinds an event to mousetrap
905 *
906 * the unbinding sets the callback function of the specified key combo
907 * to an empty function and deletes the corresponding key in the
908 * _directMap dict.
909 *
910 * TODO: actually remove this from the _callbacks dictionary instead
911 * of binding an empty function
912 *
913 * the keycombo+action has to be exactly the same as
914 * it was defined in the bind method
915 *
916 * @param {string|Array} keys
917 * @param {string} action
918 * @returns void
919 */
920 Mousetrap.prototype.unbind = function(keys, action) {
921 var self = this;
922 return self.bind.call(self, keys, function() {}, action);
923 };
924
925 /**
926 * triggers an event that has already been bound
927 *
928 * @param {string} keys
929 * @param {string=} action
930 * @returns void
931 */
932 Mousetrap.prototype.trigger = function(keys, action) {
933 var self = this;
934 if (self._directMap[keys + ':' + action]) {
935 self._directMap[keys + ':' + action]({}, keys);
936 }
937 return self;
938 };
939
940 /**
941 * resets the library back to its initial state. this is useful
942 * if you want to clear out the current keyboard shortcuts and bind
943 * new ones - for example if you switch to another page
944 *
945 * @returns void
946 */
947 Mousetrap.prototype.reset = function() {
948 var self = this;
949 self._callbacks = {};
950 self._directMap = {};
951 return self;
952 };
953
954 /**
955 * should we stop this event before firing off callbacks
956 *
957 * @param {Event} e
958 * @param {Element} element
959 * @return {boolean}
960 */
961 Mousetrap.prototype.stopCallback = function(e, element) {
962 var self = this;
963
964 // if the element has the class "mousetrap" then no need to stop
965 if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
966 return false;
967 }
968
969 if (_belongsTo(element, self.target)) {
970 return false;
971 }
972
973 // stop for input, select, and textarea
974 return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable;
975 };
976
977 /**
978 * exposes _handleKey publicly so it can be overwritten by extensions
979 */
980 Mousetrap.prototype.handleKey = function() {
981 var self = this;
982 return self._handleKey.apply(self, arguments);
983 };
984
985 /**
986 * Init the global mousetrap functions
987 *
988 * This method is needed to allow the global mousetrap functions to work
989 * now that mousetrap is a constructor function.
990 */
991 Mousetrap.init = function() {
992 var documentMousetrap = Mousetrap(document);
993 for (var method in documentMousetrap) {
994 if (method.charAt(0) !== '_') {
995 Mousetrap[method] = (function(method) {
996 return function() {
997 return documentMousetrap[method].apply(documentMousetrap, arguments);
998 };
999 } (method));
1000 }
1001 }
1002 };
1003
1004 Mousetrap.init();
1005
1006 // expose mousetrap to the global object
1007 window.Mousetrap = Mousetrap;
1008
1009 // expose as a common js module
1010 if (typeof module !== 'undefined' && module.exports) {
1011 module.exports = Mousetrap;
1012 }
1013
1014 // expose mousetrap as an AMD module
1015 if (typeof define === 'function' && define.amd) {
1016 define(function() {
1017 return Mousetrap;
1018 });
1019 }
1020 }) (window, document);
+0
-11
faraday/server/www/script/mousetrap.min.js less more
0 /* mousetrap v1.5.2 craig.is/killing/mice */
1 (function(C,r,g){function t(a,b,h){a.addEventListener?a.addEventListener(b,h,!1):a.attachEvent("on"+b,h)}function x(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return l[a.which]?l[a.which]:p[a.which]?p[a.which]:String.fromCharCode(a.which).toLowerCase()}function D(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function u(a){return"shift"==a||"ctrl"==a||"alt"==a||
2 "meta"==a}function y(a,b){var h,c,e,g=[];h=a;"+"===h?h=["+"]:(h=h.replace(/\+{2}/g,"+plus"),h=h.split("+"));for(e=0;e<h.length;++e)c=h[e],z[c]&&(c=z[c]),b&&"keypress"!=b&&A[c]&&(c=A[c],g.push("shift")),u(c)&&g.push(c);h=c;e=b;if(!e){if(!k){k={};for(var m in l)95<m&&112>m||l.hasOwnProperty(m)&&(k[l[m]]=m)}e=k[h]?"keydown":"keypress"}"keypress"==e&&g.length&&(e="keydown");return{key:c,modifiers:g,action:e}}function B(a,b){return a===r?!1:a===b?!0:B(a.parentNode,b)}function c(a){function b(a){a=a||{};
3 var b=!1,n;for(n in q)a[n]?b=!0:q[n]=0;b||(v=!1)}function h(a,b,n,f,c,h){var g,e,l=[],m=n.type;if(!d._callbacks[a])return[];"keyup"==m&&u(a)&&(b=[a]);for(g=0;g<d._callbacks[a].length;++g)if(e=d._callbacks[a][g],(f||!e.seq||q[e.seq]==e.level)&&m==e.action){var k;(k="keypress"==m&&!n.metaKey&&!n.ctrlKey)||(k=e.modifiers,k=b.sort().join(",")===k.sort().join(","));k&&(k=f&&e.seq==f&&e.level==h,(!f&&e.combo==c||k)&&d._callbacks[a].splice(g,1),l.push(e))}return l}function g(a,b,n,f){d.stopCallback(b,b.target||
4 b.srcElement,n,f)||!1!==a(b,n)||(b.preventDefault?b.preventDefault():b.returnValue=!1,b.stopPropagation?b.stopPropagation():b.cancelBubble=!0)}function e(a){"number"!==typeof a.which&&(a.which=a.keyCode);var b=x(a);b&&("keyup"==a.type&&w===b?w=!1:d.handleKey(b,D(a),a))}function l(a,c,n,f){function e(c){return function(){v=c;++q[a];clearTimeout(k);k=setTimeout(b,1E3)}}function h(c){g(n,c,a);"keyup"!==f&&(w=x(c));setTimeout(b,10)}for(var d=q[a]=0;d<c.length;++d){var p=d+1===c.length?h:e(f||y(c[d+1]).action);
5 m(c[d],p,f,a,d)}}function m(a,b,c,f,e){d._directMap[a+":"+c]=b;a=a.replace(/\s+/g," ");var g=a.split(" ");1<g.length?l(a,g,b,c):(c=y(a,c),d._callbacks[c.key]=d._callbacks[c.key]||[],h(c.key,c.modifiers,{type:c.action},f,a,e),d._callbacks[c.key][f?"unshift":"push"]({callback:b,modifiers:c.modifiers,action:c.action,seq:f,level:e,combo:a}))}var d=this;a=a||r;if(!(d instanceof c))return new c(a);d.target=a;d._callbacks={};d._directMap={};var q={},k,w=!1,p=!1,v=!1;d._handleKey=function(a,c,e){var f=h(a,
6 c,e),d;c={};var k=0,l=!1;for(d=0;d<f.length;++d)f[d].seq&&(k=Math.max(k,f[d].level));for(d=0;d<f.length;++d)f[d].seq?f[d].level==k&&(l=!0,c[f[d].seq]=1,g(f[d].callback,e,f[d].combo,f[d].seq)):l||g(f[d].callback,e,f[d].combo);f="keypress"==e.type&&p;e.type!=v||u(a)||f||b(c);p=l&&"keydown"==e.type};d._bindMultiple=function(a,b,c){for(var d=0;d<a.length;++d)m(a[d],b,c)};t(a,"keypress",e);t(a,"keydown",e);t(a,"keyup",e)}var l={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",
7 27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},p={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},A={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},z={option:"alt",command:"meta","return":"enter",escape:"esc",
8 plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},k;for(g=1;20>g;++g)l[111+g]="f"+g;for(g=0;9>=g;++g)l[g+96]=g;c.prototype.bind=function(a,b,c){a=a instanceof Array?a:[a];this._bindMultiple.call(this,a,b,c);return this};c.prototype.unbind=function(a,b){return this.bind.call(this,a,function(){},b)};c.prototype.trigger=function(a,b){if(this._directMap[a+":"+b])this._directMap[a+":"+b]({},a);return this};c.prototype.reset=function(){this._callbacks={};this._directMap={};return this};
9 c.prototype.stopCallback=function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")||B(b,this.target)?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable};c.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)};c.init=function(){var a=c(r),b;for(b in a)"_"!==b.charAt(0)&&(c[b]=function(b){return function(){return a[b].apply(a,arguments)}}(b))};c.init();C.Mousetrap=c;"undefined"!==typeof module&&module.exports&&(module.exports=c);"function"===
10 typeof define&&define.amd&&define(function(){return c})})(window,document);
+0
-2
faraday/server/www/script/oui.web.min.js less more
0 /*! oui web v | (c) silverwind | BSD license */
1 !function(o){if("object"==typeof exports&&"object"==typeof module)module.exports=o();else{if("function"==typeof define&&define.amd)return define([],o);this.oui=o()}}(function(){"use strict";var o={"000000":"Xerox Corporation","000001":"Xerox Corporation","000002":"Xerox Corporation","000003":"Xerox Corporation","000004":"Xerox Corporation","000005":"Xerox Corporation","000006":"Xerox Corporation","000007":"Xerox Corporation","000008":"Xerox Corporation","000009":"Xerox Corporation","00000A":"Omron Tateisi Electronics Co.","00000B":"Matrix Corporation","00000C":"Cisco Systems Inc.","00000D":"Fibronics Ltd","00000E":"Fujitsu Limited","00000F":"Next, Inc.","000010":"Sytek Inc.","000011":"Normerel Systemes","000012":"Information Technology Limited","000013":"Camex","000014":"Netronix","000015":"Datapoint Corporation","000016":"DU Pont Pixel Systems","000017":"Oracle","000018":"Webster Computer Corporation","000019":"Applied Dynamics International","00001A":"Advanced Micro Devices","00001B":"Novell, Inc.","00001C":"Bell Technologies","00001D":"Cabletron Systems, Inc.","00001E":"Telsist Industria Electronica","00001F":"Telco Systems, Inc.","000020":"Dataindustrier Diab AB","000021":"Sureman Comp. & Commun. Corp.","000022":"Visual Technology Inc.","000023":"ABB Industrial Systems AB","000024":"Connect AS","000025":"Ramtek Corp.","000026":"SHA-KEN Co. Ltd","000027":"Japan Radio Company","000028":"Prodigy Systems Corporation","000029":"IMC Networks Corp.","00002A":"TRW - Sedd/INP","00002B":"Crisp Automation, Inc","00002C":"Autotote Limited","00002D":"Chromatics Inc","00002E":"Societe Evira","00002F":"Timeplex Inc.","000030":"VG Laboratory Systems Ltd","000031":"Qpsx Communications Ltd","000032":"Marconi plc","000033":"Egan Machinery Company","000034":"Network Resources Corporation","000035":"Spectragraphics Corporation","000036":"Atari Corporation","000037":"Oxford Metrics Limited","000038":"CSS Labs","000039":"Toshiba Corporation","00003A":"Chyron Corporation","00003B":"i Controls, Inc.","00003C":"Auspex Systems Inc.","00003D":"Unisys","00003E":"Simpact","00003F":"Syntrex, Inc.","000040":"Applicon, Inc.","000041":"ICE Corporation","000042":"Metier Management Systems Ltd","000043":"Micro Technology","000044":"Castelle Corporation","000045":"Ford Aerospace & Comm. Corp.","000046":"Olivetti North America","000047":"Nicolet Instruments Corp.","000048":"Seiko Epson Corporation","000049":"Apricot Computers Ltd","00004A":"ADC Codenoll Technology Corp.","00004B":"ICL Data Oy","00004C":"NEC Corporation","00004D":"DCI Corporation","00004E":"Ampex Corporation","00004F":"Logicraft, Inc.","000050":"Radisys Corporation","000051":"HOB Electronic GmbH & Co. KG","000052":"Intrusion.com, Inc.","000053":"Compucorp","000054":"Schneider Electric","000055":"Commissariat A L`Energie Atom.","000056":"DR. B. Struck","000057":"Scitex Corporation Ltd","000058":"Racore Computer Products Inc.","000059":"Hellige GmbH","00005A":"SysKonnect GmbH","00005B":"Eltec Elektronik AG","00005C":"Telematics International Inc.","00005D":"CS Telecom","00005E":"ICANN, IANA Department","00005F":"Sumitomo Electric Industries Ltd","000060":"Kontron Elektronik GmbH","000061":"Gateway Communications","000062":"Bull HN Information Systems","000063":"Barco Control Rooms GmbH","000064":"Yokogawa Digital Computer Corporation","000065":"Network General Corporation","000066":"Talaris Systems, Inc.","000067":"Soft * Rite, Inc.","000068":"Rosemount Controls","000069":"Concord Communications Inc","00006A":"Computer Consoles Inc.","00006B":"Silicon Graphics Inc./Mips","00006C":"Private","00006D":"Cray Communications Ltd","00006E":"Artisoft Inc.","00006F":"Madge Ltd","000070":"HCL Limited","000071":"Adra Systems Inc.","000072":"Miniware Technology","000073":"Siecor Corporation","000074":"Ricoh Company Ltd","000075":"Nortel Networks","000076":"Abekas Video System","000077":"Interphase Corporation","000078":"Labtam Limited","000079":"Networth Incorporated","00007A":"Dana Computer Inc.","00007B":"Research Machines","00007C":"Ampere Incorporated","00007D":"Oracle Corporation","00007E":"Clustrix Corporation","00007F":"Linotype-Hell AG","000080":"Cray Communications A/S","000081":"Bay Networks","000082":"Lectra Systemes SA","000083":"Tadpole Technology PLC","000084":"Supernet","000085":"Canon Inc.","000086":"Megahertz Corporation","000087":"Hitachi Ltd","000088":"Brocade Communications Systems, Inc.","000089":"Cayman Systems Inc.","00008A":"Datahouse Information Systems","00008B":"Infotron","00008C":"Alloy Computer Products (Australia) Pty Ltd","00008D":"Cryptek Inc.","00008E":"Solbourne Computer, Inc.","00008F":"Raytheon","000090":"Microcom","000091":"Anritsu Corporation","000092":"Cogent Data Technologies","000093":"Proteon Inc.","000094":"Asante Technologies","000095":"Sony Tektronix Corp.","000096":"Marconi Electronics Ltd","000097":"Dell EMC","000098":"Crosscomm Corporation","000099":"MTX, Inc.","00009A":"RC Computer A/S","00009B":"Information International, Inc","00009C":"Rolm MIL-Spec Computers","00009D":"Locus Computing Corporation","00009E":"Marli S.A.","00009F":"Ameristar Technologies Inc.","0000A0":"SANYO Electric Co. Ltd","0000A1":"Marquette Electric Co.","0000A2":"Bay Networks","0000A3":"Network Application Technology","0000A4":"Acorn Computers Limited","0000A5":"Tattile SRL","0000A6":"Network General Corporation","0000A7":"Network Computing Devices Inc.","0000A8":"Stratus Technologies","0000A9":"Network Systems Corp.","0000AA":"Xerox Corporation","0000AB":"Logic Modeling Corporation","0000AC":"Conware Computer Consulting","0000AD":"Bruker Instruments Inc.","0000AE":"Dassault Electronique","0000AF":"Canberra Industries, Inc.","0000B0":"RND-RAD Network Devices","0000B1":"Alpha Micro","0000B2":"Televideo Systems, Inc.","0000B3":"Cimlinc Incorporated","0000B4":"Edimax Technology Co. Ltd","0000B5":"Datability Software Sys. Inc.","0000B6":"Micro-Matic Research","0000B7":"Dove Computer Corporation","0000B8":"Seikosha Co. Ltd","0000B9":"Mcdonnell Douglas Computer Sys","0000BA":"Siig, Inc.","0000BB":"TRI-Data","0000BC":"Rockwell Automation","0000BD":"Mitsubishi Cable Company","0000BE":"THE NTI Group","0000BF":"Symmetric Computer Systems","0000C0":"Western Digital Corporation","0000C1":"Madge Ltd","0000C2":"Information Presentation Tech.","0000C3":"Harris Corp Computer Sys Div","0000C4":"Waters Div. Of Millipore","0000C5":"ARRIS Group, Inc.","0000C6":"EON Systems","0000C7":"Arix Corporation","0000C8":"Altos Computer Systems","0000C9":"Emulex Corporation","0000CA":"ARRIS Group, Inc.","0000CB":"Compu-Shack Electronic GmbH","0000CC":"Densan Co. Ltd","0000CD":"Allied Telesis Labs Ltd","0000CE":"Megadata Corp.","0000CF":"Hayes Microcomputer Products","0000D0":"Develcon Electronics Ltd","0000D1":"Adaptec Incorporated","0000D2":"SBE, Inc.","0000D3":"Wang Laboratories Inc.","0000D4":"Pure Data Ltd","0000D5":"Micrognosis International","0000D6":"Punch Line Holding","0000D7":"Dartmouth College","0000D8":"Novell, Inc.","0000D9":"Nippon Telegraph & Telephone","0000DA":"Atex","0000DB":"British Telecommunications plc","0000DC":"Hayes Microcomputer Products","0000DD":"TCL Incorporated","0000DE":"Cetia","0000DF":"Bell & Howell Pub Sys Div","0000E0":"Quadram Corp.","0000E1":"Grid Systems","0000E2":"Acer Technologies Corp.","0000E3":"Integrated Micro Products Ltd","0000E4":"IN2 Groupe Intertechnique","0000E5":"Sigmex Ltd","0000E6":"Aptor Produits de Comm Indust","0000E7":"Star Gate Technologies","0000E8":"Accton Technology Corp.","0000E9":"Isicad, Inc.","0000EA":"Upnod AB","0000EB":"Matsushita Comm. Ind. Co. Ltd","0000EC":"Microprocess","0000ED":"April","0000EE":"Network Designers Ltd","0000EF":"KTI","0000F0":"Samsung Electronics Co. Ltd","0000F1":"Magna Computer Corporation","0000F2":"Spider Communications","0000F3":"Gandalf Data Limited","0000F4":"Allied Telesis, Inc.","0000F5":"Diamond Sales Limited","0000F6":"Applied Microsystems Corp.","0000F7":"Youth Keep Enterprise Co Ltd","0000F8":"Digital Equipment Corporation","0000F9":"Quotron Systems Inc.","0000FA":"Microsage Computer Systems Inc","0000FB":"Rechner ZUR Kommunikation","0000FC":"Meiko","0000FD":"High Level Hardware","0000FE":"Annapolis Micro Systems, Inc.","0000FF":"Camtec Electronics Ltd","000100":"Equip'Trans","000101":"Private","000102":"3Com Corporation","000103":"3Com Corporation","000104":"DVICO Co. Ltd","000105":"Beckhoff Automation GmbH","000106":"Tews Datentechnik GmbH","000107":"Leiser GmbH","000108":"AVLAB Technology, Inc.","000109":"Nagano Japan Radio Co. Ltd","00010A":"CIS Technology Inc.","00010B":"Space CyberLink, Inc.","00010C":"System Talks Inc.","00010D":"Teledyne DALSA Inc.","00010E":"Bri-Link Technologies Co. Ltd","00010F":"Brocade Communications Systems, Inc.","000110":"Gotham Networks","000111":"iDigm Inc.","000112":"Shark Multimedia Inc.","000113":"Olympus Corporation","000114":"Kanda Tsushin Kogyo Co. Ltd","000115":"Extratech Corporation","000116":"Netspect Technologies, Inc.","000117":"Canal +","000118":"EZ Digital Co. Ltd","000119":"RTUnet (Australia)","00011A":"Hoffmann und Burmeister GbR","00011B":"Unizone Technologies, Inc.","00011C":"Universal Talkware Corporation","00011D":"Centillium Communications","00011E":"Precidia Technologies, Inc.","00011F":"RC Networks, Inc.","000120":"Oscilloquartz S.A.","000121":"Watchguard Technologies, Inc.","000122":"Trend Communications Ltd","000123":"Schneider Electric Japan Holdings Ltd","000124":"Acer Incorporated","000125":"Yaesu Musen Co. Ltd","000126":"PAC Labs","000127":"OPEN Networks Pty Ltd","000128":"EnjoyWeb, Inc.","000129":"DFI Inc.","00012A":"Telematica Sistems Inteligente","00012B":"TELENET Co. Ltd","00012C":"Aravox Technologies, Inc.","00012D":"Komodo Technology","00012E":"PC Partner Ltd","00012F":"Twinhead International Corp","000130":"Extreme Networks, Inc.","000131":"Bosch Security Systems, Inc.","000132":"Dranetz - BMI","000133":"KYOWA Electronic Instruments C","000134":"Selectron Systems AG","000135":"KDC Corp.","000136":"CyberTAN Technology Inc.","000137":"IT Farm Corporation","000138":"XAVi Technologies Corp.","000139":"Point Multimedia Systems","00013A":"Shelcad Communications Ltd","00013B":"BNA Systems","00013C":"TIW Systems","00013D":"RiscStation Ltd","00013E":"Ascom Tateco AB","00013F":"Neighbor World Co. Ltd","000140":"Sendtek Corporation","000141":"Cable Print","000142":"Cisco Systems Inc.","000143":"Cisco Systems Inc.","000144":"Dell EMC","000145":"Winsystems, Inc.","000146":"Tesco Controls, Inc.","000147":"Zhone Technologies","000148":"X-traWeb Inc.","000149":"T.D.T. Transfer Data Test GmbH","00014A":"Sony Corporation","00014B":"Ennovate Networks, Inc.","00014C":"Berkeley Process Control","00014D":"Shin Kin Enterprises Co. Ltd","00014E":"WIN Enterprises, Inc.","00014F":"Adtran Inc","000150":"Gilat Communications Ltd","000151":"Ensemble Communications","000152":"Chromatek Inc.","000153":"Archtek Telecom Corporation","000154":"G3M Corporation","000155":"Promise Technology, Inc.","000156":"Firewiredirect.com, Inc.","000157":"Syswave Co. Ltd","000158":"Electro Industries/Gauge Tech","000159":"S1 Corporation","00015A":"Digital Video Broadcasting","00015B":"ITALTEL S.p.A/RF-UP-I","00015C":"Cadant Inc.","00015D":"Oracle Corporation","00015E":"Best Technology Co. Ltd","00015F":"DIGITAL DESIGN GmbH","000160":"ELMEX Co. Ltd","000161":"Meta Machine Technology","000162":"Cygnet Technologies, Inc.","000163":"Cisco Systems Inc.","000164":"Cisco Systems Inc.","000165":"AirSwitch Corporation","000166":"TC Group A/S","000167":"Hioki E.E. Corporation","000168":"Vitana Corporation","000169":"Celestix Networks Pte Ltd","00016A":"Alitec","00016B":"LightChip, Inc.","00016C":"Foxconn","00016D":"CarrierComm Inc.","00016E":"Conklin Corporation","00016F":"Inkel Corp.","000170":"ESE Embedded System Engineer'g","000171":"Allied Data Technologies","000172":"TechnoLand Co. Ltd","000173":"AMCC","000174":"CyberOptics Corporation","000175":"Radiant Communications Corp.","000176":"Orient Silver Enterprises","000177":"EDSL","000178":"MARGI Systems, Inc.","000179":"Wireless Technology, Inc.","00017A":"Chengdu Maipu Electric Industrial Co. Ltd","00017B":"Heidelberger Druckmaschinen AG","00017C":"AG-E GmbH","00017D":"ThermoQuest","00017E":"ADTEK System Science Co. Ltd","00017F":"Experience Music Project","000180":"AOpen, Inc.","000181":"Nortel Networks","000182":"Dica Technologies AG","000183":"Anite Telecoms","000184":"Sieb & Meyer AG","000185":"Hitachi Aloka Medical Ltd","000186":"Uwe Disch","000187":"I2SE GmbH","000188":"LXCO Technologies ag","000189":"Refraction Technology, Inc.","00018A":"ROI Computer AG","00018B":"NetLinks Co. Ltd","00018C":"Mega Vision","00018D":"AudeSi Technologies","00018E":"Logitec Corporation","00018F":"Kenetec, Inc.","000190":"SMK-M","000191":"SYRED Data Systems","000192":"Texas Digital Systems","000193":"Hanbyul Telecom Co. Ltd","000194":"Capital Equipment Corporation","000195":"Sena Technologies, Inc.","000196":"Cisco Systems Inc.","000197":"Cisco Systems Inc.","000198":"Darim Vision","000199":"HeiSei Electronics","00019A":"LEUNIG GmbH","00019B":"Kyoto Microcomputer Co. Ltd","00019C":"JDS Uniphase Inc.","00019D":"E-Control Systems, Inc.","00019E":"ESS Technology, Inc.","00019F":"ReadyNet","0001A0":"Infinilink Corporation","0001A1":"Mag-Tek, Inc.","0001A2":"Logical Co. Ltd","0001A3":"Genesys Logic, Inc.","0001A4":"Microlink Corporation","0001A5":"Nextcomm, Inc.","0001A6":"Scientific-Atlanta Arcodan A/S","0001A7":"Unex Technology Corporation","0001A8":"Welltech Computer Co. Ltd","0001A9":"BMW AG","0001AA":"Airspan Communications Ltd","0001AB":"Main Street Networks","0001AC":"Sitara Networks, Inc.","0001AD":"Coach Master International d.b.a. CMI Worldwide, Inc.","0001AE":"Trex Enterprises","0001AF":"Artesyn Embedded Technologies","0001B0":"Fulltek Technology Co. Ltd","0001B1":"General Bandwidth","0001B2":"Digital Processing Systems, Inc.","0001B3":"Precision Electronic Manufacturing","0001B4":"Wayport, Inc.","0001B5":"Turin Networks, Inc.","0001B6":"SAEJIN T&M Co. Ltd","0001B7":"Centos, Inc.","0001B8":"Netsensity, Inc.","0001B9":"SKF (U.K.) Limited","0001BA":"IC-Net, Inc.","0001BB":"Frequentis","0001BC":"Brains Corporation","0001BD":"Peterson Electro-Musical Products, Inc.","0001BE":"Gigalink Co. Ltd","0001BF":"Teleforce Co. Ltd","0001C0":"CompuLab Ltd","0001C1":"Vitesse Semiconductor Corporation","0001C2":"ARK Research Corp.","0001C3":"Acromag, Inc.","0001C4":"NeoWave, Inc.","0001C5":"Simpler Networks","0001C6":"Quarry Technologies","0001C7":"Cisco Systems Inc.","0001C8":"Conrad Corp.","0001C9":"Cisco Systems Inc.","0001CA":"Geocast Network Systems, Inc.","0001CB":"EVR","0001CC":"Japan Total Design Communication Co. Ltd","0001CD":"ARtem","0001CE":"Custom Micro Products Ltd","0001CF":"Alpha Data Parallel Systems Ltd","0001D0":"VitalPoint, Inc.","0001D1":"CoNet Communications, Inc.","0001D2":"inXtron, Inc.","0001D3":"PAXCOMM, Inc.","0001D4":"Leisure Time, Inc.","0001D5":"Haedong Info & Comm Co. Ltd","0001D6":"manroland AG","0001D7":"F5 Networks, Inc.","0001D8":"Teltronics, Inc.","0001D9":"Sigma, Inc.","0001DA":"WINCOMM Corporation","0001DB":"Freecom Technologies GmbH","0001DC":"Activetelco","0001DD":"Avail Networks","0001DE":"Trango Systems, Inc.","0001DF":"ISDN Communications Ltd","0001E0":"Fast Systems, Inc.","0001E1":"Kinpo Electronics, Inc.","0001E2":"Ando Electric Corporation","0001E3":"Siemens AG","0001E4":"Sitera, Inc.","0001E5":"Supernet, Inc.","0001E6":"Hewlett-Packard Company","0001E7":"Hewlett-Packard Company","0001E8":"Force10 Networks, Inc.","0001E9":"Litton Marine Systems B.V.","0001EA":"Cirilium Corp.","0001EB":"C-CoM Corporation","0001EC":"Ericsson Group","0001ED":"SETA Corp.","0001EE":"Comtrol Europe Ltd","0001EF":"Camtel Technology Corp.","0001F0":"Tridium, Inc.","0001F1":"Innovative Concepts, Inc.","0001F2":"Mark Of the Unicorn, Inc.","0001F3":"QPS, Inc.","0001F4":"Enterasys","0001F5":"Erim S.A.","0001F6":"Association Of Musical Electronics Industry","0001F7":"Image Display Systems, Inc.","0001F8":"Texio Technology Corporation","0001F9":"TeraGlobal Communications Corp.","0001FA":"Horoscas","0001FB":"DoTop Technology, Inc.","0001FC":"Keyence Corporation","0001FD":"Digital Voice Systems, Inc.","0001FE":"Digital Equipment Corporation","0001FF":"Data Direct Networks, Inc.","000200":"Net & Sys Co. Ltd","000201":"IFM Electronic GmbH","000202":"Amino Communications Ltd","000203":"Woonsang Telecom, Inc.","000204":"Bodmann Industries Elektronik GmbH","000205":"Hitachi Denshi Ltd","000206":"Telital R&D Denmark A/S","000207":"VisionGlobal Network Corp.","000208":"Unify Networks, Inc.","000209":"Shenzhen SED Information Technology Co. Ltd","00020A":"Gefran Spa","00020B":"Native Networks, Inc.","00020C":"Metro-Optix","00020D":"Micronpc.com","00020E":"ECI Telecom Ltd","00020F":"Aatr","000210":"Fenecom","000211":"Nature Worldwide Technology Corp.","000212":"SierraCom","000213":"S.D.E.L.","000214":"Dtvro","000215":"Cotas Computer Technology A/B","000216":"Cisco Systems Inc.","000217":"Cisco Systems Inc.","000218":"Advanced Scientific Corp","000219":"Paralon Technologies","00021A":"Zuma Networks","00021B":"Kollmorgen-Servotronix","00021C":"Network Elements, Inc.","00021D":"Data General Communication Ltd","00021E":"Simtel S.R.L.","00021F":"Aculab PLC","000220":"Canon Finetech Inc.","000221":"DSP Application Ltd","000222":"Chromisys, Inc.","000223":"ClickTV","000224":"C-CoR","000225":"One Stop Systems","000226":"XESystems, Inc.","000227":"ESD Electronic System Design GmbH","000228":"Necsom Ltd","000229":"Adtec Corporation","00022A":"Asound Electronic","00022B":"SAXA, Inc.","00022C":"ABB Bomem, Inc.","00022D":"Agere Systems","00022E":"TEAC Corp. R& D","00022F":"P-Cube Ltd","000230":"Intersoft Electronics","000231":"Ingersoll-Rand","000232":"Avision, Inc.","000233":"Mantra Communications, Inc.","000234":"Imperial Technology, Inc.","000235":"Paragon Networks International","000236":"INIT GmbH","000237":"Cosmo Research Corp.","000238":"Serome Technology, Inc.","000239":"Visicom","00023A":"ZSK Stickmaschinen GmbH","00023B":"Ericsson","00023C":"Creative Technology Ltd","00023D":"Cisco Systems Inc.","00023E":"Selta Telematica S.p.a","00023F":"Compal Electronics, Inc.","000240":"Seedek Co. Ltd","000241":"Amer.com","000242":"Videoframe Systems","000243":"Raysis Co. Ltd","000244":"SURECOM Technology Co.","000245":"Lampus Co Ltd","000246":"All-Win Tech Co. Ltd","000247":"Great Dragon Information Technology (Group) Co. Ltd","000248":"Pilz GmbH & Co.","000249":"Aviv Infocom Co Ltd","00024A":"Cisco Systems Inc.","00024B":"Cisco Systems Inc.","00024C":"SiByte, Inc.","00024D":"Mannesman Dematic Colby Pty. Ltd","00024E":"Datacard Group","00024F":"IPM Datacom S.R.L.","000250":"Geyser Networks, Inc.","000251":"Soma Networks, Inc.","000252":"Carrier Corporation","000253":"Televideo, Inc.","000254":"WorldGate","000255":"IBM Corp","000256":"Alpha Processor, Inc.","000257":"Microcom Corp.","000258":"Flying Packets Communications","000259":"Tsann Kuen China (Shanghai)Enterprise Co. Ltd IT Group","00025A":"Catena Networks","00025B":"Cambridge Silicon Radio","00025C":"SCI Systems (Kunshan) Co. Ltd","00025D":"Calix Networks","00025E":"High Technology Ltd","00025F":"Nortel Networks","000260":"Accordion Networks, Inc.","000261":"Tilgin AB","000262":"Soyo Group Soyo Com Tech Co. Ltd","000263":"UPS Manufacturing SRL","000264":"AudioRamp.com","000265":"Virditech Co. Ltd","000266":"Thermalogic Corporation","000267":"Node Runner, Inc.","000268":"Harris Government Communications","000269":"Nadatel Co. Ltd","00026A":"Cocess Telecom Co. Ltd","00026B":"BCM Computers Co. Ltd","00026C":"Philips CFT","00026D":"Adept Telecom","00026E":"NeGeN Access, Inc.","00026F":"Senao International Co. Ltd","000270":"Crewave Co. Ltd","000271":"Zhone Technologies","000272":"CC&C Technologies, Inc.","000273":"Coriolis Networks","000274":"Tommy Technologies Corp.","000275":"SMART Technologies, Inc.","000276":"Primax Electronics Ltd","000277":"Cash Systemes Industrie","000278":"Samsung Electro Mechanics Co. Ltd","000279":"Control Applications Ltd","00027A":"IOI Technology Corporation","00027B":"Amplify Net, Inc.","00027C":"Trilithic, Inc.","00027D":"Cisco Systems Inc.","00027E":"Cisco Systems Inc.","00027F":"ask-technologies.com","000280":"Mu Net, Inc.","000281":"Madge Ltd","000282":"ViaClix, Inc.","000283":"Spectrum Controls, Inc.","000284":"Areva T&D","000285":"Riverstone Networks","000286":"Occam Networks","000287":"Adapcom","000288":"Global Village Communication","000289":"DNE Technologies","00028A":"Ambit Microsystems Corporation","00028B":"VDSL Systems Oy","00028C":"Micrel-Synergy Semiconductor","00028D":"Movita Technologies, Inc.","00028E":"Rapid 5 Networks, Inc.","00028F":"Globetek, Inc.","000290":"Woorigisool, Inc.","000291":"Open Network Co. Ltd","000292":"Logic Innovations, Inc.","000293":"Solid Data Systems","000294":"Tokyo Sokushin Co. Ltd","000295":"IP.Access Limited","000296":"Lectron Co,. Ltd","000297":"C-CoR.net","000298":"Broadframe Corporation","000299":"Apex, Inc.","00029A":"Storage Apps","00029B":"Kreatel Communications AB","00029C":"3Com Corporation","00029D":"Merix Corp.","00029E":"Information Equipment Co. Ltd","00029F":"L-3 Communication Aviation Recorders","0002A0":"Flatstack Ltd","0002A1":"World Wide Packets","0002A2":"Hilscher GmbH","0002A3":"ABB Switzerland Ltd, Power Systems","0002A4":"AddPac Technology Co. Ltd","0002A5":"Hewlett-Packard Company","0002A6":"Effinet Systems Co. Ltd","0002A7":"Vivace Networks","0002A8":"Air Link Technology","0002A9":"RACOM, s.r.o.","0002AA":"PLcom Co. Ltd","0002AB":"CTC Union Technologies Co. Ltd","0002AC":"3PAR data","0002AD":"HOYA Corporation","0002AE":"Scannex Electronics Ltd","0002AF":"TeleCruz Technology, Inc.","0002B0":"Hokubu Communication & Industrial Co. Ltd","0002B1":"Anritsu Ltd","0002B2":"Cablevision","0002B3":"Intel Corporation","0002B4":"Daphne","0002B5":"Avnet, Inc.","0002B6":"Acrosser Technology Co. Ltd","0002B7":"Watanabe Electric Industry Co. Ltd","0002B8":"WHI Konsult AB","0002B9":"Cisco Systems Inc.","0002BA":"Cisco Systems Inc.","0002BB":"Continuous Computing Corp","0002BC":"LVL 7 Systems, Inc.","0002BD":"Bionet Co. Ltd","0002BE":"Totsu Engineering, Inc.","0002BF":"dotRocket, Inc.","0002C0":"Bencent Tzeng Industry Co. Ltd","0002C1":"Innovative Electronic Designs, Inc.","0002C2":"Net Vision Telecom","0002C3":"Arelnet Ltd","0002C4":"Vector International BVBA","0002C5":"Evertz Microsystems Ltd","0002C6":"Data Track Technology PLC","0002C7":"Alps Electric Co. Ltd","0002C8":"Technocom Communications Technology (pte) Ltd","0002C9":"Mellanox Technologies, Inc.","0002CA":"EndPoints, Inc.","0002CB":"TriState Ltd","0002CC":"M.C.C.I","0002CD":"TeleDream, Inc.","0002CE":"FoxJet, Inc.","0002CF":"ZyGate Communications, Inc.","0002D0":"Comdial Corporation","0002D1":"Vivotek, Inc.","0002D2":"Workstation AG","0002D3":"NetBotz, Inc.","0002D4":"PDA Peripherals, Inc.","0002D5":"ACR","0002D6":"NICE Systems","0002D7":"EMPEG Ltd","0002D8":"BRECIS Communications Corporation","0002D9":"Reliable Controls","0002DA":"ExiO Communications, Inc.","0002DB":"Netsec","0002DC":"Fujitsu General Limited","0002DD":"Bromax Communications Ltd","0002DE":"Astrodesign, Inc.","0002DF":"Net Com Systems, Inc.","0002E0":"ETAS GmbH","0002E1":"Integrated Network Corporation","0002E2":"NDC Infared Engineering","0002E3":"LITE-ON Communications, Inc.","0002E4":"JC HYUN Systems, Inc.","0002E5":"Timeware Ltd","0002E6":"Gould Instrument Systems, Inc.","0002E7":"CAB GmbH & Co KG","0002E8":"E.D.&A.","0002E9":"CS Systemes de Securite - C3S","0002EA":"Focus Enhancements","0002EB":"Pico Communications","0002EC":"Maschoff Design Engineering","0002ED":"DXO Telecom Co. Ltd","0002EE":"Nokia Danmark A/S","0002EF":"CCC Network Systems Group Ltd","0002F0":"AME Optimedia Technology Co. Ltd","0002F1":"Pinetron Co. Ltd","0002F2":"eDevice, Inc.","0002F3":"Media Serve Co. Ltd","0002F4":"PCTEL, Inc.","0002F5":"VIVE Synergies, Inc.","0002F6":"Equipe Communications","0002F7":"ARM","0002F8":"SEAKR Engineering, Inc.","0002F9":"MIMOS Berhad","0002FA":"DX Antenna Co. Ltd","0002FB":"Baumuller Aulugen-Systemtechnik GmbH","0002FC":"Cisco Systems Inc.","0002FD":"Cisco Systems Inc.","0002FE":"Viditec, Inc.","0002FF":"Handan BroadInfoCom","000300":"Barracuda Networks, Inc.","000301":"Exfo","000302":"Charles Industries Ltd","000303":"JAMA Electronics Co. Ltd","000304":"Pacific Broadband Communications","000305":"MSC Vertriebs GmbH","000306":"Fusion In Tech Co. Ltd","000307":"Secure Works, Inc.","000308":"AM Communications, Inc.","000309":"Texcel Technology PLC","00030A":"Argus Technologies","00030B":"Hunter Technology, Inc.","00030C":"Telesoft Technologies Ltd","00030D":"Uniwill Computer Corp.","00030E":"Core Communications Co. Ltd","00030F":"Digital China (Shanghai) Networks Ltd","000310":"E-Globaledge Corporation","000311":"Micro Technology Co. Ltd","000312":"TR-Systemtechnik GmbH","000313":"Access Media SPA","000314":"Teleware Network Systems","000315":"Cidco Incorporated","000316":"Nobell Communications, Inc.","000317":"Merlin Systems, Inc.","000318":"Cyras Systems, Inc.","000319":"Infineon AG","00031A":"Beijing Broad Telecom Ltd, China","00031B":"Cellvision Systems, Inc.","00031C":"Svenska Hardvarufabriken AB","00031D":"Taiwan Commate Computer, Inc.","00031E":"Optranet, Inc.","00031F":"Condev Ltd","000320":"Xpeed, Inc.","000321":"Reco Research Co. Ltd","000322":"IDIS Co. Ltd","000323":"Cornet Technology, Inc.","000324":"SANYO Consumer Electronics Co. Ltd","000325":"Arima Computer Corp.","000326":"Iwasaki Information Systems Co. Ltd","000327":"ACT'L","000328":"Mace Group, Inc.","000329":"F3, Inc.","00032A":"UniData Communication Systems, Inc.","00032B":"GAI Datenfunksysteme GmbH","00032C":"ABB Switzerland Ltd","00032D":"IBASE Technology, Inc.","00032E":"Scope Information Management Ltd","00032F":"Global Sun Technology, Inc.","000330":"Imagenics, Co. Ltd","000331":"Cisco Systems Inc.","000332":"Cisco Systems Inc.","000333":"Digitel Co. Ltd","000334":"Newport Electronics","000335":"Mirae Technology","000336":"Zetes Technologies","000337":"Vaone, Inc.","000338":"Oak Technology","000339":"Eurologic Systems Ltd","00033A":"Silicon Wave, Inc.","00033B":"TAMI Tech Co. Ltd","00033C":"Daiden Co. Ltd","00033D":"ILSHin Lab","00033E":"Tateyama System Laboratory Co. Ltd","00033F":"BigBand Networks Ltd","000340":"Floware Wireless Systems Ltd","000341":"Axon Digital Design","000342":"Nortel Networks","000343":"Martin Professional A/S","000344":"Tietech.Co. Ltd","000345":"Routrek Networks Corporation","000346":"Hitachi Kokusai Electric, Inc.","000347":"Intel Corporation","000348":"Norscan Instruments Ltd","000349":"Vidicode Datacommunicatie B.V.","00034A":"RIAS Corporation","00034B":"Nortel Networks","00034C":"Shanghai DigiVision Technology Co. Ltd","00034D":"Chiaro Networks Ltd","00034E":"Pos Data Company Ltd","00034F":"Sur-Gard Security","000350":"Bticino SPA","000351":"Diebold, Inc.","000352":"Colubris Networks","000353":"Mitac, Inc.","000354":"Fiber Logic Communications","000355":"TeraBeam Internet Systems","000356":"Wincor Nixdorf International GmbH","000357":"Intervoice-Brite, Inc.","000358":"Hanyang Digitech Co.Ltd","000359":"DigitalSis","00035A":"Photron Limited","00035B":"BridgeWave Communications","00035C":"Saint Song Corp.","00035D":"Bosung Hi-Net Co. Ltd","00035E":"Metropolitan Area Networks, Inc.","00035F":"Pr?ftechnik Condition Monitoring GmbH & Co. KG","000360":"PAC Interactive Technology, Inc.","000361":"Widcomm, Inc.","000362":"Vodtel Communications, Inc.","000363":"Miraesys Co. Ltd","000364":"Scenix Semiconductor, Inc.","000365":"Kira Information & Communications Ltd","000366":"ASM Pacific Technology","000367":"Jasmine Networks, Inc.","000368":"Embedone Co. Ltd","000369":"Nippon Antenna Co. Ltd","00036A":"Mainnet Ltd","00036B":"Cisco Systems Inc.","00036C":"Cisco Systems Inc.","00036D":"Runtop, Inc.","00036E":"Nicon Systems (Pty) Limited","00036F":"Telsey SPA","000370":"NXTV, Inc.","000371":"Acomz Networks Corp.","000372":"Ulan","000373":"Aselsan A.S","000374":"Control Microsystems","000375":"NetMedia, Inc.","000376":"Graphtec Technology, Inc.","000377":"Gigabit Wireless","000378":"HUMAX Co. Ltd","000379":"Proscend Communications, Inc.","00037A":"Taiyo Yuden Co. Ltd","00037B":"IDEC IZUMI Corporation","00037C":"Coax Media","00037D":"Stellcom","00037E":"PORTech Communications, Inc.","00037F":"Atheros Communications, Inc.","000380":"SSH Communications Security Corp.","000381":"Ingenico International","000382":"A-One Co. Ltd","000383":"Metera Networks, Inc.","000384":"Aeta","000385":"Actelis Networks, Inc.","000386":"Ho Net, Inc.","000387":"Blaze Network Products","000388":"Fastfame Technology Co. Ltd","000389":"Plantronics, Inc.","00038A":"America Online, Inc.","00038B":"PLUS-ONE I&T, Inc.","00038C":"Total Impact","00038D":"PCS Revenue Control Systems, Inc.","00038E":"Atoga Systems, Inc.","00038F":"Weinschel Corporation","000390":"Digital Video Communications, Inc.","000391":"Advanced Digital Broadcast Ltd","000392":"Hyundai Teletek Co. Ltd","000393":"Apple","000394":"Connect One","000395":"California Amplifier","000396":"EZ Cast Co. Ltd","000397":"FireBrick Limited","000398":"Wisi","000399":"Dongju Informations & Communications Co. Ltd","00039A":"SiConnect","00039B":"NetChip Technology, Inc.","00039C":"OptiMight Communications, Inc.","00039D":"Qisda Corporation","00039E":"Tera System Co. Ltd","00039F":"Cisco Systems Inc.","0003A0":"Cisco Systems Inc.","0003A1":"HIPER Information & Communication, Inc.","0003A2":"Catapult Communications","0003A3":"MAVIX Ltd","0003A4":"Imation Corp.","0003A5":"Medea Corporation","0003A6":"Traxit Technology, Inc.","0003A7":"Unixtar Technology, Inc.","0003A8":"IDOT Computers, Inc.","0003A9":"AXCENT Media AG","0003AA":"Watlow","0003AB":"Bridge Information Systems","0003AC":"Fronius Schweissmaschinen","0003AD":"Emerson Energy Systems AB","0003AE":"Allied Advanced Manufacturing Pte Ltd","0003AF":"Paragea Communications","0003B0":"Xsense Technology Corp.","0003B1":"Hospira Inc.","0003B2":"Radware","0003B3":"IA Link Systems Co. Ltd","0003B4":"Macrotek International Corp.","0003B5":"Entra Technology Co.","0003B6":"QSI Corporation","0003B7":"ZACCESS Systems","0003B8":"NetKit Solutions, LLC","0003B9":"Hualong Telecom Co. Ltd","0003BA":"Oracle Corporation","0003BB":"Signal Communications Limited","0003BC":"CoT GmbH","0003BD":"OmniCluster Technologies, Inc.","0003BE":"Netility","0003BF":"Centerpoint Broadband Technologies, Inc.","0003C0":"RFTNC Co. Ltd","0003C1":"Packet Dynamics Ltd","0003C2":"Solphone K.K.","0003C3":"Micronik Multimedia","0003C4":"Tomra Systems ASA","0003C5":"Mobotix AG","0003C6":"ICUE Systems, Inc.","0003C7":"hopf Elektronik GmbH","0003C8":"CML Emergency Services","0003C9":"TECOM Co. Ltd","0003CA":"MTS Systems Corp.","0003CB":"Nippon Systems Development Co. Ltd","0003CC":"Momentum Computer, Inc.","0003CD":"Clovertech, Inc.","0003CE":"ETEN Technologies, Inc.","0003CF":"Muxcom, Inc.","0003D0":"KOANKEISO Co. Ltd","0003D1":"Takaya Corporation","0003D2":"Crossbeam Systems, Inc.","0003D3":"Internet Energy Systems, Inc.","0003D4":"Alloptic, Inc.","0003D5":"Advanced Communications Co. Ltd","0003D6":"RADVision Ltd","0003D7":"NextNet Wireless, Inc.","0003D8":"iMPath Networks, Inc.","0003D9":"Secheron SA","0003DA":"Takamisawa Cybernetics Co. Ltd","0003DB":"Apogee Electronics Corp.","0003DC":"Lexar Media, Inc.","0003DD":"Comark Interactive Solutions","0003DE":"OTC Wireless","0003DF":"Desana Systems","0003E0":"ARRIS Group, Inc.","0003E1":"Winmate Communication, Inc.","0003E2":"Comspace Corporation","0003E3":"Cisco Systems Inc.","0003E4":"Cisco Systems Inc.","0003E5":"Hermstedt SG","0003E6":"Entone, Inc.","0003E7":"Logostek Co. Ltd","0003E8":"Wavelength Digital Limited","0003E9":"Akara Canada, Inc.","0003EA":"Mega System Technologies, Inc.","0003EB":"Atrica","0003EC":"ICG Research, Inc.","0003ED":"Shinkawa Electric Co. Ltd","0003EE":"MKNet Corporation","0003EF":"Oneline AG","0003F0":"Redfern Broadband Networks","0003F1":"Cicada Semiconductor, Inc.","0003F2":"Seneca Networks","0003F3":"Dazzle Multimedia, Inc.","0003F4":"NetBurner","0003F5":"Chip2Chip","0003F6":"Allegro Networks, Inc.","0003F7":"Plast-Control GmbH","0003F8":"SanCastle Technologies, Inc.","0003F9":"Pleiades Communications, Inc.","0003FA":"TiMetra Networks","0003FB":"ENEGATE Co. Ltd","0003FC":"Intertex Data AB","0003FD":"Cisco Systems Inc.","0003FE":"Cisco Systems Inc.","0003FF":"Microsoft Corporation","000400":"Lexmark International, Inc.","000401":"Osaki Electric Co. Ltd","000402":"Nexsan Technologies Ltd","000403":"Nexsi Corporation","000404":"Makino Milling Machine Co. Ltd","000405":"ACN Technologies","000406":"Fa. Metabox AG","000407":"Topcon Positioning Systems, Inc.","000408":"Sanko Electronics Co. Ltd","000409":"Cratos Networks","00040A":"Sage Systems","00040B":"3Com Europe Ltd","00040C":"Kanno Works Ltd","00040D":"Avaya Inc","00040E":"AVM GmbH","00040F":"Asus Network Technologies, Inc.","000410":"Spinnaker Networks, Inc.","000411":"Inkra Networks, Inc.","000412":"WaveSmith Networks, Inc.","000413":"SNOM Technology AG","000414":"Umezawa Musen Denki Co. Ltd","000415":"Rasteme Systems Co. Ltd","000416":"Parks S/A Comunicacoes Digitais","000417":"Elau AG","000418":"Teltronic S.A.U.","000419":"Fibercycle Networks, Inc.","00041A":"Ines Test and Measurement GmbH & CoKG","00041B":"Bridgeworks Ltd","00041C":"ipDialog, Inc.","00041D":"Corega Of America","00041E":"Shikoku Instrumentation Co. Ltd","00041F":"Sony Interactive Entertainment Inc.","000420":"Slim Devices, Inc.","000421":"Ocular Networks","000422":"Studio Technologies, Inc","000423":"Intel Corporation","000424":"TMC s.r.l.","000425":"Atmel Corporation","000426":"Autosys","000427":"Cisco Systems Inc.","000428":"Cisco Systems Inc.","000429":"Pixord Corporation","00042A":"Wireless Networks, Inc.","00042B":"IT Access Co. Ltd","00042C":"Minet, Inc.","00042D":"Sarian Systems Ltd","00042E":"Netous Technologies Ltd","00042F":"International Communications Products, Inc.","000430":"Netgem","000431":"GlobalStreams, Inc.","000432":"Voyetra Turtle Beach, Inc.","000433":"Cyberboard A/S","000434":"Accelent Systems, Inc.","000435":"InfiNet LLC","000436":"ELANsat Technologies, Inc.","000437":"Powin Information Technology, Inc.","000438":"Nortel Networks","000439":"Rosco Entertainment Technology, Inc.","00043A":"Intelligent Telecommunications, Inc.","00043B":"Lava Computer Mfg., Inc.","00043C":"SONOS Co. Ltd","00043D":"Indel AG","00043E":"Telencomm","00043F":"ESTeem Wireless Modems, Inc","000440":"cyberPIXIE, Inc.","000441":"Half Dome Systems, Inc.","000442":"Nact","000443":"Agilent Technologies, Inc.","000444":"Western Multiplex Corporation","000445":"LMS Skalar Instruments GmbH","000446":"CYZENTECH Co. Ltd","000447":"Acrowave Systems Co. Ltd","000448":"Polaroid Corporation","000449":"Mapletree Networks","00044A":"iPolicy Networks, Inc.","00044B":"Nvidia","00044C":"Jenoptik","00044D":"Cisco Systems Inc.","00044E":"Cisco Systems Inc.","00044F":"Schubert System Elektronik GmbH","000450":"DMD Computers SRL","000451":"Medrad, Inc.","000452":"RocketLogix, Inc.","000453":"YottaYotta, Inc.","000454":"Quadriga UK","000455":"ANTARA.net","000456":"Cambium Networks Limited","000457":"Universal Access Technology, Inc.","000458":"Fusion X Co. Ltd","000459":"Veristar Corporation","00045A":"The Linksys Group, Inc.","00045B":"Techsan Electronics Co. Ltd","00045C":"Mobiwave Pte Ltd","00045D":"BEKA Elektronik","00045E":"PolyTrax Information Technology AG","00045F":"Avalue Technology, Inc.","000460":"Knilink Technology, Inc.","000461":"EPOX Computer Co. Ltd","000462":"DAKOS Data & Communication Co. Ltd","000463":"Bosch Security Systems","000464":"Pulse-Link Inc","000465":"i.s.t isdn-support technik GmbH","000466":"ARMITEL Co.","000467":"Wuhan Research Institute Of MII","000468":"Vivity, Inc.","000469":"Innocom, Inc.","00046A":"Navini Networks","00046B":"Palm Wireless, Inc.","00046C":"Cyber Technology Co. Ltd","00046D":"Cisco Systems Inc.","00046E":"Cisco Systems Inc.","00046F":"Digitel S/A Industria Eletronica","000470":"ipUnplugged AB","000471":"IPrad","000472":"Telelynx, Inc.","000473":"Photonex Corporation","000474":"Legrand","000475":"3Com Corporation","000476":"3Com Corporation","000477":"Scalant Systems, Inc.","000478":"G. Star Technology Corporation","000479":"Radius Co. Ltd","00047A":"Axxessit ASA","00047B":"Schlumberger","00047C":"Skidata AG","00047D":"Pelco","00047E":"Siqura B.V.","00047F":"Chr. Mayr GmbH & Co. KG","000480":"Brocade Communications Systems, Inc.","000481":"Econolite Control Products, Inc.","000482":"Medialogic Corp.","000483":"Deltron Technology, Inc.","000484":"Amann GmbH","000485":"PicoLight","000486":"ITTC, University Of Kansas","000487":"Cogency Semiconductor, Inc.","000488":"Eurotherm Controls","000489":"YAFO Networks, Inc.","00048A":"Temia Vertriebs GmbH","00048B":"Poscon Corporation","00048C":"Nayna Networks, Inc.","00048D":"Teo Technologies, Inc","00048E":"Ohm Tech Labs, Inc.","00048F":"TD Systems Corporation","000490":"Optical Access","000491":"Technovision, Inc.","000492":"Hive Internet Ltd","000493":"Tsinghua Unisplendour Co. Ltd","000494":"Breezecom Ltd","000495":"Tejas Networks India Limited","000496":"Extreme Networks, Inc.","000497":"MacroSystem Digital Video AG","000498":"Mahi Networks","000499":"Chino Corporation","00049A":"Cisco Systems Inc.","00049B":"Cisco Systems Inc.","00049C":"Surgient Networks, Inc.","00049D":"Ipanema Technologies","00049E":"Wirelink Co. Ltd","00049F":"Freescale Semiconductor","0004A0":"Verity Instruments, Inc.","0004A1":"Pathway Connectivity","0004A2":"L.S.I. Japan Co. Ltd","0004A3":"Microchip Technology Inc.","0004A4":"NetEnabled, Inc.","0004A5":"Barco Projection Systems NV","0004A6":"SAF Tehnika Ltd","0004A7":"FabiaTech Corporation","0004A8":"Broadmax Technologies, Inc.","0004A9":"SandStream Technologies, Inc.","0004AA":"Jetstream Communications","0004AB":"Comverse Network Systems, Inc.","0004AC":"IBM Corp","0004AD":"Malibu Networks","0004AE":"Sullair Corporation","0004AF":"Digital Fountain, Inc.","0004B0":"ELESIGN Co. Ltd","0004B1":"Signal Technology, Inc.","0004B2":"Essegi SRL","0004B3":"Videotek, Inc.","0004B4":"Ciac","0004B5":"Equitrac Corporation","0004B6":"Stratex Networks, Inc.","0004B7":"AMB i.t. Holding","0004B8":"Kumahira Co. Ltd","0004B9":"S.I. Soubou, Inc.","0004BA":"KDD Media Will Corporation","0004BB":"Bardac Corporation","0004BC":"Giantec, Inc.","0004BD":"ARRIS Group, Inc.","0004BE":"OptXCon, Inc.","0004BF":"VersaLogic Corp.","0004C0":"Cisco Systems Inc.","0004C1":"Cisco Systems Inc.","0004C2":"Magnipix, Inc.","0004C3":"CASTOR Informatique","0004C4":"Allen & Heath Limited","0004C5":"ASE Technologies, USA","0004C6":"Yamaha Motor Co. Ltd","0004C7":"NetMount","0004C8":"LIBA Maschinenfabrik GmbH","0004C9":"Micro Electron Co. Ltd","0004CA":"FreeMs Corp.","0004CB":"Tdsoft Communication Ltd","0004CC":"Peek Traffic B.V.","0004CD":"Extenway Solutions Inc","0004CE":"Patria Ailon","0004CF":"Seagate Technology","0004D0":"Softlink s.r.o.","0004D1":"Drew Technologies, Inc.","0004D2":"Adcon Telemetry GmbH","0004D3":"Toyokeiki Co. Ltd","0004D4":"Proview Electronics Co. Ltd","0004D5":"Hitachi Information & Communication Engineering Ltd","0004D6":"Takagi Industrial Co. Ltd","0004D7":"Omitec Instrumentation Ltd","0004D8":"IPWireless, Inc.","0004D9":"Titan Electronics, Inc.","0004DA":"Relax Technology, Inc.","0004DB":"Tellus Group Corp.","0004DC":"Nortel Networks","0004DD":"Cisco Systems Inc.","0004DE":"Cisco Systems Inc.","0004DF":"Teracom Telematica Ltda.","0004E0":"Procket Networks","0004E1":"Infinior Microsystems","0004E2":"SMC Networks, Inc.","0004E3":"Accton Technology Corp","0004E4":"Daeryung Ind., Inc.","0004E5":"Glonet Systems, Inc.","0004E6":"Banyan Network Private Limited","0004E7":"Lightpointe Communications, Inc","0004E8":"IER, Inc.","0004E9":"Infiniswitch Corporation","0004EA":"Hewlett-Packard Company","0004EB":"Paxonet Communications, Inc.","0004EC":"Memobox SA","0004ED":"Billion Electric Co. Ltd","0004EE":"Lincoln Electric Company","0004EF":"Polestar Corp.","0004F0":"International Computers Ltd","0004F1":"WhereNet","0004F2":"Polycom","0004F3":"FS FORTH-SysTEME GmbH","0004F4":"Infinite Electronics Inc.","0004F5":"SnowShore Networks, Inc.","0004F6":"Amphus","0004F7":"Omega Band, Inc.","0004F8":"QUALICABLE TV Industria E Com. Ltda","0004F9":"Xtera Communications, Inc.","0004FA":"NBS Technologies Inc.","0004FB":"Commtech, Inc.","0004FC":"Stratus Technologies","0004FD":"Japan Control Engineering Co. Ltd","0004FE":"Pelago Networks","0004FF":"Acronet Co. Ltd","000500":"Cisco Systems Inc.","000501":"Cisco Systems Inc.","000502":"Apple","000503":"Iconag","000504":"Naray Information & Communication Enterprise","000505":"Systems Integration Solutions, Inc.","000506":"Reddo Networks AB","000507":"Fine Appliance Corp.","000508":"Inetcam, Inc.","000509":"AVOC Nishimura Ltd","00050A":"ICS Spa","00050B":"SICOM Systems, Inc.","00050C":"Network Photonics, Inc.","00050D":"Midstream Technologies, Inc.","00050E":"3ware, Inc.","00050F":"Tanaka S/S Ltd","000510":"Infinite Shanghai Communication Terminals Ltd","000511":"Complementary Technologies Ltd","000512":"Zebra Technologies Inc","000513":"VTLinx Multimedia Systems, Inc.","000514":"KDT Systems Co. Ltd","000515":"Nuark Co. Ltd","000516":"SMART Modular Technologies","000517":"Shellcomm, Inc.","000518":"Jupiters Technology","000519":"Siemens Building Technologies AG,","00051A":"3Com Europe Ltd","00051B":"Magic Control Technology Corporation","00051C":"Xnet Technology Corp.","00051D":"Airocon, Inc.","00051E":"Brocade Communications Systems, Inc.","00051F":"Taijin Media Co. Ltd","000520":"Smartronix, Inc.","000521":"Control Microsystems","000522":"LEA*D Corporation, Inc.","000523":"AVL List GmbH","000524":"BTL System (HK) Limited","000525":"Puretek Industrial Co. Ltd","000526":"IPAS GmbH","000527":"SJ Tek Co. Ltd","000528":"New Focus, Inc.","000529":"Shanghai Broadan Communication Technology Co. Ltd","00052A":"Ikegami Tsushinki Co. Ltd","00052B":"HORIBA Ltd","00052C":"Supreme Magic Corporation","00052D":"Zoltrix International Limited","00052E":"Cinta Networks","00052F":"Leviton Network Solutions","000530":"Andiamo Systems, Inc.","000531":"Cisco Systems Inc.","000532":"Cisco Systems Inc.","000533":"Brocade Communications Systems, Inc.","000534":"Northstar Engineering Ltd","000535":"Chip PC Ltd","000536":"Danam Communications, Inc.","000537":"Nets Technology Co. Ltd","000538":"Merilus, Inc.","000539":"A Brand New World in Sweden AB","00053A":"Willowglen Services Pte Ltd","00053B":"Harbour Networks Ltd, Co. Beijing","00053C":"Xircom","00053D":"Agere Systems","00053E":"KID Systeme GmbH","00053F":"VisionTek, Inc.","000540":"FAST Corporation","000541":"Advanced Systems Co. Ltd","000542":"Otari, Inc.","000543":"IQ Wireless GmbH","000544":"Valley Technologies, Inc.","000545":"Internet Photonics","000546":"KDDI Network & Solultions Inc.","000547":"Starent Networks","000548":"Disco Corporation","000549":"Salira Optical Network Systems","00054A":"Ario Data Networks, Inc.","00054B":"Eaton Automation AG","00054C":"RF Innovations Pty Ltd","00054D":"Brans Technologies, Inc.","00054E":"Philips","00054F":"Garmin International","000550":"Vcomms Connect Limited","000551":"F & S Elektronik Systeme GmbH","000552":"Xycotec Computer GmbH","000553":"DVC Company, Inc.","000554":"Rangestar Wireless","000555":"Japan Cash Machine Co. Ltd","000556":"360 Systems","000557":"Agile TV Corporation","000558":"Synchronous, Inc.","000559":"Intracom S.A.","00055A":"Power Dsine Ltd","00055B":"Charles Industries Ltd","00055C":"Kowa Company Ltd","00055D":"D-Link Systems, Inc.","00055E":"Cisco Systems Inc.","00055F":"Cisco Systems Inc.","000560":"Leader Comm.Co. Ltd","000561":"nac Image Technology, Inc.","000562":"Digital View Limited","000563":"J-Works, Inc.","000564":"Tsinghua Bitway Co. Ltd","000565":"Tailyn Communication Company Ltd","000566":"Secui.com Corporation","000567":"Etymonic Design, Inc.","000568":"Piltofish Networks AB","000569":"VMware, Inc.","00056A":"Heuft Systemtechnik GmbH","00056B":"C.P. Technology Co. Ltd","00056C":"Hung Chang Co. Ltd","00056D":"Pacific Corporation","00056E":"National Enhance Technology, Inc.","00056F":"Innomedia Technologies Pvt. Ltd","000570":"Baydel Ltd","000571":"Seiwa Electronics Co.","000572":"Deonet Co. Ltd","000573":"Cisco Systems Inc.","000574":"Cisco Systems Inc.","000575":"CDS-Electronics BV","000576":"NSM Technology Ltd","000577":"SM Information & Communication","000578":"Private","000579":"Universal Control Solution Corp.","00057A":"Overture Networks","00057B":"Chung Nam Electronic Co. Ltd","00057C":"RCO Security AB","00057D":"Sun Communications, Inc.","00057E":"Eckelmann Steuerungstechnik GmbH","00057F":"Acqis Technology","000580":"FibroLAN Ltd","000581":"Snell","000582":"ClearCube Technology","000583":"ImageCom Limited","000584":"AbsoluteValue Systems, Inc.","000585":"Juniper Networks","000586":"Lucent Technologies","000587":"Locus, Incorporated","000588":"Sensoria Corp.","000589":"National Datacomputer","00058A":"Netcom Co. Ltd","00058B":"IPmental, Inc.","00058C":"Opentech Inc.","00058D":"Lynx Photonic Networks, Inc.","00058E":"Flextronics International GmbH & Co. Nfg. KG","00058F":"CLCsoft Co.","000590":"Swissvoice Ltd","000591":"Active Silicon Ltd","000592":"Pultek Corp.","000593":"Grammar Engine Inc.","000594":"HMS Industrial Networks","000595":"Alesis Corporation","000596":"Genotech Co. Ltd","000597":"Eagle Traffic Control Systems","000598":"CRONOS S.r.l.","000599":"DRS Test and Energy Management or DRS-TEM","00059A":"Cisco Systems Inc.","00059B":"Cisco Systems Inc.","00059C":"Kleinknecht GmbH, Ing. B?ro","00059D":"Daniel Computing Systems, Inc.","00059E":"Zinwell Corporation","00059F":"Yotta Networks, Inc.","0005A0":"MOBILINE Kft.","0005A1":"Zenocom","0005A2":"CELOX Networks","0005A3":"QEI, Inc.","0005A4":"Lucid Voice Ltd","0005A5":"Kott","0005A6":"Extron Electronics","0005A7":"HYPERCHIP Inc.","0005A8":"Wyle Electronics","0005A9":"Princeton Networks, Inc.","0005AA":"Moore Industries International Inc.","0005AB":"Cyber Fone, Inc.","0005AC":"Northern Digital, Inc.","0005AD":"Topspin Communications, Inc.","0005AE":"Mediaport USA","0005AF":"InnoScan Computing A/S","0005B0":"Korea Computer Technology Co. Ltd","0005B1":"ASB Technology BV","0005B2":"Medison Co. Ltd","0005B3":"Asahi-Engineering Co. Ltd","0005B4":"Aceex Corporation","0005B5":"Broadcom Technologies","0005B6":"INSYS Microelectronics GmbH","0005B7":"Arbor Technology Corp.","0005B8":"Electronic Design Associates, Inc.","0005B9":"Airvana, Inc.","0005BA":"Area Netwoeks, Inc.","0005BB":"Myspace AB","0005BC":"Resource Data Management Ltd","0005BD":"Roax BV","0005BE":"Kongsberg Seatex AS","0005BF":"JustEzy Technology, Inc.","0005C0":"Digital Network Alacarte Co. Ltd","0005C1":"A-Kyung Motion, Inc.","0005C2":"Soronti, Inc.","0005C3":"Pacific Instruments, Inc.","0005C4":"Telect, Inc.","0005C5":"Flaga HF","0005C6":"Triz Communications","0005C7":"I/F-CoM A/S","0005C8":"Verytech","0005C9":"LG Innotek Co. Ltd","0005CA":"Hitron Technology, Inc.","0005CB":"ROIS Technologies, Inc.","0005CC":"Sumtel Communications, Inc.","0005CD":"D&M Holdings Inc.","0005CE":"Prolink Microsystems Corporation","0005CF":"Thunder River Technologies, Inc.","0005D0":"Solinet Systems","0005D1":"Metavector Technologies","0005D2":"DAP Technologies","0005D3":"eProduction Solutions, Inc.","0005D4":"FutureSmart Networks, Inc.","0005D5":"Speedcom Wireless","0005D6":"L-3 Linkabit","0005D7":"Vista Imaging, Inc.","0005D8":"Arescom, Inc.","0005D9":"Techno Valley, Inc.","0005DA":"Apex Automationstechnik","0005DB":"PSI Nentec GmbH","0005DC":"Cisco Systems Inc.","0005DD":"Cisco Systems Inc.","0005DE":"Gi Fone Korea, Inc.","0005DF":"Electronic Innovation, Inc.","0005E0":"Empirix Corp.","0005E1":"Trellis Photonics Ltd","0005E2":"Creativ Network Technologies","0005E3":"LightSand Communications, Inc.","0005E4":"Red Lion Controls Inc.","0005E5":"Renishaw PLC","0005E6":"Egenera, Inc.","0005E7":"Netrake an AudioCodes Company","0005E8":"TurboWave, Inc.","0005E9":"Unicess Network, Inc.","0005EA":"Rednix","0005EB":"Blue Ridge Networks, Inc.","0005EC":"Mosaic Systems Inc.","0005ED":"Technikum Joanneum GmbH","0005EE":"Vanderbilt International (SWE) AB","0005EF":"ADOIR Digital Technology","0005F0":"Satec","0005F1":"Vrcom, Inc.","0005F2":"Power R, Inc.","0005F3":"Webyn","0005F4":"System Base Co. Ltd","0005F5":"Geospace Technologies","0005F6":"Young Chang Co. Ltd","0005F7":"Analog Devices, Inc.","0005F8":"Real Time Access, Inc.","0005F9":"TOA Corporation","0005FA":"IPOptical, Inc.","0005FB":"ShareGate, Inc.","0005FC":"Schenck Pegasus Corp.","0005FD":"PacketLight Networks Ltd","0005FE":"Traficon N.V.","0005FF":"SNS Solutions, Inc.","000600":"Toshiba Teli Corporation","000601":"Otanikeiki Co. Ltd","000602":"Cirkitech Electronics Co.","000603":"Baker Hughes Inc.","000604":"@Track Communications, Inc.","000605":"Inncom International, Inc.","000606":"RapidWAN, Inc.","000607":"Omni Directional Control Technology Inc.","000608":"At-Sky SAS","000609":"Crossport Systems","00060A":"Blue2space","00060B":"Artesyn Embedded Technologies","00060C":"Melco Industries, Inc.","00060D":"Wave7 Optics","00060E":"IGYS Systems, Inc.","00060F":"Narad Networks Inc","000610":"Abeona Networks Inc","000611":"Zeus Wireless, Inc.","000612":"Accusys, Inc.","000613":"Kawasaki Microelectronics Incorporated","000614":"Prism Holdings","000615":"Kimoto Electric Co. Ltd","000616":"Tel Net Co. Ltd","000617":"Redswitch Inc.","000618":"DigiPower Manufacturing Inc.","000619":"Connection Technology Systems","00061A":"Zetari Inc.","00061B":"Notebook Development Lab. Lenovo Japan Ltd","00061C":"Hoshino Metal Industries Ltd","00061D":"MIP Telecom, Inc.","00061E":"Maxan Systems","00061F":"Vision Components GmbH","000620":"Serial System Ltd","000621":"Hinox, Co. Ltd","000622":"Chung Fu Chen Yeh Enterprise Corp.","000623":"MGE UPS Systems France","000624":"Gentner Communications Corp.","000625":"The Linksys Group, Inc.","000626":"MWE GmbH","000627":"Uniwide Technologies, Inc.","000628":"Cisco Systems Inc.","000629":"IBM Corp","00062A":"Cisco Systems Inc.","00062B":"Intraserver Technology","00062C":"Bivio Networks","00062D":"TouchStar Technologies, L.L.C.","00062E":"Aristos Logic Corp.","00062F":"Pivotech Systems Inc.","000630":"Adtranz Sweden","000631":"Calix Inc.","000632":"Mesco Engineering GmbH","000633":"Cross Match Technologies GmbH","000634":"GTE Airfone Inc.","000635":"PacketAir Networks, Inc.","000636":"Jedai Broadband Networks","000637":"Toptrend-Meta Information (ShenZhen) Inc.","000638":"Sungjin C&C Co. Ltd","000639":"Newtec","00063A":"Dura Micro, Inc.","00063B":"Arcturus Networks Inc.","00063C":"Intrinsyc Software International Inc.","00063D":"Microwave Data Systems Inc.","00063E":"Opthos Inc.","00063F":"Everex Communications Inc.","000640":"White Rock Networks","000641":"Itcn","000642":"Genetel Systems Inc.","000643":"SONO Computer Co. Ltd","000644":"neix,Inc","000645":"Meisei Electric Co. Ltd","000646":"ShenZhen XunBao Network Technology Co Ltd","000647":"Etrali S.A.","000648":"Seedsware, Inc.","000649":"3M Deutschland GmbH","00064A":"Honeywell Co. Ltd (KOREA)","00064B":"Alexon Co. Ltd","00064C":"Invicta Networks, Inc.","00064D":"Sencore","00064E":"Broad Net Technology Inc.","00064F":"PRO-NETS Technology Corporation","000650":"Tiburon Networks, Inc.","000651":"Aspen Networks Inc.","000652":"Cisco Systems Inc.","000653":"Cisco Systems Inc.","000654":"Winpresa Building Automation Technologies GmbH","000655":"Yipee, Inc.","000656":"Tactel AB","000657":"Market Central, Inc.","000658":"Helmut Fischer GmbH Institut f?r Elektronik und Messtechnik","000659":"EAL (Apeldoorn) B.V.","00065A":"Strix Systems","00065B":"Dell Inc.","00065C":"Malachite Technologies, Inc.","00065D":"Heidelberg Web Systems","00065E":"Photuris, Inc.","00065F":"ECI Telecom Ltd","000660":"NADEX Co. Ltd","000661":"NIA Home Technologies Corp.","000662":"MBM Technology Ltd","000663":"Human Technology Co. Ltd","000664":"Fostex Corporation","000665":"Sunny Giken, Inc.","000666":"Roving Networks","000667":"Tripp Lite","000668":"Vicon Industries Inc.","000669":"Datasound Laboratories Ltd","00066A":"InfiniCon Systems, Inc.","00066B":"Sysmex Corporation","00066C":"Robinson Corporation","00066D":"Compuprint S.P.A.","00066E":"Delta Electronics, Inc.","00066F":"Korea Data Systems","000670":"Upponetti Oy","000671":"Softing AG","000672":"Netezza","000673":"TKH Security Solutions USA","000674":"Spectrum Control, Inc.","000675":"Banderacom, Inc.","000676":"Novra Technologies Inc.","000677":"Sick AG","000678":"D&M Holdings Inc.","000679":"Konami Corporation","00067A":"JMP Systems","00067B":"Toplink C&C Corporation","00067C":"Cisco Systems Inc.","00067D":"Takasago Ltd","00067E":"WinCom Systems, Inc.","00067F":"Digeo, Inc.","000680":"Card Access, Inc.","000681":"Goepel Electronic GmbH","000682":"Convedia","000683":"Bravara Communications, Inc.","000684":"Biacore AB","000685":"NetNearU Corporation","000686":"ZARDCOM Co. Ltd","000687":"Omnitron Systems Technology, Inc.","000688":"Telways Communication Co. Ltd","000689":"yLez Technologies Pte Ltd","00068A":"NeuronNet Co. Ltd R&D Center","00068B":"AirRunner Technologies, Inc.","00068C":"3Com Corporation","00068D":"SEPATON, Inc.","00068E":"HID Corporation","00068F":"Telemonitor, Inc.","000690":"Euracom Communication GmbH","000691":"PT Inovacao","000692":"Intruvert Networks, Inc.","000693":"Flexus Computer Technology, Inc.","000694":"Mobillian Corporation","000695":"Ensure Technologies, Inc.","000696":"Advent Networks","000697":"R & D Center","000698":"egnite GmbH","000699":"Vida Design Co.","00069A":"e & Tel","00069B":"AVT Audio Video Technologies GmbH","00069C":"Transmode Systems AB","00069D":"Petards Ltd","00069E":"UNIQA, Inc.","00069F":"Kuokoa Networks","0006A0":"Mx Imaging","0006A1":"Celsian Technologies, Inc.","0006A2":"Microtune, Inc.","0006A3":"Bitran Corporation","0006A4":"INNOWELL Corp.","0006A5":"PINON Corp.","0006A6":"Artistic Licence Engineering Ltd","0006A7":"Primarion","0006A8":"KC Technology, Inc.","0006A9":"Universal Instruments Corp.","0006AA":"VT Miltope","0006AB":"W-Link Systems, Inc.","0006AC":"Intersoft Co.","0006AD":"KB Electronics Ltd","0006AE":"Himachal Futuristic Communications Ltd","0006AF":"Xalted Networks","0006B0":"Comtech EF Data Corp.","0006B1":"Sonicwall","0006B2":"Linxtek Co.","0006B3":"Diagraph Corporation","0006B4":"Vorne Industries, Inc.","0006B5":"Source Photonics, Inc.","0006B6":"Nir-Or Israel Ltd","0006B7":"TELEM GmbH","0006B8":"Bandspeed Pty Ltd","0006B9":"A5TEK Corp.","0006BA":"Westwave Communications","0006BB":"ATI Technologies Inc.","0006BC":"Macrolink, Inc.","0006BD":"BNTECHNOLOGY Co. Ltd","0006BE":"Baumer Optronic GmbH","0006BF":"Accella Technologies Co. Ltd","0006C0":"United Internetworks, Inc.","0006C1":"Cisco Systems Inc.","0006C2":"Smartmatic Corporation","0006C3":"Schindler Elevator Ltd","0006C4":"Piolink Inc.","0006C5":"INNOVI Technologies Limited","0006C6":"lesswire AG","0006C7":"RFNET Technologies Pte Ltd (S)","0006C8":"Sumitomo Metal Micro Devices, Inc.","0006C9":"Technical Marketing Research, Inc.","0006CA":"American Computer & Digital Components, Inc. (ACDC)","0006CB":"Jotron Electronics A/S","0006CC":"JMI Electronics Co. Ltd","0006CD":"Leaf Imaging Ltd","0006CE":"Dateno","0006CF":"Thales Avionics In-Flight Systems, LLC","0006D0":"Elgar Electronics Corp.","0006D1":"Tahoe Networks, Inc.","0006D2":"Tundra Semiconductor Corp.","0006D3":"Alpha Telecom, Inc. U.S.A.","0006D4":"Interactive Objects, Inc.","0006D5":"Diamond Systems Corp.","0006D6":"Cisco Systems Inc.","0006D7":"Cisco Systems Inc.","0006D8":"Maple Optical Systems","0006D9":"IPM-Net S.p.A.","0006DA":"ITRAN Communications Ltd","0006DB":"ICHIPS Co. Ltd","0006DC":"Syabas Technology (Amquest)","0006DD":"AT & T Laboratories - Cambridge Ltd","0006DE":"Flash Technology","0006DF":"AIDONIC Corporation","0006E0":"MAT Co. Ltd","0006E1":"Techno Trade s.a","0006E2":"Ceemax Technology Co. Ltd","0006E3":"Quantitative Imaging Corporation","0006E4":"Citel Technologies Ltd","0006E5":"Fujian Newland Computer Ltd Co.","0006E6":"DongYang Telecom Co. Ltd","0006E7":"Bit Blitz Communications Inc.","0006E8":"Optical Network Testing, Inc.","0006E9":"Intime Corp.","0006EA":"ELZET80 Mikrocomputer GmbH&Co. KG","0006EB":"Global Data","0006EC":"Harris Corporation","0006ED":"Inara Networks","0006EE":"Shenyang Neu-era Information & Technology Stock Co. Ltd","0006EF":"Maxxan Systems, Inc.","0006F0":"Digeo, Inc.","0006F1":"Optillion","0006F2":"Platys Communications","0006F3":"AcceLight Networks","0006F4":"Prime Electronics & Satellitics Inc.","0006F5":"Alps Electric Co. Ltd","0006F6":"Cisco Systems Inc.","0006F7":"Alps Electric Co. Ltd","0006F8":"The Boeing Company","0006F9":"Mitsui Zosen Systems Research Inc.","0006FA":"IP SQUARE Co Ltd","0006FB":"Hitachi Printing Solutions Ltd","0006FC":"Fnet Co. Ltd","0006FD":"Comjet Information Systems Corp.","0006FE":"Ambrado, Inc","0006FF":"Sheba Systems Co. Ltd","000700":"Zettamedia Korea","000701":"Racal-Datacom","000702":"Varian Medical Systems","000703":"CSEE Transport","000704":"Alps Electric Co. Ltd","000705":"Endress & Hauser GmbH & Co","000706":"Sanritz Corporation","000707":"Interalia Inc.","000708":"Bitrage Inc.","000709":"Westerstrand Urfabrik AB","00070A":"Unicom Automation Co. Ltd","00070B":"Novabase SGPS, SA","00070C":"SVA-Intrusion.com Co. Ltd","00070D":"Cisco Systems Inc.","00070E":"Cisco Systems Inc.","00070F":"Fujant, Inc.","000710":"Adax, Inc.","000711":"Acterna","000712":"JAL Information Technology","000713":"IP One, Inc.","000714":"Brightcom","000715":"General Research Of Electronics, Inc.","000716":"J & S Marine Ltd","000717":"Wieland Electric GmbH","000718":"iCanTek Co. Ltd","000719":"Mobiis Co. Ltd","00071A":"Finedigital Inc.","00071B":"CDVI Americas Ltd","00071C":"AT&T","00071D":"Satelsa Sistemas Y Aplicaciones de Telecomunicaciones, S.A.","00071E":"Tri-M Engineering / Nupak Dev. Corp.","00071F":"European Systems Integration","000720":"Trutzschler GmbH & Co. KG","000721":"Formac Elektronik GmbH","000722":"The Nielsen Company","000723":"ELCON Systemtechnik GmbH","000724":"Telemax Co. Ltd","000725":"Bematech International Corp.","000726":"Shenzhen Gongjin Electronics Co.,LT","000727":"Zi Corporation (HK) Ltd","000728":"Neo Telecom","000729":"Kistler Instrumente AG","00072A":"Innovance Networks","00072B":"Jung Myung Telecom Co. Ltd","00072C":"Fabricom","00072D":"CNSystems","00072E":"North Node AB","00072F":"Intransa, Inc.","000730":"Hutchison OPTEL Telecom Technology Co. Ltd","000731":"Ophir-Spiricon LLC","000732":"AAEON Technology Inc.","000733":"DANCONTROL Engineering","000734":"ONStor, Inc.","000735":"Flarion Technologies, Inc.","000736":"Data Video Technologies Co. Ltd","000737":"Soriya Co. Ltd","000738":"Young Technology Co. Ltd","000739":"Scotty Group Austria GmbH","00073A":"Inventel Systemes","00073B":"Tenovis GmbH & Co KG","00073C":"Telecom Design","00073D":"Nanjing Postel Telecommunications Co. Ltd","00073E":"China Great-Wall Computer Shenzhen Co. Ltd","00073F":"Woojyun Systec Co. Ltd","000740":"Buffalo.Inc","000741":"Sierra Automated Systems","000742":"Ormazabal","000743":"Chelsio Communications","000744":"Unico, Inc.","000745":"Radlan Computer Communications Ltd","000746":"TURCK, Inc.","000747":"Mecalc","000748":"The Imaging Source Europe","000749":"CENiX Inc.","00074A":"Carl Valentin GmbH","00074B":"Daihen Corporation","00074C":"Beicom Inc.","00074D":"Zebra Technologies Corp.","00074E":"IPFRONT Inc","00074F":"Cisco Systems Inc.","000750":"Cisco Systems Inc.","000751":"m-u-t AG","000752":"Rhythm Watch Co. Ltd","000753":"Beijing Qxcomm Technology Co. Ltd","000754":"Xyterra Computing, Inc.","000755":"Lafon","000756":"Juyoung Telecom","000757":"Topcall International AG","000758":"Dragonwave","000759":"Boris Manufacturing Corp.","00075A":"Air Products and Chemicals, Inc.","00075B":"Gibson Guitars","00075C":"Eastman Kodak Company","00075D":"Celleritas Inc.","00075E":"Ametek Power Instruments","00075F":"VCS Video Communication Systems AG","000760":"TOMIS Information & Telecom Corp.","000761":"29530","000762":"Group Sense Limited","000763":"Sunniwell Cyber Tech. Co. Ltd","000764":"YoungWoo Telecom Co. Ltd","000765":"Jade Quantum Technologies, Inc.","000766":"Chou Chin Industrial Co. Ltd","000767":"Yuxing Electronics Company Limited","000768":"Danfoss A/S","000769":"Italiana Macchi SpA","00076A":"NEXTEYE Co. Ltd","00076B":"Stralfors AB","00076C":"Daehanet, Inc.","00076D":"Flexlight Networks","00076E":"Sinetica Corporation Limited","00076F":"Synoptics Limited","000770":"Ubiquoss Inc","000771":"Embedded System Corporation","000772":"Alcatel-Lucent Shanghai Bell Co. Ltd","000773":"Ascom Powerline Communications Ltd","000774":"GuangZhou Thinker Technology Co. Ltd","000775":"Valence Semiconductor, Inc.","000776":"Federal APD","000777":"Motah Ltd","000778":"GERSTEL GmbH & Co. KG","000779":"Sungil Telecom Co. Ltd","00077A":"Infoware System Co. Ltd","00077B":"Millimetrix Broadband Networks","00077C":"Westermo Teleindustri AB","00077D":"Cisco Systems Inc.","00077E":"Elrest GmbH","00077F":"J Communications Co. Ltd","000780":"Bluegiga Technologies Oy","000781":"Itron Inc.","000782":"Oracle Corporation","000783":"SynCom Network, Inc.","000784":"Cisco Systems Inc.","000785":"Cisco Systems Inc.","000786":"Wireless Networks Inc.","000787":"Idea System Co. Ltd","000788":"Clipcomm, Inc.","000789":"Dongwon Systems","00078A":"Mentor Data System Inc.","00078B":"Wegener Communications, Inc.","00078C":"Elektronikspecialisten i Borlange AB","00078D":"NetEngines Ltd","00078E":"Garz & Friche GmbH","00078F":"Emkay Innovative Products","000790":"Tri-M Technologies (s) Limited","000791":"International Data Communications, Inc.","000792":"S?tron Electronic GmbH","000793":"Shin Satellite Public Company Limited","000794":"Simple Devices, Inc.","000795":"Elitegroup Computer Systems Co. Ltd","000796":"LSI Systems, Inc.","000797":"Netpower Co. Ltd","000798":"Selea SRL","000799":"Tipping Point Technologies, Inc.","00079A":"Verint Systems Inc","00079B":"Aurora Networks","00079C":"Golden Electronics Technology Co. Ltd","00079D":"Musashi Co. Ltd","00079E":"Ilinx Co. Ltd","00079F":"Action Digital Inc.","0007A0":"e-Watch Inc.","0007A1":"VIASYS Healthcare GmbH","0007A2":"Opteon Corporation","0007A3":"Ositis Software, Inc.","0007A4":"GN Netcom Ltd","0007A5":"Y.D.K Co. Ltd","0007A6":"Leviton Manufacturing Co., Inc.","0007A7":"A-Z Inc.","0007A8":"Haier Group Technologies Ltd","0007A9":"Novasonics","0007AA":"Quantum Data Inc.","0007AB":"Samsung Electronics Co. Ltd","0007AC":"Eolring","0007AD":"Pentacon GmbH Foto-und Feinwerktechnik","0007AE":"Britestream Networks, Inc.","0007AF":"Red Lion Controls, LP","0007B0":"Office Details, Inc.","0007B1":"Equator Technologies","0007B2":"Transaccess S.A.","0007B3":"Cisco Systems Inc.","0007B4":"Cisco Systems Inc.","0007B5":"Any One Wireless Ltd","0007B6":"Telecom Technology Ltd","0007B7":"Samurai Ind. Prods Eletronicos Ltda","0007B8":"Corvalent Corporation","0007B9":"Ginganet Corporation","0007BA":"UTStarcom Inc","0007BB":"Candera Inc.","0007BC":"Identix Inc.","0007BD":"Radionet Ltd","0007BE":"DataLogic SpA","0007BF":"Armillaire Technologies, Inc.","0007C0":"NetZerver Inc.","0007C1":"Overture Networks, Inc.","0007C2":"Netsys Telecom","0007C3":"Thomson","0007C4":"JEAN Co. Ltd","0007C5":"Gcom, Inc.","0007C6":"VDS Vosskuhler GmbH","0007C7":"Synectics Systems Limited","0007C8":"Brain21, Inc.","0007C9":"Technol Seven Co. Ltd","0007CA":"Creatix Polymedia Ges Fur Kommunikaitonssysteme","0007CB":"Freebox SAS","0007CC":"Kaba Benzing GmbH","0007CD":"Kumoh Electronic Co Ltd","0007CE":"Cabletime Limited","0007CF":"Anoto AB","0007D0":"Automat Engenharia de Automa??o Ltda.","0007D1":"Spectrum Signal Processing Inc.","0007D2":"Logopak Systeme GmbH & Co. KG","0007D3":"SPGPrints B.V.","0007D4":"Zhejiang Yutong Network Communication Co Ltd","0007D5":"3e Technologies Int;., Inc.","0007D6":"Commil Ltd","0007D7":"Caporis Networks AG","0007D8":"Hitron Technologies. Inc","0007D9":"Splicecom","0007DA":"Neuro Telecom Co. Ltd","0007DB":"Kirana Networks, Inc.","0007DC":"Atek Co Ltd","0007DD":"Cradle Technologies","0007DE":"eCopilt AB","0007DF":"Vbrick Systems Inc.","0007E0":"Palm Inc.","0007E1":"WIS Communications Co. Ltd","0007E2":"Bitworks, Inc.","0007E3":"Navcom Technology, Inc.","0007E4":"SoftRadio Co. Ltd","0007E5":"Coup Corporation","0007E6":"edgeflow Canada Inc.","0007E7":"FreeWave Technologies","0007E8":"EdgeWave","0007E9":"Intel Corporation","0007EA":"Massana, Inc.","0007EB":"Cisco Systems Inc.","0007EC":"Cisco Systems Inc.","0007ED":"Altera Corporation","0007EE":"telco Informationssysteme GmbH","0007EF":"Lockheed Martin Tactical Systems","0007F0":"LogiSync LLC","0007F1":"TeraBurst Networks Inc.","0007F2":"IOA Corporation","0007F3":"Thinkengine Networks","0007F4":"Eletex Co. Ltd","0007F5":"Bridgeco Co AG","0007F6":"Qqest Software Systems","0007F7":"Galtronics","0007F8":"ITDevices, Inc.","0007F9":"Sensaphone","0007FA":"ITT Co. Ltd","0007FB":"Giga Stream UMTS Technologies GmbH","0007FC":"Adept Systems Inc.","0007FD":"LANergy Ltd","0007FE":"Rigaku Corporation","0007FF":"Gluon Networks","000800":"Multitech Systems, Inc.","000801":"HighSpeed Surfing Inc.","000802":"Hewlett-Packard Company","000803":"Cos Tron","000804":"ICA Inc.","000805":"Techno-Holon Corporation","000806":"Raonet Systems, Inc.","000807":"Access Devices Limited","000808":"PPT Vision, Inc.","000809":"Systemonic AG","00080A":"Espera-Werke GmbH","00080B":"Birka BPA Informationssystem AB","00080C":"VDA Elettronica spa","00080D":"Toshiba","00080E":"ARRIS Group, Inc.","00080F":"Proximion Fiber Optics AB","000810":"Key Technology, Inc.","000811":"VOIX Corporation","000812":"GM-2 Corporation","000813":"Diskbank, Inc.","000814":"TIL Technologies","000815":"CATS Co. Ltd","000816":"Bluelon ApS","000817":"EmergeCore Networks LLC","000818":"Pixelworks, Inc.","000819":"Banksys","00081A":"Sanrad Intelligence Storage Communications (2000) Ltd","00081B":"Windigo Systems","00081C":"@pos.com","00081D":"Ipsil, Incorporated","00081E":"Repeatit AB","00081F":"Pou Yuen Tech Corp. Ltd","000820":"Cisco Systems Inc.","000821":"Cisco Systems Inc.","000822":"InPro Comm","000823":"Texa Corp.","000824":"Nuance Document Imaging","000825":"Acme Packet","000826":"Colorado Med Tech","000827":"ADB Broadband Italia","000828":"Koei Engineering Ltd","000829":"Aval Nagasaki Corporation","00082A":"Powerwallz Network Security","00082B":"Wooksung Electronics, Inc.","00082C":"Homag AG","00082D":"Indus Teqsite Private Limited","00082E":"Multitone Electronics PLC","00082F":"Cisco Systems Inc.","000830":"Cisco Systems Inc.","000831":"Cisco Systems Inc.","000832":"Cisco Systems Inc.","00084E":"DivergeNet, Inc.","00084F":"Qualstar Corporation","000850":"Arizona Instrument Corp.","000851":"Canadian Bank Note Company Ltd","000852":"Davolink Co. Inc.","000853":"Schleicher GmbH & Co. Relaiswerke KG","000854":"Netronix, Inc.","000855":"NASA-Goddard Space Flight Center","000856":"Gamatronic Electronic Industries Ltd","000857":"Polaris Networks, Inc.","000858":"Novatechnology Inc.","000859":"ShenZhen Unitone Electronics Co. Ltd","00085A":"IntiGate Inc.","00085B":"Hanbit Electronics Co. Ltd","00085C":"Shanghai Dare Technologies Co. Ltd","00085D":"Aastra","00085E":"PCO AG","00085F":"Picanol N.V.","000860":"LodgeNet Entertainment Corp.","000861":"SoftEnergy Co. Ltd","000862":"NEC Eluminant Technologies, Inc.","000863":"Entrisphere Inc.","000864":"Fasy S.p.A.","000865":"Jascom Co. Ltd","000866":"DSX Access Systems, Inc.","000867":"Uptime Devices","000868":"PurOptix","000869":"Command-e Technology Co. Ltd","00086A":"Securiton GmbH","00086B":"Mipsys","00086C":"Plasmon LMS","00086D":"Missouri FreeNet","00086E":"Hyglo AB","00086F":"Resources Computer Network Ltd","000870":"Rasvia Systems, Inc.","000871":"NORTHDATA Co. Ltd","000872":"Sorenson Communications","000873":"DapTechnology B.V.","000874":"Dell Inc.","000875":"Acorp Electronics Corp.","000876":"SDSystem","000877":"Liebert-Hiross Spa","000878":"Benchmark Storage Innovations","000879":"CEM Corporation","00087A":"Wipotec GmbH","00087B":"RTX Telecom A/S","00087C":"Cisco Systems Inc.","00087D":"Cisco Systems Inc.","00087E":"Bon Electro-Telecom Inc.","00087F":"SPAUN electronic GmbH & Co. KG","000880":"BroadTel Canada Communications Inc.","000881":"Digital Hands Co. Ltd","000882":"Sigma Corporation","000883":"Hewlett-Packard Company","000884":"Index Braille AB","000885":"EMS Dr. Thomas W?nsche","000886":"Hansung Teliann, Inc.","000887":"Maschinenfabrik Reinhausen GmbH","000888":"OULLIM Information Technology Inc,.","000889":"Dish Technologies Corp","00088A":"Minds@Work","00088B":"Tropic Networks Inc.","00088C":"Quanta Network Systems Inc.","00088D":"Sigma-Links Inc.","00088E":"Nihon Computer Co. Ltd","00088F":"Advanced Digital Technology","000890":"Avilinks SA","000891":"Lyan Inc.","000892":"EM Solutions","000893":"LE Information Communication Inc.","000894":"InnoVISION Multimedia Ltd","000895":"DIRC Technologie GmbH & Co.KG","000896":"Printronix, Inc.","000897":"Quake Technologies","000898":"Gigabit Optics Corporation","000899":"Netbind, Inc.","00089A":"Alcatel Microelectronics","00089B":"ICP Electronics Inc.","00089C":"Elecs Industry Co. Ltd","00089D":"UHD-Elektronik","00089E":"Beijing Enter-Net Co.Ltd","00089F":"EFM Networks","0008A0":"Stotz Feinmesstechnik GmbH","0008A1":"CNet Technology Inc.","0008A2":"ADI Engineering, Inc.","0008A3":"Cisco Systems Inc.","0008A4":"Cisco Systems Inc.","0008A5":"Peninsula Systems Inc.","0008A6":"Multiware & Image Co. Ltd","0008A7":"iLogic Inc.","0008A8":"Systec Co. Ltd","0008A9":"SangSang Technology, Inc.","0008AA":"Karam","0008AB":"EnerLinx.com, Inc.","0008AC":"Eltromat GmbH","0008AD":"Toyo-Linx Co. Ltd","0008AE":"PacketFront Network Products AB","0008AF":"Novatec Corporation","0008B0":"BKtel Communications GmbH","0008B1":"ProQuent Systems","0008B2":"Shenzhen Compass Technology Development Co. Ltd","0008B3":"Fastwel","0008B4":"Syspol","0008B5":"TAI Guen Enterprise Co. Ltd","0008B6":"RouteFree, Inc.","0008B7":"HIT Incorporated","0008B8":"E.F. Johnson","0008B9":"Kaonmedia Co. Ltd","0008BA":"Erskine Systems Ltd","0008BB":"NetExcell","0008BC":"Ilevo AB","0008BD":"Tepg-US","0008BE":"XENPAK MSA Group","0008BF":"Aptus Elektronik AB","0008C0":"ASA Systems","0008C1":"Avistar Communications Corporation","0008C2":"Cisco Systems Inc.","0008C3":"Contex A/S","0008C4":"Hikari Co. Ltd","0008C5":"Liontech Co. Ltd","0008C6":"Philips Consumer Communications","0008C7":"Hewlett-Packard Company","0008C8":"Soneticom, Inc.","0008C9":"TechniSat Digital GmbH Daun","0008CA":"TwinHan Technology Co. Ltd","0008CB":"Zeta Broadband Inc.","0008CC":"Remotec, Inc.","0008CD":"With-Net Inc","0008CE":"IPMobileNet Inc.","0008CF":"Nippon Koei Power Systems Co. Ltd","0008D0":"Musashi Engineering Co. Ltd","0008D1":"Karel Inc.","0008D2":"ZOOM Networks Inc.","0008D3":"Hercules Technologies S.A.S.","0008D4":"IneoQuest Technologies, Inc","0008D5":"Vanguard Networks Solutions, LLC","0008D6":"HASSNET Inc.","0008D7":"HOW Corporation","0008D8":"Dowkey Microwave","0008D9":"Mitadenshi Co. Ltd","0008DA":"SofaWare Technologies Ltd","0008DB":"Corrigent Systems","0008DC":"Wiznet","0008DD":"Telena Communications, Inc.","0008DE":"3UP Systems","0008DF":"Alistel Inc.","0008E0":"ATO Technology Ltd","0008E1":"Barix AG","0008E2":"Cisco Systems Inc.","0008E3":"Cisco Systems Inc.","0008E4":"Envenergy Inc","0008E5":"IDK Corporation","0008E6":"Littlefeet","0008E7":"SHI ControlSystems Ltd","0008E8":"Excel Master Ltd","0008E9":"NextGig","0008EA":"Motion Control Engineering, Inc","0008EB":"ROMWin Co. Ltd","0008EC":"Optical Zonu Corporation","0008ED":"ST&T Instrument Corp.","0008EE":"Logic Product Development","0008EF":"Dibal,S.A.","0008F0":"Next Generation Systems, Inc.","0008F1":"Voltaire","0008F2":"C&S Technology","0008F3":"Wany","0008F4":"Bluetake Technology Co. Ltd","0008F5":"YESTECHNOLOGY Co. Ltd","0008F6":"Sumitomo Electric Industries Ltd","0008F7":"Hitachi Ltd, Semiconductor & Integrated Circuits Gr","0008F8":"UTC CCS","0008F9":"Artesyn Embedded Technologies","0008FA":"KEB Automation KG","0008FB":"SonoSite, Inc.","0008FC":"Gigaphoton Inc.","0008FD":"BlueKorea Co. Ltd","0008FE":"UNIK C&C Co. Ltd","0008FF":"Trilogy Communications Ltd","000900":"TMT","000901":"Shenzhen Shixuntong Information & Technoligy Co","000902":"Redline Communications Inc.","000903":"Panasas, Inc","000904":"MONDIAL electronic","000905":"iTEC Technologies Ltd","000906":"Esteem Networks","000907":"Chrysalis Development","000908":"VTech Technology Corp.","000909":"Telenor Connect A/S","00090A":"SnedFar Technology Co. Ltd","00090B":"MTL Instruments PLC","00090C":"Mayekawa Mfg. Co. Ltd","00090D":"Leader Electronics Corp.","00090E":"Helix Technology Inc.","00090F":"Fortinet Inc.","000910":"Simple Access Inc.","000911":"Cisco Systems Inc.","000912":"Cisco Systems Inc.","000913":"SystemK Corporation","000914":"Computrols Inc.","000915":"CAS Corp.","000916":"Listman Home Technologies, Inc.","000917":"WEM Technology Inc","000918":"Samsung Techwin Co. Ltd","000919":"MDS Gateways","00091A":"Macat Optics & Electronics Co. Ltd","00091B":"Digital Generation Inc.","00091C":"CacheVision, Inc","00091D":"Proteam Computer Corporation","00091E":"Firstech Technology Corp.","00091F":"A&D Co. Ltd","000920":"EpoX CoMPUTER Co. Ltd","000921":"Planmeca Oy","000922":"TST Biometrics GmbH","000923":"Heaman System Co. Ltd","000924":"Telebau GmbH","000925":"VSN Systemen BV","000926":"Yoda Communications, Inc.","000927":"Toyokeiki Co. Ltd","000928":"Telecore","000929":"Sanyo Industries (UK) Limited","00092A":"MYTECS Co. Ltd","00092B":"iQstor Networks, Inc.","00092C":"Hitpoint Inc.","00092D":"HTC Corporation","00092E":"B&Tech System Inc.","00092F":"Akom Technology Corporation","000930":"AeroConcierge Inc.","000931":"Future Internet, Inc.","000932":"Omnilux","000933":"Ophit Co.Ltd","000934":"Dream-Multimedia-Tv GmbH","000935":"Sandvine Incorporated","000936":"Ipetronik GmbH & Co. KG","000937":"Inventec Appliance Corp","000938":"Allot Communications","000939":"ShibaSoku Co. Ltd","00093A":"Molex","00093B":"Hyundai Networks Inc.","00093C":"Jacques Technologies P/L","00093D":"Newisys,Inc.","00093E":"C&I Technologies","00093F":"Double-Win Enterpirse Co. Ltd","000940":"AGFEO GmbH & Co. KG","000941":"Allied Telesis R&D Center K.K.","000942":"Wireless Technologies, Inc","000943":"Cisco Systems Inc.","000944":"Cisco Systems Inc.","000945":"Palmmicro Communications Inc","000946":"Cluster Labs GmbH","000947":"Aztek, Inc.","000948":"Vista Control Systems, Corp.","000949":"Glyph Technologies Inc.","00094A":"Homenet Communications","00094B":"FillFactory NV","00094C":"Communication Weaver Co. Ltd","00094D":"Braintree Communications Pty Ltd","00094E":"Bartech Systems International, Inc","00094F":"elmegt GmbH & Co. KG","000950":"Independent Storage Corporation","000951":"Apogee Imaging Systems","000952":"Auerswald GmbH & Co. KG","000953":"Linkage System Integration Co.Ltd","000954":"AMiT spol. s. r. o.","000955":"Young Generation International Corp.","000956":"Network Systems Group Ltd (NSG)","000957":"Supercaller, Inc.","000958":"Intelnet S.A.","000959":"Sitecsoft","00095A":"Racewood Technology","00095B":"Netgear","00095C":"Philips Medical Systems - Cardiac and Monitoring Systems (CM","00095D":"Dialogue Technology Corp.","00095E":"Masstech Group Inc.","00095F":"Telebyte, Inc.","000960":"YOZAN Inc.","000961":"Switchgear and Instrumentation Ltd","000962":"Sonitor Technologies AS","000963":"Dominion Lasercom Inc.","000964":"Hi-Techniques, Inc.","000965":"HyunJu Computer Co. Ltd","000966":"Trimble Europe BV","000967":"Tachyon, Inc","000968":"Technoventure, Inc.","000969":"Meret Optical Communications","00096A":"Cloverleaf Communications Inc.","00096B":"IBM Corp","00096C":"Imedia Semiconductor Corp.","00096D":"Powernet Technologies Corp.","00096E":"Giant Electronics Ltd","00096F":"Beijing Zhongqing Elegant Tech. Corp.,Limited","000970":"Vibration Research Corporation","000971":"Time Management, Inc.","000972":"Securebase,Inc","000973":"Lenten Technology Co. Ltd","000974":"Innopia Technologies, Inc.","000975":"fSONA Communications Corporation","000976":"Datasoft ISDN Systems GmbH","000977":"Brunner Elektronik AG","000978":"AIJI System Co. Ltd","000979":"Advanced Television Systems Committee, Inc.","00097A":"Louis Design Labs.","00097B":"Cisco Systems Inc.","00097C":"Cisco Systems Inc.","00097D":"SecWell Networks Oy","00097E":"IMI Technology Co. Ltd","00097F":"Vsecure 2000 Ltd","000980":"Power Zenith Inc.","000981":"Newport Networks","000982":"Loewe Opta GmbH","000983":"GlobalTop Technology, Inc.","000984":"MyCasa Network Inc.","000985":"Auto Telecom Company","000986":"Metalink Ltd","000987":"Nishi Nippon Electric Wire & Cable Co. Ltd","000988":"Nudian Electron Co. Ltd","000989":"VividLogic Inc.","00098A":"EqualLogic Inc","00098B":"Entropic Communications, Inc.","00098C":"Option Wireless Sweden","00098D":"Velocity Semiconductor","00098E":"ipcas GmbH","00098F":"Cetacean Networks","000990":"ACKSYS Communications & Systems","000991":"GE Fanuc Automation Manufacturing, Inc.","000992":"InterEpoch Technology,Inc.","000993":"Visteon Corporation","000994":"Cronyx Engineering","000995":"Castle Technology Ltd","000996":"RDI","000997":"Nortel Networks","000998":"Capinfo Company Limited","000999":"CP Georges Renault","00099A":"Elmo Company, Limited","00099B":"Western Telematic Inc.","00099C":"Naval Research Laboratory","00099D":"Haliplex Communications","00099E":"Testech, Inc.","00099F":"Videx Inc.","0009A0":"Microtechno Corporation","0009A1":"Telewise Communications, Inc.","0009A2":"Interface Co. Ltd","0009A3":"Leadfly Techologies Corp. Ltd","0009A4":"HARTEC Corporation","0009A5":"Hansung Eletronic Industries Development Co. Ltd","0009A6":"Ignis Optics, Inc.","0009A7":"Bang & Olufsen A/S","0009A8":"Eastmode Pte Ltd","0009A9":"Ikanos Communications","0009AA":"Data Comm for Business, Inc.","0009AB":"Netcontrol Oy","0009AC":"Lanvoice","0009AD":"Hyundai Syscomm, Inc.","0009AE":"Okano Electric Co. Ltd","0009AF":"e-generis","0009B0":"Onkyo Corporation","0009B1":"Kanematsu Electronics Ltd","0009B2":"L&F Inc.","0009B3":"MCM Systems Ltd","0009B4":"Kisan Telecom Co. Ltd","0009B5":"3J Tech. Co. Ltd","0009B6":"Cisco Systems Inc.","0009B7":"Cisco Systems Inc.","0009B8":"Entise Systems","0009B9":"Action Imaging Solutions","0009BA":"MAKU Informationstechik GmbH","0009BB":"MathStar, Inc.","0009BC":"Utility, Inc","0009BD":"Epygi Technologies Ltd","0009BE":"Mamiya-OP Co. Ltd","0009BF":"Nintendo Co. Ltd","0009C0":"6WIND","0009C1":"Proces-Data A/S","0009C2":"Onity, Inc.","0009C3":"Netas","0009C4":"Medicore Co. Ltd","0009C5":"KINGENE Technology Corporation","0009C6":"Visionics Corporation","0009C7":"Movistec","0009C8":"Sinagawa Tsushin Keisou Service","0009C9":"BlueWINC Co. Ltd","0009CA":"iMaxNetworks(Shenzhen)Limited.","0009CB":"HBrain","0009CC":"Moog GmbH","0009CD":"Hudson Soft Co. Ltd","0009CE":"SpaceBridge Semiconductor Corp.","0009CF":"iAd GmbH","0009D0":"Solacom Technologies Inc.","0009D1":"Seranoa Networks Inc","0009D2":"Mai Logic Inc.","0009D3":"Western DataCom Co., Inc.","0009D4":"Transtech Networks","0009D5":"Signal Communication, Inc.","0009D6":"KNC One GmbH","0009D7":"DC Security Products","0009D8":"F?lt Communications AB","0009D9":"Neoscale Systems, Inc","0009DA":"Control Module Inc.","0009DB":"eSpace","0009DC":"Galaxis Technology AG","0009DD":"Mavin Technology Inc.","0009DE":"Samjin Information & Communications Co. Ltd","0009DF":"Vestel Komunikasyon Sanayi ve Ticaret A.S.","0009E0":"Xemics S.A.","0009E1":"Gemtek Technology Co. Ltd","0009E2":"Sinbon Electronics Co. Ltd","0009E3":"Angel Iglesias S.A.","0009E4":"K Tech Infosystem Inc.","0009E5":"Hottinger Baldwin Messtechnik GmbH","0009E6":"Cyber Switching Inc.","0009E7":"ADC Techonology","0009E8":"Cisco Systems Inc.","0009E9":"Cisco Systems Inc.","0009EA":"YEM Inc.","0009EB":"HuMANDATA Ltd","0009EC":"Daktronics, Inc.","0009ED":"CipherOptics","0009EE":"Meikyo Electric Co. Ltd","0009EF":"Vocera Communications","0009F0":"Shimizu Technology Inc.","0009F1":"Yamaki Electric Corporation","0009F2":"Cohu, Inc., Electronics Division","0009F3":"WELL Communication Corp.","0009F4":"Alcon Laboratories, Inc.","0009F5":"Emerson Network Power Co. Ltd","0009F6":"Shenzhen Eastern Digital Tech Ltd","0009F7":"SED, a Division Of Calian","0009F8":"Unimo Technology Co. Ltd","0009F9":"ART Japan Co. Ltd","0009FB":"Philips Patient Monitoring","0009FC":"IPFLEX Inc.","0009FD":"Ubinetics Limited","0009FE":"Daisy Technologies, Inc.","0009FF":"X.net 2000 GmbH","000A00":"Mediatek Corp.","000A01":"SOHOware, Inc.","000A02":"Annso Co. Ltd","000A03":"Endesa Servicios, S.L.","000A04":"3Com Ltd","000A05":"Widax Corp.","000A06":"Teledex LLC","000A07":"WebWayOne Ltd","000A08":"Alpine Electronics, Inc.","000A09":"TaraCom Integrated Products, Inc.","000A0A":"SUNIX Co. Ltd","000A0B":"Sealevel Systems, Inc.","000A0C":"Scientific Research Corporation","000A0D":"FCI Deutschland GmbH","000A0E":"Invivo Research Inc.","000A0F":"Ilryung Telesys, Inc","000A10":"FAST media integrations AG","000A11":"ExPet Technologies, Inc","000A12":"Azylex Technology, Inc","000A13":"Honeywell Video Systems","000A14":"TECO a.s.","000A15":"Silicon Data, Inc","000A16":"Lassen Research","000A17":"Nestar Communications, Inc","000A18":"Vichel Inc.","000A19":"Valere Power, Inc.","000A1A":"Imerge Ltd","000A1B":"Stream Labs","000A1C":"Bridge Information Co. Ltd","000A1D":"Optical Communications Products Inc.","000A1E":"Red-M Products Limited","000A1F":"ART WARE Telecommunication Co. Ltd","000A20":"SVA Networks, Inc.","000A21":"Integra Telecom Co. Ltd","000A22":"Amperion Inc","000A23":"Parama Networks Inc","000A24":"Octave Communications","000A25":"Ceragon Networks","000A26":"CEIA S.p.A.","000A27":"Apple","000A28":"Motorola","000A29":"Pan Dacom Networking AG","000A2A":"QSI Systems Inc.","000A2B":"Etherstuff","000A2C":"Active Tchnology Corporation","000A2D":"Cabot Communications Limited","000A2E":"Maple Networks Co. Ltd","000A2F":"Artnix Inc.","000A30":"Visteon Corporation","000A31":"HCV Consulting","000A32":"Xsido Corporation","000A33":"Emulex Corporation","000A34":"Identicard Systems Incorporated","000A35":"Xilinx","000A36":"Synelec Telecom Multimedia","000A37":"Procera Networks, Inc.","000A38":"Apani Networks","000A39":"LoPA Information Technology","000A3A":"J-THREE INTERNATIONAL Holding Co. Ltd","000A3B":"GCT Semiconductor, Inc","000A3C":"Enerpoint Ltd","000A3D":"Elo Sistemas Eletronicos S.A.","000A3E":"EADS Telecom","000A3F":"Data East Corporation","000A40":"Crown Audio -- Harmanm International","000A41":"Cisco Systems Inc.","000A42":"Cisco Systems Inc.","000A43":"Chunghwa Telecom Co. Ltd","000A44":"Avery Dennison Deutschland GmbH","000A45":"Audio-Technica Corp.","000A46":"ARO Welding Technologies SAS","000A47":"Allied Vision Technologies","000A48":"Albatron Technology","000A49":"F5 Networks, Inc.","000A4A":"Targa Systems Ltd","000A4B":"DataPower Technology, Inc.","000A4C":"Molecular Devices Corporation","000A4D":"Noritz Corporation","000A4E":"UNITEK Electronics Inc.","000A4F":"Brain Boxes Limited","000A50":"Remotek Corporation","000A51":"GyroSignal Technology Co. Ltd","000A52":"AsiaRF Ltd","000A53":"Intronics, Incorporated","000A54":"Laguna Hills, Inc.","000A55":"MARKEM Corporation","000A56":"HITACHI Maxell Ltd","000A57":"Hewlett-Packard Company","000A58":"Freyer & Siegel Elektronik GmbH & Co. KG","000A59":"HW server","000A5A":"GreenNET Technologies Co. Ltd","000A5B":"Power-One as","000A5C":"Carel s.p.a.","000A5D":"FingerTec Worldwide Sdn Bhd","000A5E":"3Com Corporation","000A5F":"almedio Inc.","000A60":"Autostar Technology Pte Ltd","000A61":"Cellinx Systems Inc.","000A62":"Crinis Networks, Inc.","000A63":"DHD GmbH","000A64":"Eracom Technologies","000A65":"GentechMedia.Co. Ltd","000A66":"Mitsubishi Electric System & Service Co. Ltd","000A67":"OngCorp","000A68":"Solarflare Communications Inc","000A69":"SUNNY bell Technology Co. Ltd","000A6A":"SVM Microwaves s.r.o.","000A6B":"Tadiran Telecom Business Systems Ltd","000A6C":"Walchem Corporation","000A6D":"EKS Elektronikservice GmbH","000A6E":"Harmonic, Inc","000A6F":"ZyFLEX Technologies Inc","000A70":"MPLS Forum","000A71":"Avrio Technologies, Inc","000A72":"Stec, Inc.","000A73":"Scientific Atlanta","000A74":"Manticom Networks Inc.","000A75":"Caterpillar, Inc","000A76":"Beida Jade Bird Huaguang Technology Co. Ltd","000A77":"Bluewire Technologies LLC","000A78":"Olitec","000A79":"Corega K.K","000A7A":"Kyoritsu Electric Co. Ltd","000A7B":"Cornelius Consult","000A7C":"Tecton Ltd","000A7D":"Valo, Inc.","000A7E":"The Advantage Group","000A7F":"Teradon Industries, Inc","000A80":"Telkonet Inc.","000A81":"TEIMA Audiotex S.L.","000A82":"Tatsuta System Electronics Co. Ltd","000A83":"Salto Systems S.L.","000A84":"Rainsun Enterprise Co. Ltd","000A85":"PLAT'C2,Inc","000A86":"Lenze","000A87":"Integrated Micromachines Inc.","000A88":"Incypher S.A.","000A89":"Creval Systems, Inc.","000A8A":"Cisco Systems Inc.","000A8B":"Cisco Systems Inc.","000A8C":"Guardware Systems Ltd","000A8D":"Eurotherm Limited","000A8E":"Invacom Ltd","000A8F":"Aska International Inc.","000A90":"Bayside Interactive, Inc.","000A91":"HemoCue AB","000A92":"Presonus Corporation","000A93":"W2 Networks, Inc.","000A94":"ShangHai cellink Co. Ltd","000A95":"Apple","000A96":"Mewtel Technology Inc.","000A97":"SONICblue, Inc.","000A98":"M+F Gwinner GmbH & Co","000A99":"Calamp Wireless Networks Inc","000A9A":"Aiptek International Inc","000A9B":"TB Group Inc","000A9C":"Server Technology, Inc.","000A9D":"King Young Technology Co. Ltd","000A9E":"BroadWeb Corportation","000A9F":"Pannaway Technologies, Inc.","000AA0":"Cedar Point Communications","000AA1":"V V S Limited","000AA2":"Systek Inc.","000AA3":"Shimafuji Electric Co. Ltd","000AA4":"Shanghai Surveillance Technology Co Ltd","000AA5":"Maxlink Industries Limited","000AA6":"Hochiki Corporation","000AA7":"FEI Electron Optics","000AA8":"ePipe Pty. Ltd","000AA9":"Brooks Automation GmbH","000AAA":"AltiGen Communications Inc.","000AAB":"Toyota Technical Development Corporation","000AAC":"TerraTec Electronic GmbH","000AAD":"Stargames Corporation","000AAE":"Rosemount Process Analytical","000AAF":"Pipal Systems","000AB0":"LOYTEC electronics GmbH","000AB1":"GENETEC Corporation","000AB2":"Fresnel Wireless Systems","000AB3":"Fa. GIRA","000AB4":"ETIC Telecommunications","000AB5":"Digital Electronic Network","000AB6":"Compunetix, Inc","000AB7":"Cisco Systems Inc.","000AB8":"Cisco Systems Inc.","000AB9":"Astera Technologies Corp.","000ABA":"Arcon Technology Limited","000ABB":"Taiwan Secom Co,. Ltd","000ABC":"Seabridge Ltd","000ABD":"Rupprecht & Patashnick Co.","000ABE":"OPNET Technologies Co. Ltd","000ABF":"Hirota SS","000AC0":"Fuyoh Video Industry Co. Ltd","000AC1":"Futuretel","000AC2":"Wuhan FiberHome Digital Technology Co. Ltd","000AC3":"eM Technics Co. Ltd","000AC4":"Daewoo Teletech Co. Ltd","000AC5":"Color Kinetics","000AC6":"Overture Networks.","000AC7":"Unication Group","000AC8":"ZPSYS Co. Ltd (Planning&Management)","000AC9":"Zambeel Inc","000ACA":"YOKOYAMA SHOKAI Co. Ltd","000ACB":"XPAK MSA Group","000ACC":"Winnow Networks, Inc.","000ACD":"Sunrich Technology Limited","000ACE":"Radiantech, Inc.","000ACF":"PROVIDEO Multimedia Co. Ltd","000AD0":"Niigata Develoment Center, F.I.T. Co. Ltd","000AD1":"MWS","000AD2":"JEPICO Corporation","000AD3":"INITECH Co. Ltd","000AD4":"CoreBell Systems Inc.","000AD5":"Brainchild Electronic Co. Ltd","000AD6":"BeamReach Networks","000AD7":"Origin ELECTRIC Co. Ltd","000AD8":"IPCserv Technology Corp.","000AD9":"Sony Mobile Communications AB","000ADA":"Vindicator Technologies","000ADB":"SkyPilot Network, Inc","000ADC":"RuggedCom Inc.","000ADD":"Allworx Corp.","000ADE":"Happy Communication Co. Ltd","000ADF":"Gennum Corporation","000AE0":"Fujitsu Softek","000AE1":"EG Technology","000AE2":"Binatone Electronics International Ltd","000AE3":"Yang MEI Technology Co. Ltd","000AE4":"Wistron Corporation","000AE5":"ScottCare Corporation","000AE6":"Elitegroup Computer Systems Co. Ltd","000AE7":"Eliop S.A.","000AE8":"Cathay Roxus Information Technology Co. Ltd","000AE9":"AirVast Technology Inc.","000AEA":"Adam Elektronik Ltd ?TI","000AEB":"TP-Link Technologies Co. Ltd","000AEC":"Koatsu Gas Kogyo Co. Ltd","000AED":"HARTING Electronics GmbH","000AEE":"GCD Hard- & Software GmbH","000AEF":"Otrum ASA","000AF0":"Shin-OH Electronics Co. Ltd R&D","000AF1":"Clarity Design, Inc.","000AF2":"NeoAxiom Corp.","000AF3":"Cisco Systems Inc.","000AF4":"Cisco Systems Inc.","000AF5":"Airgo Networks, Inc.","000AF6":"Emerson Climate Technologies Retail Solutions, Inc.","000AF7":"Broadcom","000AF8":"American Telecare Inc.","000AF9":"HiConnect, Inc.","000AFA":"Traverse Technologies Australia","000AFB":"Ambri Limited","000AFC":"Core Tec Communications, LLC","000AFD":"Kentec Electronics","000AFE":"NovaPal Ltd","000AFF":"Kilchherr Elektronik AG","000B00":"Fujian Start Computer Equipment Co. Ltd","000B01":"Daiichi Electronics Co. Ltd","000B02":"Dallmeier electronic","000B03":"Taekwang Industrial Co. Ltd","000B04":"Volktek Corporation","000B05":"Pacific Broadband Networks","000B06":"ARRIS Group, Inc.","000B07":"Voxpath Networks","000B08":"Pillar Data Systems","000B09":"Ifoundry Systems Singapore","000B0A":"dBm Optics","000B0B":"Corrent Corporation","000B0C":"Agile Systems Inc.","000B0D":"Air2U, Inc.","000B0E":"Trapeze Networks","000B0F":"Bosch Rexroth","000B10":"11wave Technonlogy Co. Ltd","000B11":"Himeji ABC Trading Co. Ltd","000B12":"NURI Telecom Co. Ltd","000B13":"Zetron Inc","000B14":"ViewSonic Corporation","000B15":"Platypus Technology","000B16":"Communication Machinery Corporation","000B17":"MKS Instruments","000B18":"Private","000B19":"Vernier Networks, Inc.","000B1A":"Industrial Defender, Inc.","000B1B":"Systronix, Inc.","000B1C":"SIBCO bv","000B1D":"LayerZero Power Systems, Inc.","000B1E":"KAPPA opto-electronics GmbH","000B1F":"I CoN Computer Co.","000B20":"Hirata Corporation","000B21":"G-Star Communications Inc.","000B22":"Environmental Systems and Services","000B23":"Siemens Subscriber Networks","000B24":"AirLogic","000B25":"Aeluros","000B26":"Wetek Corporation","000B27":"Scion Corporation","000B28":"Quatech Inc.","000B29":"LS(LG) Industrial Systems Co. Ltd","000B2A":"HOWTEL Co. Ltd","000B2B":"Hostnet Corporation","000B2C":"Eiki Industrial Co. Ltd","000B2D":"Danfoss Inc.","000B2E":"Cal-Comp Electronics & Communications Company Ltd","000B2F":"bplan GmbH","000B30":"Beijing Gongye Science & Technology Co. Ltd","000B31":"Yantai ZhiYang Scientific and technology Industry Co. Ltd","000B32":"Vormetric, Inc.","000B33":"Vivato Technologies","000B34":"ShangHai Broadband Technologies Co.Ltd","000B35":"Quad Bit System Co. Ltd","000B36":"Productivity Systems, Inc.","000B37":"Manufacture DES Montres Rolex SA","000B38":"Kn?rr GmbH","000B39":"Keisoku Giken Co. Ltd","000B3A":"QuStream Corporation","000B3B":"devolo AG","000B3C":"Cygnal Integrated Products, Inc.","000B3D":"CoNTAL OK Ltd","000B3E":"BittWare, Inc","000B3F":"Anthology Solutions Inc.","000B40":"Oclaro","000B41":"Ing. B?ro Dr. Beutlhauser","000B42":"Commax Co. Ltd","000B43":"Microscan Systems, Inc.","000B44":"Concord IDea Corp.","000B45":"Cisco Systems Inc.","000B46":"Cisco Systems Inc.","000B47":"Advanced Energy","000B48":"sofrel","000B49":"RF-Link System Inc.","000B4A":"Visimetrics (UK) Ltd","000B4B":"Visiowave SA","000B4C":"Clarion (M) Sdn Bhd","000B4D":"Emuzed","000B4E":"VertexRSI, General Dynamics SatCOM Technologies, Inc.","000B4F":"Verifone","000B50":"Oxygnet","000B51":"Micetek International Inc.","000B52":"Joymax Electronics Co. Ltd","000B53":"INITIUM Co. Ltd","000B54":"BiTMICRO Networks, Inc.","000B55":"ADInstruments","000B56":"Cybernetics","000B57":"Silicon Laboratories","000B58":"Astronautics C.A Ltd","000B59":"ScriptPro, LLC","000B5A":"HyperEdge","000B5B":"Rincon Research Corporation","000B5C":"Newtech Co. Ltd","000B5D":"Fujitsu Limited","000B5E":"Audio Engineering Society Inc.","000B5F":"Cisco Systems Inc.","000B60":"Cisco Systems Inc.","000B61":"Friedrich L?tze GmbH & Co. KG","000B62":"ib-mohnen KG","000B63":"Kaleidescape","000B64":"Kieback & Peter GmbH & Co KG","000B65":"Sy.A.C. srl","000B66":"Teralink Communications","000B67":"Topview Technology Corporation","000B68":"Addvalue Communications Pte Ltd","000B69":"Franke Finland Oy","000B6A":"Asiarock Technology Limited","000B6B":"Wistron Neweb Corporation","000B6C":"Sychip Inc.","000B6D":"Solectron Japan Nakaniida","000B6E":"Neff Instrument Corp.","000B6F":"Media Streaming Networks Inc","000B70":"Load Technology, Inc.","000B71":"Litchfield Communications Inc.","000B72":"Lawo AG","000B73":"Kodeos Communications","000B74":"Kingwave Technology Co. Ltd","000B75":"Iosoft Ltd","000B76":"ET&T Technology Co. Ltd","000B77":"Cogent Systems, Inc.","000B78":"Taifatech Inc.","000B79":"X-CoM, Inc.","000B7A":"L-3 Linkabit","000B7B":"Test-Um Inc.","000B7C":"Telex Communications","000B7D":"Solomon Extreme International Ltd","000B7E":"SAGINOMIYA Seisakusho Inc.","000B7F":"Align Engineering LLC","000B80":"Lycium Networks","000B81":"Kaparel Corporation","000B82":"Grandstream Networks, Inc.","000B83":"Datawatt B.V.","000B84":"Bodet","000B85":"Cisco Systems Inc.","000B86":"Aruba Networks","000B87":"American Reliance Inc.","000B88":"Vidisco Ltd","000B89":"Top Global Technology Ltd","000B8A":"MITEQ Inc.","000B8B":"Kerajet, S.A.","000B8C":"Flextronics","000B8D":"Avvio Networks","000B8E":"Ascent Corporation","000B8F":"Akita Electronics Systems Co. Ltd","000B90":"ADVA Optical Networking Ltd","000B91":"Aglaia Gesellschaft f?r Bildverarbeitung und Kommunikation mbH","000B92":"Ascom Danmark A/S","000B93":"Ritter Elektronik","000B94":"Digital Monitoring Products, Inc.","000B95":"eBet Gaming Systems Pty Ltd","000B96":"Innotrac Diagnostics Oy","000B97":"Matsushita Electric Industrial Co. Ltd","000B98":"NiceTechVision","000B99":"SensAble Technologies, Inc.","000B9A":"Shanghai Ulink Telecom Equipment Co. Ltd","000B9B":"Sirius System Co Ltd","000B9C":"TriBeam Technologies, Inc.","000B9D":"TwinMOS Technologies Inc.","000B9E":"Yasing Technology Corp.","000B9F":"Neue ELSA GmbH","000BA0":"T&L Information Inc.","000BA1":"Fujikura Solutions Ltd","000BA2":"Sumitomo Electric Industries Ltd","000BA3":"Siemens AG, I&S","000BA4":"Shiron Satellite Communications Ltd (1996)","000BA5":"Quasar Cipta Mandiri, PT","000BA6":"Miyakawa Electric Works Ltd","000BA7":"Maranti Networks","000BA8":"Hanback Electronics Co. Ltd","000BA9":"CloudShield Technologies, Inc.","000BAA":"Aiphone Co. Ltd","000BAB":"Advantech Technology (CHINA) Co. Ltd","000BAC":"3Com Ltd","000BAD":"PC-PoS Inc.","000BAE":"Vitals System Inc.","000BAF":"WOOJU CoMMUNICATIONS Co,.Ltd","000BB0":"Sysnet Telematica srl","000BB1":"Super Star Technology Co. Ltd","000BB2":"Smallbig Technology","000BB3":"RiT technologies Ltd","000BB4":"RDC Semiconductor Inc.,","000BB5":"nStor Technologies, Inc.","000BB6":"Metalligence Technology Corp.","000BB7":"Micro Systems Co. Ltd","000BB8":"Kihoku Electronic Co.","000BB9":"Imsys AB","000BBA":"Harmonic, Inc","000BBB":"Etin Systems Co. Ltd","000BBC":"En Garde Systems, Inc.","000BBD":"Connexionz Limited","000BBE":"Cisco Systems Inc.","000BBF":"Cisco Systems Inc.","000BC0":"China IWNComm Co. Ltd","000BC1":"Bay Microsystems, Inc.","000BC2":"Corinex Communication Corp.","000BC3":"Multiplex, Inc.","000BC4":"BIOTRONIK GmbH & Co","000BC5":"SMC Networks, Inc.","000BC6":"ISAC, Inc.","000BC7":"ICET S.p.A.","000BC8":"AirFlow Networks","000BC9":"Electroline Equipment","000BCA":"Datavan TC","000BCB":"Fagor Automation , S. Coop","000BCC":"Jusan, S.A.","000BCD":"Hewlett-Packard Company","000BCE":"Free2move AB","000BCF":"Agfa NDT Inc.","000BD0":"XiMeta Technology Americas Inc.","000BD1":"Aeronix, Inc.","000BD2":"Remopro Technology Inc.","000BD3":"cd3o","000BD4":"Beijing Wise Technology & Science Development Co.Ltd","000BD5":"Nvergence, Inc.","000BD6":"Paxton Access Ltd","000BD7":"DORMA Time + Access GmbH","000BD8":"Industrial Scientific Corp.","000BD9":"General Hydrogen","000BDA":"EyeCross Co.,Inc.","000BDB":"Dell Inc.","000BDC":"Akcp","000BDD":"TOHOKU RICOH Co. Ltd","000BDE":"TELDIX GmbH","000BDF":"Shenzhen RouterD Networks Limited","000BE0":"SercoNet Ltd","000BE1":"Nokia NET Product Operations","000BE2":"Lumenera Corporation","000BE3":"Key Stream Co. Ltd","000BE4":"Hosiden Corporation","000BE5":"HIMS International Corporation","000BE6":"Datel Electronics","000BE7":"Comflux Technology Inc.","000BE8":"Aoip","000BE9":"Actel Corporation","000BEA":"Zultys Technologies","000BEB":"Systegra AG","000BEC":"Nippon Electric Instrument, Inc.","000BED":"ELM Inc.","000BEE":"Inc.jet, Incorporated","000BEF":"Code Corporation","000BF0":"MoTEX Products Co. Ltd","000BF1":"LAP Laser Applikations","000BF2":"Chih-Kan Technology Co. Ltd","000BF3":"BAE Systems","000BF4":"Private","000BF5":"Shanghai Sibo Telecom Technology Co. Ltd","000BF6":"Nitgen Co. Ltd","000BF7":"Nidek Co. Ltd","000BF8":"Infinera","000BF9":"Gemstone Communications, Inc.","000BFA":"Exemys SRL","000BFB":"D-NET International Corporation","000BFC":"Cisco Systems Inc.","000BFD":"Cisco Systems Inc.","000BFE":"CASTEL Broadband Limited","000BFF":"Berkeley Camera Engineering","000C00":"BEB Industrie-Elektronik AG","000C01":"Abatron AG","000C02":"ABB Oy","000C03":"HDMI Licensing, LLC","000C04":"Tecnova","000C05":"RPA Reserch Co. Ltd","000C06":"Nixvue Systems Pte Ltd","000C07":"Iftest AG","000C08":"HUMEX Technologies Corp.","000C09":"Hitachi IE Systems Co. Ltd","000C0A":"Guangdong Province Electronic Technology Research Institute","000C0B":"Broadbus Technologies","000C0C":"Appro Technology Inc.","000C0D":"Communications & Power Industries / Satcom Division","000C0E":"XtremeSpectrum, Inc.","000C0F":"Techno-One Co. Ltd","000C10":"PNI Corporation","000C11":"Nippon Dempa Co. Ltd","000C12":"Micro-Optronic-Messtechnik GmbH","000C13":"MediaQ","000C14":"Diagnostic Instruments, Inc.","000C15":"CyberPower Systems, Inc.","000C16":"Concorde Microsystems Inc.","000C17":"AJA Video Systems Inc","000C18":"Zenisu Keisoku Inc.","000C19":"Telio Communications GmbH","000C1A":"Quest Technical Solutions Inc.","000C1B":"ORACOM Co Ltd","000C1C":"MicroWeb Co. Ltd","000C1D":"Mettler & Fuchs AG","000C1E":"Global Cache","000C1F":"Glimmerglass Networks","000C20":"Fi WIn, Inc.","000C21":"Faculty Of Science and Technology, Keio University","000C22":"Double D Electronics Ltd","000C23":"Beijing Lanchuan Tech. Co. Ltd","000C24":"Anator","000C25":"Allied Telesis Labs, Inc.","000C26":"Weintek Labs. Inc.","000C27":"Sammy Corporation","000C28":"Rifatron","000C29":"VMware, Inc.","000C2A":"OCTTEL Communication Co. Ltd","000C2B":"ELIAS Technology, Inc.","000C2C":"Enwiser Inc.","000C2D":"FullWave Technology Co. Ltd","000C2E":"Openet Information technology(shenzhen) Co. Ltd","000C2F":"SeorimTechnology Co. Ltd","000C30":"Cisco Systems Inc.","000C31":"Cisco Systems Inc.","000C32":"Avionic Design Development GmbH","000C33":"Compucase Enterprise Co. Ltd","000C34":"Vixen Co. Ltd","000C35":"KaVo Dental GmbH & Co. KG","000C36":"Sharp Takaya Electronics Industry Co. Ltd","000C37":"Geomation, Inc.","000C38":"TelcoBridges Inc.","000C39":"Sentinel Wireless Inc.","000C3A":"Oxance","000C3B":"Orion Electric Co. Ltd","000C3C":"MediaChorus, Inc.","000C3D":"Glsystech Co. Ltd","000C3E":"Crest Audio","000C3F":"Cogent Defence & Security Networks,","000C40":"Altech Controls","000C41":"Cisco-Linksys LLC","000C42":"Routerboard.com","000C43":"Ralink Technology, Corp.","000C44":"Automated Interfaces, Inc.","000C45":"Animation Technologies Inc.","000C46":"Allied Telesyn Inc.","000C47":"SK Teletech(R&D Planning Team)","000C48":"QoStek Corporation","000C49":"Dangaard Telecom Denmark A/S","000C4A":"Cygnus Microsystems (P) Limited","000C4B":"Cheops Elektronik","000C4C":"Arcor AG&Co.","000C4D":"Curtiss-Wright Controls Avionics & Electronics","000C4E":"Winbest Technology Co,LT","000C4F":"UDTech Japan Corporation","000C50":"Seagate Technology","000C51":"Scientific Technologies Inc.","000C52":"Roll Systems Inc.","000C53":"Private","000C54":"Pedestal Networks, Inc","000C55":"Microlink Communications Inc.","000C56":"Megatel Computer (1986) Corp.","000C57":"MACKIE Engineering Services Belgium BVBA","000C58":"M&S Systems","000C59":"Indyme Electronics, Inc.","000C5A":"IBSmm Embedded Electronics Consulting","000C5B":"Hanwang Technology Co. Ltd","000C5C":"GTN Systems B.V.","000C5D":"Chic Technology (China) Corp.","000C5E":"Calypso Medical","000C5F":"Avtec, Inc.","000C60":"ACM Systems","000C61":"AC Tech Corporation DBA Advanced Digital","000C62":"ABB AB, Cewe-Control","000C63":"Zenith Electronics Corporation","000C64":"X2 MSA Group","000C65":"Sunin Telecom","000C66":"Pronto Networks Inc","000C67":"OyO Electric Co. Ltd","000C68":"SigmaTel, Inc.","000C69":"National Radio Astronomy Observatory","000C6A":"Mbari","000C6B":"Kurz Industrie-Elektronik GmbH","000C6C":"Elgato Systems LLC","000C6D":"Edwards Ltd","000C6E":"ASUSTek Computer Inc.","000C6F":"Amtek System Co. Ltd","000C70":"ACC GmbH","000C71":"Wybron, Inc","000C72":"Tempearl Industrial Co. Ltd","000C73":"Telson Electronics Co. Ltd","000C74":"Rivertec Corporation","000C75":"Oriental integrated electronics. Ltd","000C76":"Micro-Star International","000C77":"Life Racing Ltd","000C78":"In-Tech Electronics Limited","000C79":"Extel Communications P/L","000C7A":"DaTARIUS Technologies GmbH","000C7B":"ALPHA PROJECT Co. Ltd","000C7C":"Internet Information Image Inc.","000C7D":"Teikoku Electric MFG. Co. Ltd","000C7E":"Tellium Incorporated","000C7F":"synertronixx GmbH","000C80":"Opelcomm Inc.","000C81":"Schneider Electric (Australia)","000C82":"Network Technologies Inc","000C83":"Logical Solutions","000C84":"Eazix, Inc.","000C85":"Cisco Systems Inc.","000C86":"Cisco Systems Inc.","000C87":"AMD","000C88":"Apache Micro Peripherals, Inc.","000C89":"AC Electric Vehicles Ltd","000C8A":"Bose Corporation","000C8B":"Connect Tech Inc","000C8C":"Kodicom Co. Ltd","000C8D":"MATRIX VISION GmbH","000C8E":"Mentor Engineering Inc","000C8F":"Nergal s.r.l.","000C90":"Octasic Inc.","000C91":"Riverhead Networks Inc.","000C92":"WolfVision GmbH","000C93":"Xeline Co. Ltd","000C94":"United Electronic Industries, Inc. (EUI)","000C95":"PrimeNet","000C96":"OQO, Inc.","000C97":"NV ADB TTV Technologies SA","000C98":"LETEK Communications Inc.","000C99":"HITEL LINK Co. Ltd","000C9A":"Hitech Electronics Corp.","000C9B":"EE Solutions, Inc","000C9C":"Chongho Information & Communications","000C9D":"UbeeAirWalk, Inc.","000C9E":"MemoryLink Corp.","000C9F":"NKE Corporation","000CA0":"StorCase Technology, Inc.","000CA1":"SIGMACOM Co. Ltd","000CA2":"Harmonic Video Network","000CA3":"Rancho Technology, Inc.","000CA4":"Prompttec Product Management GmbH","000CA5":"Naman NZ Ltd","000CA6":"Mintera Corporation","000CA7":"Metro (Suzhou) Technologies Co. Ltd","000CA8":"Garuda Networks Corporation","000CA9":"Ebtron Inc.","000CAA":"Cubic Transportation Systems Inc","000CAB":"Commend International GmbH","000CAC":"Citizen Watch Co. Ltd","000CAD":"BTU International","000CAE":"Ailocom Oy","000CAF":"TRI Term Co. Ltd","000CB0":"Star Semiconductor Corporation","000CB1":"Salland Engineering (Europe) BV","000CB2":"UNION Co. Ltd","000CB3":"ROUND Co. Ltd","000CB4":"AutoCell Laboratories, Inc.","000CB5":"Premier Technolgies, Inc","000CB6":"Nanjing SEU Mobile & Internet Technology Co. Ltd","000CB7":"Nanjing Huazhuo Electronics Co. Ltd","000CB8":"Medion AG","000CB9":"LEA","000CBA":"Jamex, Inc.","000CBB":"Iskraemeco","000CBC":"Iscutum","000CBD":"Interface Masters, Inc","000CBE":"Innominate Security Technologies AG","000CBF":"Holy Stone Ent. Co. Ltd","000CC0":"Genera Oy","000CC1":"Eaton Corporation","000CC2":"ControlNet (India) Private Limited","000CC3":"BeWAN Systems","000CC4":"Tiptel AG","000CC5":"Nextlink Co. Ltd","000CC6":"Ka-Ro electronics GmbH","000CC7":"Intelligent Computer Solutions Inc.","000CC8":"Xytronix Research & Design, Inc.","000CC9":"Ilwoo Data & Technology Co. Ltd","000CCA":"HGST a Western Digital Company","000CCB":"Design Combus Ltd","000CCC":"Aeroscout Ltd","000CCD":"IEC - TC57","000CCE":"Cisco Systems Inc.","000CCF":"Cisco Systems Inc.","000CD0":"Symetrix","000CD1":"SFOM Technology Corp.","000CD2":"Schaffner EMV AG","000CD3":"Prettl Elektronik Radeberg GmbH","000CD4":"Positron Public Safety Systems Inc.","000CD5":"Passave Inc.","000CD6":"Partner Tech","000CD7":"Nallatech Ltd","000CD8":"M. K. Juchheim GmbH & Co","000CD9":"Itcare Co. Ltd","000CDA":"FreeHand Systems, Inc.","000CDB":"Brocade Communications Systems, Inc.","000CDC":"BECS Technology, Inc","000CDD":"AOS technologies AG","000CDE":"ABB STOTZ-KONTAKT GmbH","000CDF":"PULNiX America, Inc","000CE0":"Trek Diagnostics Inc.","000CE1":"The Open Group","000CE2":"Rolls-Royce","000CE3":"Option International N.V.","000CE4":"NeuroCom International, Inc.","000CE5":"ARRIS Group, Inc.","000CE6":"Meru Networks Inc","000CE7":"MediaTek Inc.","000CE8":"GuangZhou AnJuBao Co. Ltd","000CE9":"Bloomberg L.P.","000CEA":"aphona Kommunikationssysteme","000CEB":"CNMP Networks, Inc.","000CEC":"Spectracom Corp.","000CED":"Real Digital Media","000CEE":"jp-embedded","000CEF":"Open Networks Engineering Ltd","000CF0":"M & N GmbH","000CF1":"Intel Corporation","000CF2":"GAMESA E?lica","000CF3":"Call Image SA","000CF4":"Akatsuki Electric MFG.Co. Ltd","000CF5":"InfoExpress","000CF6":"Sitecom Europe BV","000CF7":"Nortel Networks","000CF8":"Nortel Networks","000CF9":"Xylem Water Solutions","000CFA":"Digital Systems Corp","000CFB":"Korea Network Systems","000CFC":"S2io Technologies Corp","000CFD":"Hyundai ImageQuest Co. Ltd","000CFE":"Grand Electronic Co. Ltd","000CFF":"MRO-TEK Limited","000D00":"Seaway Networks Inc.","000D01":"P&E Microcomputer Systems, Inc.","000D02":"NEC Platforms Ltd","000D03":"Matrics, Inc.","000D04":"Foxboro Eckardt Development GmbH","000D05":"cybernet manufacturing Inc.","000D06":"Compulogic Limited","000D07":"Calrec Audio Ltd","000D08":"AboveCable, Inc.","000D09":"Yuehua(Zhuhai) Electronic Co. Ltd","000D0A":"Projectiondesign as","000D0B":"Buffalo.Inc","000D0C":"MDI Security Systems","000D0D":"ITSupported, LLC","000D0E":"Inqnet Systems, Inc.","000D0F":"Finlux Ltd","000D10":"Embedtronics Oy","000D11":"DENTSPLY - Gendex","000D12":"AXELL Corporation","000D13":"Wilhelm Rutenbeck GmbH&Co.KG","000D14":"Vtech Innovation LP dba Advanced American Telephones","000D15":"Voipac s.r.o.","000D16":"UHS Systems Pty Ltd","000D17":"Turbo Networks Co.Ltd","000D18":"Mega-Trend Electronics Co. Ltd","000D19":"ROBE Show lighting","000D1A":"Mustek System Inc.","000D1B":"Kyoto Electronics Manufacturing Co. Ltd","000D1C":"Amesys Defense","000D1D":"High-TEK Harness ENT. Co. Ltd","000D1E":"Control Techniques","000D1F":"AV Digital","000D20":"Asahikasei Technosystem Co. Ltd","000D21":"WISCORE Inc.","000D22":"Unitronics Ltd","000D23":"Smart Solution, Inc","000D24":"Sentec E&E Co. Ltd","000D25":"Sanden Corporation","000D26":"Primagraphics Limited","000D27":"MICROPLEX Printware AG","000D28":"Cisco Systems Inc.","000D29":"Cisco Systems Inc.","000D2A":"Scanmatic AS","000D2B":"Racal Instruments","000D2C":"Net2Edge Limited","000D2D":"NCT Deutschland GmbH","000D2E":"Matsushita Avionics Systems Corporation","000D2F":"AIN Comm.Tech.Co. Ltd","000D30":"IceFyre Semiconductor","000D31":"Compellent Technologies, Inc.","000D32":"DispenseSource, Inc.","000D33":"Prediwave Corp.","000D34":"Shell International Exploration and Production, Inc.","000D35":"PAC International Ltd","000D36":"Wu Han Routon Electronic Co. Ltd","000D37":"Wiplug","000D38":"Nissin Inc.","000D39":"Network Electronics","000D3A":"Microsoft Corporation","000D3B":"Microelectronics Technology Inc.","000D3C":"i.Tech Dynamic Ltd","000D3D":"Hammerhead Systems, Inc.","000D3E":"APLUX Communications Ltd","000D3F":"VTI Instruments Corporation","000D40":"Verint Loronix Video Solutions","000D41":"Siemens AG ICM MP UC RD IT KLF1","000D42":"Newbest Development Limited","000D43":"DRS Tactical Systems Inc.","000D44":"Audio BU - Logitech","000D45":"Tottori SANYO Electric Co. Ltd","000D46":"Parker SSD Drives","000D47":"Collex","000D48":"AEWIN Technologies Co. Ltd","000D49":"Triton Systems Of Delaware, Inc.","000D4A":"Steag ETA-Optik","000D4B":"Roku, Inc.","000D4C":"Outline Electronics Ltd","000D4D":"Ninelanes","000D4E":"NDR Co. Ltd","000D4F":"Kenwood Corporation","000D50":"Galazar Networks","000D51":"DivR Systems, Inc.","000D52":"Comart System","000D53":"Beijing 5w Communication Corp.","000D54":"3Com Ltd","000D55":"SANYCOM Technology Co. Ltd","000D56":"Dell Inc.","000D57":"Fujitsu I-Network Systems Limited.","000D58":"Private","000D59":"Amity Systems, Inc.","000D5A":"Tiesse SpA","000D5B":"Smart Empire Investments Limited","000D5C":"Robert Bosch GmbH, VT-ATMO","000D5D":"Raritan Computer, Inc","000D5E":"NEC Personal Products","000D5F":"Minds Inc","000D60":"IBM Corp","000D61":"Giga-Byte Technology Co. Ltd","000D62":"Funkwerk Dabendorf GmbH","000D63":"DENT Instruments, Inc.","000D64":"CoMAG Handels AG","000D65":"Cisco Systems Inc.","000D66":"Cisco Systems Inc.","000D67":"Ericsson","000D68":"Vinci Systems, Inc.","000D69":"TMT&D Corporation","000D6A":"Redwood Technologies Ltd","000D6B":"Mita-Teknik A/S","000D6C":"M-Audio","000D6D":"K-Tech Devices Corp.","000D6E":"K-Patents Oy","000D6F":"Ember Corporation","000D70":"Datamax Corporation","000D71":"boca Systems","000D72":"2Wire Inc.","000D73":"Technical Support, Inc.","000D74":"Sand Network Systems, Inc.","000D75":"Kobian Pte Ltd - Taiwan Branch","000D76":"Hokuto Denshi Co,. Ltd","000D77":"FalconStor Software","000D78":"Engineering & Security","000D79":"Dynamic Solutions Co,.Ltd","000D7A":"DiGATTO Asia Pacific Pte Ltd","000D7B":"Consensys Computers Inc.","000D7C":"Codian Ltd","000D7D":"Afco Systems","000D7E":"Axiowave Networks, Inc.","000D7F":"MIDAS CoMMUNICATION TECHNOLOGIES PTE Ltd ( Foreign Branch)","000D80":"Online Development Inc","000D81":"Pepperl+Fuchs GmbH","000D82":"PHS srl","000D83":"Sanmina-SCI Hungary Ltd","000D84":"Makus Inc.","000D85":"Tapwave, Inc.","000D86":"Huber + Suhner AG","000D87":"Elitegroup Computer Systems Co. Ltd","000D88":"D-Link Corporation","000D89":"Bils Technology Inc","000D8A":"Winners Electronics Co. Ltd","000D8B":"T&D Corporation","000D8C":"Shanghai Wedone Digital Ltd Co.","000D8D":"Prosoft Technology, Inc","000D8E":"Koden Electronics Co. Ltd","000D8F":"King Tsushin Kogyo Co. Ltd","000D90":"Factum Electronics AB","000D91":"Eclipse (HQ Espana) S.L.","000D92":"ARIMA Communications Corp.","000D93":"Apple","000D94":"AFAR Communications,Inc","000D95":"Opti-cell, Inc.","000D96":"Vtera Technology Inc.","000D97":"ABB Inc./Tropos","000D98":"S.W.A.C. Schmitt-Walter Automation Consult GmbH","000D99":"Orbital Sciences Corp.; Launch Systems Group","000D9A":"Infotec Ltd","000D9B":"Heraeus Electro-Nite International N.V.","000D9C":"Elan GmbH & Co KG","000D9D":"Hewlett-Packard Company","000D9E":"TOKUDEN OHIZUMI SEISAKUSYO Co. Ltd","000D9F":"RF Micro Devices","000DA0":"Nedap N.V.","000DA1":"MIRAE ITS Co. Ltd","000DA2":"Infrant Technologies, Inc.","000DA3":"Emerging Technologies Limited","000DA4":"Dosch & Amand Systems AG","000DA5":"Fabric7 Systems, Inc","000DA6":"Universal Switching Corporation","000DA7":"Private","000DA8":"TElectronics Technology Corporation","000DA9":"T.E.A.M. S.L.","000DAA":"S.A.Tehnology Co. Ltd","000DAB":"Parker Hannifin GmbH Electromechanical Division Europe","000DAC":"Japan CBM Corporation","000DAD":"Dataprobe, Inc.","000DAE":"Samsung Heavy Industries Co. Ltd","000DAF":"Plexus Corp (UK) Ltd","000DB0":"Olym-tech Co. Ltd","000DB1":"Japan Network Service Co. Ltd","000DB2":"Ammasso, Inc.","000DB3":"SDO Communication Corperation","000DB4":"Netasq","000DB5":"Globalsat Technology Corporation","000DB6":"Broadcom","000DB7":"Sanko Electric Co,.Ltd","000DB8":"Schiller AG","000DB9":"PC Engines GmbH","000DBA":"Oc? Document Technologies GmbH","000DBB":"Nippon Dentsu Co. Ltd","000DBC":"Cisco Systems Inc.","000DBD":"Cisco Systems Inc.","000DBE":"Bel Fuse Europe Ltd,UK","000DBF":"TekTone Sound & Signal Mfg., Inc.","000DC0":"Spagat AS","000DC1":"SafeWeb Inc","000DC2":"Private","000DC3":"First Communication, Inc.","000DC4":"Emcore Corporation","000DC5":"EchoStar Global B.V.","000DC6":"DigiRose Technology Co. Ltd","000DC7":"Cosmic Engineering Inc.","000DC8":"AirMagnet, Inc","000DC9":"THALES Elektronik Systeme GmbH","000DCA":"Tait Electronics","000DCB":"Petcomkorea Co. Ltd","000DCC":"NEOSMART Corp.","000DCD":"Groupe Txcom","000DCE":"Dynavac Technology Pte Ltd","000DCF":"Cidra Corp.","000DD0":"TetraTec Instruments GmbH","000DD1":"Stryker Corporation","000DD2":"Simrad Optronics ASA","000DD3":"SAMWOO Telecommunication Co. Ltd","000DD4":"Symantec Corporation","000DD5":"O'Rite Technology Co. Ltd","000DD6":"ITI Ltd","000DD7":"Bright","000DD8":"BBN","000DD9":"Anton Paar GmbH","000DDA":"Allied Telesis K.K.","000DDB":"Airwave Technologies Inc.","000DDC":"VAC","000DDD":"Profilo Telra Elektronik Sanayi ve Ticaret. A.?","000DDE":"Joyteck Co. Ltd","000DDF":"Japan Image & Network Inc.","000DE0":"ICPDAS Co. Ltd","000DE1":"Control Products, Inc.","000DE2":"CMZ Sistemi Elettronici","000DE3":"AT Sweden AB","000DE4":"DIGINICS, Inc.","000DE5":"Samsung Thales","000DE6":"Youngbo Engineering Co. Ltd","000DE7":"Snap-on OEM Group","000DE8":"Nasaco Electronics Pte. Ltd","000DE9":"Napatech Aps","000DEA":"Kingtel Telecommunication Corp.","000DEB":"CompXs Limited","000DEC":"Cisco Systems Inc.","000DED":"Cisco Systems Inc.","000DEE":"Andrew RF Power Amplifier Group","000DEF":"Soc. Coop. Bilanciai","000DF0":"Qcom Technology Inc.","000DF1":"Ionix Inc.","000DF2":"Private","000DF3":"Asmax Solutions","000DF4":"Watertek Co.","000DF5":"TElectronics International Inc.","000DF6":"Technology Thesaurus Corp.","000DF7":"Space Dynamics Lab","000DF8":"ORGA Kartensysteme GmbH","000DF9":"NDS Limited","000DFA":"Micro Control Systems Ltd","000DFB":"Komax AG","000DFC":"ITFOR Inc.","000DFD":"Huges Hi-Tech Inc.,","000DFE":"Hauppauge Computer Works, Inc.","000DFF":"Chenming Mold Industry Corp.","000E00":"Atrie","000E01":"ASIP Technologies Inc.","000E02":"Advantech AMT Inc.","000E03":"Emulex Corporation","000E04":"CMA/Microdialysis AB","000E05":"Wireless Matrix Corp.","000E06":"Team Simoco Ltd","000E07":"Sony Mobile Communications AB","000E08":"Cisco-Linksys LLC","000E09":"Shenzhen Coship Software Co. Ltd","000E0A":"Sakuma Design Office","000E0B":"Netac Technology Co. Ltd","000E0C":"Intel Corporation","000E0D":"Hesch Schr?der GmbH","000E0E":"ESA elettronica S.P.A.","000E0F":"Ermme","000E10":"C-guys, Inc.","000E11":"BDT B?ro und Datentechnik GmbH & Co.KG","000E12":"Adaptive Micro Systems Inc.","000E13":"Accu-Sort Systems Inc.","000E14":"Visionary Solutions, Inc.","000E15":"Tadlys Ltd","000E16":"SouthWing S.L.","000E17":"Private","000E18":"MyA Technology","000E19":"LogicaCMG Pty Ltd","000E1A":"JPS Communications","000E1B":"IAV GmbH","000E1C":"Hach Company","000E1D":"ARION Technology Inc.","000E1E":"QLogic Corporation","000E1F":"TCL Networks Equipment Co. Ltd","000E20":"ACCESS Systems Americas, Inc.","000E21":"MTU Friedrichshafen GmbH","000E22":"Private","000E23":"Incipient, Inc.","000E24":"Huwell Technology Inc.","000E25":"Hannae Technology Co. Ltd","000E26":"Gincom Technology Corp.","000E27":"Crere Networks, Inc.","000E28":"Dynamic Ratings P/L","000E29":"Shester Communications Inc","000E2A":"Private","000E2B":"Safari Technologies","000E2C":"Netcodec Co.","000E2D":"Hyundai Digital Technology Co. Ltd","000E2E":"Edimax Technology Co. Ltd","000E2F":"Roche Diagnostics GmbH","000E30":"AERAS Networks, Inc.","000E31":"Olympus Soft Imaging Solutions GmbH","000E32":"Kontron Medical","000E33":"Shuko Electronics Co. Ltd","000E34":"NexGen City, LP","000E35":"Intel Corporation","000E36":"HEINESYS, Inc.","000E37":"Harms & Wende GmbH & Co.KG","000E38":"Cisco Systems Inc.","000E39":"Cisco Systems Inc.","000E3A":"Cirrus Logic","000E3B":"Hawking Technologies, Inc.","000E3C":"Transact Technologies Inc","000E3D":"Televic N.V.","000E3E":"Sun Optronics Inc","000E3F":"Soronti, Inc.","000E40":"Nortel Networks","000E41":"Nihon Mechatronics Co. Ltd","000E42":"Motic Incoporation Ltd","000E43":"G-Tek Electronics Sdn. Bhd.","000E44":"Digital 5, Inc.","000E45":"Beijing Newtry Electronic Technology Ltd","000E46":"Niigata Seimitsu Co. Ltd","000E47":"NCI System Co. Ltd","000E48":"Lipman TransAction Solutions","000E49":"Forsway Scandinavia AB","000E4A":"Changchun Huayu WEBPAD Co. Ltd","000E4B":"atrium c and i","000E4C":"Bermai Inc.","000E4D":"Numesa Inc.","000E4E":"Waveplus Technology Co. Ltd","000E4F":"Trajet GmbH","000E50":"Thomson Telecom Belgium","000E51":"tecna elettronica srl","000E52":"Optium Corporation","000E53":"AV Tech Corporation","000E54":"AlphaCell Wireless Ltd","000E55":"Auvitran","000E56":"4G Systems GmbH & Co. KG","000E57":"Iworld Networking, Inc.","000E58":"Sonos, Inc.","000E59":"Sagemcom Broadband SAS","000E5A":"TELEFIELD Inc.","000E5B":"ParkerVision - Direct2Data","000E5C":"ARRIS Group, Inc.","000E5D":"Triple Play Technologies A/S","000E5E":"Raisecom Technology","000E5F":"activ-net GmbH & Co. KG","000E60":"360SUN Digital Broadband Corporation","000E61":"Microtrol Limited","000E62":"Nortel Networks","000E63":"Lemke Diagnostics GmbH","000E64":"Elphel, Inc","000E65":"TransCore","000E66":"Hitachi Industry & Control Solutions Ltd","000E67":"Eltis Microelectronics Ltd","000E68":"E-TOP Network Technology Inc.","000E69":"China Electric Power Research Institute","000E6A":"3Com Ltd","000E6B":"Janitza electronics GmbH","000E6C":"Device Drivers Limited","000E6D":"Murata Manufacturing Co. Ltd","000E6E":"MAT S.A. (Mircrelec Advanced Technology)","000E6F":"IRIS Corporation Berhad","000E70":"in2 Networks","000E71":"Gemstar Technology Development Ltd","000E72":"CTS electronics","000E73":"Tpack A/S","000E74":"Solar Telecom. Tech","000E75":"New York Air Brake Corp.","000E76":"Gemsoc Innovision Inc.","000E77":"Decru, Inc.","000E78":"Amtelco","000E79":"Ample Communications Inc.","000E7A":"GemWon Communications Co. Ltd","000E7B":"Toshiba","000E7C":"Televes S.A.","000E7D":"Electronics Line 3000 Ltd","000E7E":"ionSign Oy","000E7F":"Hewlett-Packard Company","000E80":"Thomson Technology Inc","000E81":"Devicescape Software, Inc.","000E82":"Commtech Wireless","000E83":"Cisco Systems Inc.","000E84":"Cisco Systems Inc.","000E85":"Catalyst Enterprises, Inc.","000E86":"Alcatel North America","000E87":"adp Gauselmann GmbH","000E88":"Videotron Corp.","000E89":"Clematic","000E8A":"Avara Technologies Pty. Ltd","000E8B":"Astarte Technology Co Ltd","000E8C":"Siemens AG A&D ET","000E8D":"Systems in Progress Holding GmbH","000E8E":"SparkLAN Communications, Inc.","000E8F":"Sercomm Corp.","000E90":"Ponico Corp.","000E91":"Navico Auckland Ltd","000E92":"Open Telecom","000E93":"Mil?nio 3 Sistemas Electr?nicos, Lda.","000E94":"Maas International BV","000E95":"Fujiya Denki Seisakusho Co. Ltd","000E96":"Cubic Defense Applications, Inc.","000E97":"Ultracker Technology Co., Inc","000E98":"HME Clear-Com Ltd","000E99":"Spectrum Digital, Inc","000E9A":"BOE Technology Group Co. Ltd","000E9B":"Ambit Microsystems Corporation","000E9C":"Benchmark Electronics","000E9D":"Tiscali UK Ltd","000E9E":"Topfield Co. Ltd","000E9F":"TEMIC SDS GmbH","000EA0":"NetKlass Technology Inc.","000EA1":"Formosa Teletek Corporation","000EA2":"McAfee, Inc","000EA3":"CNCR-IT Co. Ltd,HangZhou P.R.CHINA","000EA4":"Certance Inc.","000EA5":"BLIP Systems","000EA6":"ASUSTek Computer Inc.","000EA7":"Endace Technology","000EA8":"United Technologists Europe Limited","000EA9":"Shanghai Xun Shi Communications Equipment Ltd Co.","000EAA":"Scalent Systems, Inc.","000EAB":"Cray Inc","000EAC":"Mintron Enterprise Co. Ltd","000EAD":"Metanoia Technologies, Inc.","000EAE":"Gawell Technologies Corp.","000EAF":"Castel","000EB0":"Solutions Radio BV","000EB1":"Newcotech Ltd","000EB2":"Micro-Research Finland Oy","000EB3":"Hewlett-Packard Company","000EB4":"Guangzhou Gaoke Communications Technology Co.Ltd","000EB5":"Ecastle Electronics Co. Ltd","000EB6":"Riverbed Technology, Inc.","000EB7":"Knovative, Inc.","000EB8":"Iiga Co. Ltd","000EB9":"HASHIMOTO Electronics Industry Co. Ltd","000EBA":"Hanmi Semiconductor Co. Ltd","000EBB":"Everbee Networks","000EBC":"Paragon Fidelity GmbH","000EBD":"Burdick, a Quinton Compny","000EBE":"B&B Electronics Manufacturing Co.","000EBF":"Remsdaq Limited","000EC0":"Nortel Networks","000EC1":"MYNAH Technologies","000EC2":"Lowrance Electronics, Inc.","000EC3":"Logic Controls, Inc.","000EC4":"Iskra Transmission d.d.","000EC5":"Digital Multitools Inc","000EC6":"Asix Electronics Corp.","000EC7":"Motorola Korea","000EC8":"Zoran Corporation","000EC9":"YOKO Technology Corp.","000ECA":"WTSS Inc","000ECB":"VineSys Technology","000ECC":"Tableau, LLC","000ECD":"Skov A/S","000ECE":"S.I.T.T.I. S.p.A.","000ECF":"PROFIBUS Nutzerorganisation e.V.","000ED0":"Privaris, Inc.","000ED1":"Osaka Micro Computer.","000ED2":"Filtronic plc","000ED3":"Epicenter, Inc.","000ED4":"Cresitt Industrie","000ED5":"CoPAN Systems Inc.","000ED6":"Cisco Systems Inc.","000ED7":"Cisco Systems Inc.","000ED8":"Positron Access Solutions Corp","000ED9":"Aksys Ltd","000EDA":"C-Tech United Corp.","000EDB":"XiNCOM Corp.","000EDC":"Tellion Inc.","000EDD":"Shure Incorporated","000EDE":"REMEC, Inc.","000EDF":"PLX Technology","000EE0":"Mcharge","000EE1":"ExtremeSpeed Inc.","000EE2":"Custom Engineering","000EE3":"Chiyu Technology Co. Ltd","000EE4":"BOE Technology Group Co. Ltd","000EE5":"bitWallet, Inc.","000EE6":"Adimos Systems Ltd","000EE7":"AAC Electronics Corp.","000EE8":"Zioncom Electronics (Shenzhen) Ltd","000EE9":"WayTech Development, Inc.","000EEA":"Shadong Luneng Jicheng Electronics,Co. Ltd","000EEB":"Sandmartin(zhong shan)Electronics Co. Ltd","000EEC":"Orban","000EED":"Nokia Danmark A/S","000EEE":"Muco Industrie BV","000EEF":"Private","000EF0":"Festo AG & Co. KG","000EF1":"Ezquest Inc.","000EF2":"Infinico Corporation","000EF3":"Smarthome","000EF4":"Kasda Networks Inc","000EF5":"iPAC Technology Co. Ltd","000EF6":"E-TEN Information Systems Co. Ltd","000EF7":"Vulcan Portals Inc","000EF8":"SBC ASI","000EF9":"REA Elektronik GmbH","000EFA":"Optoway Technology Incorporation","000EFB":"Macey Enterprises","000EFC":"JTAG Technologies B.V.","000EFD":"Fujinon Corporation","000EFE":"EndRun Technologies LLC","000EFF":"Megasolution,Inc.","000F00":"Legra Systems, Inc.","000F01":"Digitalks Inc","000F02":"Digicube Technology Co. Ltd","000F03":"CoM&C Co. Ltd","000F04":"cim-usa Inc","000F05":"3B System Inc.","000F06":"Nortel Networks","000F07":"Mangrove Systems, Inc.","000F08":"Indagon Oy","000F09":"Private","000F0A":"Clear Edge Networks","000F0B":"Kentima Technologies AB","000F0C":"Synchronic Engineering","000F0D":"Hunt Electronic Co. Ltd","000F0E":"WaveSplitter Technologies, Inc.","000F0F":"Real ID Technology Co. Ltd","000F10":"RDM Corporation","000F11":"Prodrive B.V.","000F12":"Panasonic Europe Ltd","000F13":"Nisca Corporation","000F14":"Mindray Co. Ltd","000F15":"Kjaerulff1 A/S","000F16":"JAY HOW Technology Co.,","000F17":"Insta Elektro GmbH","000F18":"Industrial Control Systems","000F19":"Boston Scientific","000F1A":"Gaming Support B.V.","000F1B":"Ego Systems Inc.","000F1C":"DigitAll World Co. Ltd","000F1D":"Cosmo Techs Co. Ltd","000F1E":"Chengdu KT Electric Co.Of High & New Technology","000F1F":"Dell Inc.","000F20":"Hewlett-Packard Company","000F21":"Scientific Atlanta, Inc","000F22":"Helius, Inc.","000F23":"Cisco Systems Inc.","000F24":"Cisco Systems Inc.","000F25":"AimValley B.V.","000F26":"WorldAccxx LLC","000F27":"TEAL Electronics, Inc.","000F28":"Itronix Corporation","000F29":"Augmentix Corporation","000F2A":"Cableware Electronics","000F2B":"Greenbell Systems","000F2C":"Uplogix, Inc.","000F2D":"Chung-Hsin Electric & Machinery MFG.Corp.","000F2E":"Megapower International Corp.","000F2F":"W-Linx Technology Co. Ltd","000F30":"Raza Microelectronics Inc","000F31":"Allied Vision Technologies Canada Inc","000F32":"Lootom Telcovideo Network Wuxi Co Ltd","000F33":"DUALi Inc.","000F34":"Cisco Systems Inc.","000F35":"Cisco Systems Inc.","000F36":"Accurate Techhnologies, Inc.","000F37":"Xambala Incorporated","000F38":"Netstar","000F39":"Iris Sensors","000F3A":"Hisharp","000F3B":"Fuji System Machines Co. Ltd","000F3C":"Endeleo Limited","000F3D":"D-Link Corporation","000F3E":"CardioNet, Inc","000F3F":"Big Bear Networks","000F40":"Optical Internetworking Forum","000F41":"Zipher Ltd","000F42":"Xalyo Systems","000F43":"Wasabi Systems Inc.","000F44":"Tivella Inc.","000F45":"Stretch, Inc.","000F46":"Sinar AG","000F47":"Robox SPA","000F48":"Polypix Inc.","000F49":"Northover Solutions Limited","000F4A":"Kyushu-kyohan Co. Ltd","000F4B":"Oracle Corporation","000F4C":"Elextech Inc","000F4D":"TalkSwitch","000F4E":"Cellink","000F4F":"PCS Systemtechnik GmbH","000F50":"StreamScale Limited","000F51":"Azul Systems, Inc.","000F52":"YORK Refrigeration, Marine & Controls","000F53":"Solarflare Communications Inc","000F54":"Entrelogic Corporation","000F55":"Datawire Communication Networks Inc.","000F56":"Continuum Photonics Inc","000F57":"CABLELOGIC Co. Ltd","000F58":"Adder Technology Limited","000F59":"Phonak AG","000F5A":"Peribit Networks","000F5B":"Delta Information Systems, Inc.","000F5C":"Day One Digital Media Limited","000F5D":"Genexis BV","000F5E":"Veo","000F5F":"Nicety Technologies Inc. (NTS)","000F60":"Lifetron Co. Ltd","000F61":"Hewlett-Packard Company","000F62":"Alcatel Bell Space N.V.","000F63":"Obzerv Technologies","000F64":"D&R Electronica Weesp BV","000F65":"icube Corp.","000F66":"Cisco-Linksys LLC","000F67":"West Instruments","000F68":"Vavic Network Technology, Inc.","000F69":"SEW Eurodrive GmbH & Co. KG","000F6A":"Nortel Networks","000F6B":"GateWare Communications GmbH","000F6C":"ADDI-DATA GmbH","000F6D":"Midas Engineering","000F6E":"BBox","000F6F":"FTA Communication Technologies","000F70":"Wintec Industries, Inc.","000F71":"Sanmei Electronics Co. Ltd","000F72":"Sandburst","000F73":"RS Automation Co. Ltd","000F74":"Qamcom Technology AB","000F75":"First Silicon Solutions","000F76":"Digital Keystone, Inc.","000F77":"Dentum Co. Ltd","000F78":"Datacap Systems Inc","000F79":"Bluetooth Interest Group Inc.","000F7A":"BeiJing NuQX Technology Co. Ltd","000F7B":"Arce Sistemas, S.A.","000F7C":"ACTi Corporation","000F7D":"Xirrus","000F7E":"Ablerex Electronics Co. Ltd","000F7F":"UBSTORAGE Co. Ltd","000F80":"Trinity Security Systems,Inc.","000F81":"PAL Pacific Inc.","000F82":"Mortara Instrument, Inc.","000F83":"Brainium Technologies Inc.","000F84":"Astute Networks, Inc.","000F85":"ADDO-Japan Corporation","000F86":"BlackBerry RTS","000F87":"Maxcess International","000F88":"AMETEK, Inc.","000F89":"Winnertec System Co. Ltd","000F8A":"WideView","000F8B":"Orion MultiSystems Inc","000F8C":"Gigawavetech Pte Ltd","000F8D":"FAST TV-Server AG","000F8E":"Dongyang Telecom Co. Ltd","000F8F":"Cisco Systems Inc.","000F90":"Cisco Systems Inc.","000F91":"Aerotelecom Co. Ltd","000F92":"Microhard Systems Inc.","000F93":"Landis+Gyr Ltd","000F94":"Genexis BV","000F95":"ELECOM Co. Ltd Laneed Division","000F96":"Telco Systems, Inc.","000F97":"Avanex Corporation","000F98":"Avamax Co. Ltd","000F99":"APAC opto Electronics Inc.","000F9A":"Synchrony, Inc.","000F9B":"Ross Video Limited","000F9C":"Panduit Corp","000F9D":"DisplayLink (UK) Ltd","000F9E":"Murrelektronik GmbH","000F9F":"ARRIS Group, Inc.","000FA0":"Canon Korea Business Solutions Inc.","000FA1":"Gigabit Systems Inc.","000FA2":"2xWireless","000FA3":"Alpha Networks Inc.","000FA4":"Sprecher Automation GmbH","000FA5":"BWA Technology GmbH","000FA6":"S2 Security Corporation","000FA7":"Raptor Networks Technology","000FA8":"Photometrics, Inc.","000FA9":"PC Fabrik","000FAA":"Nexus Technologies","000FAB":"Kyushu Electronics Systems Inc.","000FAC":"IEEE 802.11","000FAD":"FMN Communications GmbH","000FAE":"E2O Communications","000FAF":"Dialog Inc.","000FB0":"Compal Electronics, Inc.","000FB1":"Cognio Inc.","000FB2":"Broadband Pacenet (India) Pvt. Ltd","000FB3":"Actiontec Electronics, Inc","000FB4":"Timespace Technology","000FB5":"Netgear","000FB6":"Europlex Technologies","000FB7":"Cavium","000FB8":"CallURL Inc.","000FB9":"Adaptive Instruments","000FBA":"Tevebox AB","000FBB":"Nokia Siemens Networks GmbH & Co. KG.","000FBC":"Onkey Technologies, Inc.","000FBD":"MRV Communications (Networks) Ltd","000FBE":"e-w/you Inc.","000FBF":"DGT Sp. z o.o.","000FC0":"DELCOMp","000FC1":"WAVE Corporation","000FC2":"Uniwell Corporation","000FC3":"PalmPalm Technology, Inc.","000FC4":"NST Co. Ltd","000FC5":"KeyMed Ltd","000FC6":"Eurocom Industries A/S","000FC7":"Dionica R&D Ltd","000FC8":"Chantry Networks","000FC9":"Allnet GmbH","000FCA":"A-JIN Techline Co Ltd","000FCB":"3Com Ltd","000FCC":"ARRIS Group, Inc.","000FCD":"Nortel Networks","000FCE":"Kikusui Electronics Corp.","000FCF":"DataWind Research","000FD0":"Astri","000FD1":"Applied Wireless Identifications Group, Inc.","000FD2":"EWA Technologies, Inc.","000FD3":"Digium","000FD4":"Soundcraft","000FD5":"Schwechat - RISE","000FD6":"Sarotech Co. Ltd","000FD7":"Harman Music Group","000FD8":"Force, Inc.","000FD9":"FlexDSL Telecommunications AG","000FDA":"Yazaki Corporation","000FDB":"Westell Technologies Inc.","000FDC":"Ueda Japan Radio Co. Ltd","000FDD":"Sordin AB","000FDE":"Sony Mobile Communications AB","000FDF":"SOLOMON Technology Corp.","000FE0":"NComputing Co. Ltd","000FE1":"ID Digital Corporation","000FE2":"Hangzhou H3C Technologies Co., Limited","000FE3":"Damm Cellular Systems A/S","000FE4":"Pantech Co. Ltd","000FE5":"Mercury Security Corporation","000FE6":"MBTech Systems, Inc.","000FE7":"Lutron Electronics Co., Inc.","000FE8":"Lobos, Inc.","000FE9":"GW Technologies Co. Ltd","000FEA":"Giga-Byte Technology Co. Ltd","000FEB":"Cylon Controls","000FEC":"ARKUS Inc.","000FED":"Anam Electronics Co. Ltd","000FEE":"XTec, Incorporated","000FEF":"Thales e-Transactions GmbH","000FF0":"Sunray Co. Ltd","000FF1":"nex-G Systems Pte.Ltd","000FF2":"Loud Technologies Inc.","000FF3":"Jung Myoung Communications&Technology","000FF4":"Guntermann & Drunck GmbH","000FF5":"GN&S Company","000FF6":"Darfon Lighting Corp","000FF7":"Cisco Systems Inc.","000FF8":"Cisco Systems Inc.","000FF9":"Valcretec, Inc.","000FFA":"Optinel Systems, Inc.","000FFB":"Nippon Denso Industry Co. Ltd","000FFC":"Merit Li-Lin Ent.","000FFD":"Glorytek Network Inc.","000FFE":"G-PRO Computer","000FFF":"Control4","001000":"Cable Television Laboratories, Inc.","001001":"Citel","001002":"Actia","001003":"Imatron, Inc.","001004":"THE Brantley Coile Company,Inc","001005":"UEC Commercial","001006":"Thales Contact Solutions Ltd","001007":"Cisco Systems Inc.","001008":"Vienna Systems Corporation","001009":"Horanet","00100A":"Williams Communications Group","00100B":"Cisco Systems Inc.","00100C":"ITO Co. Ltd","00100D":"Cisco Systems Inc.","00100E":"Micro Linear Coporation","00100F":"Industrial CPU Systems","001010":"Initio Corporation","001011":"Cisco Systems Inc.","001012":"Processor Systems (I) PVT Ltd","001013":"Kontron America, Inc.","001014":"Cisco Systems Inc.","001015":"OOmon Inc.","001016":"T.Sqware","001017":"Bosch Access Systems GmbH","001018":"Broadcom","001019":"SIRONA DENTAL SysTEMS GmbH & Co. KG","00101A":"PictureTel Corp.","00101B":"Cornet Technology, Inc.","00101C":"OHM Technologies Intl, LLC","00101D":"Winbond Electronics Corp.","00101E":"Matsushita Electronic Instruments Corp.","00101F":"Cisco Systems Inc.","001020":"Hand Held Products Inc","001021":"Encanto Networks, Inc.","001022":"SatCom Media Corporation","001023":"Network Equipment Technologies","001024":"Nagoya Electric Works Co. Ltd","001025":"Grayhill, Inc","001026":"Accelerated Networks, Inc.","001027":"L-3 Communications East","001028":"Computer Technica, Inc.","001029":"Cisco Systems Inc.","00102A":"ZF Microsystems, Inc.","00102B":"Umax Data Systems, Inc.","00102C":"Lasat Networks A/S","00102D":"Hitachi Software Engineering","00102E":"Network Systems & Technologies PVT. Ltd","00102F":"Cisco Systems Inc.","001030":"EION Inc.","001031":"Objective Communications, Inc.","001032":"Alta Technology","001033":"Accesslan Communications, Inc.","001034":"GNP Computers","001035":"Elitegroup Computer Systems Co. Ltd","001036":"Inter-TEL Integrated Systems","001037":"CYQ've Technology Co. Ltd","001038":"Micro Research Institute, Inc.","001039":"Vectron Systems AG","00103A":"Diamond Network Tech","00103B":"Hippi Networking Forum","00103C":"IC Ensemble, Inc.","00103D":"Phasecom Ltd","00103E":"Netschools Corporation","00103F":"Tollgrade Communications, Inc.","001040":"Intermec Corporation","001041":"Bristol Babcock, Inc.","001042":"Alacritech, Inc.","001043":"A2 Corporation","001044":"InnoLabs Corporation","001045":"Nortel Networks","001046":"Alcorn Mcbride Inc.","001047":"Echo Eletric Co. Ltd","001048":"Htrc Automation, Inc.","001049":"ShoreTel, Inc","00104A":"The Parvus Corporation","00104B":"3Com Corporation","00104C":"Teledyne LeCroy, Inc","00104D":"Surtec Industries, Inc.","00104E":"Ceologic","00104F":"Oracle Corporation","001050":"Rion Co. Ltd","001051":"Cmicro Corporation","001052":"Mettler-Toledo (Albstadt) GmbH","001053":"Computer Technology Corp.","001054":"Cisco Systems Inc.","001055":"Fujitsu Microelectronics, Inc.","001056":"Sodick Co. Ltd","001057":"Rebel.com, Inc.","001058":"ArrowPoint Communications","001059":"Diablo Research Co. LLC","00105A":"3Com Corporation","00105B":"NET Insight AB","00105C":"Quantum Designs (H.K.) Ltd","00105D":"Draeger Medical","00105E":"Spirent plc, Service Assurance Broadband","00105F":"Zodiac Data Systems","001060":"Billionton Systems, Inc.","001061":"Hostlink Corp.","001062":"NX Server, Ilnc.","001063":"Starguide Digital Networks","001064":"Dnpg, LLC","001065":"Radyne Corporation","001066":"Advanced Control Systems, Inc.","001067":"Ericsson","001068":"Comos Telecom","001069":"Helioss Communications, Inc.","00106A":"Digital Microwave Corporation","00106B":"Sonus Networks, Inc.","00106C":"EDNT GmbH","00106D":"Axxcelera Broadband Wireless","00106E":"Tadiran CoM. Ltd","00106F":"Trenton Technology Inc.","001070":"Caradon Trend Ltd","001071":"Advanet Inc.","001072":"GVN Technologies, Inc.","001073":"Technobox, Inc.","001074":"Aten International Co. Ltd","001075":"Segate Technology LLC","001076":"EUREM GmbH","001077":"SAF Drive Systems Ltd","001078":"Nuera Communications, Inc.","001079":"Cisco Systems Inc.","00107A":"AmbiCom, Inc.","00107B":"Cisco Systems Inc.","00107C":"P-CoM, Inc.","00107D":"Aurora Communications Ltd","00107E":"BACHMANN ELECTRONIC GmbH","00107F":"Crestron Electronics, Inc.","001080":"Metawave Communications","001081":"DPS, Inc.","001082":"JNA Telecommunications Limited","001083":"Hewlett-Packard Company","001084":"K-BOT Communications","001085":"Polaris Communications, Inc.","001086":"ATTO Technology, Inc.","001087":"Xstreamis PLC","001088":"American Networks Inc.","001089":"WebSonic","00108A":"TeraLogic, Inc.","00108B":"Laseranimation Sollinger GmbH","00108C":"Fujitsu Services Ltd","00108D":"Johnson Controls, Inc.","00108E":"HUGH SYMONS CoNCEPT Technologies Ltd","00108F":"Raptor Systems","001090":"Cimetrics, Inc.","001091":"NO Wires Needed BV","001092":"Netcore Inc.","001093":"CMS Computers Ltd","001094":"Performance Analysis Broadband, Spirent plc","001095":"Thomson Inc.","001096":"Tracewell Systems, Inc.","001097":"WinNet Metropolitan Communications Systems, Inc.","001098":"Starnet Technologies, Inc.","001099":"InnoMedia, Inc.","00109A":"Netline","00109B":"Emulex Corporation","00109C":"M-System Co. Ltd","00109D":"Clarinet Systems, Inc.","00109E":"Aware, Inc.","00109F":"Pavo, Inc.","0010A0":"Innovex Technologies, Inc.","0010A1":"Kendin Semiconductor, Inc.","0010A2":"TNS","0010A3":"Omnitronix, Inc.","0010A4":"Xircom","0010A5":"Oxford Instruments","0010A6":"Cisco Systems Inc.","0010A7":"Unex Technology Corporation","0010A8":"Reliance Computer Corp.","0010A9":"Adhoc Technologies","0010AA":"MEDIA4, Inc.","0010AB":"Koito Electric Industries Ltd","0010AC":"Imci Technologies","0010AD":"Softronics USB, Inc.","0010AE":"Shinko Electric Industries Co.","0010AF":"TAC Systems, Inc.","0010B0":"Meridian Technology Corp.","0010B1":"FOR-A Co. Ltd","0010B2":"Coactive Aesthetics","0010B3":"Nokia Multimedia Terminals","0010B4":"Atmosphere Networks","0010B5":"Accton Technology Corp","0010B6":"Entrata Communications Corp.","0010B7":"Coyote Technologies, LLC","0010B8":"Ishigaki Computer System Co.","0010B9":"Maxtor Corp.","0010BA":"Martinho-Davis Systems, Inc.","0010BB":"Data & Information Technology","0010BC":"Aastra Telecom","0010BD":"THE Telecommunication Technology Committee (TTC)","0010BE":"March Networks Corporation","0010BF":"InterAir Wireless","0010C0":"ARMA, Inc.","0010C1":"OI Electric Co. Ltd","0010C2":"Willnet, Inc.","0010C3":"CSI-Control Systems","0010C4":"Media Global Links Co. Ltd","0010C5":"Protocol Technologies, Inc.","0010C6":"Universal Global Scientific Industrial Co. Ltd","0010C7":"Data Transmission Network","0010C8":"Communications Electronics Security Group","0010C9":"Mitsubishi Electronics Logistic Support Co.","0010CA":"Telco Systems, Inc.","0010CB":"Facit K.K.","0010CC":"CLP CoMPUTER LOGISTIK PLANUNG GmbH","0010CD":"Interface Concept","0010CE":"Volamp Ltd","0010CF":"Fiberlane Communications","0010D0":"Witcom Ltd","0010D1":"Top Layer Networks, Inc.","0010D2":"Nitto Tsushinki Co. Ltd","0010D3":"Grips Electronic GmbH","0010D4":"Storage Computer Corporation","0010D5":"Imasde Canarias, S.A.","0010D6":"Exelis","0010D7":"Argosy Research Inc.","0010D8":"Calista","0010D9":"IBM Japan, Fujisawa MT+D","0010DA":"Kollmorgen Corp","0010DB":"Juniper Networks","0010DC":"Micro-Star International","0010DD":"Enable Semiconductor, Inc.","0010DE":"International Datacasting Corporation","0010DF":"Rise Computer Inc.","0010E0":"Oracle Corporation","0010E1":"S.I. Tech, Inc.","0010E2":"ArrayComm, Inc.","0010E3":"Hewlett-Packard Company","0010E4":"NSI Corporation","0010E5":"Solectron Texas","0010E6":"Applied Intelligent Systems, Inc.","0010E7":"Breezecom Ltd","0010E8":"Telocity, Incorporated","0010E9":"Raidtec Ltd","0010EA":"Adept Technology","0010EB":"Selsius Systems, Inc.","0010EC":"Rpcg, LLC","0010ED":"Sundance Technology, Inc.","0010EE":"CTI Products, Inc.","0010EF":"Dbtel Incorporated","0010F0":"RITTAL-WERK RUDOLF LOH GmbH & Co.","0010F1":"I-O Corporation","0010F2":"Antec","0010F3":"Nexcom International Co. Ltd","0010F4":"Vertical Communications","0010F5":"Amherst Systems, Inc.","0010F6":"Cisco Systems Inc.","0010F7":"IRIICHI TECHNOLOGIES Inc.","0010F8":"Texio Technology Corporation","0010F9":"Unique Systems, Inc.","0010FA":"Apple","0010FB":"Zida Technologies Limited","0010FC":"Broadband Networks, Inc.","0010FD":"Cocom A/S","0010FE":"Digital Equipment Corporation","0010FF":"Cisco Systems Inc.","001100":"Schneider Electric","001101":"CET Technologies Pte Ltd","001102":"Aurora Multimedia Corp.","001103":"kawamura electric Inc.","001104":"Telexy","001105":"Sunplus Technology Co. Ltd","001106":"Siemens NV (Belgium)","001107":"RGB Networks Inc.","001108":"Orbital Data Corporation","001109":"Micro-Star International","00110A":"Hewlett-Packard Company","00110B":"Franklin Technology Systems","00110C":"Atmark Techno, Inc.","00110D":"SANBlaze Technology, Inc.","00110E":"Tsurusaki Sealand Transportation Co. Ltd","00110F":"netplat,Inc.","001110":"Maxanna Technology Co. Ltd","001111":"Intel Corporation","001112":"Honeywell CMSS","001113":"Fraunhofer FOKUS","001114":"EverFocus Electronics Corp.","001115":"EPIN Technologies, Inc.","001116":"Coteau Vert Co. Ltd","001117":"Cesnet","001118":"BLX IC Design Corp. Ltd","001119":"Solteras, Inc.","00111A":"ARRIS Group, Inc.","00111B":"Targa Systems Div L-3 Communications","00111C":"Pleora Technologies Inc.","00111D":"Hectrix Limited","00111E":"EPSG (Ethernet Powerlink Standardization Group)","00111F":"Doremi Labs, Inc.","001120":"Cisco Systems Inc.","001121":"Cisco Systems Inc.","001122":"CIMSYS Inc","001123":"Appointech, Inc.","001124":"Apple","001125":"IBM Corp","001126":"Venstar Inc.","001127":"TASI, Inc","001128":"Streamit","001129":"Paradise Datacom Ltd","00112A":"Niko NV","00112B":"NetModule AG","00112C":"IZT GmbH","00112D":"iPulse Systems","00112E":"Ceicom","00112F":"ASUSTek Computer Inc.","001130":"Allied Telesis (Hong Kong) Ltd","001131":"Unatech. Co. Ltd","001132":"Synology Incorporated","001133":"Siemens Austria SIMEA","001134":"MediaCell, Inc.","001135":"Grandeye Ltd","001136":"Goodrich Sensor Systems","001137":"Aichi Electric Co. Ltd","001138":"Taishin Co. Ltd","001139":"STOEBER ANTRIEBSTECHNIK GmbH + Co. KG.","00113A":"Shinboram","00113B":"Micronet Communications Inc.","00113C":"Micronas GmbH","00113D":"KN Soltec Co. Ltd","00113E":"JL Corporation","00113F":"Alcatel DI","001140":"Nanometrics Inc.","001141":"GoodMan Corporation","001142":"e-SMARTCOM Inc.","001143":"Dell Inc.","001144":"Assurance Technology Corp","001145":"ValuePoint Networks","001146":"Telecard-Pribor Ltd","001147":"Secom-Industry Co.Ltd","001148":"Prolon Control Systems","001149":"Proliphix Inc.","00114A":"KAYABA IndUSTRY Co,.Ltd","00114B":"Francotyp-Postalia GmbH","00114C":"caffeina applied research Ltd","00114D":"Atsumi Electric Co. Ltd","00114E":"690885 Ontario Inc.","00114F":"US Digital Television, Inc","001150":"Belkin Corporation","001151":"Mykotronx","001152":"Eidsvoll Electronics AS","001153":"Trident Tek, Inc.","001154":"Webpro Technologies Inc.","001155":"Sevis Systems","001156":"Pharos Systems NZ","001157":"Oki Electric Industry Co. Ltd","001158":"Nortel Networks","001159":"Matisse Networks Inc","00115A":"Ivoclar Vivadent AG","00115B":"Elitegroup Computer Systems Co. Ltd","00115C":"Cisco Systems Inc.","00115D":"Cisco Systems Inc.","00115E":"ProMinent Dosiertechnik GmbH","00115F":"ITX Security Co. Ltd","001160":"ARTDIO Company Co. Ltd","001161":"NetStreams, LLC","001162":"Star Micronics Co. Ltd","001163":"System SPA Dept. Electronics","001164":"ACARD Technology Corp.","001165":"ZNYX Networks, Inc.","001166":"Taelim Electronics Co. Ltd","001167":"Integrated System Solution Corp.","001168":"HomeLogic LLC","001169":"EMS Satcom","00116A":"Domo Ltd","00116B":"Digital Data Communications Asia Co. Ltd","00116C":"Nanwang Multimedia Inc. Ltd","00116D":"American Time and Signal","00116E":"Peplink International Ltd","00116F":"Netforyou Co. Ltd","001170":"GSC SRL","001171":"DEXTER Communications, Inc.","001172":"Cotron Corporation","001173":"SMART Storage Systems","001174":"Mojo Networks, Inc.","001175":"Intel Corporation","001176":"Intellambda Systems, Inc.","001177":"Coaxial Networks, Inc.","001178":"Chiron Technology Ltd","001179":"Singular Technology Co. Ltd","00117A":"Singim International Corp.","00117B":"B?chi Labortechnik AG","00117C":"e-zy.net","00117D":"ZMD America, Inc.","00117E":"Midmark Corp","00117F":"Neotune Information Technology Corporation,.Ltd","001180":"ARRIS Group, Inc.","001181":"InterEnergy Co.Ltd,","001182":"IMI Norgren Ltd","001183":"Datalogic ADC, Inc.","001184":"Humo Laboratory Ltd","001185":"Hewlett-Packard Company","001186":"Prime Systems, Inc.","001187":"Category Solutions, Inc","001188":"Enterasys","001189":"Aerotech Inc","00118A":"Viewtran Technology Limited","00118B":"Alcatel-Lucent Enterprise","00118C":"Missouri Department Of Transportation","00118D":"Hanchang System Corp.","00118E":"Halytech Mace","00118F":"Eutech Instruments PTE. Ltd","001190":"Digital Design Corporation","001191":"CTS-Clima Temperatur Systeme GmbH","001192":"Cisco Systems Inc.","001193":"Cisco Systems Inc.","001194":"Chi Mei Communication Systems, Inc.","001195":"D-Link Corporation","001196":"Actuality Systems, Inc.","001197":"Monitoring Technologies Limited","001198":"Prism Media Products Limited","001199":"2wcom Systems GmbH","00119A":"Alkeria srl","00119B":"Telesynergy Research Inc.","00119C":"EP&T Energy","00119D":"Diginfo Technology Corporation","00119E":"Solectron Brazil","00119F":"Nokia Danmark A/S","0011A0":"Vtech Engineering Canada Ltd","0011A1":"Vision Netware Co. Ltd","0011A2":"Manufacturing Technology Inc","0011A3":"LanReady Technologies Inc.","0011A4":"JStream Technologies Inc.","0011A5":"Fortuna Electronic Corp.","0011A6":"Sypixx Networks","0011A7":"Infilco Degremont Inc.","0011A8":"Quest Technologies","0011A9":"MOIMSTONE Co. Ltd","0011AA":"Uniclass Technology, Co. Ltd","0011AB":"Trustable Technology Co. Ltd","0011AC":"Simtec Electronics","0011AD":"Shanghai Ruijie Technology","0011AE":"ARRIS Group, Inc.","0011AF":"Medialink-i,Inc","0011B0":"Fortelink Inc.","0011B1":"BlueExpert Technology Corp.","0011B2":"2001 Technology Inc.","0011B3":"Yoshimiya Co. Ltd","0011B4":"Westermo Teleindustri AB","0011B5":"Shenzhen Powercom Co. Ltd","0011B6":"Open Systems International","0011B7":"Octalix B.V.","0011B8":"Liebherr - Elektronik GmbH","0011B9":"Inner Range Pty. Ltd","0011BA":"Elexol Pty Ltd","0011BB":"Cisco Systems Inc.","0011BC":"Cisco Systems Inc.","0011BD":"Bombardier Transportation","0011BE":"AGP Telecom Co. Ltd","0011BF":"AESYS S.p.A.","0011C0":"Aday Technology Inc","0011C1":"4P Mobile Data Processing","0011C2":"United Fiber Optic Communication","0011C3":"Transceiving System Technology Corporation","0011C4":"Terminales de Telecomunicacion Terrestre, S.L.","0011C5":"TEN Technology","0011C6":"Seagate Technology","0011C7":"Raymarine UK Ltd","0011C8":"Powercom Co. Ltd","0011C9":"MTT Corporation","0011CA":"Long Range Systems, Inc.","0011CB":"Jacobsons AB","0011CC":"Guangzhou Jinpeng Group Co. Ltd","0011CD":"Axsun Technologies","0011CE":"Ubisense Limited","0011CF":"Thrane & Thrane A/S","0011D0":"Tandberg Data ASA","0011D1":"Soft Imaging System GmbH","0011D2":"Perception Digital Ltd","0011D3":"NextGenTel Holding ASA","0011D4":"NetEnrich, Inc","0011D5":"Hangzhou Sunyard System Engineering Co. Ltd","0011D6":"HandEra, Inc.","0011D7":"eWerks Inc","0011D8":"ASUSTek Computer Inc.","0011D9":"TiVo","0011DA":"Vivaas Technology Inc.","0011DB":"Land-Cellular Corporation","0011DC":"Glunz & Jensen","0011DD":"FROMUS TEC. Co. Ltd","0011DE":"Eurilogic","0011DF":"Current Energy","0011E0":"U-MEDIA Communications, Inc.","0011E1":"Arcelik A.S","0011E2":"Hua Jung Components Co. Ltd","0011E3":"Thomson, Inc.","0011E4":"Danelec Electronics A/S","0011E5":"KCodes Corporation","0011E6":"Scientific Atlanta","0011E7":"WORLDSAT - Texas de France","0011E8":"Tixi.com","0011E9":"Starnex Co. Ltd","0011EA":"IWICS Inc.","0011EB":"Innovative Integration","0011EC":"Avix Inc.","0011ED":"802 Global","0011EE":"Estari, Inc.","0011EF":"Conitec Datensysteme GmbH","0011F0":"Wideful Limited","0011F1":"QinetiQ Ltd","0011F2":"Institute Of Network Technologies","0011F3":"NeoMedia Europe AG","0011F4":"woori-net","0011F5":"Askey Computer Corp","0011F6":"Asia Pacific Microsystems , Inc.","0011F7":"Shenzhen Forward Industry Co. Ltd","0011F8":"AIRAYA Corp","0011F9":"Nortel Networks","0011FA":"Rane Corporation","0011FB":"Heidelberg Engineering GmbH","0011FC":"HARTING Electronics GmbH","0011FD":"Korg Inc.","0011FE":"Keiyo System Research, Inc.","0011FF":"Digitro Tecnologia Ltda","001200":"Cisco Systems Inc.","001201":"Cisco Systems Inc.","001202":"Decrane Aerospace - Audio International Inc.","001203":"ActivNetworks","001204":"u10 Networks, Inc.","001205":"Terrasat Communications, Inc.","001206":"iQuest (NZ) Ltd","001207":"Head Strong International Limited","001208":"Gantner Instruments GmbH","001209":"Fastrax Ltd","00120A":"Emerson Climate Technologies GmbH","00120B":"Chinasys Technologies Limited","00120C":"CE-Infosys Pte Ltd","00120D":"Advanced Telecommunication Technologies, Inc.","00120E":"AboCom","00120F":"IEEE 802.3","001210":"WideRay Corp","001211":"Protechna Herbst GmbH & Co. KG","001212":"PLUS Corporation","001213":"Metrohm AG","001214":"Koenig & Bauer AG","001215":"iStor Networks, Inc.","001216":"ICP Internet Communication Payment AG","001217":"Cisco-Linksys LLC","001218":"ARUZE Corporation","001219":"General Datacomm LLC","00121A":"Techno Soft Systemnics Inc.","00121B":"Sound Devices, LLC","00121C":"Parrot SA","00121D":"Netfabric Corporation","00121E":"Juniper Networks","00121F":"Harding Instruments","001220":"Cadco Systems","001221":"B.Braun Melsungen AG","001222":"Skardin (UK) Ltd","001223":"Pixim","001224":"NexQL Corporation","001225":"ARRIS Group, Inc.","001226":"Japan Direx Corporation","001227":"Franklin Electric Co., Inc.","001228":"Data Ltd","001229":"BroadEasy Technologies Co. Ltd","00122A":"VTech Telecommunications Ltd","00122B":"Virbiage Pty Ltd","00122C":"Soenen Controls N.V.","00122D":"SiNett Corporation","00122E":"Signal Technology - AISD","00122F":"Sanei Electric Inc.","001230":"Picaso Infocommunication Co. Ltd","001231":"Motion Control Systems, Inc.","001232":"LeWiz Communications Inc.","001233":"JRC TOKKI Co. Ltd","001234":"Camille Bauer","001235":"Andrew Corporation","001236":"ConSentry Networks","001237":"Texas Instruments","001238":"SetaBox Technology Co. Ltd","001239":"S Net Systems Inc.","00123A":"Posystech Inc., Co.","00123B":"KeRo Systems ApS","00123C":"Second Rule LLC","00123D":"GES Co Ltd","00123E":"ERUNE technology Co. Ltd","00123F":"Dell Inc.","001240":"Amoi Electronics Co. Ltd","001241":"a2i marketing center","001242":"Millennial Net","001243":"Cisco Systems Inc.","001244":"Cisco Systems Inc.","001245":"Zellweger Analytics, Inc.","001246":"T.O.M Technology Inc..","001247":"Samsung Electronics Co. Ltd","001248":"Dell EMC","001249":"Delta Elettronica S.p.A.","00124A":"Dedicated Devices, Inc.","00124B":"Texas Instruments","00124C":"BBWM Corporation","00124D":"Inducon BV","00124E":"XAC Automation Corp.","00124F":"Pentair Thermal Management","001250":"Tokyo Aircaft Instrument Co. Ltd","001251":"Silink","001252":"Citronix, LLC","001253":"AudioDev AB","001254":"Spectra Technologies Holdings Company Ltd","001255":"NetEffect Incorporated","001256":"LG Information & Comm.","001257":"LeapComm Communication Technologies Inc.","001258":"Activis Polska","001259":"Thermo Electron Karlsruhe","00125A":"Microsoft Corporation","00125B":"Kaimei Electroni","00125C":"Green Hills Software, Inc.","00125D":"CyberNet Inc.","00125E":"Caen","00125F":"AWIND Inc.","001260":"Stanton Magnetics,Inc.","001261":"Adaptix, Inc","001262":"Nokia Danmark A/S","001263":"Data Voice Technologies GmbH","001264":"daum electronic GmbH","001265":"Enerdyne Technologies, Inc.","001266":"Swisscom Hospitality Services SA","001267":"Panasonic Corporation","001268":"IPS d.o.o.","001269":"Value Electronics","00126A":"OPTOELECTRONICS Co. Ltd","00126B":"Ascalade Communications Limited","00126C":"Visonic Technologies 1993 Ltd","00126D":"University Of California, Berkeley","00126E":"Seidel Elektronik GmbH Nfg.KG","00126F":"Rayson Technology Co. Ltd","001270":"NGES Denro Systems","001271":"Measurement Computing Corp","001272":"Redux Communications Ltd","001273":"Stoke Inc","001274":"NIT lab","001275":"Sentilla Corporation","001276":"CG Power Systems Ireland Limited","001277":"Korenix Technologies Co. Ltd","001278":"International Bar Code","001279":"Hewlett-Packard Company","00127A":"Sanyu Industry Co. Ltd","00127B":"VIA Networking Technologies, Inc.","00127C":"Swegon AB","00127D":"MobileAria","00127E":"Digital Lifestyles Group, Inc.","00127F":"Cisco Systems Inc.","001280":"Cisco Systems Inc.","001281":"March Networks S.p.A.","001282":"Qovia","001283":"Nortel Networks","001284":"Lab33 Srl","001285":"Gizmondo Europe Ltd","001286":"Endevco Corp","001287":"Digital Everywhere Unterhaltungselektronik GmbH","001288":"2Wire Inc.","001289":"Advance Sterilization Products","00128A":"ARRIS Group, Inc.","00128B":"Sensory Networks Inc","00128C":"Woodward Governor","00128D":"STB Datenservice GmbH","00128E":"Q-Free ASA","00128F":"Montilio","001290":"KYOWA Electric & Machinery Corp.","001291":"KWS Computersysteme GmbH","001292":"Griffin Technology","001293":"GE Energy","001294":"Sumitomo Electric Device Innovations, Inc","001295":"Aiware Inc.","001296":"Addlogix","001297":"O2Micro, Inc.","001298":"Mico Electric(Shenzhen) Limited","001299":"Ktech Telecommunications Inc","00129A":"IRT Electronics Pty Ltd","00129B":"E2S Electronic Engineering Solutions, S.L.","00129C":"Yulinet","00129D":"First International Computer do Brasil","00129E":"Surf Communications Inc.","00129F":"RAE Systems","0012A0":"NeoMeridian Sdn Bhd","0012A1":"BluePacket Communications Co. Ltd","0012A2":"Vita","0012A3":"Trust International B.V.","0012A4":"ThingMagic, LLC","0012A5":"Stargen, Inc.","0012A6":"Dolby Australia","0012A7":"ISR TECHNOLOGIES Inc","0012A8":"intec GmbH","0012A9":"3Com Ltd","0012AA":"IEE, Inc.","0012AB":"WiLife, Inc.","0012AC":"Ontimetek Inc.","0012AD":"IDS GmbH","0012AE":"HLS HARD-LINE Solutions Inc.","0012AF":"ELPRO Technologies","0012B0":"Efore Oyj (Plc)","0012B1":"Dai Nippon Printing Co. Ltd","0012B2":"Avolites Ltd","0012B3":"Advance Wireless Technology Corp.","0012B4":"Work Microwave GmbH","0012B5":"Vialta, Inc.","0012B6":"Santa Barbara Infrared, Inc.","0012B7":"PTW Freiburg","0012B8":"G2 Microsystems","0012B9":"Fusion Digital Technology","0012BA":"FSI Systems, Inc.","0012BB":"Telecommunications Industry Association TR-41 Committee","0012BC":"Echolab LLC","0012BD":"Avantec Manufacturing Limited","0012BE":"Astek Corporation","0012BF":"Arcadyan Technology Corporation","0012C0":"HotLava Systems, Inc.","0012C1":"Check Point Software Technologies","0012C2":"Apex Electronics Factory","0012C3":"WIT S.A.","0012C4":"Viseon, Inc.","0012C5":"V-Show Technology (China) Co. Ltd","0012C6":"TGC America, Inc","0012C7":"SECURAY Technologies LtdCo.","0012C8":"Perfect tech","0012C9":"ARRIS Group, Inc.","0012CA":"Mechatronic Brick Aps","0012CB":"CSS Inc.","0012CC":"Bitatek Co. Ltd","0012CD":"ASEM SpA","0012CE":"Advanced Cybernetics Group","0012CF":"Accton Technology Corp","0012D0":"Gossen-Metrawatt-GmbH","0012D1":"Texas Instruments","0012D2":"Texas Instruments","0012D3":"Zetta Systems, Inc.","0012D4":"Princeton Technology Ltd","0012D5":"Motion Reality Inc.","0012D6":"Jiangsu Yitong High-Tech Co. Ltd","0012D7":"Invento Networks, Inc.","0012D8":"International Games System Co. Ltd","0012D9":"Cisco Systems Inc.","0012DA":"Cisco Systems Inc.","0012DB":"ZIEHL Industrie-elektronik GmbH + Co KG","0012DC":"SunCorp Industrial Limited","0012DD":"Shengqu Information Technology (Shanghai) Co. Ltd","0012DE":"Radio Components Sweden AB","0012DF":"Novomatic AG","0012E0":"Codan Limited","0012E1":"Alliant Networks, Inc","0012E2":"ALAXALA Networks Corporation","0012E3":"Agat-RT Ltd","0012E4":"ZIEHL Industrie-electronik GmbH + Co KG","0012E5":"Time America, Inc.","0012E6":"Spectec Computer Co. Ltd","0012E7":"Projectek Networking Electronics Corp.","0012E8":"Fraunhofer IMS","0012E9":"Abbey Systems Ltd","0012EA":"Trane","0012EB":"PDH Solutions, LLC","0012EC":"Movacolor b.v.","0012ED":"AVG Advanced Technologies","0012EE":"Sony Mobile Communications AB","0012EF":"OneAccess SA","0012F0":"Intel Corporation","0012F1":"Ifotec","0012F2":"Brocade Communications Systems, Inc.","0012F3":"ConnectBlue AB","0012F4":"Belco International Co. Ltd","0012F5":"Imarda New Zealand Limited","0012F6":"MDK Co. Ltd","0012F7":"Xiamen Xinglian Electronics Co. Ltd","0012F8":"WNI Resources, LLC","0012F9":"Uryu Seisaku Ltd","0012FA":"THX Ltd","0012FB":"Samsung Electronics Co. Ltd","0012FC":"PLANET System Co. Ltd","0012FD":"Optimus IC S.A.","0012FE":"Lenovo Mobile Communication Technology Ltd","0012FF":"Lely Industries N.V.","001300":"IT-Factory, Inc.","001301":"IronGate S.L.","001302":"Intel Corporation","001303":"GateConnect","001304":"Flaircomm Technologies Co. Ltd","001305":"Epicom, Inc.","001306":"Always On Wireless","001307":"Paravirtual Corporation","001308":"Nuvera Fuel Cells","001309":"Ocean Broadband Networks","00130A":"Nortel Networks","00130B":"Mextal B.V.","00130C":"HF System Corporation","00130D":"Galileo Avionica","00130E":"Focusrite Audio Engineering Limited","00130F":"EGEMEN Bilgisayar Muh San ve Tic Ltd STI","001310":"Cisco-Linksys LLC","001311":"ARRIS Group, Inc.","001312":"Amedia Networks Inc.","001313":"GuangZhou Post & Telecom Equipment Ltd","001314":"Asiamajor Inc.","001315":"Sony Interactive Entertainment Inc.","001316":"L-S-B Broadcast Technologies GmbH","001317":"GN Netcom A/S","001318":"DGSTATION Co. Ltd","001319":"Cisco Systems Inc.","00131A":"Cisco Systems Inc.","00131B":"BeCell Innovations Corp.","00131C":"LiteTouch, Inc.","00131D":"Scanvaegt International A/S","00131E":"Peiker acustic GmbH & Co. KG","00131F":"NxtPhase T&D, Corp.","001320":"Intel Corporation","001321":"Hewlett-Packard Company","001322":"DAQ Electronics, Inc.","001323":"Cap Co. Ltd","001324":"Schneider Electric Ultra Terminal","001325":"Cortina Systems Inc","001326":"ECM Systems Ltd","001327":"Data Acquisitions limited","001328":"Westech Korea Inc.,","001329":"VSST Co. Ltd","00132A":"Sitronics Telecom Solutions","00132B":"Phoenix Digital","00132C":"MAZ Brandenburg GmbH","00132D":"iWise Communications","00132E":"ITian Coporation","00132F":"Interactek","001330":"Euro Protection Surveillance","001331":"CellPoint Connect","001332":"Beijing Topsec Network Security Technology Co. Ltd","001333":"BaudTec Corporation","001334":"Arkados, Inc.","001335":"VS Industry Berhad","001336":"Tianjin 712 Communication Broadcasting Co. Ltd","001337":"Orient Power Home Network Ltd","001338":"Fresenius-Vial","001339":"CCV Deutschland GmbH","00133A":"VadaTech Inc.","00133B":"Speed Dragon Multimedia Limited","00133C":"Quintron Systems Inc.","00133D":"Micro Memory Curtiss Wright Co","00133E":"MetaSwitch","00133F":"Eppendorf Instrumente GmbH","001340":"AD.EL s.r.l.","001341":"Shandong New Beiyang Information Technology Co. Ltd","001342":"Vision Research, Inc.","001343":"Matsushita Electronic Components (Europe) GmbH","001344":"Fargo Electronics Inc.","001345":"Eaton Corporation","001346":"D-Link Corporation","001347":"Red Lion Controls, LP","001348":"Artila Electronics Co. Ltd","001349":"ZyXEL Communications Corp","00134A":"Engim, Inc.","00134B":"ToGoldenNet Technology Inc.","00134C":"YDT Technology International","00134D":"Inepro BV","00134E":"Valox Systems, Inc.","00134F":"Tranzeo Wireless Technologies Inc.","001350":"Silver Spring Networks, Inc","001351":"Niles Audio Corporation","001352":"Naztec, Inc.","001353":"HYDAC Filtertechnik GmbH","001354":"Zcomax Technologies, Inc.","001355":"TOMEN Cyber-business Solutions, Inc.","001356":"FLIR Radiation Inc","001357":"Soyal Technology Co. Ltd","001358":"Realm Systems, Inc.","001359":"ProTelevision Technologies A/S","00135A":"Project T&E Limited","00135B":"PanelLink Cinema, LLC","00135C":"OnSite Systems, Inc.","00135D":"NTTPC Communications, Inc.","00135E":"EAB/RWI/K","00135F":"Cisco Systems Inc.","001360":"Cisco Systems Inc.","001361":"Biospace Co. Ltd","001362":"ShinHeung Precision Co. Ltd","001363":"Verascape, Inc.","001364":"Paradigm Technology Inc..","001365":"Nortel Networks","001366":"Neturity Technologies Inc.","001367":"Narayon. Co. Ltd","001368":"Saab Danmark A/S","001369":"Honda Electron Co., LED.","00136A":"Hach Lange Sarl","00136B":"E-TEC","00136C":"TomTom","00136D":"Tentaculus AB","00136E":"Techmetro Corp.","00136F":"PacketMotion, Inc.","001370":"Nokia Danmark A/S","001371":"ARRIS Group, Inc.","001372":"Dell Inc.","001373":"BLwave Electronics Co. Ltd","001374":"Atheros Communications, Inc.","001375":"American Security Products Co.","001376":"Tabor Electronics Ltd","001377":"Samsung Electronics Co. Ltd","001378":"Qsan Technology, Inc.","001379":"Ponder Information Industries Ltd","00137A":"Netvox Technology Co. Ltd","00137B":"Movon Corporation","00137C":"Kaicom Co. Ltd","00137D":"Dynalab, Inc.","00137E":"CorEdge Networks, Inc.","00137F":"Cisco Systems Inc.","001380":"Cisco Systems Inc.","001381":"CHIPS & Systems, Inc.","001382":"Cetacea Networks Corporation","001383":"Application Technologies and Engineering Research Laboratory","001384":"Advanced Motion Controls","001385":"Add-On Technology Co. Ltd","001386":"ABB Inc/Totalflow","001387":"27M Technologies AB","001388":"WiMedia Alliance","001389":"Redes de Telefon?a M?vil S.A.","00138A":"Qingdao Goertek Electronics Co. Ltd","00138B":"Phantom Technologies LLC","00138C":"Kumyoung.Co.Ltd","00138D":"Kinghold","00138E":"FOAB Elektronik AB","00138F":"Asiarock Technology Limited","001390":"Termtek Computer Co. Ltd","001391":"Ouen Co. Ltd","001392":"Ruckus Wireless","001393":"Panta Systems, Inc.","001394":"Infohand Co. Ltd","001395":"Congatec AG","001396":"Acbel Polytech Inc.","001397":"Oracle Corporation","001398":"TrafficSim Co. Ltd","001399":"STAC Corporation.","00139A":"K-ubique ID Corp.","00139B":"ioIMAGE Ltd","00139C":"Exavera Technologies, Inc.","00139D":"MaxLinear Hispania S.L.U.","00139E":"Ciara Technologies Inc.","00139F":"Electronics Design Services, Co. Ltd","0013A0":"ALGOSYSTEM Co. Ltd","0013A1":"Crow Electronic Engeneering","0013A2":"MaxStream, Inc","0013A3":"Siemens Com CPE Devices","0013A4":"KeyEye Communications","0013A5":"General Solutions Ltd","0013A6":"Extricom Ltd","0013A7":"Battelle Memorial Institute","0013A8":"Tanisys Technology","0013A9":"Sony Corporation","0013AA":"ALS & TEC Ltd","0013AB":"Telemotive AG","0013AC":"Sunmyung Electronics Co. Ltd","0013AD":"Sendo Ltd","0013AE":"Radiance Technologies, Inc.","0013AF":"NUMA Technology,Inc.","0013B0":"Jablotron","0013B1":"Intelligent Control Systems (Asia) Pte Ltd","0013B2":"Carallon Limited","0013B3":"Ecom Communications Technology Co. Ltd","0013B4":"Appear TV","0013B5":"Wavesat","0013B6":"Sling Media, Inc.","0013B7":"Scantech ID","0013B8":"RyCo Electronic Systems Limited","0013B9":"BM SPA","0013BA":"ReadyLinks Inc","0013BB":"Smartvue Corporation","0013BC":"Artimi Ltd","0013BD":"Hymatom SA","0013BE":"Virtual Conexions","0013BF":"Media System Planning Corp.","0013C0":"Trix Tecnologia Ltda.","0013C1":"Asoka USA Corporation","0013C2":"WACOM Co. Ltd","0013C3":"Cisco Systems Inc.","0013C4":"Cisco Systems Inc.","0013C5":"Lightron Fiber-Optic Devices Inc.","0013C6":"OpenGear, Inc","0013C7":"IONOS Co. Ltd","0013C8":"ADB Broadband Italia","0013C9":"Beyond Achieve Enterprises Ltd","0013CA":"Pico Digital","0013CB":"Zenitel Norway AS","0013CC":"Tall Maple Systems","0013CD":"MTI Co. Ltd","0013CE":"Intel Corporation","0013CF":"4Access Communications","0013D0":"t+ Medical Ltd","0013D1":"KIRK telecom A/S","0013D2":"Page Iberica, S.A.","0013D3":"Micro-Star International","0013D4":"ASUSTek Computer Inc.","0013D5":"RuggedCom","0013D6":"TII Network Technologies, Inc.","0013D7":"SPIDCOM Technologies SA","0013D8":"Princeton Instruments","0013D9":"Matrix Product Development, Inc.","0013DA":"Diskware Co. Ltd","0013DB":"SHOEI Electric Co. Ltd","0013DC":"Ibtek Inc.","0013DD":"Abbott Diagnostics","0013DE":"Adapt4, LLC","0013DF":"Ryvor Corp.","0013E0":"Murata Manufacturing Co. Ltd","0013E1":"Iprobe AB","0013E2":"GeoVision Inc.","0013E3":"CoVi Technologies, Inc.","0013E4":"Yangjae Systems Corp.","0013E5":"Tenosys, Inc.","0013E6":"Technolution","0013E7":"Halcro","0013E8":"Intel Corporation","0013E9":"VeriWave, Inc.","0013EA":"Kamstrup A/S","0013EB":"Sysmaster Corporation","0013EC":"Netsnapper Technologies SARL","0013ED":"Psia","0013EE":"JBX Designs Inc.","0013EF":"Kingjon Digital Technology Co. Ltd","0013F0":"Wavefront Semiconductor","0013F1":"AMOD Technology Co. Ltd","0013F2":"Klas Ltd","0013F3":"Giga-byte Communications Inc.","0013F4":"Psitek (Pty) Ltd","0013F5":"Akimbi Systems","0013F6":"Cintech","0013F7":"SMC Networks, Inc.","0013F8":"Dex Security Solutions","0013F9":"Cavera Systems","0013FA":"LifeSize Communications, Inc","0013FB":"RKC Instrument Inc.","0013FC":"SiCortex, Inc","0013FD":"Nokia Danmark A/S","0013FE":"Grandtec Electronic Corp.","0013FF":"Dage-MTI Of MC, Inc.","001400":"Minerva Korea Co. Ltd","001401":"Rivertree Networks Corp.","001402":"kk-electronic a/s","001403":"Renasis, LLC","001404":"ARRIS Group, Inc.","001405":"OpenIB, Inc.","001406":"Go Networks","001407":"Sperian Protection Instrumentation","001408":"Eka Systems Inc.","001409":"MAGNETI MARELLI S.E. S.p.A.","00140A":"WEPIO Co. Ltd","00140B":"First International Computer, Inc.","00140C":"GKB Cctv Co. Ltd","00140D":"Nortel Networks","00140E":"Nortel Networks","00140F":"Federal State Unitary Enterprise Leningrad R&D Institute Of","001410":"Suzhou Keda Technology Co. Ltd","001411":"Deutschmann Automation GmbH & Co. KG","001412":"S-TEC electronics AG","001413":"Trebing & Himstedt Prozessautomation GmbH & Co. KG","001414":"Jumpnode Systems LLC.","001415":"Intec Automation Inc.","001416":"Scosche Industries, Inc.","001417":"RSE Informations Technologie GmbH","001418":"C4Line","001419":"Sidsa","00141A":"Deicy Corporation","00141B":"Cisco Systems Inc.","00141C":"Cisco Systems Inc.","00141D":"LTi DRIVES GmbH","00141E":"P.A. Semi, Inc.","00141F":"SunKwang Electronics Co. Ltd","001420":"G-Links networking Company","001421":"Total Wireless Technologies Pte. Ltd","001422":"Dell Inc.","001423":"J-S Co. NEUROCOM","001424":"Merry Electrics Co. Ltd","001425":"Galactic Computing Corp.","001426":"NL Technology","001427":"JazzMutant","001428":"Vocollect Inc","001429":"V Center Technologies Co. Ltd","00142A":"Elitegroup Computer Systems Co. Ltd","00142B":"Edata Communication Inc.","00142C":"Koncept International, Inc.","00142D":"Toradex AG","00142E":"77 Elektronika Kft.","00142F":"Savvius","001430":"ViPowER, Inc","001431":"PDL Electronics Ltd","001432":"Tarallax Wireless, Inc.","001433":"Empower Technologies(Canada) Inc.","001434":"Keri Systems, Inc","001435":"CityCom Corp.","001436":"Qwerty Elektronik AB","001437":"GSTeletech Co. Ltd","001438":"Hewlett Packard Enterprise","001439":"Blonder Tongue Laboratories, Inc","00143A":"Raytalk International SRL","00143B":"Sensovation AG","00143C":"Rheinmetall Canada Inc.","00143D":"Aevoe Inc.","00143E":"AirLink Communications, Inc.","00143F":"Hotway Technology Corporation","001440":"ATOMIC Corporation","001441":"Innovation Sound Technology Co. Ltd","001442":"Atto Corporation","001443":"Consultronics Europe Ltd","001444":"Grundfos Holding","001445":"Telefon-Gradnja d.o.o.","001446":"SuperVision Solutions LLC","001447":"BOAZ Inc.","001448":"Inventec Multimedia & Telecom Corporation","001449":"Sichuan Changhong Electric Ltd","00144A":"Taiwan Thick-Film Ind. Corp.","00144B":"Hifn, Inc.","00144C":"General Meters Corp.","00144D":"Intelligent Systems","00144E":"Srisa","00144F":"Oracle Corporation","001450":"Heim Systems GmbH","001451":"Apple","001452":"Calculex,Inc.","001453":"Advantech Technologies Co. Ltd","001454":"Symwave","001455":"Coder Electronics Corporation","001456":"Edge Products","001457":"T-Vips AS","001458":"HS Automatic ApS","001459":"Moram Co. Ltd","00145A":"Neratec Solutions AG","00145B":"SeekerNet Inc.","00145C":"Intronics B.V.","00145D":"WJ Communications, Inc.","00145E":"IBM Corp","00145F":"Aditec Co. Ltd","001460":"Kyocera Wireless Corp.","001461":"Corona Corporation","001462":"Digiwell Technology, Inc","001463":"Idcs N.V.","001464":"Cryptosoft","001465":"Novo Nordisk A/S","001466":"Kleinhenz Elektronik GmbH","001467":"ArrowSpan Inc.","001468":"CelPlan International, Inc.","001469":"Cisco Systems Inc.","00146A":"Cisco Systems Inc.","00146B":"Anagran, Inc.","00146C":"Netgear","00146D":"RF Technologies","00146E":"H. Stoll GmbH & Co. KG","00146F":"Kohler Co","001470":"Prokom Software SA","001471":"Eastern Asia Technology Limited","001472":"China Broadband Wireless IP Standard Group","001473":"Bookham Inc","001474":"K40 Electronics","001475":"Wiline Networks, Inc.","001476":"MultiCom Industries Limited","001477":"Nertec Inc.","001478":"TP-Link Technologies Co. Ltd","001479":"NEC Magnus Communications Ltd","00147A":"Eubus GmbH","00147B":"Iteris, Inc.","00147C":"3Com Ltd","00147D":"Aeon Digital International","00147E":"InnerWireless","00147F":"Thomson Telecom Belgium","001480":"Hitachi-LG Data Storage Korea, Inc","001481":"Multilink Inc","001482":"Aurora Networks","001483":"eXS Inc.","001484":"Cermate Technologies Inc.","001485":"Giga-Byte","001486":"Echo Digital Audio Corporation","001487":"American Technology Integrators","001488":"Akorri","001489":"B15402100 - Jandei, S.L.","00148A":"Elin Ebg Traction GmbH","00148B":"Globo Electronic GmbH & Co. KG","00148C":"General Dynamics Mission Systems","00148D":"Cubic Defense Simulation Systems","00148E":"Tele Power Inc.","00148F":"Protronic (Far East) Ltd","001490":"ASP Corporation","001491":"Daniels Electronics Ltd dbo Codan Rado Communications","001492":"Liteon, Mobile Media Solution SBU","001493":"Systimax Solutions","001494":"ESU AG","001495":"2Wire Inc.","001496":"Phonic Corp.","001497":"ZHIYUAN Electronics Co. Ltd","001498":"Viking Design Technology","001499":"Helicomm Inc","00149A":"ARRIS Group, Inc.","00149B":"Nokota Communications, LLC","00149C":"HF Company","00149D":"Sound ID Inc.","00149E":"UbONE Co. Ltd","00149F":"System and Chips, Inc.","0014A0":"Accsense, Inc.","0014A1":"Synchronous Communication Corp","0014A2":"Core Micro Systems Inc.","0014A3":"Vitelec BV","0014A4":"Hon Hai Precision Ind. Co. Ltd","0014A5":"Gemtek Technology Co. Ltd","0014A6":"Teranetics, Inc.","0014A7":"Nokia Danmark A/S","0014A8":"Cisco Systems Inc.","0014A9":"Cisco Systems Inc.","0014AA":"Ashly Audio, Inc.","0014AB":"Senhai Electronic Technology Co. Ltd","0014AC":"Bountiful WiFi","0014AD":"Gassner Wiege- und Messtechnik GmbH","0014AE":"Wizlogics Co. Ltd","0014AF":"Datasym POS Inc.","0014B0":"Naeil Community","0014B1":"Axell Wireless Limited","0014B2":"mCubelogics Corporation","0014B3":"CoreStar International Corp","0014B4":"General Dynamics United Kingdom Ltd","0014B5":"Physiometrix,Inc","0014B6":"Enswer Technology Inc.","0014B7":"AR Infotek Inc.","0014B8":"Hill-Rom","0014B9":"Mstar Semiconductor","0014BA":"Carvers SA de CV","0014BB":"Open Interface North America","0014BC":"Synectic Telecom Exports PVT. Ltd","0014BD":"IncNETWORKS, Inc","0014BE":"Wink Communication technology Co.Ltd","0014BF":"Cisco-Linksys LLC","0014C0":"Symstream Technology Group Ltd","0014C1":"U.S. Robotics Corporation","0014C2":"Hewlett-Packard Company","0014C3":"Seagate Technology","0014C4":"Vitelcom Mobile Technology","0014C5":"Alive Technologies Pty Ltd","0014C6":"Quixant Ltd","0014C7":"Nortel Networks","0014C8":"Contemporary Research Corp","0014C9":"Brocade Communications Systems, Inc.","0014CA":"Key Radio Systems Limited","0014CB":"LifeSync Corporation","0014CC":"Zetec, Inc.","0014CD":"DigitalZone Co. Ltd","0014CE":"NF Corporation","0014CF":"INVISIO Communications","0014D0":"BTI Systems Inc.","0014D1":"TRENDnet, Inc.","0014D2":"Kyuden Technosystems Corporation","0014D3":"Sepsa","0014D4":"K Technology Corporation","0014D5":"Datang Telecom Technology Co. , LCD,Optical Communication Br","0014D6":"Jeongmin Electronics Co. Ltd","0014D7":"Datastore Technology Corp","0014D8":"bio-logic SA","0014D9":"IP Fabrics, Inc.","0014DA":"Huntleigh Healthcare","0014DB":"Elma Trenew Electronic GmbH","0014DC":"Communication System Design & Manufacturing (CSDM)","0014DD":"Covergence Inc.","0014DE":"Sage Instruments Inc.","0014DF":"HI-P Tech Corporation","0014E0":"LET'S Corporation","0014E1":"Data Display AG","0014E2":"datacom Systems Inc.","0014E3":"mm-lab GmbH","0014E4":"Infinias, LLC","0014E5":"Alticast","0014E6":"AIM Infrarotmodule GmbH","0014E7":"Stolinx,. Inc","0014E8":"ARRIS Group, Inc.","0014E9":"Nortech International","0014EA":"S Digm Inc. (Safe Paradigm Inc.)","0014EB":"AwarePoint Corporation","0014EC":"Acro Telecom","0014ED":"Airak, Inc.","0014EE":"Western Digital Technologies, Inc.","0014EF":"TZero Technologies, Inc.","0014F0":"Business Security OL AB","0014F1":"Cisco Systems Inc.","0014F2":"Cisco Systems Inc.","0014F3":"ViXS Systems Inc","0014F4":"DekTec Digital Video B.V.","0014F5":"OSI Security Devices","0014F6":"Juniper Networks","0014F7":"CREVIS Co. Ltd","0014F8":"Scientific Atlanta","0014F9":"Vantage Controls","0014FA":"AsGa S.A.","0014FB":"Technical Solutions Inc.","0014FC":"Extandon, Inc.","0014FD":"Thecus Technology Corp.","0014FE":"Artech Electronics","0014FF":"Precise Automation, Inc.","001500":"Intel Corporation","001501":"LexBox","001502":"BETA tech","001503":"PROFIcomms s.r.o.","001504":"Game Plus Co. Ltd","001505":"Actiontec Electronics, Inc","001506":"Neo Photonics","001507":"Renaissance Learning Inc","001508":"Global Target Enterprise Inc","001509":"Plus Technology Co. Ltd","00150A":"Sonoa Systems, Inc","00150B":"Sage Infotech Ltd","00150C":"AVM GmbH","00150D":"Hoana Medical, Inc.","00150E":"Openbrain Technologies Co. Ltd","00150F":"mingjong","001510":"Techsphere Co. Ltd","001511":"Data Center Systems","001512":"Zurich University Of Applied Sciences","001513":"EFS sas","001514":"Hu Zhou NAVA Networks&Electronics Ltd","001515":"Leipold+Co.GmbH","001516":"Uriel Systems Inc.","001517":"Intel Corporation","001518":"Shenzhen 10MOONS Technology Development Co. Ltd","001519":"StoreAge Networking Technologies","00151A":"Hunter Engineering Company","00151B":"Isilon Systems Inc.","00151C":"Leneco","00151D":"M2I Corporation","00151E":"Ethernet Powerlink Standardization Group (EPSG)","00151F":"Multivision Intelligent Surveillance (Hong Kong) Ltd","001520":"Radiocrafts AS","001521":"Horoquartz","001522":"Dea Security","001523":"Meteor Communications Corporation","001524":"Numatics, Inc.","001525":"Chamberlain Access Solutions","001526":"Remote Technologies Inc","001527":"Balboa Instruments","001528":"Beacon Medical Products LLC d.b.a. BeaconMedaes","001529":"N3 Corporation","00152A":"Nokia Corporation","00152B":"Cisco Systems Inc.","00152C":"Cisco Systems Inc.","00152D":"TenX Networks, LLC","00152E":"PacketHop, Inc.","00152F":"ARRIS Group, Inc.","001530":"Dell EMC","001531":"Kocom","001532":"Consumer Technologies Group, LLC","001533":"Nadam.Co. Ltd","001534":"A Beltr?nica-Companhia de Comunica??es, Lda","001535":"OTE Spa","001536":"Powertech Co. Ltd","001537":"Ventus Networks","001538":"RFID, Inc.","001539":"Technodrive srl","00153A":"Shenzhen Syscan Technology Co. Ltd","00153B":"EMH metering GmbH & Co. KG","00153C":"Kprotech Co. Ltd","00153D":"Elim Product Co.","00153E":"Q-Matic Sweden AB","00153F":"Alcatel Alenia Space Italia","001540":"Nortel Networks","001541":"StrataLight Communications, Inc.","001542":"Microhard S.R.L.","001543":"Aberdeen Test Center","001544":"CoM.s.a.t. AG","001545":"SEECODE Co. Ltd","001546":"ITG Worldwide Sdn Bhd","001547":"AiZen Solutions Inc.","001548":"Cube Technologies","001549":"Dixtal Biomedica Ind. Com. Ltda","00154A":"Wanshih Electronic Co. Ltd","00154B":"Wonde Proud Technology Co. Ltd","00154C":"Saunders Electronics","00154D":"Netronome Systems, Inc.","00154E":"IEC","00154F":"one RF Technology","001550":"Nits Technology Inc","001551":"RadioPulse Inc.","001552":"Wi-Gear Inc.","001553":"Cytyc Corporation","001554":"Atalum Wireless S.A.","001555":"DFM GmbH","001556":"Sagemcom Broadband SAS","001557":"Olivetti","001558":"Foxconn","001559":"Securaplane Technologies, Inc.","00155A":"Dainippon Pharmaceutical Co. Ltd","00155B":"Sampo Corporation","00155C":"Dresser Wayne","00155D":"Microsoft Corporation","00155E":"Morgan Stanley","00155F":"GreenPeak Technologies","001560":"Hewlett-Packard Company","001561":"JJPlus Corporation","001562":"Cisco Systems Inc.","001563":"Cisco Systems Inc.","001564":"BEHRINGER Spezielle Studiotechnik GmbH","001565":"Xiamen Yealink Network Technology Co. Ltd","001566":"A-First Technology Co. Ltd","001567":"RADWIN Inc.","001568":"Dilithium Networks","001569":"PECO II, Inc.","00156A":"DG2L Technologies Pvt. Ltd","00156B":"Perfisans Networks Corp.","00156C":"Sane System Co. Ltd","00156D":"Ubiquiti Networks Inc.","00156E":"A. W. Communication Systems Ltd","00156F":"Xiranet Communications GmbH","001570":"Zebra Technologies Inc","001571":"Nolan Systems","001572":"Red-Lemon","001573":"NewSoft Technology Corporation","001574":"Horizon Semiconductors Ltd","001575":"Nevis Networks Inc.","001576":"LABiTec - Labor Biomedical Technologies GmbH","001577":"Allied Telesis, Inc.","001578":"Audio / Video Innovations","001579":"Lunatone Industrielle Elektronik GmbH","00157A":"Telefin S.p.A.","00157B":"Leuze electronic GmbH + Co. KG","00157C":"Dave Networks, Inc.","00157D":"Posdata","00157E":"Weidm?ller Interface GmbH & Co. KG","00157F":"ChuanG International Holding Co. Ltd","001580":"U-WAY Corporation","001581":"MAKUS Inc.","001582":"Pulse Eight Limited","001583":"IVT Corporation","001584":"Schenck Process GmbH","001585":"Aonvision Technolopy Corp.","001586":"Xiamen Overseas Chinese Electronic Co. Ltd","001587":"Takenaka Seisakusho Co. Ltd","001588":"Salutica Allied Solutions Sdn Bhd","001589":"D-MAX Technology Co. Ltd","00158A":"SURECOM Technology Corp.","00158B":"Park Air Systems Ltd","00158C":"Liab ApS","00158D":"Jennic Ltd","00158E":"Plustek.Inc","00158F":"NTT Advanced Technology Corporation","001590":"Hectronic GmbH","001591":"RLW Inc.","001592":"Facom UK Ltd (Melksham)","001593":"U4EA Technologies Inc.","001594":"Bixolon Co. Ltd","001595":"Quester Tangent Corporation","001596":"ARRIS Group, Inc.","001597":"Aeta Audio Systems","001598":"Kolektor group","001599":"Samsung Electronics Co. Ltd","00159A":"ARRIS Group, Inc.","00159B":"Nortel Networks","00159C":"B-KYUNG SysTEM Co. Ltd","00159D":"Tripp Lite","00159E":"Mad Catz Interactive Inc","00159F":"Terascala, Inc.","0015A0":"Nokia Danmark A/S","0015A1":"ECA-Sinters","0015A2":"ARRIS Group, Inc.","0015A3":"ARRIS Group, Inc.","0015A4":"ARRIS Group, Inc.","0015A5":"DCI Co. Ltd","0015A6":"Digital Electronics Products Ltd","0015A7":"Robatech AG","0015A8":"ARRIS Group, Inc.","0015A9":"Kwang WOO I&C Co. Ltd","0015AA":"Rextechnik International Co.,","0015AB":"PRO Co Sound Inc","0015AC":"Capelon AB","0015AD":"Accedian Networks","0015AE":"kyung il","0015AF":"Azurewave Technologies Inc.","0015B0":"Autotelenet Co. Ltd","0015B1":"Ambient Corporation","0015B2":"Advanced Industrial Computer, Inc.","0015B3":"Caretech AB","0015B4":"Polymap Wireless LLC","0015B5":"CI Network Corp.","0015B6":"ShinMaywa Industries Ltd","0015B7":"Toshiba","0015B8":"Tahoe","0015B9":"Samsung Electronics Co. Ltd","0015BA":"iba AG","0015BB":"SMA Solar Technology AG","0015BC":"Develco","0015BD":"Group 4 Technology Ltd","0015BE":"Iqua Ltd","0015BF":"technicob","0015C0":"Digital Telemedia Co. Ltd","0015C1":"Sony Interactive Entertainment Inc.","0015C2":"3M Germany","0015C3":"Ruf Telematik AG","0015C4":"Flovel Co. Ltd","0015C5":"Dell Inc.","0015C6":"Cisco Systems Inc.","0015C7":"Cisco Systems Inc.","0015C8":"FlexiPanel Ltd","0015C9":"Gumstix, Inc","0015CA":"TeraRecon, Inc.","0015CB":"Surf Communication Solutions Ltd","0015CC":"Uquest Ltd","0015CD":"Exartech International Corp.","0015CE":"ARRIS Group, Inc.","0015CF":"ARRIS Group, Inc.","0015D0":"ARRIS Group, Inc.","0015D1":"ARRIS Group, Inc.","0015D2":"Xantech Corporation","0015D3":"Pantech&Curitel Communications, Inc.","0015D4":"Emitor AB","0015D5":"Nicevt","0015D6":"OSLiNK Sp. z o.o.","0015D7":"Reti Corporation","0015D8":"Interlink Electronics","0015D9":"PKC Electronics Oy","0015DA":"Iritel A.D.","0015DB":"Canesta Inc.","0015DC":"KT&C Co. Ltd","0015DD":"IP Control Systems Ltd","0015DE":"Nokia Danmark A/S","0015DF":"Clivet S.p.A.","0015E0":"Ericsson","0015E1":"Picochip Ltd","0015E2":"Dr.Ing. Herbert Knauer GmbH","0015E3":"Dream Technologies Corporation","0015E4":"Zimmer Elektromedizin","0015E5":"Cheertek Inc.","0015E6":"MOBILE TECHNIKA Inc.","0015E7":"Quantec Tontechnik","0015E8":"Nortel Networks","0015E9":"D-Link Corporation","0015EA":"Tellumat (Pty) Ltd","0015EB":"zte Corporation","0015EC":"Boca Devices LLC","0015ED":"Fulcrum Microsystems, Inc.","0015EE":"Omnex Control Systems","0015EF":"NEC TOKIN Corporation","0015F0":"EGO BV","0015F1":"KYLINK Communications Corp.","0015F2":"ASUSTek Computer Inc.","0015F3":"Peltor AB","0015F4":"Eventide","0015F5":"Sustainable Energy Systems","0015F6":"Science AND Engineering Services, Inc.","0015F7":"Wintecronics Ltd","0015F8":"Kingtronics Industrial Co. Ltd","0015F9":"Cisco Systems Inc.","0015FA":"Cisco Systems Inc.","0015FB":"setex schermuly textile Computer GmbH","0015FC":"Littelfuse Startco","0015FD":"Complete Media Systems","0015FE":"Schilling Robotics LLC","0015FF":"Novatel Wireless Solutions, Inc.","001600":"CelleBrite Mobile Synchronization","001601":"Buffalo.Inc","001602":"Ceyon Technology Co. Ltd","001603":"CoOLKSKY Co. Ltd","001604":"Sigpro","001605":"Yorkville Sound Inc.","001606":"Ideal Industries","001607":"Curves International Inc.","001608":"Sequans Communications","001609":"Unitech electronics Co. Ltd","00160A":"SWEEX Europe BV","00160B":"TVWorks LLC","00160C":"LPL Development S.A. de C.V","00160D":"Be Here Corporation","00160E":"Optica Technologies Inc.","00160F":"Badger Meter Inc","001610":"Carina Technology","001611":"Altecon Srl","001612":"Otsuka Electronics Co. Ltd","001613":"LibreStream Technologies Inc.","001614":"Picosecond Pulse Labs","001615":"Nittan Company, Limited","001616":"Browan Communication Inc.","001617":"MSI","001618":"HIVION Co. Ltd","001619":"Lancelan Technologies S.L.","00161A":"Dametric AB","00161B":"Micronet Corporation","00161C":"e:cue","00161D":"Innovative Wireless Technologies, Inc.","00161E":"Woojinnet","00161F":"SUNWAVETEC Co. Ltd","001620":"Sony Mobile Communications AB","001621":"Colorado Vnet","001622":"BBH Systems GmbH","001623":"Interval Media","001624":"Teneros, Inc.","001625":"Impinj, Inc.","001626":"ARRIS Group, Inc.","001627":"embedded-logic DESIGN AND MORE GmbH","001628":"Magicard Ltd","001629":"Nivus GmbH","00162A":"Antik Computers & Communications s.r.o.","00162B":"Togami Electric Mfg.Co. Ltd","00162C":"Xanboo","00162D":"STNet Co. Ltd","00162E":"Space Shuttle Hi-Tech Co. Ltd","00162F":"Geutebr?ck GmbH","001630":"Vativ Technologies","001631":"Xteam","001632":"Samsung Electronics Co. Ltd","001633":"Oxford Diagnostics Ltd","001634":"Mathtech, Inc.","001635":"Hewlett-Packard Company","001636":"Quanta Computer Inc.","001637":"CITEL SpA","001638":"TECOM Co. Ltd","001639":"Ubiquam Co. Ltd","00163A":"Yves Technology Co. Ltd","00163B":"VertexRSI/General Dynamics","00163C":"Rebox B.V.","00163D":"Tsinghua Tongfang Legend Silicon Tech. Co. Ltd","00163E":"Xensource, Inc.","00163F":"CReTE SysTEMS Inc.","001640":"Asmobile Communication Inc.","001641":"Universal Global Scientific Industrial Co. Ltd","001642":"Pangolin","001643":"Sunhillo Corporation","001644":"LITE-ON Technology Corp.","001645":"Power Distribution, Inc.","001646":"Cisco Systems Inc.","001647":"Cisco Systems Inc.","001648":"SSD Company Limited","001649":"SetOne GmbH","00164A":"Vibration Technology Limited","00164B":"Quorion Data Systems GmbH","00164C":"PLANET INT Co. Ltd","00164D":"Alcatel-Lucent IPD","00164E":"Nokia Danmark A/S","00164F":"World Ethnic Broadcastin Inc.","001650":"Kratos EPD","001651":"Exeo Systems","001652":"Hoatech Technologies, Inc.","001653":"LEGO System A/S IE Electronics Division","001654":"Flex-P Industries Sdn. Bhd.","001655":"FUHO TECHNOLOGY Co. Ltd","001656":"Nintendo Co. Ltd","001657":"Aegate Ltd","001658":"Fusiontech Technologies Inc.","001659":"Z.M.P. Radwag","00165A":"Harman Specialty Group","00165B":"Grip Audio","00165C":"Trackflow Ltd","00165D":"AirDefense, Inc.","00165E":"Precision I/O","00165F":"Fairmount Automation","001660":"Nortel Networks","001661":"Novatium Solutions (P) Ltd","001662":"Liyuh Technology Ltd","001663":"KBT Mobile","001664":"Prod-El SpA","001665":"Cellon France","001666":"Quantier Communication Inc.","001667":"A-TEC Subsystem Inc.","001668":"Eishin Electronics","001669":"MRV Communication (Networks) Ltd","00166A":"TPS","00166B":"Samsung Electronics Co. Ltd","00166C":"Samsung Electronics Co. Ltd","00166D":"Yulong Computer Telecommunication Scientific (Shenzhen) Co. Ltd","00166E":"Arbitron Inc.","00166F":"Intel Corporation","001670":"SKNET Corporation","001671":"Symphox Information Co.","001672":"Zenway enterprise Ltd","001673":"Bury GmbH & Co. KG","001674":"EuroCB (Phils.), Inc.","001675":"ARRIS Group, Inc.","001676":"Intel Corporation","001677":"Bihl + Wiedemann GmbH","001678":"Shenzhen Baoan Gaoke Electronics Co. Ltd","001679":"eOn Communications","00167A":"Skyworth Overseas Development Ltd","00167B":"Haver&Boecker","00167C":"iRex Technologies BV","00167D":"Sky-Line Information Co. Ltd","00167E":"Diboss.Co. Ltd","00167F":"Bluebird Soft Inc.","001680":"Bally Gaming + Systems","001681":"Vector Informatik GmbH","001682":"Pro Dex, Inc","001683":"WEBIO International Co.,.Ltd","001684":"Donjin Co. Ltd","001685":"Elisa Oyj","001686":"Karl Storz Imaging","001687":"Chubb CSC-Vendor AP","001688":"ServerEngines LLC","001689":"Pilkor Electronics Co. Ltd","00168A":"id-Confirm Inc","00168B":"Paralan Corporation","00168C":"DSL Partner AS","00168D":"KORWIN Co. Ltd","00168E":"Vimicro Corporation","00168F":"GN Netcom A/S","001690":"J-TEK Incorporation","001691":"Moser-Baer AG","001692":"Scientific-Atlanta, Inc.","001693":"PowerLink Technology Inc.","001694":"Sennheiser Communications A/S","001695":"AVC Technology (International) Limited","001696":"QDI Technology (H.K.) Limited","001697":"NEC Corporation","001698":"T&A Mobile Phones","001699":"Tonic DVB Marketing Ltd","00169A":"Quadrics Ltd","00169B":"Alstom Transport","00169C":"Cisco Systems Inc.","00169D":"Cisco Systems Inc.","00169E":"TV One Ltd","00169F":"Vimtron Electronics Co. Ltd","0016A0":"Auto-Maskin","0016A1":"3Leaf Networks","0016A2":"CentraLite Systems, Inc.","0016A3":"Ingeteam Transmission&Distribution, S.A.","0016A4":"Ezurio Ltd","0016A5":"Tandberg Storage ASA","0016A6":"Dovado FZ-LLC","0016A7":"Aweta G&P","0016A8":"CWT Co. Ltd","0016A9":"2EI","0016AA":"Kei Communication Technology Inc.","0016AB":"Dansensor A/S","0016AC":"Toho Technology Corp.","0016AD":"BT-Links Company Limited","0016AE":"Inventel","0016AF":"Shenzhen Union Networks Equipment Co. Ltd","0016B0":"VK Corporation","0016B1":"KBS","0016B2":"DriveCam Inc","0016B3":"Photonicbridges (China) Co. Ltd","0016B4":"Private","0016B5":"ARRIS Group, Inc.","0016B6":"Cisco-Linksys LLC","0016B7":"Seoul Commtech","0016B8":"Sony Mobile Communications AB","0016B9":"ProCurve Networking by HP","0016BA":"Weathernews Inc.","0016BB":"Law-Chain Computer Technology Co Ltd","0016BC":"Nokia Danmark A/S","0016BD":"ATI Industrial Automation","0016BE":"InfRANET, Inc.","0016BF":"PaloDEx Group Oy","0016C0":"Semtech Corporation","0016C1":"Eleksen Ltd","0016C2":"Avtec Systems Inc","0016C3":"BA Systems Inc","0016C4":"SiRF Technology, Inc.","0016C5":"Shenzhen Xing Feng Industry Co. Ltd","0016C6":"North Atlantic Industries","0016C7":"Cisco Systems Inc.","0016C8":"Cisco Systems Inc.","0016C9":"NAT Seattle, Inc.","0016CA":"Nortel Networks","0016CB":"Apple","0016CC":"Xcute Mobile Corp.","0016CD":"Hiji High-Tech Co. Ltd","0016CE":"Hon Hai Precision Ind. Co. Ltd","0016CF":"Hon Hai Precision Ind. Co. Ltd","0016D0":"ATech elektronika d.o.o.","0016D1":"ZAT a.s.","0016D2":"Caspian","0016D3":"Wistron Corporation","0016D4":"Compal Communications, Inc.","0016D5":"Synccom Co. Ltd","0016D6":"TDA Tech Pty Ltd","0016D7":"Sunways AG","0016D8":"Senea AB","0016D9":"Ningbo Bird Co. Ltd","0016DA":"Futronic Technology Co. Ltd","0016DB":"Samsung Electronics Co. Ltd","0016DC":"Archos","0016DD":"Gigabeam Corporation","0016DE":"FAST Inc","0016DF":"Lundinova AB","0016E0":"3Com Ltd","0016E1":"SiliconStor, Inc.","0016E2":"American Fibertek, Inc.","0016E3":"Askey Computer Corp","0016E4":"Vanguard Security Engineering Corp.","0016E5":"Fordley Development Limited","0016E6":"Giga-Byte Technology Co. Ltd","0016E7":"Dynamix Promotions Limited","0016E8":"Sigma Designs, Inc.","0016E9":"Tiba Medical Inc","0016EA":"Intel Corporation","0016EB":"Intel Corporation","0016EC":"Elitegroup Computer Systems Co. Ltd","0016ED":"Utility, Inc","0016EE":"Royaldigital Inc.","0016EF":"Koko Fitness, Inc.","0016F0":"Dell Inc.","0016F1":"OmniSense, LLC","0016F2":"Dmobile System Co. Ltd","0016F3":"CAST Information Co. Ltd","0016F4":"Eidicom Co. Ltd","0016F5":"Dalian Golden Hualu Digital Technology Co. Ltd","0016F6":"Video Products Group","0016F7":"L-3 Communications, Aviation Recorders","0016F8":"Aviqtech Technology Co. Ltd","0016F9":"CETRTA POT, d.o.o., Kranj","0016FA":"ECI Telecom Ltd","0016FB":"Shenzhen MTC Co Ltd","0016FC":"Tohken Co. Ltd","0016FD":"Jaty Electronics","0016FE":"Alps Electric Co. Ltd","0016FF":"Wamin Optocomm Mfg Corp","001700":"ARRIS Group, Inc.","001701":"KDE, Inc.","001702":"Osung Midicom Co. Ltd","001703":"MOSDAN Internation Co. Ltd","001704":"Shinco Electronics Group Co. Ltd","001705":"Methode Electronics","001706":"Techfaithwireless Communication Technology Limited.","001707":"InGrid, Inc","001708":"Hewlett-Packard Company","001709":"Exalt Communications","00170A":"Inew Digital Company","00170B":"Contela, Inc.","00170C":"Twig Com Ltd","00170D":"Dust Networks Inc.","00170E":"Cisco Systems Inc.","00170F":"Cisco Systems Inc.","001710":"Casa Systems Inc.","001711":"GE Healthcare Bio-Sciences AB","001712":"ISCO International","001713":"Tiger NetCom","001714":"BR Controls Nederland bv","001715":"Qstik","001716":"Qno Technology Inc.","001717":"Leica Geosystems AG","001718":"Vansco Electronics Oy","001719":"Audiocodes USA, Inc","00171A":"Winegard Company","00171B":"Innovation Lab Corp.","00171C":"NT MicroSystems, Inc.","00171D":"Digit","00171E":"Theo Benning GmbH & Co. KG","00171F":"IMV Corporation","001720":"Image Sensing Systems, Inc.","001721":"FITRE S.p.A.","001722":"Hanazeder Electronic GmbH","001723":"Summit Data Communications","001724":"Studer Professional Audio GmbH","001725":"Liquid Computing","001726":"m2c Electronic Technology Ltd","001727":"Thermo Ramsey Italia s.r.l.","001728":"Selex Communications","001729":"Ubicod Co.Ltd","00172A":"Proware Technology Corp.(By Unifosa)","00172B":"Global Technologies Inc.","00172C":"Taejin Infotech","00172D":"Axcen Photonics Corporation","00172E":"FXC Inc.","00172F":"NeuLion Incorporated","001730":"Automation Electronics","001731":"ASUSTek Computer Inc.","001732":"Science-Technical Center RISSA","001733":"SFR","001734":"ADC Telecommunications","001735":"Intel Wireless Network Group","001736":"iiTron Inc.","001737":"Industrie Dial Face S.p.A.","001738":"International Business Machines","001739":"Bright Headphone Electronics Company","00173A":"Cloudastructure Inc","00173B":"Cisco Systems Inc.","00173C":"Extreme Engineering Solutions","00173D":"Neology","00173E":"LeucotronEquipamentos Ltda.","00173F":"Belkin International Inc.","001740":"Bluberi Gaming Technologies Inc","001741":"Defidev","001742":"Fujitsu Limited","001743":"Deck Srl","001744":"Araneo Ltd","001745":"INNOTZ Co. Ltd","001746":"Freedom9 Inc.","001747":"Trimble","001748":"Neokoros Brasil Ltda","001749":"Hyundae Yong-O-SA Co. Ltd","00174A":"Socomec","00174B":"Nokia Danmark A/S","00174C":"Millipore","00174D":"Dynamic Network Factory, Inc.","00174E":"Parama-tech Co. Ltd","00174F":"iCatch Inc.","001750":"GSI Group, MicroE Systems","001751":"Online Corporation","001752":"DAGS, Inc","001753":"nFore Technology Inc.","001754":"Arkino HiTOP Corporation Limited","001755":"GE Security","001756":"Vinci Labs Oy","001757":"RIX Technology Limited","001758":"ThruVision Ltd","001759":"Cisco Systems Inc.","00175A":"Cisco Systems Inc.","00175B":"ACS Solutions Switzerland Ltd","00175C":"Sharp Corporation","00175D":"Dongseo System.","00175E":"Zed-3","00175F":"XENOLINK Communications Co. Ltd","001760":"Naito Densei Machida MFG.Co. Ltd","001761":"Private","001762":"Solar Technology, Inc.","001763":"Essentia S.p.A.","001764":"ATMedia GmbH","001765":"Nortel Networks","001766":"Accense Technology, Inc.","001767":"Earforce AS","001768":"Zinwave Ltd","001769":"Cymphonix Corp","00176A":"Avago Technologies","00176B":"Kiyon, Inc.","00176C":"Pivot3, Inc.","00176D":"Core Corporation","00176E":"Ducati Sistemi","00176F":"PAX Computer Technology(Shenzhen) Ltd","001770":"Arti Industrial Electronics Ltd","001771":"APD Communications Ltd","001772":"ASTRO Strobel Kommunikationssysteme GmbH","001773":"Laketune Technologies Co. Ltd","001774":"Elesta GmbH","001775":"TTE Germany GmbH","001776":"Meso Scale Diagnostics, LLC","001777":"Obsidian Research Corporation","001778":"Central Music Co.","001779":"QuickTel","00177A":"Assa Abloy AB","00177B":"Azalea Networks Inc","00177C":"Smartlink Network Systems Limited","00177D":"IDT Technology Limited","00177E":"Meshcom Technologies Inc.","00177F":"Worldsmart Retech","001780":"Applied Biosystems B.V.","001781":"Greystone Data System, Inc.","001782":"LoBenn Inc.","001783":"Texas Instruments","001784":"ARRIS Group, Inc.","001785":"Sparr Electronics Ltd","001786":"wisembed","001787":"Brother, Brother & Sons ApS","001788":"Philips Lighting BV","001789":"Zenitron Corporation","00178A":"Darts Technologies Corp.","00178B":"Teledyne Technologies Incorporated","00178C":"Independent Witness, Inc","00178D":"Checkpoint Systems, Inc.","00178E":"Gunnebo Cash Automation AB","00178F":"Ningbo Yidong Electronic Co. Ltd","001790":"HYUNDAI DIGITECH Co Ltd","001791":"LinTech GmbH","001792":"Falcom Wireless Comunications GmbH","001793":"Tigi Corporation","001794":"Cisco Systems Inc.","001795":"Cisco Systems Inc.","001796":"Rittmeyer AG","001797":"Telsy Elettronica S.p.A.","001798":"Azonic Technology Co. Ltd","001799":"SmarTire Systems Inc.","00179A":"D-Link Corporation","00179B":"Chant Sincere Co. Ltd","00179C":"DEPRAG SCHULZ GmbH u. Co.","00179D":"Kelman Limited","00179E":"Sirit Inc","00179F":"Apricorn","0017A0":"RoboTech srl","0017A1":"3soft Inc.","0017A2":"Camrivox Ltd","0017A3":"MIX s.r.l.","0017A4":"Hewlett-Packard Company","0017A5":"Ralink Technology Corp","0017A6":"Yosin Electronics Co. Ltd","0017A7":"Mobile Computing Promotion Consortium","0017A8":"EDM Corporation","0017A9":"Sentivision","0017AA":"elab-experience Inc.","0017AB":"Nintendo Co. Ltd","0017AC":"O'Neil Product Development Inc.","0017AD":"AceNet Corporation","0017AE":"GAI-Tronics","0017AF":"Enermet","0017B0":"Nokia Danmark A/S","0017B1":"ACIST Medical Systems, Inc.","0017B2":"SK Telesys","0017B3":"Aftek Infosys Limited","0017B4":"Remote Security Systems, LLC","0017B5":"Peerless Systems Corporation","0017B6":"Aquantia","0017B7":"Tonze Technology Co.","0017B8":"Novatron Co. Ltd","0017B9":"Gambro Lundia AB","0017BA":"Sedo Co. Ltd","0017BB":"Syrinx Industrial Electronics","0017BC":"Touchtunes Music Corporation","0017BD":"Tibetsystem","0017BE":"Tratec Telecom B.V.","0017BF":"Coherent Research Limited","0017C0":"PureTech Systems, Inc.","0017C1":"CM Precision Technology Ltd","0017C2":"ADB Broadband Italia","0017C3":"KTF Technologies Inc.","0017C4":"Quanta Microsystems, Inc.","0017C5":"SonicWALL","0017C6":"Cross Match Technologies Inc","0017C7":"MARA Systems Consulting AB","0017C8":"KYOCERA Display Corporation","0017C9":"Samsung Electronics Co. Ltd","0017CA":"Qisda Corporation","0017CB":"Juniper Networks","0017CC":"Alcatel-Lucent","0017CD":"CEC Wireless R&D Ltd","0017CE":"Screen Service Spa","0017CF":"iMCA-GmbH","0017D0":"Opticom Communications, LLC","0017D1":"Nortel Networks","0017D2":"Thinlinx Pty Ltd","0017D3":"Etymotic Research, Inc.","0017D4":"Monsoon Multimedia, Inc","0017D5":"Samsung Electronics Co. Ltd","0017D6":"Bluechips Microhouse Co. Ltd","0017D7":"ION Geophysical Corporation Inc.","0017D8":"Magnum Semiconductor, Inc.","0017D9":"AAI Corporation","0017DA":"Spans Logic","0017DB":"Canko Technologies Inc.","0017DC":"Daemyung ZERO1","0017DD":"Clipsal Australia","0017DE":"Advantage Six Ltd","0017DF":"Cisco Systems Inc.","0017E0":"Cisco Systems Inc.","0017E1":"DACOS Technologies Co. Ltd","0017E2":"ARRIS Group, Inc.","0017E3":"Texas Instruments","0017E4":"Texas Instruments","0017E5":"Texas Instruments","0017E6":"Texas Instruments","0017E7":"Texas Instruments","0017E8":"Texas Instruments","0017E9":"Texas Instruments","0017EA":"Texas Instruments","0017EB":"Texas Instruments","0017EC":"Texas Instruments","0017ED":"WooJooIT Ltd","0017EE":"ARRIS Group, Inc.","0017EF":"IBM Corp","0017F0":"SZCOM Broadband Network Technology Co. Ltd","0017F1":"Renu Electronics Pvt Ltd","0017F2":"Apple","0017F3":"Harris Corparation","0017F4":"Zeron Alliance","0017F5":"LIG Neoptek","0017F6":"Pyramid Meriden Inc.","0017F7":"CEM Solutions Pvt Ltd","0017F8":"Motech Industries Inc.","0017F9":"Forcom Sp. z o.o.","0017FA":"Microsoft Corporation","0017FB":"FA","0017FC":"Suprema Inc.","0017FD":"Amulet Hotkey","0017FE":"Talos System Inc.","0017FF":"PLAYLINE Co. Ltd","001800":"Unigrand Ltd","001801":"Actiontec Electronics, Inc","001802":"Alpha Networks Inc.","001803":"ArcSoft Shanghai Co. Ltd","001804":"E-TEK Digital Technology Limited","001805":"Beijing InHand Networking Technology Co. Ltd","001806":"Hokkei Industries Co. Ltd","001807":"Fanstel Corp.","001808":"SightLogix, Inc.","001809":"Cresyn","00180A":"Cisco Meraki","00180B":"Brilliant Telecommunications","00180C":"Optelian Access Networks","00180D":"Terabytes Server Storage Tech Corp","00180E":"Avega Systems","00180F":"Nokia Danmark A/S","001810":"IPTrade S.A.","001811":"Neuros Technology International, LLC.","001812":"Beijing Xinwei Telecom Technology Co. Ltd","001813":"Sony Mobile Communications AB","001814":"Mitutoyo Corporation","001815":"GZ Technologies, Inc.","001816":"Ubixon Co. Ltd","001817":"D. E. Shaw Research, LLC","001818":"Cisco Systems Inc.","001819":"Cisco Systems Inc.","00181A":"AVerMedia Information Inc.","00181B":"TaiJin Metal Co. Ltd","00181C":"Exterity Limited","00181D":"Asia Electronics Co. Ltd","00181E":"GDX Technologies Ltd","00181F":"Palmmicro Communications","001820":"w5networks","001821":"Sindoricoh","001822":"CEC Telecom Co. Ltd","001823":"Delta Electronics, Inc.","001824":"Kimaldi Electronics, S.L.","001825":"Private","001826":"Cale Access AB","001827":"NEC Unified Solutions Nederland B.V.","001828":"e2v technologies (UK) Ltd","001829":"Gatsometer","00182A":"Taiwan Video & Monitor","00182B":"Softier","00182C":"Ascend Networks, Inc.","00182D":"Artec Design","00182E":"XStreamHD","00182F":"Texas Instruments","001830":"Texas Instruments","001831":"Texas Instruments","001832":"Texas Instruments","001833":"Texas Instruments","001834":"Texas Instruments","001835":"Thoratec / ITC","001836":"Reliance Electric Limited","001837":"Universal ABIT Co. Ltd","001838":"PanAccess Communications,Inc.","001839":"Cisco-Linksys LLC","00183A":"Westell Technologies Inc.","00183B":"CENITS Co. Ltd","00183C":"Encore Software Limited","00183D":"Vertex Link Corporation","00183E":"Digilent, Inc","00183F":"2Wire Inc.","001840":"3 Phoenix, Inc.","001841":"High Tech Computer Corp","001842":"Nokia Danmark A/S","001843":"Dawevision Ltd","001844":"Heads Up Technologies, Inc.","001845":"Pulsar-Telecom LLC.","001846":"Crypto S.A.","001847":"AceNet Technology Inc.","001848":"Vecima Networks Inc.","001849":"Pigeon Point Systems LLC","00184A":"Catcher, Inc.","00184B":"Las Vegas Gaming, Inc.","00184C":"Bogen Communications","00184D":"Netgear","00184E":"Lianhe Technologies, Inc.","00184F":"8 Ways Technology Corp.","001850":"Secfone Kft","001851":"SWsoft","001852":"StorLink Semiconductors, Inc.","001853":"Atera Networks Ltd","001854":"Argard Co. Ltd","001855":"Aeromaritime Systembau GmbH","001856":"EyeFi, Inc","001857":"Unilever R&D","001858":"TagMaster AB","001859":"Strawberry Linux Co. Ltd","00185A":"uControl, Inc.","00185B":"Network Chemistry, Inc","00185C":"EDSLAB Technologies","00185D":"Taiguen Technology (Shen-Zhen) Co. Ltd","00185E":"Nexterm Inc.","00185F":"TAC Inc.","001860":"SIM Technology Group Shanghai Simcom Ltd,","001861":"Ooma, Inc.","001862":"Seagate Technology","001863":"Veritech Electronics Limited","001864":"Eaton Corporation","001865":"Siemens Healthcare Diagnostics Manufacturing Ltd","001866":"Leutron Vision","001867":"Datalogic ADC","001868":"Cisco SPVTG","001869":"Kingjim","00186A":"Global Link Digital Technology Co,.Ltd","00186B":"Sambu Communics Co. Ltd","00186C":"Neonode AB","00186D":"Zhenjiang Sapphire Electronic Industry Co.","00186E":"3Com Ltd","00186F":"Setha Industria Eletronica LtdA","001870":"E28 Shanghai Limited","001871":"Hewlett-Packard Company","001872":"Expertise Engineering","001873":"Cisco Systems Inc.","001874":"Cisco Systems Inc.","001875":"AnaCise Testnology Pte Ltd","001876":"WowWee Ltd","001877":"Amplex A/S","001878":"Mackware GmbH","001879":"dSys","00187A":"Wiremold","00187B":"4NSYS Co. Ltd","00187C":"Intercross, LLC","00187D":"Armorlink Co .Ltd","00187E":"RGB Spectrum","00187F":"Zodianet","001880":"Maxim Integrated Products","001881":"Buyang Electronics Industrial Co. Ltd","001882":"Huawei Technologies Co. Ltd","001883":"FORMOSA21 Inc.","001884":"Fon Technology S.L.","001885":"Avigilon Corporation","001886":"EL-Tech, Inc.","001887":"Metasystem SpA","001888":"GOTIVE a.s.","001889":"WinNet Solutions Limited","00188A":"Infinova LLC","00188B":"Dell Inc.","00188C":"Mobile Action Technology Inc.","00188D":"Nokia Danmark A/S","00188E":"Ekahau, Inc.","00188F":"Montgomery Technology, Inc.","001890":"RadioCOM, s.r.o.","001891":"Zhongshan General K-mate Electronics Co. Ltd","001892":"ads-tec GmbH","001893":"Shenzhen Photon Broadband Technology Co. Ltd","001894":"NPCore, Inc.","001895":"Hansun Technologies Inc.","001896":"Great Well Electronic Ltd","001897":"JESS-LINK PRODUCTS Co. Ltd","001898":"Kingstate Electronics Corporation","001899":"ShenZhen jieshun Science&Technology Industry Co Ltd","00189A":"HANA Micron Inc.","00189B":"Thomson Inc.","00189C":"Weldex Corporation","00189D":"Navcast Inc.","00189E":"OMNIKEY GmbH.","00189F":"Lenntek Corporation","0018A0":"Cierma Ascenseurs","0018A1":"Tiqit Computers, Inc.","0018A2":"XIP Technology AB","0018A3":"Zippy Technology Corp.","0018A4":"ARRIS Group, Inc.","0018A5":"ADigit Technologies Corp.","0018A6":"Persistent Systems, LLC","0018A7":"Yoggie Security Systems Ltd","0018A8":"AnNeal Technology Inc.","0018A9":"Ethernet Direct Corporation","0018AA":"Protec Fire Detection plc","0018AB":"Beijing Lhwt Microelectronics Inc.","0018AC":"Shanghai Jiao Da HISYS Technology Co. Ltd","0018AD":"Nidec Sankyo Corporation","0018AE":"TVT Co. Ltd","0018AF":"Samsung Electronics Co. Ltd","0018B0":"Nortel Networks","0018B1":"IBM Corp","0018B2":"Adeunis RF","0018B3":"TEC WizHome Co. Ltd","0018B4":"Dawon Media Inc.","0018B5":"Magna Carta","0018B6":"S3C, Inc.","0018B7":"D3 LED, LLC","0018B8":"New Voice International AG","0018B9":"Cisco Systems Inc.","0018BA":"Cisco Systems Inc.","0018BB":"Eliwell Controls srl","0018BC":"ZAO NVP Bolid","0018BD":"Shenzhen Dvbworld Technology Co. Ltd","0018BE":"ANSA Corporation","0018BF":"Essence Technology Solution, Inc.","0018C0":"ARRIS Group, Inc.","0018C1":"Almitec Inform?tica e Com?rcio","0018C2":"Firetide, Inc","0018C3":"CS Corporation","0018C4":"Raba Technologies LLC","0018C5":"Nokia Danmark A/S","0018C6":"OPW Fuel Management Systems","0018C7":"Real Time Automation","0018C8":"ISONAS Inc.","0018C9":"EOps Technology Limited","0018CA":"Viprinet GmbH","0018CB":"Tecobest Technology Limited","0018CC":"Axiohm SAS","0018CD":"Erae Electronics Industry Co. Ltd","0018CE":"Dreamtech Co. Ltd","0018CF":"Baldor Electric Company","0018D0":"AtRoad, A Trimble Company","0018D1":"Siemens Home & Office Comm. Devices","0018D2":"High-Gain Antennas LLC","0018D3":"Teamcast","0018D4":"Unified Display Interface SIG","0018D5":"Reigncom","0018D6":"Swirlnet A/S","0018D7":"JAVAD GNSS, Inc.","0018D8":"ARCH METER Corporation","0018D9":"Santosha Internatonal, Inc","0018DA":"AMBER wireless GmbH","0018DB":"EPL Technology Ltd","0018DC":"Prostar Co. Ltd","0018DD":"Silicondust Engineering Ltd","0018DE":"Intel Corporation","0018DF":"The Morey Corporation","0018E0":"Anaveo","0018E1":"Verkerk Service Systemen","0018E2":"Topdata Sistemas de Automacao Ltda","0018E3":"Visualgate Systems, Inc.","0018E4":"Yiguang","0018E5":"Adhoco AG","0018E6":"Computer Hardware Design SIA","0018E7":"Cameo Communications, Inc.","0018E8":"Hacetron Corporation","0018E9":"Numata Corporation","0018EA":"Alltec GmbH","0018EB":"Blue Zen Enterprises Private Limited","0018EC":"Welding Technology Corporation","0018ED":"Accutech Ultrasystems Co. Ltd","0018EE":"Videology Imaging Solutions, Inc.","0018EF":"Escape Communications, Inc.","0018F0":"JOYTOTO Co. Ltd","0018F1":"Chunichi Denshi Co. Ltd","0018F2":"Beijing Tianyu Communication Equipment Co. Ltd","0018F3":"ASUSTek Computer Inc.","0018F4":"EO TECHNICS Co. Ltd","0018F5":"Shenzhen Streaming Video Technology Company Limited","0018F6":"Thomson Telecom Belgium","0018F7":"Kameleon Technologies","0018F8":"Cisco-Linksys LLC","0018F9":"VVOND, Inc.","0018FA":"Yushin Precision Equipment Co. Ltd","0018FB":"Compro Technology","0018FC":"Altec Electronic AG","0018FD":"Optimal Technologies International Inc.","0018FE":"Hewlett-Packard Company","0018FF":"PowerQuattro Co.","001900":"Intelliverese - DBA Voicecom","001901":"F1MEDIA","001902":"Cambridge Consultants Ltd","001903":"Bigfoot Networks Inc","001904":"WB Electronics Sp. z o.o.","001905":"SCHRACK Seconet AG","001906":"Cisco Systems Inc.","001907":"Cisco Systems Inc.","001908":"Duaxes Corporation","001909":"DEVI - Danfoss A/S","00190A":"Hasware Inc.","00190B":"Southern Vision Systems, Inc.","00190C":"Encore Electronics, Inc.","00190D":"IEEE 1394c","00190E":"Atech Technology Co. Ltd","00190F":"Advansus Corp.","001910":"Knick Elektronische Messgeraete GmbH & Co. KG","001911":"Just In Mobile Information Technologies (Shanghai) Co. Ltd","001912":"Welcat Inc","001913":"Chuang-Yi Network Equipment Co.Ltd","001914":"Winix Co. Ltd","001915":"TECOM Co. Ltd","001916":"PayTec AG","001917":"Posiflex Inc.","001918":"Interactive Wear AG","001919":"ASTEL Inc.","00191A":"Irlink","00191B":"Sputnik Engineering AG","00191C":"Sensicast Systems","00191D":"Nintendo Co. Ltd","00191E":"Beyondwiz Co. Ltd","00191F":"Microlink Communications Inc.","001920":"KUME electric Co. Ltd","001921":"Elitegroup Computer Systems Co. Ltd","001922":"CM Comandos Lineares","001923":"Phonex Korea Co. Ltd","001924":"LBNL Engineering","001925":"Intelicis Corporation","001926":"BitsGen Co. Ltd","001927":"ImCoSys Ltd","001928":"Siemens AG, Transportation Systems","001929":"2M2B Montadora de Maquinas Bahia Brasil LtdA","00192A":"Antiope Associates","00192B":"Aclara RF Systems Inc.","00192C":"ARRIS Group, Inc.","00192D":"Nokia Corporation","00192E":"Spectral Instruments, Inc.","00192F":"Cisco Systems Inc.","001930":"Cisco Systems Inc.","001931":"Balluff GmbH","001932":"Gude Analog- und Digialsysteme GmbH","001933":"Strix Systems, Inc.","001934":"Trendon Touch Technology Corp.","001935":"Duerr Dental AG","001936":"Sterlite Optical Technologies Limited","001937":"CommerceGuard AB","001938":"UMB Communications Co. Ltd","001939":"Gigamips","00193A":"Oesolutions","00193B":"Wilibox Deliberant Group LLC","00193C":"HighPoint Technologies Incorporated","00193D":"GMC Guardian Mobility Corp.","00193E":"ADB Broadband Italia","00193F":"RDI technology(Shenzhen) Co. Ltd","001940":"Rackable Systems","001941":"Pitney Bowes, Inc","001942":"ON Software International Limited","001943":"Belden","001944":"Fossil Partners, L.P.","001945":"RF Concepts, LLC","001946":"Cianet Industria e Comercio S/A","001947":"Cisco SPVTG","001948":"AireSpider Networks","001949":"Tentel Comtech Co. Ltd","00194A":"Testo AG","00194B":"Sagemcom Broadband SAS","00194C":"Fujian Stelcom Information & Technology Co. Ltd","00194D":"Avago Technologies Sdn Bhd","00194E":"Ultra Electronics - TCS (Tactical Communication Systems)","00194F":"Nokia Danmark A/S","001950":"Harman Multimedia","001951":"NETCONS, s.r.o.","001952":"ACOGITO Co. Ltd","001953":"Chainleader Communications Corp.","001954":"Leaf Corporation.","001955":"Cisco Systems Inc.","001956":"Cisco Systems Inc.","001957":"Saafnet Canada Inc.","001958":"Bluetooth SIG, Inc.","001959":"Staccato Communications Inc.","00195A":"Jenaer Antriebstechnik GmbH","00195B":"D-Link Corporation","00195C":"Innotech Corporation","00195D":"ShenZhen XinHuaTong Opto Electronics Co. Ltd","00195E":"ARRIS Group, Inc.","00195F":"Valemount Networks Corporation","001960":"DoCoMo Systems, Inc.","001961":"Blaupunkt Embedded Systems GmbH","001962":"Commerciant, LP","001963":"Sony Mobile Communications AB","001964":"Doorking Inc.","001965":"YuHua TelTech (ShangHai) Co. Ltd","001966":"Asiarock Technology Limited","001967":"TELDAT Sp.J.","001968":"Digital Video Networks(Shanghai) Co. Ltd","001969":"Nortel Networks","00196A":"MikroM GmbH","00196B":"Danpex Corporation","00196C":"Etrovision Technology","00196D":"Raybit Systems Korea, Inc","00196E":"Metacom (Pty) Ltd","00196F":"SensoPart GmbH","001970":"Z-Com, Inc.","001971":"Guangzhou Unicomp Technology Co. Ltd","001972":"Plexus (Xiamen) Co. Ltd","001973":"Zeugma Systems","001974":"16063","001975":"Beijing Huisen networks technology Inc","001976":"Xipher Technologies, LLC","001977":"Aerohive Networks Inc.","001978":"Datum Systems, Inc.","001979":"Nokia Danmark A/S","00197A":"MAZeT GmbH","00197B":"Picotest Corp.","00197C":"Riedel Communications GmbH","00197D":"Hon Hai Precision Ind. Co. Ltd","00197E":"Hon Hai Precision Ind. Co. Ltd","00197F":"Plantronics, Inc.","001980":"Gridpoint Systems","001981":"Vivox Inc","001982":"SmarDTV","001983":"CCT R&D Limited","001984":"ESTIC Corporation","001985":"IT Watchdogs, Inc","001986":"Cheng Hongjian","001987":"Panasonic Mobile Communications Co. Ltd","001988":"Wi2Wi, Inc","001989":"Sonitrol Corporation","00198A":"Northrop Grumman Systems Corp.","00198B":"Novera Optics Korea, Inc.","00198C":"iXSea","00198D":"Ocean Optics, Inc.","00198E":"Oticon A/S","00198F":"Alcatel Bell N.V.","001990":"ELM DATA Co. Ltd","001991":"avinfo","001992":"Adtran Inc","001993":"Changshu Switchgear MFG. Co. Ltd (Former Changshu Switchgea","001994":"Jorjin Technologies Inc.","001995":"Jurong Hi-Tech (Suzhou)Co.Ltd","001996":"TurboChef Technologies Inc.","001997":"Soft Device Sdn Bhd","001998":"Sato Corporation","001999":"Fujitsu Technology Solutions GmbH","00199A":"EDO-EVI","00199B":"Diversified Technical Systems, Inc.","00199C":"Ctring","00199D":"Vizio, Inc","00199E":"Nifty","00199F":"DKT A/S","0019A0":"Nihon Data Systens, Inc.","0019A1":"LG Information & Comm.","0019A2":"Ordyn Technologies","0019A3":"asteel electronique atlantique","0019A4":"Austar Technology (hang zhou) Co. Ltd","0019A5":"RadarFind Corporation","0019A6":"ARRIS Group, Inc.","0019A7":"ITU-T","0019A8":"WiQuest Communications","0019A9":"Cisco Systems Inc.","0019AA":"Cisco Systems Inc.","0019AB":"Raycom Co . Ltd","0019AC":"GSP SysTEMS Inc.","0019AD":"Bobst SA","0019AE":"Hopling Technologies b.v.","0019AF":"Rigol Technologies, Inc.","0019B0":"HanYang System","0019B1":"Arrow7 Corporation","0019B2":"XYnetsoft Co. Ltd","0019B3":"Stanford Research Systems","0019B4":"Intellio Ltd","0019B5":"Famar Fueguina S.A.","0019B6":"Euro Emme s.r.l.","0019B7":"Nokia Danmark A/S","0019B8":"Boundary Devices","0019B9":"Dell Inc.","0019BA":"Paradox Security Systems Ltd","0019BB":"Hewlett-Packard Company","0019BC":"Electro Chance SRL","0019BD":"New Media Life","0019BE":"Altai Technologies Limited","0019BF":"Citiway technology Co. Ltd","0019C0":"ARRIS Group, Inc.","0019C1":"Alps Electric Co. Ltd","0019C2":"Equustek Solutions, Inc.","0019C3":"Qualitrol","0019C4":"Infocrypt Inc.","0019C5":"Sony Interactive Entertainment Inc.","0019C6":"zte Corporation","0019C7":"Cambridge Industries(Group) Co. Ltd","0019C8":"AnyDATA Corporation","0019C9":"S&C Electric Company","0019CA":"Broadata Communications, Inc","0019CB":"ZyXEL Communications Corp","0019CC":"RCG (HK) Ltd","0019CD":"Chengdu ethercom Information technology Ltd","0019CE":"Progressive Gaming International","0019CF":"Salicru, S.A.","0019D0":"Cathexis","0019D1":"Intel Corporation","0019D2":"Intel Corporation","0019D3":"TRAK Microwave","0019D4":"ICX Technologies","0019D5":"IP Innovations, Inc.","0019D6":"LS Cable and System Ltd","0019D7":"Fortunetek Co. Ltd","0019D8":"Maxfor","0019D9":"Zeutschel GmbH","0019DA":"Welltrans O&E Technology Co. Ltd","0019DB":"Micro-Star International","0019DC":"ENENSYS Technologies","0019DD":"FEI-Zyfer, Inc.","0019DE":"Mobitek","0019DF":"Thomson Inc.","0019E0":"TP-Link Technologies Co. Ltd","0019E1":"Nortel Networks","0019E2":"Juniper Networks","0019E3":"Apple","0019E4":"2Wire Inc.","0019E5":"Lynx Studio Technology, Inc.","0019E6":"Toyo Medic Co. Ltd","0019E7":"Cisco Systems Inc.","0019E8":"Cisco Systems Inc.","0019E9":"S-Information Technolgy, Co. Ltd","0019EA":"TeraMage Technologies Co. Ltd","0019EB":"Pyronix Ltd","0019EC":"Sagamore Systems, Inc.","0019ED":"Axesstel Inc.","0019EE":"CARLO GAVAZZI CoNTROLS SPA-Controls Division","0019EF":"Shenzhen Linnking Electronics Co. Ltd","0019F0":"Unionman Technology Co. Ltd","0019F1":"Star Communication Network Technology Co. Ltd","0019F2":"Teradyne K.K.","0019F3":"Cetis, Inc","0019F4":"Convergens Oy Ltd","0019F5":"Imagination Technologies Ltd","0019F6":"Acconet (PTE) Ltd","0019F7":"Onset Computer Corporation","0019F8":"Embedded Systems Design, Inc.","0019F9":"TDK-Lambda","0019FA":"Cable Vision Electronics Co. Ltd","0019FB":"BSkyB Ltd","0019FC":"PT. Ufoakses Sukses Luarbiasa","0019FD":"Nintendo Co. Ltd","0019FE":"Shenzhen Seecomm Technology Co. Ltd","0019FF":"Finnzymes","001A00":"Matrix Inc.","001A01":"Smiths Medical","001A02":"Secure Care Products, Inc","001A03":"Angel Electronics Co. Ltd","001A04":"Interay Solutions BV","001A05":"Optibase Ltd","001A06":"OpVista, Inc.","001A07":"Arecont Vision","001A08":"Simoco Ltd","001A09":"Wayfarer Transit Systems Ltd","001A0A":"Adaptive Micro-Ware Inc.","001A0B":"Bona Technology Inc.","001A0C":"Swe-Dish Satellite Systems AB","001A0D":"HandHeld entertainment, Inc.","001A0E":"Cheng Uei Precision Industry Co. Ltd","001A0F":"Sistemas Avanzados de Control, S.A.","001A10":"Lucent Trans Electronics Co. Ltd","001A11":"Google, Inc.","001A12":"Essilor","001A13":"Wanlida Group Co. Ltd","001A14":"Xin Hua Control Engineering Co. Ltd","001A15":"gemalto e-Payment","001A16":"Nokia Danmark A/S","001A17":"Teak Technologies, Inc.","001A18":"Advanced Simulation Technology Inc.","001A19":"Computer Engineering Limited","001A1A":"Gentex Corporation/Electro-Acoustic Products","001A1B":"ARRIS Group, Inc.","001A1C":"GT&T Engineering Pte Ltd","001A1D":"PChome Online Inc.","001A1E":"Aruba Networks","001A1F":"Coastal Environmental Systems","001A20":"CMOTECH Co. Ltd","001A21":"Brookhuis Applied Technologies BV","001A22":"eQ-3 Entwicklung GmbH","001A23":"Ice Qube, Inc","001A24":"Galaxy Telecom Technologies Ltd","001A25":"Delta Dore","001A26":"Deltanode Solutions AB","001A27":"Ubistar","001A28":"ASWT Co. Ltd Taiwan Branch H.K.","001A29":"Johnson Outdoors Marine Electronics d/b/a Minnkota","001A2A":"Arcadyan Technology Corporation","001A2B":"Ayecom Technology Co. Ltd","001A2C":"SATEC Co. Ltd","001A2D":"The Navvo Group","001A2E":"Ziova Coporation","001A2F":"Cisco Systems Inc.","001A30":"Cisco Systems Inc.","001A31":"SCAN CoIN Industries AB","001A32":"Activa Multimedia","001A33":"ASI Communications, Inc.","001A34":"Konka Group Co. Ltd","001A35":"BARTEC GmbH","001A36":"Aipermon GmbH & Co. KG","001A37":"Lear Corporation","001A38":"Sanmina-SCI","001A39":"Merten GmbH&CoKG","001A3A":"Dongahelecomm","001A3B":"Doah Elecom Inc.","001A3C":"Technowave Ltd","001A3D":"Ajin Vision Co. Ltd","001A3E":"Faster Technology LLC","001A3F":"Intelbras","001A40":"A-Four Tech Co. Ltd","001A41":"INOCOVA Co. Ltd","001A42":"Techcity Technology Co. Ltd","001A43":"Logical Link Communications","001A44":"JWTrading Co. Ltd","001A45":"GN Netcom A/S","001A46":"Digital Multimedia Technology Co. Ltd","001A47":"Agami Systems, Inc.","001A48":"Takacom Corporation","001A49":"Micro Vision Co. Ltd","001A4A":"Qumranet Inc.","001A4B":"Hewlett-Packard Company","001A4C":"Crossbow Technology, Inc","001A4D":"Giga-Byte Technology Co. Ltd","001A4E":"NTI AG / LinMot","001A4F":"AVM GmbH","001A50":"PheeNet Technology Corp.","001A51":"Alfred Mann Foundation","001A52":"Meshlinx Wireless Inc.","001A53":"Zylaya","001A54":"Hip Shing Electronics Ltd","001A55":"ACA-Digital Corporation","001A56":"ViewTel Co,. Ltd","001A57":"Matrix Design Group, LLC","001A58":"CCV Deutschland GmbH - Celectronic eHealth Div.","001A59":"Ircona","001A5A":"Korea Electric Power Data Network (KDN) Co. Ltd","001A5B":"NetCare Service Co. Ltd","001A5C":"Euchner GmbH+Co. KG","001A5D":"Mobinnova Corp.","001A5E":"Thincom Technology Co. Ltd","001A5F":"KitWorks.fi Ltd","001A60":"Wave Electronics Co. Ltd","001A61":"PacStar Corp.","001A62":"Data Robotics, Incorporated","001A63":"Elster Solutions, LLC,","001A64":"IBM Corp","001A65":"Seluxit","001A66":"ARRIS Group, Inc.","001A67":"Infinite QL Sdn Bhd","001A68":"Weltec Enterprise Co. Ltd","001A69":"Wuhan Yangtze Optical Technology Co. Ltd","001A6A":"Tranzas, Inc.","001A6B":"Universal Global Scientific Industrial Co. Ltd","001A6C":"Cisco Systems Inc.","001A6D":"Cisco Systems Inc.","001A6E":"Impro Technologies","001A6F":"MI.TEL s.r.l.","001A70":"Cisco-Linksys LLC","001A71":"Diostech Co. Ltd","001A72":"Mosart Semiconductor Corp.","001A73":"Gemtek Technology Co. Ltd","001A74":"Procare International Co","001A75":"Sony Mobile Communications AB","001A76":"SDT Information Technology Co. Ltd","001A77":"ARRIS Group, Inc.","001A78":"ubtos","001A79":"Telecomunication Technologies Ltd","001A7A":"Lismore Instruments Limited","001A7B":"Teleco, Inc.","001A7C":"Hirschmann Multimedia B.V.","001A7D":"cyber-blue(HK)Ltd","001A7E":"LN Srithai Comm Ltd","001A7F":"GCI Science & Technology Co. Ltd","001A80":"Sony Corporation","001A81":"Zelax","001A82":"PROBA Building Automation Co. Ltd","001A83":"Pegasus Technologies Inc.","001A84":"V One Multimedia Pte Ltd","001A85":"NV Michel Van de Wiele","001A86":"AdvancedIO Systems Inc","001A87":"Canhold International Limited","001A88":"Venergy,Co Ltd","001A89":"Nokia Danmark A/S","001A8A":"Samsung Electronics Co. Ltd","001A8B":"Chunil Electric Ind., Co.","001A8C":"Sophos Ltd","001A8D":"AVECS Bergen GmbH","001A8E":"3Way Networks Ltd","001A8F":"Nortel Networks","001A90":"Tr?pico Sistemas e Telecomunica??es da Amaz?nia LtdA.","001A91":"FusionDynamic Ltd","001A92":"ASUSTek Computer Inc.","001A93":"ERCO Leuchten GmbH","001A94":"Votronic GmbH","001A95":"Hisense Mobile Communications Technoligy Co. Ltd","001A96":"Ecler S.A.","001A97":"fitivision technology Inc.","001A98":"Asotel Communication Limited Taiwan Branch","001A99":"Smarty (HZ) Information Electronics Co. Ltd","001A9A":"Skyworth Digital Technology(Shenzhen) Co. Ltd","001A9B":"ADEC & Parter AG","001A9C":"RightHand Technologies, Inc.","001A9D":"Skipper Wireless, Inc.","001A9E":"ICON Digital International Limited","001A9F":"A-Link Ltd","001AA0":"Dell Inc.","001AA1":"Cisco Systems Inc.","001AA2":"Cisco Systems Inc.","001AA3":"Delorme","001AA4":"Future University-Hakodate","001AA5":"BRN Phoenix","001AA6":"Telefunken Radio Communication Systems GmbH &Co.KG","001AA7":"Torian Wireless","001AA8":"Mamiya Digital Imaging Co. Ltd","001AA9":"Fujian Star-NET Communication Co. Ltd","001AAA":"Analogic Corp.","001AAB":"eWings s.r.l.","001AAC":"Corelatus AB","001AAD":"ARRIS Group, Inc.","001AAE":"Savant Systems LLC","001AAF":"Blusens Technology","001AB0":"Signal Networks Pvt. Ltd,","001AB1":"Asia Pacific Satellite Industries Co. Ltd","001AB2":"Cyber Solutions Inc.","001AB3":"Visionite Inc.","001AB4":"FFEI Ltd","001AB5":"Home Network System","001AB6":"Texas Instruments","001AB7":"Ethos Networks Ltd","001AB8":"Anseri Corporation","001AB9":"PMC","001ABA":"Caton Overseas Limited","001ABB":"Fontal Technology Incorporation","001ABC":"U4EA Technologies Ltd","001ABD":"Impatica Inc.","001ABE":"Computer HI-Tech Inc.","001ABF":"TRUMPF Laser Marking Systems AG","001AC0":"Joybien Technologies Co. Ltd","001AC1":"3Com Ltd","001AC2":"YEC Co. Ltd","001AC3":"Scientific-Atlanta, Inc","001AC4":"2Wire Inc.","001AC5":"BreakingPoint Systems, Inc.","001AC6":"Micro Control Designs","001AC7":"Unipoint","001AC8":"ISL (Instrumentation Scientifique de Laboratoire)","001AC9":"Suzuken Co. Ltd","001ACA":"Tilera Corporation","001ACB":"Autocom Products Ltd","001ACC":"Celestial Semiconductor Ltd","001ACD":"Tidel Engineering LP","001ACE":"Yupiteru Corporation","001ACF":"C.T. Elettronica","001AD0":"Albis Technologies AG","001AD1":"Fargo Co. Ltd","001AD2":"Eletronica Nitron Ltda","001AD3":"Vamp Ltd","001AD4":"iPOX Technology Co. Ltd","001AD5":"KMC Chain Industrial Co. Ltd","001AD6":"Jiagnsu Aetna Electric Co. Ltd","001AD7":"Christie Digital Systems, Inc.","001AD8":"AlsterAero GmbH","001AD9":"International Broadband Electric Communications, Inc.","001ADA":"Biz-2-Me Inc.","001ADB":"ARRIS Group, Inc.","001ADC":"Nokia Danmark A/S","001ADD":"PePWave Ltd","001ADE":"ARRIS Group, Inc.","001ADF":"Interactivetv Pty Limited","001AE0":"Mythology Tech Express Inc.","001AE1":"Edge Access Inc","001AE2":"Cisco Systems Inc.","001AE3":"Cisco Systems Inc.","001AE4":"Medicis Technologies Corporation","001AE5":"Mvox Technologies Inc.","001AE6":"Atlanta Advanced Communications Holdings Limited","001AE7":"Aztek Networks, Inc.","001AE8":"Unify Software and Solutions GmbH & Co. KG","001AE9":"Nintendo Co. Ltd","001AEA":"Radio Terminal Systems Pty Ltd","001AEB":"Allied Telesis R&D Center K.K.","001AEC":"Keumbee Electronics Co. Ltd","001AED":"IncOTEC GmbH","001AEE":"Shenztech Ltd","001AEF":"Loopcomm Technology, Inc.","001AF0":"Alcatel-Lucent IPD","001AF1":"Embedded Artists AB","001AF2":"Dynavisions Schweiz AG","001AF3":"Samyoung Electronics","001AF4":"Handreamnet","001AF5":"Pentaone. Co. Ltd","001AF6":"Woven Systems, Inc.","001AF7":"dataschalt e+a GmbH","001AF8":"Copley Controls Corporation","001AF9":"AeroVIronment (AV Inc)","001AFA":"Welch Allyn, Inc.","001AFB":"Joby Inc.","001AFC":"ModusLink Corporation","001AFD":"Evolis","001AFE":"Sofacreal","001AFF":"Wizyoung Tech.","001B00":"Neopost Technologies","001B01":"Applied Radio Technologies","001B02":"ED Co.Ltd","001B03":"Action Technology (SZ) Co. Ltd","001B04":"Affinity International S.p.a","001B05":"YMC AG","001B06":"Ateliers R. LAUMONIER","001B07":"Mendocino Software","001B08":"Danfoss Drives A/S","001B09":"Matrix Telecom Pvt. Ltd","001B0A":"Intelligent Distributed Controls Ltd","001B0B":"Phidgets Inc.","001B0C":"Cisco Systems Inc.","001B0D":"Cisco Systems Inc.","001B0E":"InoTec GmbH Organisationssysteme","001B0F":"Petratec","001B10":"ShenZhen Kang Hui Technology Co. Ltd","001B11":"D-Link Corporation","001B12":"Apprion","001B13":"Icron Technologies Corporation","001B14":"Carex Lighting Equipment Factory","001B15":"Voxtel, Inc.","001B16":"Celtro Ltd","001B17":"Palo Alto Networks","001B18":"Tsuken Electric Ind. Co. Ltd","001B19":"IEEE I&M Society TC9","001B1A":"e-trees Japan, Inc.","001B1B":"Siemens AG,","001B1C":"Coherent","001B1D":"Phoenix International Co. Ltd","001B1E":"HART Communication Foundation","001B1F":"DELTA - Danish Electronics, Light & Acoustics","001B20":"TPine Technology","001B21":"Intel Corporation","001B22":"Palit Microsystems ( H.K.) Ltd","001B23":"SimpleComTools","001B24":"Quanta Computer Inc.","001B25":"Nortel Networks","001B26":"RON-Telecom ZAO","001B27":"Merlin CSI","001B28":"Polygon, JSC","001B29":"Avantis.Co. Ltd","001B2A":"Cisco Systems Inc.","001B2B":"Cisco Systems Inc.","001B2C":"ATRON electronic GmbH","001B2D":"Med-Eng Systems Inc.","001B2E":"Sinkyo Electron Inc","001B2F":"Netgear","001B30":"Solitech Inc.","001B31":"Neural Image. Co. Ltd","001B32":"QLogic Corporation","001B33":"Nokia Danmark A/S","001B34":"Focus System Inc.","001B35":"ChongQing JINOU Science & Technology Development Co. Ltd","001B36":"Tsubata Engineering Co. Ltd (Head Office)","001B37":"Computec Oy","001B38":"Compal Information (Kunshan) Co. Ltd","001B39":"Proxicast","001B3A":"SIMS Corp.","001B3B":"Yi-Qing Co. Ltd","001B3C":"Software Technologies Group,Inc.","001B3D":"EuroTel Spa","001B3E":"Curtis, Inc.","001B3F":"ProCurve Networking by HP","001B40":"Network Automation mxc AB","001B41":"General Infinity Co. Ltd","001B42":"Wise & Blue","001B43":"Beijing DG Telecommunications equipment Co. Ltd","001B44":"SanDisk Corporation","001B45":"ABB AS, Division Automation Products","001B46":"Blueone Technology Co. Ltd","001B47":"Futarque A/S","001B48":"Shenzhen Lantech Electronics Co. Ltd","001B49":"Roberts Radio limited","001B4A":"W&W Communications, Inc.","001B4B":"SANION Co. Ltd","001B4C":"Signtech","001B4D":"Areca Technology Corporation","001B4E":"Navman New Zealand","001B4F":"Avaya Inc","001B50":"Nizhny Novgorod Factory named after M.Frunze, FSUE (NZiF)","001B51":"Vector Technology Corp.","001B52":"ARRIS Group, Inc.","001B53":"Cisco Systems Inc.","001B54":"Cisco Systems Inc.","001B55":"Hurco Automation Ltd","001B56":"Tehuti Networks Ltd","001B57":"Semindia Systems Private Limited","001B58":"ACE CAD Enterprise Co. Ltd","001B59":"Sony Mobile Communications AB","001B5A":"Apollo Imaging Technologies, Inc.","001B5B":"2Wire Inc.","001B5C":"Azuretec Co. Ltd","001B5D":"Vololink Pty Ltd","001B5E":"BPL Limited","001B5F":"Alien Technology","001B60":"Navigon AG","001B61":"Digital Acoustics, LLC","001B62":"JHT Optoelectronics Co. Ltd","001B63":"Apple","001B64":"IsaacLandKorea Co. Ltd,","001B65":"China Gridcom Co. Ltd","001B66":"Sennheiser electronic GmbH & Co. KG","001B67":"Cisco Systems Inc.","001B68":"Modnnet Co. Ltd","001B69":"Equaline Corporation","001B6A":"Powerwave Technologies Sweden AB","001B6B":"Swyx Solutions AG","001B6C":"LookX Digital Media BV","001B6D":"Midtronics, Inc.","001B6E":"Anue Systems, Inc.","001B6F":"Teletrak Ltd","001B70":"IRI Ubiteq, Inc.","001B71":"Telular Corp.","001B72":"Sicep s.p.a.","001B73":"DTL Broadcast Ltd","001B74":"MiraLink Corporation","001B75":"Hypermedia Systems","001B76":"Ripcode, Inc.","001B77":"Intel Corporation","001B78":"Hewlett-Packard Company","001B79":"Faiveley Transport","001B7A":"Nintendo Co. Ltd","001B7B":"The Tintometer Ltd","001B7C":"A & R Cambridge","001B7D":"CXR Anderson Jacobson","001B7E":"Beckmann GmbH","001B7F":"TMN Technologies Telecomunicacoes Ltda","001B80":"LORD Corporation","001B81":"DATAQ Instruments, Inc.","001B82":"Taiwan Semiconductor Co. Ltd","001B83":"Finsoft Ltd","001B84":"Scan Engineering Telecom","001B85":"MAN Diesel SE","001B86":"Bosch Access Systems GmbH","001B87":"Deepsound Tech. Co. Ltd","001B88":"Divinet Access Technologies Ltd","001B89":"EMZA Visual Sense Ltd","001B8A":"2M Electronic A/S","001B8B":"NEC Platforms Ltd","001B8C":"JMicron Technology Corp.","001B8D":"Electronic Computer Systems, Inc.","001B8E":"Hulu Sweden AB","001B8F":"Cisco Systems Inc.","001B90":"Cisco Systems Inc.","001B91":"Efkon AG","001B92":"l-acoustics","001B93":"JC Decaux SA DNT","001B94":"T.E.M.A. S.p.A.","001B95":"Video Systems SRL","001B96":"General Sensing","001B97":"Violin Technologies","001B98":"Samsung Electronics Co. Ltd","001B99":"KS System GmbH","001B9A":"Apollo Fire Detectors Ltd","001B9B":"Hose-McCann Communications","001B9C":"SATEL sp. z o.o.","001B9D":"Novus Security Sp. z o.o.","001B9E":"Askey Computer Corp","001B9F":"Calyptech Pty Ltd","001BA0":"Awox","001BA1":"?mic AB","001BA2":"IDS Imaging Development Systems GmbH","001BA3":"Flexit Group GmbH","001BA4":"S.A.E Afikim","001BA5":"MyungMin Systems, Inc.","001BA6":"intotech Inc.","001BA7":"Lorica Solutions","001BA8":"UBI&MOBI,.Inc","001BA9":"Brother Industries Ltd","001BAA":"XenICs nv","001BAB":"Telchemy, Incorporated","001BAC":"Curtiss Wright Controls Embedded Computing","001BAD":"iControl Incorporated","001BAE":"Micro Control Systems, Inc","001BAF":"Nokia Danmark A/S","001BB0":"Bharat Electronics","001BB1":"Wistron Neweb Corporation","001BB2":"Intellect International NV","001BB3":"Condalo GmbH","001BB4":"Airvod Limited","001BB5":"Cherry GmbH","001BB6":"Bird Electronic Corp.","001BB7":"Alta Heights Technology Corp.","001BB8":"Blueway Electronic Co;Ltd","001BB9":"Elitegroup Computer Systems Co. Ltd","001BBA":"Nortel Networks","001BBB":"RFTech Co. Ltd","001BBC":"Silver Peak Systems, Inc.","001BBD":"FMC Kongsberg Subsea AS","001BBE":"ICOP Digital","001BBF":"Sagemcom Broadband SAS","001BC0":"Juniper Networks","001BC1":"HOLUX Technology, Inc.","001BC2":"Integrated Control Technology Limitied","001BC3":"Mobisolution Co. Ltd","001BC4":"Ultratec, Inc.","001BC5":"IEEE Registration Authority","001BC6":"Strato Rechenzentrum AG","001BC7":"StarVedia Technology Inc.","001BC8":"Miura Co. Ltd","001BC9":"FSN Display Inc","001BCA":"Beijing Run Technology Ltd Company","001BCB":"Pempek Systems Pty Ltd","001BCC":"Kingtek Cctv Alliance Co. Ltd","001BCD":"Daviscomms (S) PTE Ltd","001BCE":"Measurement Devices Ltd","001BCF":"Dataupia Corporation","001BD0":"Identec Solutions","001BD1":"Sogestmatic","001BD2":"ULTRA-X ASIA PACIFIC Inc.","001BD3":"Panasonic Corporation AVC Networks Company","001BD4":"Cisco Systems Inc.","001BD5":"Cisco Systems Inc.","001BD6":"Kelvin Hughes Ltd","001BD7":"Cisco SPVTG","001BD8":"FLIR Systems Inc","001BD9":"Edgewater Wireless Systems Inc","001BDA":"UTStarcom Inc","001BDB":"Valeo VECS","001BDC":"Vencer Co. Ltd","001BDD":"ARRIS Group, Inc.","001BDE":"Renkus-Heinz, Inc.","001BDF":"Iskra Sistemi d.d.","001BE0":"TELENOT ELECTRONIC GmbH","001BE1":"ViaLogy","001BE2":"AhnLab,Inc.","001BE3":"Health Hero Network, Inc.","001BE4":"Townet SRL","001BE5":"802automation Limited","001BE6":"VR AG","001BE7":"Postek Electronics Co. Ltd","001BE8":"Ultratronik GmbH","001BE9":"Broadcom","001BEA":"Nintendo Co. Ltd","001BEB":"DMP Electronics Inc.","001BEC":"Netio Technologies Co. Ltd","001BED":"Brocade Communications Systems, Inc.","001BEE":"Nokia Danmark A/S","001BEF":"Blossoms Digital Technology Co. Ltd","001BF0":"Value Platforms Limited","001BF1":"Nanjing SilverNet Software Co. Ltd","001BF2":"Kworld Computer Co. Ltd","001BF3":"TRANSRADIO SenderSysteme Berlin AG","001BF4":"Kenwin Industrial(HK) Ltd","001BF5":"Tellink Sistemas de Telecomunicaci?n S.L.","001BF6":"CoNWISE Technology Corporation Ltd","001BF7":"Lund IP Products AB","001BF8":"Digitrax Inc.","001BF9":"Intellitect Water Ltd","001BFA":"G.i.N. mbH","001BFB":"Alps Electric Co. Ltd","001BFC":"ASUSTek Computer Inc.","001BFD":"Dignsys Inc.","001BFE":"Zavio Inc.","001BFF":"Millennia Media Inc.","001C00":"Entry Point, LLC","001C01":"ABB Oy Drives","001C02":"Pano Logic","001C03":"Betty TV Technology AG","001C04":"Airgain, Inc.","001C05":"Nonin Medical Inc.","001C06":"Siemens Numerical Control Ltd, Nanjing","001C07":"Cwlinux Limited","001C08":"Echo360, Inc.","001C09":"SAE Electronic Co. Ltd","001C0A":"Shenzhen AEE Technology Co. Ltd","001C0B":"SmartAnt Telecom","001C0C":"TANITA Corporation","001C0D":"G-Technology, Inc.","001C0E":"Cisco Systems Inc.","001C0F":"Cisco Systems Inc.","001C10":"Cisco-Linksys LLC","001C11":"ARRIS Group, Inc.","001C12":"ARRIS Group, Inc.","001C13":"Optsys Technology Co. Ltd","001C14":"VMware, Inc.","001C15":"iPhotonix LLC","001C16":"ThyssenKrupp Elevator","001C17":"Nortel Networks","001C18":"Sicert S.r.L.","001C19":"secunet Security Networks AG","001C1A":"Thomas Instrumentation, Inc","001C1B":"Hyperstone GmbH","001C1C":"Center Communication Systems GmbH","001C1D":"Chenzhou Gospell Digital Technology Co. Ltd","001C1E":"emtrion GmbH","001C1F":"Quest Retail Technology Pty Ltd","001C20":"CLB Benelux","001C21":"Nucsafe Inc.","001C22":"Aeris Elettronica s.r.l.","001C23":"Dell Inc.","001C24":"Formosa Wireless Systems Corp.","001C25":"Hon Hai Precision Ind. Co. Ltd","001C26":"Hon Hai Precision Ind. Co. Ltd","001C27":"Sunell Electronics Co.","001C28":"Sphairon Technologies GmbH","001C29":"Core Digital Electronics Co. Ltd","001C2A":"Envisacor Technologies Inc.","001C2B":"Alertme.com Limited","001C2C":"Synapse","001C2D":"FlexRadio Systems","001C2E":"HPN Supply Chain","001C2F":"Pfister GmbH","001C30":"Mode Lighting (UK ) Ltd","001C31":"Mobile XP Technology Co. Ltd","001C32":"Telian Corporation","001C33":"Sutron","001C34":"Huey Chiao International Co. Ltd","001C35":"Nokia Danmark A/S","001C36":"iNEWiT NV","001C37":"Callpod, Inc.","001C38":"Bio-Rad Laboratories, Inc.","001C39":"S Netsystems Inc.","001C3A":"Element Labs, Inc.","001C3B":"AmRoad Technology Inc.","001C3C":"Seon Design Inc.","001C3D":"WaveStorm","001C3E":"ECKey Corporation","001C3F":"International Police Technologies, Inc.","001C40":"VDG-Security bv","001C41":"scemtec Transponder Technology GmbH","001C42":"Parallels, Inc.","001C43":"Samsung Electronics Co. Ltd","001C44":"Bosch Security Systems BV","001C45":"Chenbro Micom Co. Ltd","001C46":"Qtum","001C47":"Hangzhou Hollysys Automation Co. Ltd","001C48":"WiDeFi, Inc.","001C49":"Zoltan Technology Inc.","001C4A":"AVM GmbH","001C4B":"Gener8, Inc.","001C4C":"Petrotest Instruments","001C4D":"Aplix IP Holdings Corporation","001C4E":"TASA International Limited","001C4F":"Macab AB","001C50":"TCL Technoly Electronics (Huizhou) Co. Ltd","001C51":"Celeno Communications","001C52":"Visionee SRL","001C53":"Synergy Lighting Controls","001C54":"Hillstone Networks Inc","001C55":"Shenzhen Kaifa Technology Co.","001C56":"Pado Systems, Inc.","001C57":"Cisco Systems Inc.","001C58":"Cisco Systems Inc.","001C59":"Devon IT","001C5A":"Advanced Relay Corporation","001C5B":"Chubb Electronic Security Systems Ltd","001C5C":"Integrated Medical Systems, Inc.","001C5D":"Leica Microsystems","001C5E":"ASTON France","001C5F":"Winland Electronics, Inc.","001C60":"CSP Frontier Technologies,Inc.","001C61":"Galaxy Microsystems LImited","001C62":"LG Electronics (Mobile Communications)","001C63":"Truen","001C64":"Landis+Gyr","001C65":"JoeScan, Inc.","001C66":"Ucamp Co. Ltd","001C67":"Pumpkin Networks, Inc.","001C68":"Anhui Sun Create Electronics Co. Ltd","001C69":"Packet Vision Ltd","001C6A":"Weiss Engineering Ltd","001C6B":"CoVAX Co. Ltd","001C6C":"30805","001C6D":"Kyohritsu Electronic Industry Co. Ltd","001C6E":"Newbury Networks, Inc.","001C6F":"Emfit Ltd","001C70":"Novacomm Ltda","001C71":"Emergent Electronics","001C72":"Mayer & Cie GmbH & Co KG","001C73":"Arista Networks","001C74":"Syswan Technologies Inc.","001C75":"Segnet Ltd","001C76":"The Wandsworth Group Ltd","001C77":"Prodys","001C78":"Wyplay SAS","001C79":"Cohesive Financial Technologies LLC","001C7A":"Perfectone Netware Company Ltd","001C7B":"Castlenet Technology Inc.","001C7C":"Perq Systems Corporation","001C7D":"Excelpoint Manufacturing Pte Ltd","001C7E":"Toshiba","001C7F":"Check Point Software Technologies","001C80":"New Business Division/Rhea-Information Co. Ltd","001C81":"NextGen Venturi Ltd","001C82":"Genew Technologies","001C83":"New Level Telecom Co. Ltd","001C84":"STL Solution Co. Ltd","001C85":"Eunicorn","001C86":"Cranite Systems, Inc.","001C87":"Uriver Inc.","001C88":"Transystem Inc.","001C89":"Force Communications, Inc.","001C8A":"Cirrascale Corporation","001C8B":"MJ Innovations Ltd","001C8C":"Dial Technology Ltd","001C8D":"Mesa Imaging","001C8E":"Alcatel-Lucent IPD","001C8F":"Advanced Electronic Design, Inc.","001C90":"Empacket Corporation","001C91":"Gefen Inc.","001C92":"Tervela","001C93":"ExaDigm Inc","001C94":"LI-CoR Biosciences","001C95":"Opticomm Corporation","001C96":"Linkwise Technology Pte Ltd","001C97":"Enzytek Technology Inc.,","001C98":"Lucky Technology (HK) Company Limited","001C99":"Shunra Software Ltd","001C9A":"Nokia Danmark A/S","001C9B":"FEIG ELECTRONIC GmbH","001C9C":"Nortel Networks","001C9D":"Liecthi AG","001C9E":"Dualtech IT AB","001C9F":"Razorstream, LLC","001CA0":"Production Resource Group, LLC","001CA1":"Akamai Technologies, Inc.","001CA2":"ADB Broadband Italia","001CA3":"Terra","001CA4":"Sony Mobile Communications AB","001CA5":"Zygo Corporation","001CA6":"Win4NET","001CA7":"International Quartz Limited","001CA8":"AirTies Wireless Networks","001CA9":"Audiomatica Srl","001CAA":"Bellon Pty Ltd","001CAB":"Meyer Sound Laboratories, Inc.","001CAC":"Qniq Technology Corp.","001CAD":"Wuhan Telecommunication Devices Co. Ltd","001CAE":"WiChorus, Inc.","001CAF":"Plato Networks Inc.","001CB0":"Cisco Systems Inc.","001CB1":"Cisco Systems Inc.","001CB2":"BPT SPA","001CB3":"Apple","001CB4":"Iridium Satellite LLC","001CB5":"Neihua Network Technology Co. Ltd(NHN)","001CB6":"Duzon CNT Co. Ltd","001CB7":"USC DigiArk Corporation","001CB8":"CBC Co. Ltd","001CB9":"Kwang Sung Electronics Co. Ltd","001CBA":"VerScient, Inc.","001CBB":"MusicianLink","001CBC":"CastGrabber, LLC","001CBD":"Ezze Mobile Tech., Inc.","001CBE":"Nintendo Co. Ltd","001CBF":"Intel Corporation","001CC0":"Intel Corporation","001CC1":"ARRIS Group, Inc.","001CC2":"Part II Research, Inc.","001CC3":"ARRIS Group, Inc.","001CC4":"Hewlett-Packard Company","001CC5":"3Com Ltd","001CC6":"ProStor Systems","001CC7":"Rembrandt Technologies, LLC d/b/a REMSTREAM","001CC8":"IndUSTRONIC Industrie-Electronic GmbH & Co. KG","001CC9":"Kaise Electronic Technology Co. Ltd","001CCA":"Shanghai Gaozhi Science & Technology Development Co.","001CCB":"Forth Corporation Public Company Limited","001CCC":"BlackBerry RTS","001CCD":"Alektrona Corporation","001CCE":"By Techdesign","001CCF":"Limetek","001CD0":"Circleone Co. Ltd","001CD1":"Waves Audio Ltd","001CD2":"King Champion (Hong Kong) Limited","001CD3":"ZP Engineering SEL","001CD4":"Nokia Danmark A/S","001CD5":"ZeeVee, Inc.","001CD6":"Nokia Danmark A/S","001CD7":"Harman/Becker Automotive Systems GmbH","001CD8":"BlueAnt Wireless","001CD9":"GlobalTop Technology Inc.","001CDA":"Exegin Technologies Limited","001CDB":"Carpoint Co. Ltd","001CDC":"Custom Computer Services, Inc.","001CDD":"Cowbell Engineering Co. Ltd","001CDE":"Interactive Multimedia eXchange Inc.","001CDF":"Belkin International Inc.","001CE0":"Dasan TPS","001CE1":"Indra Sistemas, S.A.","001CE2":"Attero Tech, LLC.","001CE3":"Optimedical Systems","001CE4":"EleSy JSC","001CE5":"MBS Electronic Systems GmbH","001CE6":"Innes","001CE7":"Rocon PLC Research Centre","001CE8":"Cummins Inc","001CE9":"Galaxy Technology Limited","001CEA":"Scientific-Atlanta, Inc","001CEB":"Nortel Networks","001CEC":"Mobilesoft (Aust.) Pty Ltd","001CED":"Environnement SA","001CEE":"Sharp Corporation","001CEF":"Primax Electronics Ltd","001CF0":"D-Link Corporation","001CF1":"SUPoX Technology Co. Ltd","001CF2":"Tenlon Technology Co. Ltd","001CF3":"EVS Broadcast Equipment","001CF4":"Media Technology Systems Inc","001CF5":"Wiseblue Technology Limited","001CF6":"Cisco Systems Inc.","001CF7":"AudioScience","001CF8":"Parade Technologies Ltd","001CF9":"Cisco Systems Inc.","001CFA":"Alarm.com","001CFB":"ARRIS Group, Inc.","001CFC":"Sumitomo Electric Industries Ltd","001CFD":"Universal Electronics, Inc.","001CFE":"Quartics Inc","001CFF":"Napera Networks Inc","001D00":"Brivo Systems, LLC","001D01":"Neptune Digital","001D02":"Cybertech Telecom Development","001D03":"Design Solutions Inc.","001D04":"Zipit Wireless, Inc.","001D05":"Eaton Corporation","001D06":"HM Electronics, Inc.","001D07":"Shenzhen Sang Fei Consumer Communications Co. Ltd","001D08":"Jiangsu Yinhe Electronics Co. Ltd","001D09":"Dell Inc.","001D0A":"Davis Instruments, Inc.","001D0B":"Power Standards Lab","001D0C":"MobileCompia","001D0D":"Sony Interactive Entertainment Inc.","001D0E":"Agapha Technology Co. Ltd","001D0F":"TP-Link Technologies Co. Ltd","001D10":"LightHaus Logic, Inc.","001D11":"Analogue & Micro Ltd","001D12":"Rohm Co. Ltd","001D13":"NextGTV","001D14":"Speradtone Information Technology Limited","001D15":"Shenzhen Dolphin Electronic Co. Ltd","001D16":"SFR","001D17":"Digital Sky Corporation","001D18":"Power Innovation GmbH","001D19":"Arcadyan Technology Corporation","001D1A":"OvisLink S.A.","001D1B":"Sangean Electronics Inc.","001D1C":"Gennet s.a.","001D1D":"Inter-M Corporation","001D1E":"Kyushu TEN Co. Ltd","001D1F":"Siauliu Tauro Televizoriai, JSC","001D20":"Comtrend Corporation","001D21":"Alcad SL","001D22":"Foss Analytical A/S","001D23":"Sensus","001D24":"Aclara Power-Line Systems Inc.","001D25":"Samsung Electronics Co. Ltd","001D26":"Rockridgesound Technology Co.","001D27":"NAC-Intercom","001D28":"Sony Mobile Communications AB","001D29":"Doro AB","001D2A":"Shenzhen BUL-Tech Co. Ltd","001D2B":"Wuhan Pont Technology Co. Ltd","001D2C":"Wavetrend Technologies (Pty) Limited","001D2D":"Pylone, Inc.","001D2E":"Ruckus Wireless","001D2F":"QuantumVision Corporation","001D30":"YX Wireless S.A.","001D31":"Highpro International R&D Co,.Ltd","001D32":"Longkay Communication & Technology (Shanghai) Co. Ltd","001D33":"Maverick Systems Inc.","001D34":"SYRIS Technology Corp","001D35":"Viconics Electronics Inc.","001D36":"Electronics Corporation Of India Limited","001D37":"Thales-Panda Transportation System","001D38":"Seagate Technology","001D39":"Moohadigital Co. Ltd","001D3A":"mh acoustics LLC","001D3B":"Nokia Danmark A/S","001D3C":"Muscle Corporation","001D3D":"Avidyne Corporation","001D3E":"Saka Techno Science Co. Ltd","001D3F":"Mitron Pty Ltd","001D40":"Intel - GE Care Innovations LLC","001D41":"Hardy Instruments","001D42":"Nortel Networks","001D43":"Shenzhen G-link Digital Technology Co. Ltd","001D44":"Krohne","001D45":"Cisco Systems Inc.","001D46":"Cisco Systems Inc.","001D47":"Covote GmbH & Co KG","001D48":"Sensor-Technik Wiedemann GmbH","001D49":"Innovation Wireless Inc.","001D4A":"Carestream Health, Inc.","001D4B":"Grid Connect Inc.","001D4C":"Alcatel-Lucent","001D4D":"Adaptive Recognition Hungary, Inc","001D4E":"TCM Mobile LLC","001D4F":"Apple","001D50":"Spinetix SA","001D51":"Babcock & Wilcox Power Generation Group, Inc","001D52":"Defzone B.V.","001D53":"S&O Electronics (Malaysia) Sdn. Bhd.","001D54":"Sunnic Technology & Merchandise Inc.","001D55":"ZANTAZ, Inc","001D56":"Kramer Electronics Ltd","001D57":"CAETEC Messtechnik","001D58":"CQ Inc","001D59":"Mitra Energy & Infrastructure","001D5A":"2Wire Inc.","001D5B":"Tecvan Inform?tica Ltda","001D5C":"Tom Communication Industrial Co. Ltd","001D5D":"Control Dynamics Pty. Ltd","001D5E":"Coming Media Corp.","001D5F":"OverSpeed SARL","001D60":"ASUSTek Computer Inc.","001D61":"BIJ Corporation","001D62":"InPhase Technologies","001D63":"Miele & Cie. KG","001D64":"Adam Communications Systems Int ltd","001D65":"Microwave Radio Communications","001D66":"Hyundai Telecom","001D67":"Amec","001D68":"Thomson Telecom Belgium","001D69":"Knorr-Bremse IT-Services GmbH","001D6A":"Alpha Networks Inc.","001D6B":"ARRIS Group, Inc.","001D6C":"ClariPhy Communications, Inc.","001D6D":"Confidant International LLC","001D6E":"Nokia Danmark A/S","001D6F":"Chainzone Technology Co. Ltd","001D70":"Cisco Systems Inc.","001D71":"Cisco Systems Inc.","001D72":"Wistron Corporation","001D73":"Buffalo.Inc","001D74":"Tianjin China-Silicon Microelectronics Co. Ltd","001D75":"Radioscape PLC","001D76":"Eyeheight Ltd","001D77":"NSGate","001D78":"Invengo Information Technology Co. Ltd","001D79":"Signamax LLC","001D7A":"Wideband Semiconductor, Inc.","001D7B":"Ice Energy, Inc.","001D7C":"ABE Elettronica S.p.A.","001D7D":"Giga-Byte Technology Co. Ltd","001D7E":"Cisco-Linksys LLC","001D7F":"Tekron International Ltd","001D80":"Beijing Huahuan Electronics Co. Ltd","001D81":"Guangzhou Gateway Electronics Co. Ltd","001D82":"GN Netcom A/S","001D83":"Emitech Corporation","001D84":"Gateway, Inc.","001D85":"Call Direct Cellular Solutions","001D86":"Shinwa Industries(China) Ltd","001D87":"VigTech Labs Sdn Bhd","001D88":"Clearwire","001D89":"VaultStor Corporation","001D8A":"TechTrex Inc","001D8B":"ADB Broadband Italia","001D8C":"La Crosse Technology Ltd","001D8D":"Raytek GmbH","001D8E":"Alereon, Inc.","001D8F":"PureWave Networks","001D90":"EMCO Flow Systems","001D91":"Digitize, Inc","001D92":"Micro-Star International","001D93":"Modacom","001D94":"Climax Technology Co. Ltd","001D95":"Flash, Inc.","001D96":"WatchGuard Video","001D97":"Alertus Technologies LLC","001D98":"Nokia Danmark A/S","001D99":"Cyan Optic, Inc.","001D9A":"Godex International Co. Ltd","001D9B":"Hokuyo Automatic Co. Ltd","001D9C":"Rockwell Automation","001D9D":"Artjoy International Limited","001D9E":"Axion Technologies","001D9F":"MATT R.P.Traczynscy Sp.J.","001DA0":"Heng Yu Electronic Manufacturing Company Limited","001DA1":"Cisco Systems Inc.","001DA2":"Cisco Systems Inc.","001DA3":"SabiOso","001DA4":"Hangzhou System Technology Co. Ltd","001DA5":"WB Electronics","001DA6":"Media Numerics Limited","001DA7":"Seamless Internet","001DA8":"Takahata Electronics Co. Ltd","001DA9":"Castles Technology, Co. Ltd","001DAA":"DrayTek Corp.","001DAB":"SwissQual License AG","001DAC":"Gigamon Systems LLC","001DAD":"Sinotech Engineering Consultants, Inc. Geotechnical Enginee","001DAE":"Chang Tseng Technology Co. Ltd","001DAF":"Nortel Networks","001DB0":"FuJian HengTong Information Technology Co. Ltd","001DB1":"Crescendo Networks","001DB2":"Hokkaido Electric Engineering Co. Ltd","001DB3":"HPN Supply Chain","001DB4":"Kumho ENG Co. Ltd","001DB5":"Juniper Networks","001DB6":"BestComm Networks, Inc.","001DB7":"Tendril Networks, Inc.","001DB8":"Intoto Inc.","001DB9":"Wellspring Wireless","001DBA":"Sony Corporation","001DBB":"Dynamic System Electronics Corp.","001DBC":"Nintendo Co. Ltd","001DBD":"Versamed Inc.","001DBE":"ARRIS Group, Inc.","001DBF":"Radiient Technologies, Inc.","001DC0":"Enphase Energy","001DC1":"Audinate Pty L","001DC2":"Xortec Oy","001DC3":"RIKOR TV Ltd","001DC4":"AIOI Systems Co. Ltd","001DC5":"Beijing Jiaxun Feihong Electricial Co. Ltd","001DC6":"SNR Inc.","001DC7":"L-3 Communications Geneva Aerospace","001DC8":"Navionics Research Inc., dba SCADAmetrics","001DC9":"GainSpan Corp.","001DCA":"PAV Electronics Limited","001DCB":"Ex?ns Development Oy","001DCC":"Ayon Cyber Security, Inc","001DCD":"ARRIS Group, Inc.","001DCE":"ARRIS Group, Inc.","001DCF":"ARRIS Group, Inc.","001DD0":"ARRIS Group, Inc.","001DD1":"ARRIS Group, Inc.","001DD2":"ARRIS Group, Inc.","001DD3":"ARRIS Group, Inc.","001DD4":"ARRIS Group, Inc.","001DD5":"ARRIS Group, Inc.","001DD6":"ARRIS Group, Inc.","001DD7":"Algolith","001DD8":"Microsoft Corporation","001DD9":"Hon Hai Precision Ind. Co. Ltd","001DDA":"Mikroelektronika spol. s r. o.","001DDB":"C-BEL Corporation","001DDC":"HangZhou DeChangLong Tech&Info Co. Ltd","001DDD":"DAT H.K. Limited","001DDE":"Zhejiang Broadcast&Television Technology Co. Ltd","001DDF":"Sunitec Enterprise Co. Ltd","001DE0":"Intel Corporation","001DE1":"Intel Corporation","001DE2":"Radionor Communications","001DE3":"Intuicom","001DE4":"Visioneered Image Systems","001DE5":"Cisco Systems Inc.","001DE6":"Cisco Systems Inc.","001DE7":"Marine Sonic Technology Ltd","001DE8":"Nikko Denki Tsushin Corporation(NDTC)","001DE9":"Nokia Danmark A/S","001DEA":"Commtest Instruments Ltd","001DEB":"DINEC International","001DEC":"Marusys","001DED":"Grid Net, Inc.","001DEE":"Nextvision Sistemas Digitais de Televis?O Ltda.","001DEF":"Trimm, Inc.","001DF0":"Vidient Systems, Inc.","001DF1":"Intego Systems, Inc.","001DF2":"Netflix, Inc.","001DF3":"SBS Science & Technology Co. Ltd","001DF4":"Magellan Technology Pty Limited","001DF5":"Sunshine Co Ltd","001DF6":"Samsung Electronics Co. Ltd","001DF7":"R. STAHL Schaltger?te GmbH","001DF8":"Webpro Vision Technology Corporation","001DF9":"Cybiotronics (Far East) Limited","001DFA":"Fujian LANDI Commercial Equipment Co. Ltd","001DFB":"NETCLEUS Systems Corporation","001DFC":"Ksic","001DFD":"Nokia Danmark A/S","001DFE":"Palm, Inc","001DFF":"Network Critical Solutions Ltd","001E00":"Shantou Institute Of Ultrasonic Instruments","001E01":"Renesas Technology Sales Co. Ltd","001E02":"Sougou Keikaku Kougyou Co. Ltd","001E03":"LiComm Co. Ltd","001E04":"Hanson Research Corporation","001E05":"Xseed Technologies & Computing","001E06":"Wibrain","001E07":"Winy Technology Co. Ltd","001E08":"Centec Networks Inc","001E09":"ZEFATEK Co. Ltd","001E0A":"Syba Tech Limited","001E0B":"Hewlett-Packard Company","001E0C":"Sherwood Information Partners, Inc.","001E0D":"Micran Ltd","001E0E":"Maxi View Holdings Limited","001E0F":"Briot International","001E10":"Huawei Technologies Co. Ltd","001E11":"Elelux International Ltd","001E12":"Ecolab","001E13":"Cisco Systems Inc.","001E14":"Cisco Systems Inc.","001E15":"Beech Hill Electronics","001E16":"Keytronix","001E17":"STN BV","001E18":"Radio Activity srl","001E19":"Gtri","001E1A":"Best Source Taiwan Inc.","001E1B":"Digital Stream Technology, Inc.","001E1C":"SWS Australia Pty Limited","001E1D":"East Coast Datacom, Inc.","001E1E":"Honeywell Life Safety","001E1F":"Nortel Networks","001E20":"Intertain Inc.","001E21":"Qisda Corporation","001E22":"ARVOO Imaging Products BV","001E23":"Electronic Educational Devices, Inc","001E24":"Zhejiang Bell Technology Co. Ltd","001E25":"Intek Digital","001E26":"Digifriends Co. Ltd","001E27":"SBN TECH Co. Ltd","001E28":"Lumexis Corporation","001E29":"Hypertherm Inc","001E2A":"Netgear","001E2B":"Radio Systems Design, Inc.","001E2C":"CyVerse Corporation","001E2D":"Stim","001E2E":"SIRTI S.p.A.","001E2F":"DiMoto Pty Ltd","001E30":"Shireen Inc","001E31":"Infomark Co. Ltd","001E32":"Zensys","001E33":"INVENTEC Corporation","001E34":"CryptoMetrics","001E35":"Nintendo Co. Ltd","001E36":"Ipte","001E37":"Universal Global Scientific Industrial Co. Ltd","001E38":"Bluecard Software Technology Co. Ltd","001E39":"Comsys Communication Ltd","001E3A":"Nokia Danmark A/S","001E3B":"Nokia Danmark A/S","001E3C":"Lyngbox Media AB","001E3D":"Alps Electric Co. Ltd","001E3E":"KMW Inc.","001E3F":"TrellisWare Technologies, Inc.","001E40":"Shanghai DareGlobal Technologies Co. Ltd","001E41":"Microwave Communication & Component, Inc.","001E42":"Teltonika","001E43":"Aisin AW Co. Ltd","001E44":"Santec","001E45":"Sony Mobile Communications AB","001E46":"ARRIS Group, Inc.","001E47":"PT. Hariff Daya Tunggal Engineering","001E48":"Wi-Links","001E49":"Cisco Systems Inc.","001E4A":"Cisco Systems Inc.","001E4B":"City Theatrical","001E4C":"Hon Hai Precision Ind. Co. Ltd","001E4D":"Welkin Sciences, LLC","001E4E":"DAKO EDV-Ingenieur- und Systemhaus GmbH","001E4F":"Dell Inc.","001E50":"Battistoni Research","001E51":"Converter Industry Srl","001E52":"Apple","001E53":"Further Tech Co. Ltd","001E54":"TOYO ELECTRIC Corporation","001E55":"CoWON SysTEMS,Inc.","001E56":"Bally Wulff Entertainment GmbH","001E57":"ALCOMA, spol. s r.o.","001E58":"D-Link Corporation","001E59":"Silicon Turnkey Express, LLC","001E5A":"ARRIS Group, Inc.","001E5B":"Unitron Company, Inc.","001E5C":"RB GeneralEkonomik","001E5D":"Holosys d.o.o.","001E5E":"Computime Ltd","001E5F":"KwikByte, LLC","001E60":"Digital Lighting Systems, Inc","001E61":"ITEC GmbH","001E62":"Siemon","001E63":"Vibro-Meter SA","001E64":"Intel Corporation","001E65":"Intel Corporation","001E66":"RESOL Elektronische Regelungen GmbH","001E67":"Intel Corporation","001E68":"Quanta Computer Inc.","001E69":"Thomson Inc.","001E6A":"Beijing Bluexon Technology Co. Ltd","001E6B":"Cisco SPVTG","001E6C":"Opaque Systems","001E6D":"IT R&D Center","001E6E":"Shenzhen First Mile Communications Ltd","001E6F":"Magna-Power Electronics, Inc.","001E70":"Cobham Defence Communications Ltd","001E71":"MIrcom Group Of Companies","001E72":"PCS","001E73":"zte Corporation","001E74":"Sagemcom Broadband SAS","001E75":"LG Electronics (Mobile Communications)","001E76":"Thermo Fisher Scientific","001E77":"Air2App","001E78":"Owitek Technology Ltd,","001E79":"Cisco Systems Inc.","001E7A":"Cisco Systems Inc.","001E7B":"R.I.Co. S.r.l.","001E7C":"Taiwick Limited","001E7D":"Samsung Electronics Co. Ltd","001E7E":"Nortel Networks","001E7F":"CBM Of America","001E80":"Last Mile Ltd","001E81":"CNB Technology Inc.","001E82":"SanDisk Corporation","001E83":"LAN/MAN Standards Association (LMSC)","001E84":"Pika Technologies Inc.","001E85":"Lagotek Corporation","001E86":"MEL Co. Ltd","001E87":"Realease Limited","001E88":"Andor System Support Co. Ltd","001E89":"CRFS Limited","001E8A":"eCopy, Inc","001E8B":"Infra Access Korea Co. Ltd","001E8C":"ASUSTek Computer Inc.","001E8D":"ARRIS Group, Inc.","001E8E":"Hunkeler AG","001E8F":"Canon Inc.","001E90":"Elitegroup Computer Systems Co. Ltd","001E91":"KIMIN Electronic Co. Ltd","001E92":"Jeulin S.A.","001E93":"CiriTech Systems Inc","001E94":"Supercom Technology Corporation","001E95":"Sigmalink","001E96":"Sepura Plc","001E97":"Medium Link System Technology Co. Ltd,","001E98":"GreenLine Communications","001E99":"Vantanol Industrial Corporation","001E9A":"HAMILTON Bonaduz AG","001E9B":"San-Eisha Ltd","001E9C":"Fidustron Inc","001E9D":"Recall Technologies, Inc.","001E9E":"ddm hopt + schuler GmbH + Co. KG","001E9F":"Visioneering Systems, Inc.","001EA0":"XLN-t","001EA1":"Brunata a/s","001EA2":"Symx Systems, Inc.","001EA3":"Nokia Danmark A/S","001EA4":"Nokia Danmark A/S","001EA5":"ROBOTOUS, Inc.","001EA6":"Best IT World (India) Pvt. Ltd","001EA7":"Actiontec Electronics, Inc","001EA8":"Datang Mobile Communications Equipment Co. Ltd","001EA9":"Nintendo Co. Ltd","001EAA":"E-Senza Technologies GmbH","001EAB":"TeleWell Oy","001EAC":"Armadeus Systems","001EAD":"Wingtech Group Limited","001EAE":"Continental Automotive Systems Inc.","001EAF":"Ophir Optronics Ltd","001EB0":"ImesD Electronica S.L.","001EB1":"Cryptsoft Pty Ltd","001EB2":"LG innotek","001EB3":"Primex Wireless","001EB4":"Unifat Technology Ltd","001EB5":"Ever Sparkle Technologies Ltd","001EB6":"TAG Heuer SA","001EB7":"TBTech, Co. Ltd","001EB8":"Fortis, Inc.","001EB9":"Sing Fai Technology Limited","001EBA":"High Density Devices AS","001EBB":"Bluelight Technology Inc.","001EBC":"Wintech Automation Co. Ltd","001EBD":"Cisco Systems Inc.","001EBE":"Cisco Systems Inc.","001EBF":"Haas Automation Inc.","001EC0":"Microchip Technology Inc.","001EC1":"3Com Europe Ltd","001EC2":"Apple","001EC3":"Kozio, Inc.","001EC4":"Celio Corp","001EC5":"Middle Atlantic Products Inc","001EC6":"Obvius Holdings LLC","001EC7":"2Wire Inc.","001EC8":"Rapid Mobile (Pty) Ltd","001EC9":"Dell Inc.","001ECA":"Nortel Networks","001ECB":"RPC Energoautomatika Ltd","001ECC":"Cdvi","001ECD":"KYLAND Technology Co. Ltd","001ECE":"BISA Technologies (Hong Kong) Limited","001ECF":"Philips Electronics UK Ltd","001ED0":"Ingespace","001ED1":"Keyprocessor B.V.","001ED2":"Ray Shine Video Technology Inc","001ED3":"Dot Technology Int'l Co. Ltd","001ED4":"Doble Engineering","001ED5":"Tekon-Automatics","001ED6":"Alentec & Orion AB","001ED7":"H-Stream Wireless, Inc.","001ED8":"Digital United Inc.","001ED9":"Mitsubishi Precision Co. Ltd","001EDA":"Wesemann Elektrotechniek B.V.","001EDB":"Giken Trastem Co. Ltd","001EDC":"Sony Mobile Communications AB","001EDD":"Wasko S.A.","001EDE":"BYD Company Limited","001EDF":"Master Industrialization Center Kista","001EE0":"Urmet Domus SpA","001EE1":"Samsung Electronics Co. Ltd","001EE2":"Samsung Electronics Co. Ltd","001EE3":"T&W Electronics (ShenZhen) Co. Ltd","001EE4":"ACS Solutions France","001EE5":"Cisco-Linksys LLC","001EE6":"Shenzhen Advanced Video Info-Tech Co. Ltd","001EE7":"Epic Systems Inc","001EE8":"Mytek","001EE9":"Stoneridge Electronics AB","001EEA":"Sensor Switch, Inc.","001EEB":"Talk-A-Phone Co.","001EEC":"Compal Information (Kunshan) Co. Ltd","001EED":"Adventiq Ltd","001EEE":"ETL Systems Ltd","001EEF":"Cantronic International Limited","001EF0":"Gigafin Networks","001EF1":"Servimat","001EF2":"Micro Motion Inc","001EF3":"From2","001EF4":"L-3 Communications Display Systems","001EF5":"Hitek Automated Inc.","001EF6":"Cisco Systems Inc.","001EF7":"Cisco Systems Inc.","001EF8":"Emfinity Inc.","001EF9":"Pascom Kommunikations Systeme GmbH.","001EFA":"PROTEI Ltd","001EFB":"Trio Motion Technology Ltd","001EFC":"JSC Massa-K","001EFD":"Microbit 2.0 AB","001EFE":"LEVEL s.r.o.","001EFF":"Mueller-Elektronik GmbH & Co. KG","001F00":"Nokia Danmark A/S","001F01":"Nokia Danmark A/S","001F02":"Pixelmetrix Corporation Pte Ltd","001F03":"NUM AG","001F04":"Granch Ltd","001F05":"iTAS Technology Corp.","001F06":"Integrated Dispatch Solutions","001F07":"AZTEQ Mobile","001F08":"Risco Ltd","001F09":"Jastec","001F0A":"Nortel Networks","001F0B":"Federal State Unitary Enterprise Industrial UnionElectropribor","001F0C":"Intelligent Digital Services GmbH","001F0D":"L3 Communications - Telemetry West","001F0E":"Japan Kyastem Co. Ltd","001F0F":"Select Engineered Systems","001F10":"Toledo DO Brasil Industria de Balancas Ltda","001F11":"Openmoko, Inc.","001F12":"Juniper Networks","001F13":"S.& A.S. Ltd","001F14":"NexG","001F15":"Bioscrypt Inc","001F16":"Wistron Corporation","001F17":"IDX Company Ltd","001F18":"Hakusan.Mfg.Co,.Ltd","001F19":"BEN-RI Electronica S.A.","001F1A":"Prominvest","001F1B":"RoyalTek Company Ltd","001F1C":"KOBISHI ELECTRIC Co. Ltd","001F1D":"Atlas Material Testing Technology LLC","001F1E":"Astec Technology Co. Ltd","001F1F":"Edimax Technology Co. Ltd","001F20":"Logitech Europe SA","001F21":"Inner Mongolia Yin An Science & Technology Development Co.,L","001F22":"Source Photonics, Inc.","001F23":"Interacoustics","001F24":"Digitview Technology Co. Ltd","001F25":"MBS GmbH","001F26":"Cisco Systems Inc.","001F27":"Cisco Systems Inc.","001F28":"HPN Supply Chain","001F29":"Hewlett-Packard Company","001F2A":"Accm","001F2B":"Orange Logic","001F2C":"Starbridge Networks","001F2D":"Electro-Optical Imaging, Inc.","001F2E":"Triangle Research Int'l Pte Ltd","001F2F":"Berker GmbH & Co. KG","001F30":"Travelping","001F31":"Radiocomp","001F32":"Nintendo Co. Ltd","001F33":"Netgear","001F34":"Lung Hwa Electronics Co. Ltd","001F35":"AIR802 LLC","001F36":"Bellwin Information Co. Ltd,","001F37":"Genesis I&C","001F38":"Positron","001F39":"Construcciones y Auxiliar de Ferrocarriles, S.A.","001F3A":"Hon Hai Precision Ind. Co. Ltd","001F3B":"Intel Corporation","001F3C":"Intel Corporation","001F3D":"Qbit GmbH","001F3E":"RP-Technik e.K.","001F3F":"AVM GmbH","001F40":"Speakercraft Inc.","001F41":"Ruckus Wireless","001F42":"Etherstack plc","001F43":"Entes Elektronik","001F44":"GE Transportation Systems","001F45":"Enterasys","001F46":"Nortel Networks","001F47":"MCS Logic Inc.","001F48":"Mojix Inc.","001F49":"Manhattan TV Ltd","001F4A":"Albentia Systems S.A.","001F4B":"Lineage Power","001F4C":"Roseman Engineering Ltd","001F4D":"Segnetics LLC","001F4E":"ConMed Linvatec","001F4F":"Thinkware Co. Ltd","001F50":"Swissdis AG","001F51":"HD Communications Corp","001F52":"UVT Unternehmensberatung fur Verkehr und Technik GmbH","001F53":"GEMAC Gesellschaft f?r Mikroelektronikanwendung Chemnitz mbH","001F54":"Lorex Technology Inc.","001F55":"Honeywell Security (China) Co. Ltd","001F56":"Digital Forecast","001F57":"Phonik Innovation Co. Ltd","001F58":"EMH Energiemesstechnik GmbH","001F59":"Kronback Tracers","001F5A":"Beckwith Electric Co.","001F5B":"Apple","001F5C":"Nokia Danmark A/S","001F5D":"Nokia Danmark A/S","001F5E":"Dyna Technology Co. Ltd","001F5F":"Blatand GmbH","001F60":"Compass Systems Corp.","001F61":"Talent Communication Networks Inc.","001F62":"JSC Stilsoft","001F63":"JSC Goodwin-Europa","001F64":"Beijing Autelan Technology Inc.","001F65":"Korea Electric Terminal Co. Ltd","001F66":"Planar LLC","001F67":"Hitachi Ltd","001F68":"Martinsson Elektronik AB","001F69":"Pingood Technology Co. Ltd","001F6A":"PacketFlux Technologies, Inc.","001F6B":"LG Electronics (Mobile Communications)","001F6C":"Cisco Systems Inc.","001F6D":"Cisco Systems Inc.","001F6E":"Vtech Engineering Corporation","001F6F":"Fujian Sunnada Communication Co. Ltd","001F70":"Botik Technologies Ltd","001F71":"xG Technology, Inc.","001F72":"QingDao Hiphone Technology Co,.Ltd","001F73":"Teraview Technology Co. Ltd","001F74":"Eigen Development","001F75":"GiBahn Media","001F76":"AirLogic Systems Inc.","001F77":"Heol Design","001F78":"Blue Fox Porini Textile","001F79":"Lodam Electronics A/S","001F7A":"WiWide Inc.","001F7B":"TechNexion Ltd","001F7C":"Witelcom AS","001F7D":"Embedded Wireless GmbH","001F7E":"ARRIS Group, Inc.","001F7F":"Phabrix Limited","001F80":"Lucas Holding bv","001F81":"Accel Semiconductor Corp","001F82":"Cal-Comp Electronics & Communications Company Ltd","001F83":"Teleplan Technology Services Sdn Bhd","001F84":"Gigle Semiconductor","001F85":"Apriva ISS, LLC","001F86":"digEcor","001F87":"Skydigital Inc.","001F88":"FMS Force Measuring Systems AG","001F89":"Signalion GmbH","001F8A":"Ellion Digital Inc.","001F8B":"Cache IQ","001F8C":"CCS Inc.","001F8D":"Ingenieurbuero Stark GmbH und Ko. KG","001F8E":"Metris USA Inc.","001F8F":"Shanghai Bellmann Digital Source Co. Ltd","001F90":"Actiontec Electronics, Inc","001F91":"DBS Lodging Technologies, LLC","001F92":"Avigilon Corporation","001F93":"Xiotech Corporation","001F94":"Lascar Electronics Ltd","001F95":"Sagemcom Broadband SAS","001F96":"Aprotech Co.Ltd","001F97":"BERTANA srl","001F98":"Daiichi-Dentsu Ltd","001F99":"SERONICS Co.Ltd","001F9A":"Nortel Networks","001F9B":"Posbro","001F9C":"Ledco","001F9D":"Cisco Systems Inc.","001F9E":"Cisco Systems Inc.","001F9F":"Thomson Telecom Belgium","001FA0":"A10 Networks","001FA1":"Gtran Inc","001FA2":"Datron World Communications, Inc.","001FA3":"T&W Electronics(Shenzhen)Co. Ltd","001FA4":"Shenzhen Gongjin Electronics Co.,LT","001FA5":"Blue-White Industries","001FA6":"Stilo srl","001FA7":"Sony Interactive Entertainment Inc.","001FA8":"Smart Energy Instruments Inc.","001FA9":"Atlanta DTH, Inc.","001FAA":"Taseon, Inc.","001FAB":"I.S High Tech.Inc","001FAC":"Goodmill Systems Ltd","001FAD":"Brown Innovations, Inc","001FAE":"Blick South Africa (Pty) Ltd","001FAF":"NextIO, Inc.","001FB0":"TimeIPS, Inc.","001FB1":"Cybertech Inc.","001FB2":"Sontheim Industrie Elektronik GmbH","001FB3":"2Wire Inc.","001FB4":"SmartShare Systems","001FB5":"I/O Interconnect Inc.","001FB6":"Chi Lin Technology Co. Ltd","001FB7":"WiMate Technologies Corp.","001FB8":"Universal Remote Control, Inc.","001FB9":"Paltronics","001FBA":"Boyoung Tech","001FBB":"Xenatech Co. Ltd","001FBC":"EVGA Corporation","001FBD":"Kyocera Wireless Corp.","001FBE":"Shenzhen Mopnet Industrial Co. Ltd","001FBF":"Fulhua Microelectronics Corp. Taiwan Branch","001FC0":"Control Express Finland Oy","001FC1":"Hanlong Technology Co. Ltd","001FC2":"Jow Tong Technology Co Ltd","001FC3":"SmartSynch, Inc","001FC4":"ARRIS Group, Inc.","001FC5":"Nintendo Co. Ltd","001FC6":"ASUSTek Computer Inc.","001FC7":"Casio Hitachi Mobile Communications Co. Ltd","001FC8":"Up-Today Industrial Co. Ltd","001FC9":"Cisco Systems Inc.","001FCA":"Cisco Systems Inc.","001FCB":"NIW Solutions","001FCC":"Samsung Electronics Co. Ltd","001FCD":"Samsung Electronics Co. Ltd","001FCE":"Qtech LLC","001FCF":"MSI Technology GmbH","001FD0":"Giga-Byte Technology Co. Ltd","001FD1":"Optex Co. Ltd","001FD2":"Commtech Technology Macao Commercial Offshore Ltd","001FD3":"RIVA Networks Inc.","001FD4":"4IPNET, Inc.","001FD5":"MICRORISC s.r.o.","001FD6":"Shenzhen Allywll","001FD7":"Telerad SA","001FD8":"A-Trust Computer Corporation","001FD9":"RSD Communications Ltd","001FDA":"Nortel Networks","001FDB":"Network Supply Corp.,","001FDC":"Mobile Safe Track Ltd","001FDD":"GDI LLC","001FDE":"Nokia Danmark A/S","001FDF":"Nokia Danmark A/S","001FE0":"EdgeVelocity Corp","001FE1":"Hon Hai Precision Ind. Co. Ltd","001FE2":"Hon Hai Precision Ind. Co. Ltd","001FE3":"LG Electronics (Mobile Communications)","001FE4":"Sony Mobile Communications AB","001FE5":"In-Circuit GmbH","001FE6":"Alphion Corporation","001FE7":"Simet","001FE8":"KURUSUGAWA Electronics Industry Inc,.","001FE9":"Printrex, Inc.","001FEA":"Applied Media Technologies Corporation","001FEB":"Trio Datacom Pty Ltd","001FEC":"Synapse ?lectronique","001FED":"Tecan Systems Inc.","001FEE":"ubisys technologies GmbH","001FEF":"Shinsei Industries Co. Ltd","001FF0":"Audio Partnership","001FF1":"Paradox Hellas S.A.","001FF2":"VIA Technologies, Inc.","001FF3":"Apple","001FF4":"Power Monitors, Inc.","001FF5":"Kongsberg Defence & Aerospace","001FF6":"PS Audio International","001FF7":"Nakajima All Precision Co. Ltd","001FF8":"Siemens AG, Sector Industry, Drive Technologies, Motion Control Systems","001FF9":"Advanced Knowledge Associates","001FFA":"Coretree, Co Ltd","001FFB":"Green Packet Bhd","001FFC":"Riccius+Sohn GmbH","001FFD":"Indigo Mobile Technologies Corp.","001FFE":"HPN Supply Chain","001FFF":"Respironics, Inc.","002000":"Lexmark International, Inc.","002001":"DSP Solutions, Inc.","002002":"Seritech Enterprise Co. Ltd","002003":"Pixel Power Ltd","002004":"Yamatake-Honeywell Co. Ltd","002005":"Simple Technology","002006":"Garrett Communications, Inc.","002007":"SFA, Inc.","002008":"Cable & Computer Technology","002009":"Packard Bell Elec., Inc.","00200A":"Source-Comm Corp.","00200B":"Octagon Systems Corp.","00200C":"Adastra Systems Corp.","00200D":"Carl Zeiss","00200E":"NSSLGlobal Technologies AS","00200F":"EBRAINS Inc","002010":"Jeol System Technology Co. Ltd","002011":"Canopus Co. Ltd","002012":"Camtronics Medical Systems","002013":"Diversified Technology, Inc.","002014":"Global View Co. Ltd","002015":"Actis Computer SA","002016":"Showa Electric Wire & Cable Co","002017":"Orbotech","002018":"CIS Technology Inc.","002019":"Ohler GmbH","00201A":"MRV Communications, Inc.","00201B":"Northern Telecom/Network","00201C":"Excel, Inc.","00201D":"Katana Products","00201E":"Netquest Corporation","00201F":"Best Power Technology, Inc.","002020":"Megatron Computer Industries Pty Ltd","002021":"Algorithms Software PVT. Ltd","002022":"NMS Communications","002023":"T.C. Technologies Pty. Ltd","002024":"Pacific Communication Sciences","002025":"Control Technology, Inc.","002026":"Amkly Systems, Inc.","002027":"Ming Fortune Industry Co. Ltd","002028":"West EGG Systems, Inc.","002029":"Teleprocessing Products, Inc.","00202A":"N.V. Dzine","00202B":"Advanced Telecommunications Modules Ltd","00202C":"Welltronix Co. Ltd","00202D":"Taiyo Corporation","00202E":"Daystar Digital","00202F":"Zeta Communications Ltd","002030":"Analog & Digital Systems","002031":"Tattile SRL","002032":"Alcatel Taisel","002033":"Synapse Technologies, Inc.","002034":"Rotec Industrieautomation GmbH","002035":"IBM Corp","002036":"BMC Software","002037":"Seagate Technology","002038":"VME Microsystems International Corporation","002039":"Scinets","00203A":"Digital BI0METRICS Inc.","00203B":"Wisdm Ltd","00203C":"Eurotime AB","00203D":"Honeywell ECC","00203E":"LogiCan Technologies, Inc.","00203F":"Juki Corporation","002040":"ARRIS Group, Inc.","002041":"Data NET","002042":"Datametrics Corp.","002043":"Neuron Company Limited","002044":"Genitech Pty Ltd","002045":"ION Networks, Inc.","002046":"Ciprico, Inc.","002047":"Steinbrecher Corp.","002048":"Marconi Communications","002049":"Comtron, Inc.","00204A":"Pronet GmbH","00204B":"Autocomputer Co. Ltd","00204C":"Mitron Computer PTE Ltd","00204D":"Inovis GmbH","00204E":"Network Security Systems, Inc.","00204F":"Deutsche Aerospace AG","002050":"Korea Computer Inc.","002051":"Verilink Corporation","002052":"Ragula Systems","002053":"Huntsville Microsystems, Inc.","002054":"Sycamore Networks","002055":"Altech Co. Ltd","002056":"Neoproducts","002057":"TITZE DATENTECHNIK GmbH","002058":"Allied Signal Inc.","002059":"Miro Computer Products AG","00205A":"Computer Identics","00205B":"Kentrox, LLC","00205C":"InterNet Systems Of Florida, Inc.","00205D":"Nanomatic Oy","00205E":"Castle Rock, Inc.","00205F":"Gammadata Computer GmbH","002060":"ALCATEL ITALIA S.p.A.","002061":"GarrettCom, Inc.","002062":"Scorpion Logic Ltd","002063":"Wipro Infotech Ltd","002064":"Protec Microsystems, Inc.","002065":"Supernet Networking Inc.","002066":"General Magic, Inc.","002067":"Private","002068":"Isdyne","002069":"Isdn Systems Corporation","00206A":"Osaka Computer Corp.","00206B":"Konica Minolta Holdings, Inc.","00206C":"Evergreen Technology Corp.","00206D":"Data Race, Inc.","00206E":"Xact, Inc.","00206F":"Flowpoint Corporation","002070":"Hynet Ltd","002071":"IBR GmbH","002072":"Worklink Innovations","002073":"Fusion Systems Corporation","002074":"Sungwoon Systems","002075":"Motorola Communication Israel","002076":"Reudo Corporation","002077":"Kardios Systems Corp.","002078":"Runtop, Inc.","002079":"Mikron GmbH","00207A":"WiSE Communications, Inc.","00207B":"Intel Corporation","00207C":"Autec GmbH","00207D":"Advanced Computer Applications","00207E":"Finecom Co. Ltd","00207F":"Kyoei Sangyo Co. Ltd","002080":"Synergy (UK) Ltd","002081":"Titan Electronics","002082":"Oneac Corporation","002083":"Presticom Incorporated","002084":"OCE Printing Systems, GmbH","002085":"Eaton Corporation","002086":"Microtech Electronics Limited","002087":"Memotec, Inc.","002088":"Global Village Communication","002089":"T3PLUS Networking, Inc.","00208A":"Sonix Communications Ltd","00208B":"Lapis Technologies, Inc.","00208C":"Galaxy Networks, Inc.","00208D":"CMD Technology","00208E":"Chevin Software ENG. Ltd","00208F":"ECI Telecom Ltd","002090":"Advanced Compression Technology, Inc.","002091":"J125, National Security Agency","002092":"Chess Engineering B.V.","002093":"Landings Technology Corp.","002094":"Cubix Corporation","002095":"Riva Electronics","002096":"Invensys","002097":"Applied Signal Technology","002098":"Hectronic AB","002099":"BON Electric Co. Ltd","00209A":"THE 3DO Company","00209B":"Ersat Electronic GmbH","00209C":"Primary Access Corp.","00209D":"Lippert Automationstechnik","00209E":"Brown'S Operating System Services Ltd","00209F":"Mercury Computer Systems, Inc.","0020A0":"OA Laboratory Co. Ltd","0020A1":"Dovatron","0020A2":"Galcom Networking Ltd","0020A3":"Harmonic, Inc","0020A4":"Multipoint Networks","0020A5":"API Engineering","0020A6":"Proxim Wireless","0020A7":"Pairgain Technologies, Inc.","0020A8":"Sast Technology Corp.","0020A9":"White Horse Industrial","0020AA":"Ericsson Television Limited","0020AB":"Micro Industries Corp.","0020AC":"Interflex Datensysteme GmbH","0020AD":"Linq Systems","0020AE":"Ornet Data Communication Tech.","0020AF":"3Com Corporation","0020B0":"Gateway Devices, Inc.","0020B1":"Comtech Research Inc.","0020B2":"GKD Gesellschaft Fur Kommunikation Und Datentechnik","0020B3":"Tattile SRL","0020B4":"Terma Elektronik AS","0020B5":"Yaskawa Electric Corporation","0020B6":"Agile Networks, Inc.","0020B7":"Namaqua Computerware","0020B8":"Prime Option, Inc.","0020B9":"Metricom, Inc.","0020BA":"Center FOR High Performance","0020BB":"ZAX Corporation","0020BC":"Long Reach Networks Pty Ltd","0020BD":"Niobrara R & D Corporation","0020BE":"LAN Access Corp.","0020BF":"Aehr Test Systems","0020C0":"Pulse Electronics, Inc.","0020C1":"SAXA, Inc.","0020C2":"Texas Memory Systems, Inc.","0020C3":"Counter Solutions Ltd","0020C4":"Inet,Inc.","0020C5":"Eagle Technology","0020C6":"Nectec","0020C7":"AKAI Professional M.I. Corp.","0020C8":"Larscom Incorporated","0020C9":"Victron BV","0020CA":"Digital Ocean","0020CB":"Pretec Electronics Corp.","0020CC":"Digital Services Ltd","0020CD":"Hybrid Networks, Inc.","0020CE":"Logical Design Group, Inc.","0020CF":"Test & Measurement Systems Inc","0020D0":"Versalynx Corporation","0020D1":"Microcomputer Systems (M) SDN.","0020D2":"RAD Data Communications Ltd","0020D3":"OST (Ouest Standard Telematiqu","0020D4":"Cabletron Systems, Inc.","0020D5":"Vipa GmbH","0020D6":"Breezecom Ltd","0020D7":"JAPAN MINICOMPUTER SysTEMS Co. Ltd","0020D8":"Nortel Networks","0020D9":"Panasonic Technologies, Inc./Mieco-US","0020DA":"Alcatel-Lucent Enterprise","0020DB":"Xnet Technology, Inc.","0020DC":"Densitron Taiwan Ltd","0020DD":"Cybertec Pty Ltd","0020DE":"Japan Digital Laborat'Y Co.Ltd","0020DF":"Kyosan Electric MFG. Co. Ltd","0020E0":"Actiontec Electronics, Inc","0020E1":"Alamar Electronics","0020E2":"Information Resource Engineering","0020E3":"MCD Kencom Corporation","0020E4":"Hsing Tech Enterprise Co. Ltd","0020E5":"Apex Data, Inc.","0020E6":"Lidkoping Machine Tools AB","0020E7":"B&W Nuclear Service Company","0020E8":"Datatrek Corporation","0020E9":"Dantel","0020EA":"Efficient Networks, Inc.","0020EB":"Cincinnati Microwave, Inc.","0020EC":"Techware Systems Corp.","0020ED":"Giga-Byte Technology Co. Ltd","0020EE":"Gtech Corporation","0020EF":"USC Corporation","0020F0":"Universal Microelectronics Co.","0020F1":"Altos India Limited","0020F2":"Oracle Corporation","0020F3":"Raynet Corporation","0020F4":"Spectrix Corporation","0020F5":"Pandatel AG","0020F6":"NET TEK AND Karlnet, Inc.","0020F7":"Cyberdata Corporation","0020F8":"Carrera Computers, Inc.","0020F9":"Paralink Networks, Inc.","0020FA":"GDE Systems, Inc.","0020FB":"Octel Communications Corp.","0020FC":"Matrox","0020FD":"ITV Technologies, Inc.","0020FE":"Topware Inc. / Grand Computer","0020FF":"Symmetrical Technologies","002100":"Gemtek Technology Co. Ltd","002101":"Aplicaciones Electronicas Quasar (AEQ)","002102":"UpdateLogic Inc.","002103":"GHI Electronics, LLC","002104":"Gigaset Communications GmbH","002105":"Alcatel-Lucent IPD","002106":"RIM Testing Services","002107":"Seowonintech Co Ltd","002108":"Nokia Danmark A/S","002109":"Nokia Danmark A/S","00210A":"byd:sign Corporation","00210B":"Gemini Traze Rfid PVT. Ltd","00210C":"Cymtec Systems, Inc.","00210D":"Samsin Innotec","00210E":"Orpak Systems L.t.d.","00210F":"Cernium Corp","002110":"Clearbox Systems","002111":"Uniphone Inc.","002112":"Wiscom System Co. Ltd","002113":"Padtec S/A","002114":"Hylab Technology Inc.","002115":"PHYWE Systeme GmbH & Co. KG","002116":"Transcon Electronic Systems, spol. s r. o.","002117":"Tellord","002118":"Athena Tech, Inc.","002119":"Samsung Electro Mechanics Co. Ltd","00211A":"LInTech Corporation","00211B":"Cisco Systems Inc.","00211C":"Cisco Systems Inc.","00211D":"Dataline AB","00211E":"ARRIS Group, Inc.","00211F":"Shinsung Deltatech Co. Ltd","002120":"Sequel Technologies","002121":"VRmagic GmbH","002122":"Chip-pro Ltd","002123":"Aerosat Avionics","002124":"Optos Plc","002125":"KUK JE TONG SHIN Co. Ltd","002126":"Shenzhen Torch Equipment Co. Ltd","002127":"TP-Link Technologies Co. Ltd","002128":"Oracle Corporation","002129":"Cisco-Linksys LLC","00212A":"Audiovox Corporation","00212B":"MSA Auer","00212C":"SemIndia System Private Limited","00212D":"Scimolex Corporation","00212E":"dresden-elektronik","00212F":"Phoebe Micro Inc.","002130":"Keico Hightech Inc.","002131":"Blynke Inc.","002132":"Masterclock, Inc.","002133":"Building B, Inc","002134":"Brandywine Communications","002135":"Alcatel-Lucent","002136":"ARRIS Group, Inc.","002137":"Bay Controls, LLC","002138":"Cepheid","002139":"Escherlogic Inc.","00213A":"Winchester Systems Inc.","00213B":"Berkshire Products, Inc","00213C":"AliphCom","00213D":"Cermetek Microelectronics, Inc.","00213E":"TomTom","00213F":"A-Team Technology Ltd","002140":"EN Technologies Inc.","002141":"Radlive","002142":"Advanced Control Systems doo","002143":"ARRIS Group, Inc.","002144":"SS Telecoms","002145":"Semptian Technologies Ltd","002146":"Sanmina-SCI","002147":"Nintendo Co. Ltd","002148":"Kaco Solar Korea","002149":"China Daheng Group ,Inc.","00214A":"Pixel Velocity, Inc","00214B":"Shenzhen HAMP Science & Technology Co. Ltd","00214C":"Samsung Electronics Co. Ltd","00214D":"Guangzhou Skytone Transmission Technology Com. Ltd","00214E":"GS Yuasa Power Supply Ltd","00214F":"Alps Electric Co. Ltd","002150":"Eyeview Electronics","002151":"Millinet Co. Ltd","002152":"General Satellite Research & Development Limited","002153":"SeaMicro Inc.","002154":"D-TACQ Solutions Ltd","002155":"Cisco Systems Inc.","002156":"Cisco Systems Inc.","002157":"National Datacast, Inc.","002158":"Style Flying Technology Co.","002159":"Juniper Networks","00215A":"Hewlett-Packard Company","00215B":"SenseAnywhere","00215C":"Intel Corporation","00215D":"Intel Corporation","00215E":"IBM Corp","00215F":"IHSE GmbH","002160":"Hidea Solutions Co. Ltd","002161":"Yournet Inc.","002162":"Nortel Networks","002163":"Askey Computer Corp","002164":"Special Design Bureau for Seismic Instrumentation","002165":"Presstek Inc.","002166":"NovAtel Inc.","002167":"HWA JIN T&I Corp.","002168":"iVeia, LLC","002169":"Prologix, LLC.","00216A":"Intel Corporation","00216B":"Intel Corporation","00216C":"Odva","00216D":"Soltech Co. Ltd","00216E":"Function ATI (Huizhou) Telecommunications Co. Ltd","00216F":"SymCom, Inc.","002170":"Dell Inc.","002171":"Wesung TNC Co. Ltd","002172":"Seoultek Valley","002173":"Ion Torrent Systems, Inc.","002174":"AvaLAN Wireless","002175":"Pacific Satellite International Ltd","002176":"YMax Telecom Ltd","002177":"W. L. Gore & Associates","002178":"Matuschek Messtechnik GmbH","002179":"IOGEAR, Inc.","00217A":"Sejin Electron, Inc.","00217B":"Bastec AB","00217C":"2Wire Inc.","00217D":"Pyxis S.R.L.","00217E":"Telit Communication s.p.a","00217F":"Intraco Technology Pte Ltd","002180":"ARRIS Group, Inc.","002181":"Si2 Microsystems Limited","002182":"SandLinks Systems Ltd","002183":"ANDRITZ HYDRO GmbH","002184":"Powersoft SRL","002185":"Micro-Star International","002186":"Universal Global Scientific Industrial Co. Ltd","002187":"Imacs GmbH","002188":"EMC Corporation","002189":"AppTech, Inc.","00218A":"Electronic Design and Manufacturing Company","00218B":"Wescon Technology, Inc.","00218C":"TopControl GmbH","00218D":"AP Router Ind. Eletronica LtdA","00218E":"Mekics Co. Ltd","00218F":"Avantgarde Acoustic Lautsprechersysteme GmbH","002190":"Goliath Solutions","002191":"D-Link Corporation","002192":"Baoding Galaxy Electronic Technology Co. Ltd","002193":"Videofon MV","002194":"Ping Communication","002195":"GWD Media Limited","002196":"Telsey S.p.A.","002197":"Elitegroup Computer Systems Co. Ltd","002198":"Thai Radio Co Ltd","002199":"Vacon Plc","00219A":"Cambridge Visual Networks Ltd","00219B":"Dell Inc.","00219C":"Honeywld Technology Corp.","00219D":"Adesys BV","00219E":"Sony Mobile Communications AB","00219F":"Satel Oy","0021A0":"Cisco Systems Inc.","0021A1":"Cisco Systems Inc.","0021A2":"EKE-Electronics Ltd","0021A3":"Micromint","0021A4":"Dbii Networks","0021A5":"ERLPhase Power Technologies Ltd","0021A6":"Videotec Spa","0021A7":"Hantle System Co. Ltd","0021A8":"Telephonics Corporation","0021A9":"Mobilink Telecom Co. Ltd","0021AA":"Nokia Danmark A/S","0021AB":"Nokia Danmark A/S","0021AC":"Infrared Integrated Systems Ltd","0021AD":"Nordic ID Oy","0021AE":"Alcatel-Lucent France - WTD","0021AF":"Radio Frequency Systems","0021B0":"Tyco Telecommunications","0021B1":"Digital Solutions Ltd","0021B2":"Fiberblaze A/S","0021B3":"Ross Controls","0021B4":"Apro Media Co. Ltd","0021B5":"Galvanic Ltd","0021B6":"Triacta Power Technologies Inc.","0021B7":"Lexmark International Inc.","0021B8":"Inphi Corporation","0021B9":"Universal Devices Inc.","0021BA":"Texas Instruments","0021BB":"Riken Keiki Co. Ltd","0021BC":"Zala Computer","0021BD":"Nintendo Co. Ltd","0021BE":"Cisco SPVTG","0021BF":"Hitachi High-Tech Control Systems Corporation","0021C0":"Mobile Appliance, Inc.","0021C1":"ABB Oy / Medium Voltage Products","0021C2":"GL Communications Inc","0021C3":"CoRNELL Communications, Inc.","0021C4":"Consilium AB","0021C5":"3DSP Corp","0021C6":"CSJ Global, Inc.","0021C7":"Russound","0021C8":"LOHUIS Networks","0021C9":"Wavecom Asia Pacific Limited","0021CA":"ART System Co. Ltd","0021CB":"SMS Tecnologia Eletronica Ltda","0021CC":"Flextronics International","0021CD":"LiveTV","0021CE":"NTC-Metrotek","0021CF":"The Crypto Group","0021D0":"Global Display Solutions Spa","0021D1":"Samsung Electronics Co. Ltd","0021D2":"Samsung Electronics Co. Ltd","0021D3":"Bocom Security(Asia Pacific) Limited","0021D4":"Vollmer Werke GmbH","0021D5":"X2E GmbH","0021D6":"LXI Consortium","0021D7":"Cisco Systems Inc.","0021D8":"Cisco Systems Inc.","0021D9":"Sekonic Corporation","0021DA":"Automation Products Group Inc.","0021DB":"Santachi Video Technology (Shenzhen) Co. Ltd","0021DC":"TECNOALARM S.r.l.","0021DD":"Northstar Systems Corp","0021DE":"Firepro Wireless","0021DF":"Martin Christ GmbH","0021E0":"CommAgility Ltd","0021E1":"Nortel Networks","0021E2":"visago Systems & Controls GmbH & Co. KG","0021E3":"SerialTek LLC","0021E4":"I-WIN","0021E5":"Display Solution AG","0021E6":"Starlight Video Limited","0021E7":"Informatics Services Corporation","0021E8":"Murata Manufacturing Co. Ltd","0021E9":"Apple","0021EA":"Bystronic Laser AG","0021EB":"ESP Systems, LLC","0021EC":"Solutronic GmbH","0021ED":"Telegesis","0021EE":"Full Spectrum Inc.","0021EF":"Kapsys","0021F0":"EW3 Technologies LLC","0021F1":"Tutus Data AB","0021F2":"EASY3CALL Technology Limited","0021F3":"Si14 SpA","0021F4":"INRange Systems, Inc","0021F5":"Western Engravers Supply, Inc.","0021F6":"Oracle Corporation","0021F7":"HPN Supply Chain","0021F8":"Enseo, Inc.","0021F9":"WIRECOM Technologies","0021FA":"A4SP Technologies Ltd","0021FB":"LG Electronics (Mobile Communications)","0021FC":"Nokia Danmark A/S","0021FD":"Lacroix Traffic S.A.U","0021FE":"Nokia Danmark A/S","0021FF":"Cyfrowy Polsat SA","002200":"IBM Corp","002201":"Aksys Networks Inc","002202":"Excito Elektronik i Sk?ne AB","002203":"Glensound Electronics Ltd","002204":"Koratek","002205":"WeLink Solutions, Inc.","002206":"Cyberdyne Inc.","002207":"Inteno Broadband Technology AB","002208":"Certicom Corp","002209":"Omron Healthcare Co. Ltd","00220A":"OnLive, Inc","00220B":"National Source Coding Center","00220C":"Cisco Systems Inc.","00220D":"Cisco Systems Inc.","00220E":"Indigo Security Co. Ltd","00220F":"MoCA (Multimedia over Coax Alliance)","002210":"ARRIS Group, Inc.","002211":"Rohati Systems","002212":"CAI Networks, Inc.","002213":"PCI Corporation","002214":"Rinnai Korea","002215":"ASUSTek Computer Inc.","002216":"Shibaura Vending Machine Corporation","002217":"Neat Electronics","002218":"Verivue Inc.","002219":"Dell Inc.","00221A":"Audio Precision","00221B":"Morega Systems","00221C":"Private","00221D":"Freegene Technology Ltd","00221E":"Media Devices Co. Ltd","00221F":"eSang Technologies Co. Ltd","002220":"Mitac Technology Corp","002221":"Itoh Denki Co Ltd","002222":"Schaffner Deutschland GmbH","002223":"TimeKeeping Systems, Inc.","002224":"Good Will Instrument Co. Ltd","002225":"Thales Avionics Ltd","002226":"Avaak, Inc.","002227":"uv-electronic GmbH","002228":"Breeze Innovations Ltd","002229":"Compumedics Ltd","00222A":"SoundEar A/S","00222B":"Nucomm, Inc.","00222C":"Ceton Corp","00222D":"SMC Networks Inc.","00222E":"maintech GmbH","00222F":"Open Grid Computing, Inc.","002230":"FutureLogic Inc.","002231":"SMT&C Co. Ltd","002232":"Design Design Technology Ltd","002233":"ADB Broadband Italia","002234":"Corventis Inc.","002235":"Strukton Systems bv","002236":"Vector SP. Z O.O.","002237":"Shinhint Group","002238":"Logiplus","002239":"Indiana Life Sciences Incorporated","00223A":"Cisco SPVTG","00223B":"Communication Networks, LLC","00223C":"RATIO Entwicklungen GmbH","00223D":"JumpGen Systems, LLC","00223E":"IRTrans GmbH","00223F":"Netgear","002240":"Universal Telecom S/A","002241":"Apple","002242":"Alacron Inc.","002243":"Azurewave Technologies Inc.","002244":"Chengdu Linkon Communications Device Co. Ltd","002245":"Leine & Linde AB","002246":"Evoc Intelligent Technology Co. Ltd","002247":"DAC Engineering Co. Ltd","002248":"Microsoft Corporation","002249":"Home Multienergy SL","00224A":"Raylase AG","00224B":"Airtech Technologies, Inc.","00224C":"Nintendo Co. Ltd","00224D":"Mitac International Corp.","00224E":"SEEnergy Corp.","00224F":"Byzoro Networks Ltd","002250":"Point Six Wireless, LLC","002251":"Lumasense Technologies","002252":"ZOLL Lifecor Corporation","002253":"Entorian Technologies","002254":"Bigelow Aerospace","002255":"Cisco Systems Inc.","002256":"Cisco Systems Inc.","002257":"3Com Europe Ltd","002258":"Taiyo Yuden Co. Ltd","002259":"Guangzhou New Postcom Equipment Co. Ltd","00225A":"Garde Security AB","00225B":"Teradici Corporation","00225C":"Multimedia & Communication Technology","00225D":"Digicable Network India Pvt. Ltd","00225E":"Uwin Technologies Co. Ltd","00225F":"Liteon Technology Corporation","002260":"AFREEY Inc.","002261":"Frontier Silicon Ltd","002262":"BEP Marine","002263":"Koos Technical Services, Inc.","002264":"Hewlett-Packard Company","002265":"Nokia Danmark A/S","002266":"Nokia Danmark A/S","002267":"Nortel Networks","002268":"Hon Hai Precision Ind. Co. Ltd","002269":"Hon Hai Precision Ind. Co. Ltd","00226A":"Honeywell","00226B":"Cisco-Linksys LLC","00226C":"LinkSprite Technologies, Inc.","00226D":"Shenzhen GIEC Electronics Co. Ltd","00226E":"Gowell Electronic Limited","00226F":"3onedata Technology Co. Ltd","002270":"ABK North America, LLC","002271":"J?ger Computergesteuerte Messtechnik GmbH.","002272":"American Micro-Fuel Device Corp.","002273":"Techway","002274":"FamilyPhone AB","002275":"Belkin International Inc.","002276":"Triple EYE B.V.","002277":"NEC Australia Pty Ltd","002278":"Shenzhen Tongfang Multimedia Technology Co. Ltd","002279":"Nippon Conlux Co. Ltd","00227A":"Telecom Design","00227B":"Apogee Labs, Inc.","00227C":"Woori SMT Co. Ltd","00227D":"YE Data Inc.","00227E":"Chengdu 30Kaitian Communication Industry Co.Ltd","00227F":"Ruckus Wireless","002280":"A2B Electronics AB","002281":"Daintree Networks Pty","002282":"8086 Consultancy","002283":"Juniper Networks","002284":"Desay A&V Science AND Technology Co. Ltd","002285":"Nomus Comm Systems","002286":"Astron","002287":"Titan Wireless LLC","002288":"Sagrad, Inc.","002289":"Optosecurity Inc.","00228A":"Teratronik elektronische Systeme GmbH","00228B":"Kensington Computer Products Group","00228C":"Photon Europe GmbH","00228D":"GBS Laboratories LLC","00228E":"TV-Numeric","00228F":"Cnrs","002290":"Cisco Systems Inc.","002291":"Cisco Systems Inc.","002292":"Cinetal","002293":"zte Corporation","002294":"Kyocera Corporation","002295":"SGM Technology for lighting spa","002296":"LinoWave Corporation","002297":"XMOS Semiconductor","002298":"Sony Mobile Communications AB","002299":"SeaMicro Inc.","00229A":"Lastar, Inc.","00229B":"AverLogic Technologies, Inc.","00229C":"Verismo Networks Inc","00229D":"Pyung-HWA Ind.Co. Ltd","00229E":"Social Aid Research Co. Ltd","00229F":"Sensys Traffic AB","0022A0":"Delphi Corporation","0022A1":"Huawei Symantec Technologies Co. Ltd","0022A2":"Xtramus Technologies","0022A3":"California Eastern Laboratories","0022A4":"2Wire Inc.","0022A5":"Texas Instruments","0022A6":"Sony Computer Entertainment America","0022A7":"Tyco Electronics AMP GmbH","0022A8":"Ouman Oy","0022A9":"LG Electronics (Mobile Communications)","0022AA":"Nintendo Co. Ltd","0022AB":"Shenzhen Turbosight Technology Ltd","0022AC":"Hangzhou Siyuan Tech. Co. Ltd","0022AD":"Telesis Technologies, Inc.","0022AE":"Mattel Inc.","0022AF":"Safety Vision","0022B0":"D-Link Corporation","0022B1":"Elbit Systems Ltd","0022B2":"4RF Communications Ltd","0022B3":"Sei S.p.A.","0022B4":"ARRIS Group, Inc.","0022B5":"Novita","0022B6":"Superflow Technologies Group","0022B7":"GSS Grundig SAT-Systems GmbH","0022B8":"Norcott","0022B9":"Analogix Seminconductor, Inc","0022BA":"HUTH Elektronik Systeme GmbH","0022BB":"beyerdynamic GmbH & Co. KG","0022BC":"JDSU France SAS","0022BD":"Cisco Systems Inc.","0022BE":"Cisco Systems Inc.","0022BF":"SieAmp Group Of Companies","0022C0":"Shenzhen Forcelink Electronic Co Ltd","0022C1":"Active Storage Inc.","0022C2":"Proview Eletr?nica do Brasil LtdA","0022C3":"Zeeport Technology Inc.","0022C4":"epro GmbH","0022C5":"InfORSON Co Ltd","0022C6":"Sutus Inc","0022C7":"SEGGER Microcontroller GmbH & Co. KG","0022C8":"Applied Instruments B.V.","0022C9":"Lenord, Bauer & Co GmbH","0022CA":"Anviz Biometric Tech. Co. Ltd","0022CB":"IONODES Inc.","0022CC":"SciLog, Inc.","0022CD":"Ared Technology Co. Ltd","0022CE":"Cisco SPVTG","0022CF":"Planex Communications Inc.","0022D0":"Polar Electro Oy","0022D1":"Albrecht Jung GmbH & Co. KG","0022D2":"All Earth Com?rcio de Eletr?nicos LtdA.","0022D3":"Hub-Tech","0022D4":"ComWorth Co. Ltd","0022D5":"Eaton Corp. Electrical Group Data Center Solutions - Pulizzi","0022D6":"Cypak AB","0022D7":"Nintendo Co. Ltd","0022D8":"Shenzhen GST Security and Safety Technology Limited","0022D9":"Fortex Industrial Ltd","0022DA":"Anatek, LLC","0022DB":"Translogic Corporation","0022DC":"Vigil Health Solutions Inc.","0022DD":"Protecta Electronics Ltd","0022DE":"OPPO Digital, Inc.","0022DF":"TAMUZ Monitors","0022E0":"Atlantic Software Technologies S.r.L.","0022E1":"ZORT Labs, LLC.","0022E2":"WABTEC Transit Division","0022E3":"Amerigon","0022E4":"Apass Technology Co. Ltd","0022E5":"Fisher-Rosemount Systems Inc.","0022E6":"Intelligent Data","0022E7":"WPS Parking Systems","0022E8":"Applition Co. Ltd","0022E9":"ProVision Communications","0022EA":"Rustelcom Inc.","0022EB":"Data Respons A/S","0022EC":"Idealbt Technology Corporation","0022ED":"TSI Power Corporation","0022EE":"Algo Communication Products Ltd","0022EF":"iWDL Technologies","0022F0":"3 Greens Aviation Limited","0022F1":"Private","0022F2":"SunPower Corp","0022F3":"Sharp Corporation","0022F4":"AMPAK Technology, Inc.","0022F5":"Advanced Realtime Tracking GmbH","0022F6":"Syracuse Research Corporation","0022F7":"Conceptronic","0022F8":"PIMA Electronic Systems Ltd","0022F9":"Pollin Electronic GmbH","0022FA":"Intel Corporation","0022FB":"Intel Corporation","0022FC":"Nokia Danmark A/S","0022FD":"Nokia Danmark A/S","0022FE":"Advanced Illumination","0022FF":"Nivis LLC","002300":"Cayee Computer Ltd","002301":"Witron Technology Limited","002302":"Cobalt Digital, Inc.","002303":"LITE-ON IT Corporation","002304":"Cisco Systems Inc.","002305":"Cisco Systems Inc.","002306":"Alps Electric Co. Ltd","002307":"Future Innovation Tech Co. Ltd","002308":"Arcadyan Technology Corporation","002309":"Janam Technologies LLC","00230A":"ARBURG GmbH & Co KG","00230B":"ARRIS Group, Inc.","00230C":"Clover Electronics Co. Ltd","00230D":"Nortel Networks","00230E":"Gorba AG","00230F":"Hirsch Electronics Corporation","002310":"LNC Technology Co. Ltd","002311":"Gloscom Co. Ltd","002312":"Apple","002313":"Qool Technologies Ltd","002314":"Intel Corporation","002315":"Intel Corporation","002316":"Kisan Electronics Co","002317":"Lasercraft Inc","002318":"Toshiba","002319":"Sielox LLC","00231A":"ITF Co. Ltd","00231B":"Danaher Motion - Kollmorgen","00231C":"Fourier Systems Ltd","00231D":"Deltacom Electronics Ltd","00231E":"Cezzer Multimedia Technologies","00231F":"Guangda Electronic & Telecommunication Technology Development Co. Ltd","002320":"Nicira Networks","002321":"Avitech International Corp","002322":"KISS Teknical Solutions, Inc.","002323":"Zylin AS","002324":"G-PRO Computer","002325":"IOLAN Holding","002326":"Fujitsu Limited","002327":"Shouyo Electronics Co. Ltd","002328":"Alcon Telecommunications Co. Ltd","002329":"DDRdrive LLC","00232A":"eonas IT-Beratung und -Entwicklung GmbH","00232B":"IRD A/S","00232C":"Senticare","00232D":"SandForce","00232E":"Kedah Electronics Engineering, LLC","00232F":"Advanced Card Systems Ltd","002330":"Dizipia, Inc.","002331":"Nintendo Co. Ltd","002332":"Apple","002333":"Cisco Systems Inc.","002334":"Cisco Systems Inc.","002335":"Linkflex Co. Ltd","002336":"METEL s.r.o.","002337":"Global Star Solutions ULC","002338":"OJ-Electronics A/S","002339":"Samsung Electronics Co. Ltd","00233A":"Samsung Electronics Co. Ltd","00233B":"C-Matic Systems Ltd","00233C":"Alflex","00233D":"Laird Technologies","00233E":"Alcatel-Lucent IPD","00233F":"Purechoice Inc","002340":"MiXTelematics","002341":"Vanderbilt International (SWE) AB","002342":"Coffee Equipment Company","002343":"TEM AG","002344":"Objective Interface Systems, Inc.","002345":"Sony Mobile Communications AB","002346":"Vestac","002347":"ProCurve Networking by HP","002348":"Sagemcom Broadband SAS","002349":"Helmholtz Centre Berlin for Material and Energy","00234A":"Private","00234B":"Inyuan Technology Inc.","00234C":"KTC AB","00234D":"Hon Hai Precision Ind. Co. Ltd","00234E":"Hon Hai Precision Ind. Co. Ltd","00234F":"Luminous Power Technologies Pvt. Ltd","002350":"LynTec","002351":"2Wire Inc.","002352":"DATASENSOR S.p.A.","002353":"F E T Elettronica snc","002354":"ASUSTek Computer Inc.","002355":"Kinco Automation(Shanghai) Ltd","002356":"Packet Forensics LLC","002357":"Pitronot Technologies and Engineering P.T.E. Ltd","002358":"Systel SA","002359":"Benchmark Electronics ( Thailand ) Public Company Limited","00235A":"Compal Information (Kunshan) Co. Ltd","00235B":"Gulfstream","00235C":"Aprius, Inc.","00235D":"Cisco Systems Inc.","00235E":"Cisco Systems Inc.","00235F":"Silicon Micro Sensors GmbH","002360":"Lookit Technology Co. Ltd","002361":"Unigen Corporation","002362":"Goldline Controls","002363":"Zhuhai Raysharp Technology Co. Ltd","002364":"Power Instruments Pte Ltd","002365":"Insta Elektro GmbH","002366":"Beijing Siasun Electronic System Co. Ltd","002367":"UniControls a.s.","002368":"Zebra Technologies Inc","002369":"Cisco-Linksys LLC","00236A":"SmartRG Inc","00236B":"Xembedded, Inc.","00236C":"Apple","00236D":"ResMed Ltd","00236E":"Burster GmbH & Co KG","00236F":"DAQ System","002370":"Snell","002371":"SOAM Systel","002372":"More Star Industrial Group Limited","002373":"GridIron Systems, Inc.","002374":"ARRIS Group, Inc.","002375":"ARRIS Group, Inc.","002376":"HTC Corporation","002377":"Isotek Electronics Ltd","002378":"GN Netcom A/S","002379":"Union Business Machines Co. Ltd","00237A":"RIM","00237B":"Whdi LLC","00237C":"Neotion","00237D":"Hewlett-Packard Company","00237E":"Elster GmbH","00237F":"Plantronics, Inc.","002380":"Nanoteq","002381":"Lengda Technology(Xiamen) Co. Ltd","002382":"Lih Rong electronic Enterprise Co. Ltd","002383":"InMage Systems Inc","002384":"GGH Engineering s.r.l.","002385":"Antipode","002386":"Tour & Andersson AB","002387":"ThinkFlood, Inc.","002388":"V.T. Telematica S.p.a.","002389":"Hangzhou H3C Technologies Co., Limited","00238A":"Ciena Corporation","00238B":"Quanta Computer Inc.","00238C":"Private","00238D":"Techno Design Co. Ltd","00238E":"ADB Broadband Italia","00238F":"Nidec Copal Corporation","002390":"Algolware Corporation","002391":"Maxian","002392":"Proteus Industries Inc.","002393":"Ajinextek","002394":"Samjeon","002395":"ARRIS Group, Inc.","002396":"Andes Technology Corporation","002397":"Westell Technologies Inc.","002398":"Vutlan sro","002399":"Samsung Electronics Co. Ltd","00239A":"EasyData Hardware GmbH","00239B":"Elster Solutions, LLC","00239C":"Juniper Networks","00239D":"Mapower Electronics Co. Ltd","00239E":"Jiangsu Lemote Technology Corporation Limited","00239F":"Institut f?r Pr?ftechnik","0023A0":"Hana CNS Co. Ltd","0023A1":"Trend Electronics Ltd","0023A2":"ARRIS Group, Inc.","0023A3":"ARRIS Group, Inc.","0023A4":"New Concepts Development Corp.","0023A5":"SageTV, LLC","0023A6":"E-Mon","0023A7":"Redpine Signals, Inc.","0023A8":"Marshall Electronics","0023A9":"Beijing Detianquan Electromechanical Equipment Co. Ltd","0023AA":"HFR, Inc.","0023AB":"Cisco Systems Inc.","0023AC":"Cisco Systems Inc.","0023AD":"Xmark Corporation","0023AE":"Dell Inc.","0023AF":"ARRIS Group, Inc.","0023B0":"CoMXION Technology Inc.","0023B1":"Longcheer Technology (Singapore) Pte Ltd","0023B2":"Intelligent Mechatronic Systems Inc","0023B3":"Lyyn AB","0023B4":"Nokia Danmark A/S","0023B5":"Ortana Ltd","0023B6":"Securite Communications / Honeywell","0023B7":"Q-Light Co. Ltd","0023B8":"Sichuan Jiuzhou Electronic Technology Co. Ltd","0023B9":"Airbus Defence and Space Deutschland GmbH","0023BA":"Chroma","0023BB":"Schmitt Industries","0023BC":"EQ-Sys GmbH","0023BD":"Digital Ally, Inc.","0023BE":"Cisco SPVTG","0023BF":"Mainpine, Inc.","0023C0":"Broadway Networks","0023C1":"Securitas Direct AB","0023C2":"SAMSUNG Electronics. Co. Ltd","0023C3":"LogMeIn, Inc.","0023C4":"Lux Lumen","0023C5":"Radiation Safety and Control Services Inc","0023C6":"SMC Corporation","0023C7":"AVSystem","0023C8":"Team-R","0023C9":"Sichuan Tianyi Information Science & Technology Stock Co. Ltd","0023CA":"Behind The Set, LLC","0023CB":"Shenzhen Full-join Technology Co. Ltd","0023CC":"Nintendo Co. Ltd","0023CD":"TP-Link Technologies Co. Ltd","0023CE":"Kita Denshi Corporation","0023CF":"Cummins-Allison Corp.","0023D0":"Uniloc USA Inc.","0023D1":"TRG","0023D2":"Inhand Electronics, Inc.","0023D3":"AirLink WiFi Networking Corp.","0023D4":"Texas Instruments","0023D5":"WAREMA electronic GmbH","0023D6":"Samsung Electronics Co. Ltd","0023D7":"Samsung Electronics Co. Ltd","0023D8":"Ball-It Oy","0023D9":"Banner Engineering","0023DA":"Industrial Computer Source (Deutschland)GmbH","0023DB":"saxnet GmbH","0023DC":"Benein, Inc","0023DD":"Elgin S.A.","0023DE":"Ansync Inc.","0023DF":"Apple","0023E0":"INO Therapeutics LLC","0023E1":"Cavena Image Products AB","0023E2":"SEA Signalisation","0023E3":"Microtronic AG","0023E4":"IPnect Co. Ltd","0023E5":"IPaXiom Networks","0023E6":"Pirkus, Inc.","0023E7":"Hinke A/S","0023E8":"Demco Corp.","0023E9":"F5 Networks, Inc.","0023EA":"Cisco Systems Inc.","0023EB":"Cisco Systems Inc.","0023EC":"Algorithmix GmbH","0023ED":"ARRIS Group, Inc.","0023EE":"ARRIS Group, Inc.","0023EF":"Zuend Systemtechnik AG","0023F0":"Shanghai Jinghan Weighing Apparatus Co. Ltd","0023F1":"Sony Mobile Communications AB","0023F2":"TVLogic","0023F3":"Glocom, Inc.","0023F4":"Masternaut","0023F5":"Wilo SE","0023F6":"Softwell Technology Co. Ltd","0023F7":"Private","0023F8":"ZyXEL Communications Corp","0023F9":"Double-Take Software, Inc.","0023FA":"RG Nets, Inc.","0023FB":"IP Datatel, LLC.","0023FC":"Ultra Stereo Labs, Inc","0023FD":"AFT Atlas Fahrzeugtechnik GmbH","0023FE":"Biodevices, SA","0023FF":"Beijing HTTC Technology Ltd","002400":"Nortel Networks","002401":"D-Link Corporation","002402":"Op-Tection GmbH","002403":"Nokia Danmark A/S","002404":"Nokia Danmark A/S","002405":"Dilog Nordic AB","002406":"Pointmobile","002407":"Telem SAS","002408":"Pacific Biosciences","002409":"The Toro Company","00240A":"US Beverage Net","00240B":"Virtual Computer Inc.","00240C":"DELEC GmbH","00240D":"OnePath Networks Ltd","00240E":"Inventec Besta Co. Ltd","00240F":"Ishii Tool & Engineering Corporation","002410":"NUETEQ Technology,Inc.","002411":"PharmaSmart LLC","002412":"Benign Technologies Co Ltd","002413":"Cisco Systems Inc.","002414":"Cisco Systems Inc.","002415":"Magnetic Autocontrol GmbH","002416":"Any Use","002417":"Thomson Telecom Belgium","002418":"Nextwave Semiconductor","002419":"Private","00241A":"Red Beetle Inc.","00241B":"iWOW Communications Pte Ltd","00241C":"FuGang Electronic (DG) Co. Ltd","00241D":"Giga-Byte Technology Co. Ltd","00241E":"Nintendo Co. Ltd","00241F":"DCT-Delta GmbH","002420":"NetUP Inc.","002421":"Micro-Star International","002422":"Knapp Logistik Automation GmbH","002423":"Azurewave Technologies Inc.","002424":"Ace Axis Limited","002425":"Shenzhenshi chuangzhicheng Technology Co. Ltd","002426":"Nohmi Bosai Ltd","002427":"SSI Computer Corp","002428":"EnergyICT","002429":"MK Master Inc.","00242A":"Hittite Microwave Corporation","00242B":"Hon Hai Precision Ind. Co. Ltd","00242C":"Hon Hai Precision Ind. Co. Ltd","00242E":"Datastrip Inc.","00242F":"Micron","002430":"Ruby Tech Corp.","002431":"Uni-v Co. Ltd","002432":"Neostar Technology Co. Ltd","002433":"Alps Electric Co. Ltd","002434":"Lectrosonics, Inc.","002435":"Wide Corporation","002436":"Apple","002437":"Motorola - BSG","002438":"Brocade Communications Systems, Inc.","002439":"Digital Barriers Advanced Technologies","00243A":"Ludl Electronic Products","00243B":"CSSI (S) Pte Ltd","00243C":"S.A.A.A.","00243D":"Emerson Appliance Motors and Controls","00243F":"Storwize, Inc.","002440":"Halo Monitoring, Inc.","002441":"Wanzl Metallwarenfabrik GmbH","002442":"Axona Limited","002443":"Nortel Networks","002444":"Nintendo Co. Ltd","002445":"Adtran Inc","002446":"MMB Research Inc.","002447":"Kaztek Systems","002448":"SpiderCloud Wireless, Inc","002449":"Shen Zhen Lite Star Electronics Technology Co. Ltd","00244A":"Voyant International","00244B":"Perceptron Inc","00244C":"Solartron Metrology Ltd","00244D":"Hokkaido Electronics Corporation","00244E":"RadChips, Inc.","00244F":"Asantron Technologies Ltd","002450":"Cisco Systems Inc.","002451":"Cisco Systems Inc.","002452":"Silicon Software GmbH","002453":"Initra d.o.o.","002454":"Samsung Electronics Co. Ltd","002455":"MuLogic BV","002456":"2Wire Inc.","002458":"PA Bastion CC","002459":"ABB Automation products GmbH","00245A":"Nanjing Panda Electronics Company Limited","00245B":"Raidon Technology, Inc.","00245C":"Design-Com Technologies Pty. Ltd","00245D":"Terberg besturingstechniek B.V.","00245E":"Hivision Co. Ltd","00245F":"Vine Telecom Co. Ltd","002460":"Giaval Science Development Co. Ltd","002461":"Shin Wang Tech.","002462":"Rayzone Corporation","002463":"Phybridge Inc","002464":"Bridge Technologies Co AS","002465":"Elentec","002466":"Unitron nv","002467":"AOC International (Europe) GmbH","002468":"Sumavision Technologies Co. Ltd","002469":"Smart Doorphones","00246A":"Solid Year Co. Ltd","00246B":"Covia, Inc.","00246C":"Aruba Networks","00246D":"Weinzierl Engineering GmbH","00246E":"Phihong USA Corp.","00246F":"Onda Communication spa","002470":"AUROTECH ultrasound AS.","002471":"Fusion MultiSystems dba Fusion-io","002472":"ReDriven Power Inc.","002473":"3Com Europe Ltd","002474":"Autronica Fire And Securirty","002475":"Compass System(Embedded Dept.)","002476":"TAP.tv","002477":"Tibbo Technology","002478":"Mag Tech Electronics Co Limited","002479":"Optec Displays, Inc.","00247A":"FU YI CHENG Technology Co. Ltd","00247B":"Actiontec Electronics, Inc","00247C":"Nokia Danmark A/S","00247D":"Nokia Danmark A/S","00247E":"Universal Global Scientific Industrial Co. Ltd","00247F":"Nortel Networks","002480":"Meteocontrol GmbH","002481":"Hewlett-Packard Company","002482":"Ruckus Wireless","002483":"LG Electronics (Mobile Communications)","002484":"Bang and Olufsen Medicom a/s","002485":"ConteXtream Ltd","002486":"DesignArt Networks","002487":"Blackboard Inc.","002488":"Centre For Development Of Telematics","002489":"Vodafone Omnitel N.V.","00248A":"Kaga Electronics Co. Ltd","00248B":"Hybus Co. Ltd","00248C":"ASUSTek Computer Inc.","00248D":"Sony Interactive Entertainment Inc.","00248E":"Infoware ZRt.","00248F":"DO-Monix","002490":"Samsung Electronics Co. Ltd","002491":"Samsung Electronics Co. Ltd","002492":"Motorola, Broadband Solutions Group","002493":"ARRIS Group, Inc.","002494":"Shenzhen Baoxin Tech Co. Ltd","002495":"ARRIS Group, Inc.","002496":"Ginzinger electronic Systems","002497":"Cisco Systems Inc.","002498":"Cisco Systems Inc.","002499":"Aquila Technologies","00249A":"Beijing Zhongchuang Telecommunication Test Co. Ltd","00249B":"Action Star Enterprise Co. Ltd","00249C":"Bimeng Comunication System Co. Ltd","00249D":"NES Technology Inc.","00249E":"ADC-Elektronik GmbH","00249F":"RIM Testing Services","0024A0":"ARRIS Group, Inc.","0024A1":"ARRIS Group, Inc.","0024A2":"Hong Kong Middleware Technology Limited","0024A3":"Sonim Technologies Inc","0024A4":"Siklu Communication","0024A5":"Buffalo.Inc","0024A6":"TELESTAR DIGITAL GmbH","0024A7":"Advanced Video Communications Inc.","0024A8":"ProCurve Networking by HP","0024A9":"Ag Leader Technology","0024AA":"Dycor Technologies Ltd","0024AB":"A7 Engineering, Inc.","0024AC":"Hangzhou DPtech Technologies Co. Ltd","0024AD":"Adolf Thies GmbH & Co. KG","0024AE":"Morpho","0024AF":"Dish Technologies Corp","0024B0":"Esab AB","0024B1":"Coulomb Technologies","0024B2":"Netgear","0024B3":"Graf-Syteco GmbH & Co. KG","0024B4":"ESCATRONIC GmbH","0024B5":"Nortel Networks","0024B6":"Seagate Technology","0024B7":"GridPoint, Inc.","0024B8":"free alliance sdn bhd","0024B9":"Wuhan Higheasy Electronic Technology Development Co.Ltd","0024BA":"Texas Instruments","0024BB":"CENTRAL Corporation","0024BC":"HuRob Co. Ltd","0024BD":"Hainzl Industriesysteme GmbH","0024BE":"Sony Corporation","0024BF":"Ciat","0024C0":"NTI Comodo Inc","0024C1":"ARRIS Group, Inc.","0024C2":"Asumo Co. Ltd","0024C3":"Cisco Systems Inc.","0024C4":"Cisco Systems Inc.","0024C5":"Meridian Audio Limited","0024C6":"Hager Electro SAS","0024C7":"Mobilarm Ltd","0024C8":"Broadband Solutions Group","0024C9":"Broadband Solutions Group","0024CA":"Tobii Technology AB","0024CB":"Autonet Mobile","0024CC":"Fascinations Toys and Gifts, Inc.","0024CD":"Willow Garage, Inc.","0024CE":"Exeltech Inc","0024CF":"Inscape Data Corporation","0024D0":"Shenzhen SOGOOD Industry Co. Ltd","0024D1":"Thomson Inc.","0024D2":"Askey Computer Corp","0024D3":"QUALICA Inc.","0024D4":"Freebox SAS","0024D5":"Winward Industrial Limited","0024D6":"Intel Corporation","0024D7":"Intel Corporation","0024D8":"IlSung Precision","0024D9":"BICOM, Inc.","0024DA":"Innovar Systems Limited","0024DB":"Alcohol Monitoring Systems","0024DC":"Juniper Networks","0024DD":"Centrak, Inc.","0024DE":"GLOBAL Technology Inc.","0024DF":"Digitalbox Europe GmbH","0024E0":"DS Tech, LLC","0024E1":"Convey Computer Corp.","0024E2":"Hasegawa Electric Co. Ltd","0024E3":"CAO Group","0024E4":"Withings","0024E5":"Seer Technology, Inc","0024E6":"In Motion Technology Inc.","0024E7":"Plaster Networks","0024E8":"Dell Inc.","0024E9":"Samsung Electronics Co. Ltd","0024EA":"iris-GmbH Infrared & Intelligent sensors","0024EB":"ClearPath Networks, Inc.","0024EC":"United Information Technology Co. Ltd","0024ED":"YT Elec. Co,.Ltd","0024EE":"Wynmax Inc.","0024EF":"Sony Mobile Communications AB","0024F0":"Seanodes","0024F1":"Shenzhen Fanhai Sanjiang Electronics Co. Ltd","0024F2":"Uniphone Telecommunication Co. Ltd","0024F3":"Nintendo Co. Ltd","0024F4":"Kaminario Ltd","0024F5":"NDS Surgical Imaging","0024F6":"Miyoshi Electronics Corporation","0024F7":"Cisco Systems Inc.","0024F8":"Technical Solutions Company Ltd","0024F9":"Cisco Systems Inc.","0024FA":"Hilger u. Kern GmbH","0024FB":"Private","0024FC":"QuoPin Co. Ltd","0024FD":"Accedian Networks Inc","0024FE":"AVM GmbH","0024FF":"QLogic Corporation","002500":"Apple","002501":"JSC Supertel","002502":"NaturalPoint","002503":"IBM Corp","002504":"Valiant Communications Limited","002505":"eks Engel GmbH & Co. KG","002506":"A.I. Antitaccheggio Italia SRL","002507":"ASTAK Inc.","002508":"Maquet Cardiopulmonary AG","002509":"SHARETRONIC Group Ltd","00250A":"Security Expert Co. Ltd","00250B":"Centrofactor Inc","00250C":"Senet Inc","00250D":"GZT Telkom-Telmor sp. z o.o.","00250E":"gt german telematics GmbH","00250F":"On-Ramp Wireless, Inc.","002510":"Pico-Tesla Magnetic Therapies","002511":"Elitegroup Computer Systems Co. Ltd","002512":"zte Corporation","002513":"CXP Digital BV","002514":"PC Worth Int'l Co. Ltd","002515":"SFR","002516":"Integrated Design Tools, Inc.","002517":"Venntis, LLC","002518":"Power PLUS Communications AG","002519":"Viaas Inc","00251A":"Psiber Data Systems Inc.","00251B":"Philips CareServant","00251C":"EDT","00251D":"DSA Encore, LLC","00251E":"Rotel Technologies","00251F":"Zynus Vision Inc.","002520":"SMA Railway Technology GmbH","002521":"Logitek Electronic Systems, Inc.","002522":"ASRock Incorporation","002523":"OCP Inc.","002524":"Lightcomm Technology Co. Ltd","002525":"CTERA Networks Ltd","002526":"Genuine Technologies Co. Ltd","002527":"Bitrode Corp.","002528":"Daido Signal Co. Ltd","002529":"Comelit Group S.P.A","00252A":"Chengdu GeeYa Technology Co. Ltd","00252B":"Stirling Energy Systems","00252C":"Entourage Systems, Inc.","00252D":"Kiryung Electronics","00252E":"Cisco SPVTG","00252F":"Energy, Inc.","002530":"Aetas Systems Inc.","002531":"Cloud Engines, Inc.","002532":"Digital Recorders","002533":"Wittenstein AG","002535":"Minimax GmbH & Co KG","002536":"Oki Electric Industry Co. Ltd","002537":"Runcom Technologies Ltd","002538":"Samsung Electronics Co. Ltd, Memory Division","002539":"IfTA GmbH","00253A":"CEVA Ltd","00253B":"din Dietmar Nocker Facilitymanagement GmbH","00253C":"2Wire Inc.","00253D":"DRS Consolidated Controls","00253E":"Sensus Metering Systems","002540":"Quasar Technologies, Inc.","002541":"Maquet Critical Care AB","002542":"Pittasoft","002543":"Moneytech","002544":"LoJack Corporation","002545":"Cisco Systems Inc.","002546":"Cisco Systems Inc.","002547":"Nokia Danmark A/S","002548":"Nokia Danmark A/S","002549":"Jeorich Tech. Co. Ltd","00254A":"RingCube Technologies, Inc.","00254B":"Apple","00254C":"Videon Central, Inc.","00254D":"Singapore Technologies Electronics Limited","00254E":"Vertex Wireless Co. Ltd","00254F":"ELETTROLAB Srl","002550":"Riverbed Technology, Inc.","002551":"SE-Elektronic GmbH","002552":"VXi Corporation","002553":"ADB Broadband Italia","002554":"Pixel8 Networks","002555":"Visonic Technologies 1993 Ltd","002556":"Hon Hai Precision Ind. Co. Ltd","002557":"BlackBerry RTS","002558":"Mpedia","002559":"Syphan Technologies Ltd","00255A":"Tantalus Systems Corp.","00255B":"CoachComm, LLC","00255C":"NEC Corporation","00255D":"Morningstar Corporation","00255E":"Shanghai Dare Technologies Co. Ltd","00255F":"SenTec AG","002560":"Ibridge Networks & Communications Ltd","002561":"ProCurve Networking by HP","002562":"interbro Co. Ltd","002563":"Luxtera Inc","002564":"Dell Inc.","002565":"Vizimax Inc.","002566":"Samsung Electronics Co. Ltd","002567":"Samsung Electronics Co. Ltd","002568":"Huawei Technologies Co. Ltd","002569":"Sagemcom Broadband SAS","00256A":"inIT - Institut Industrial IT","00256B":"ATENIX E.E. s.r.l.","00256C":"Azimut Production Association JSC","00256D":"Broadband Forum","00256E":"Van Breda B.V.","00256F":"Dantherm Power","002570":"Eastern Communications Company Limited","002571":"Zhejiang Tianle Digital Electric Co. Ltd","002572":"Nemo-Q International AB","002573":"ST Electronics (Info-Security) Pte Ltd","002574":"KUNIMI MEDIA DEVICE Co. Ltd","002575":"FiberPlex Technologies, LLC","002576":"Neli Technologies","002577":"D-BOX Technologies","002578":"JSC Concern Sozvezdie","002579":"J & F Labs","00257A":"CAMCO Produktions- und Vertriebs-GmbH f?r Beschallungs- und Beleuchtungsanlagen","00257B":"STJ Electronics PVT Ltd","00257C":"Huachentel Technology Development Co. Ltd","00257D":"PointRed Telecom Private Ltd","00257E":"NEW POS Technology Limited","00257F":"CallTechSolution Co. Ltd","002580":"Equipson S.A.","002581":"x-star networks Inc.","002582":"Maksat Technologies (P) Ltd","002583":"Cisco Systems Inc.","002584":"Cisco Systems Inc.","002585":"KOKUYO S&T Co. Ltd","002586":"TP-Link Technologies Co. Ltd","002587":"Vitality, Inc.","002588":"Genie Industries, Inc.","002589":"Hills Industries Limited","00258A":"Pole/Zero Corporation","00258B":"Mellanox Technologies, Inc.","00258C":"Esus Elektronik SAN. VE DIS. TIC. Ltd STI.","00258D":"Haier","00258E":"The Weather Channel","00258F":"Trident Microsystems, Inc.","002590":"Super Micro Computer, Inc.","002591":"NEXTEK, Inc.","002592":"Guangzhou Shirui Electronic Co. Ltd","002593":"DatNet Informatikai Kft.","002594":"Eurodesign BG Ltd","002595":"Northwest Signal Supply, Inc","002596":"GIGAVISION srl","002597":"Kalki Communication Technologies","002598":"Zhong Shan City Litai Electronic Industrial Co. Ltd","002599":"Hedon e.d. B.V.","00259A":"CEStronics GmbH","00259B":"Beijing PKUNITY Microsystems Technology Co. Ltd","00259C":"Cisco-Linksys LLC","00259D":"Private","00259E":"Huawei Technologies Co. Ltd","00259F":"TechnoDigital Technologies GmbH","0025A0":"Nintendo Co. Ltd","0025A1":"Enalasys","0025A2":"Alta Definicion LINCEO S.L.","0025A3":"Trimax Wireless, Inc.","0025A4":"EuroDesign embedded technologies GmbH","0025A5":"Walnut Media Network","0025A6":"Central Network Solution Co. Ltd","0025A7":"Comverge, Inc.","0025A8":"Kontron (BeiJing) Technology Co. Ltd","0025A9":"Shanghai Embedway Information Technologies Co. Ltd","0025AA":"Beijing Soul Technology Co. Ltd","0025AB":"AIO LCD PC BU / TPV","0025AC":"I-Tech Corporation","0025AD":"Manufacturing Resources International","0025AE":"Microsoft Corporation","0025AF":"CoMFILE Technology","0025B0":"Schmartz Inc","0025B1":"Maya-Creation Corporation","0025B2":"MBDA Deutschland GmbH","0025B3":"Hewlett-Packard Company","0025B4":"Cisco Systems Inc.","0025B5":"Cisco Systems Inc.","0025B6":"Telecom FM","0025B7":"Costar electronics, Inc.,","0025B8":"Agile Communications, Inc.","0025B9":"Cypress Solutions Inc","0025BA":"Alcatel-Lucent IPD","0025BB":"INNERINT Co. Ltd","0025BC":"Apple","0025BD":"Italdata Ingegneria dell'Idea S.p.A.","0025BE":"Tektrap Systems Inc.","0025BF":"Wireless Cables Inc.","0025C0":"ZillionTV Corporation","0025C1":"Nawoo Korea Corp.","0025C2":"RingBell Co. Ltd","0025C3":"21168","0025C4":"Ruckus Wireless","0025C5":"Star Link Communication Pvt. Ltd","0025C6":"kasercorp Ltd","0025C7":"altek Corporation","0025C8":"S-Access GmbH","0025C9":"Shenzhen Huapu Digital Co. Ltd","0025CA":"LS Research, LLC","0025CB":"Reiner SCT","0025CC":"Mobile Communications Korea Incorporated","0025CD":"Skylane Optics","0025CE":"InnerSpace","0025CF":"Nokia Danmark A/S","0025D0":"Nokia Danmark A/S","0025D1":"Eastern Asia Technology Limited","0025D2":"InpegVision Co. Ltd","0025D3":"Azurewave Technologies Inc.","0025D4":"General Dynamics Mission Systems","0025D5":"Robonica (Pty) Ltd","0025D6":"The Kroger Co.","0025D7":"Cedo","0025D8":"Korea Maintenance","0025D9":"DataFab Systems Inc.","0025DA":"Secura Key","0025DB":"ATI Electronics(Shenzhen) Co. Ltd","0025DC":"Sumitomo Electric Industries Ltd","0025DD":"Sunnytek Information Co. Ltd","0025DE":"Probits Co. Ltd","0025DF":"Private","0025E0":"CeedTec Sdn Bhd","0025E1":"Shanghai Seeyoo Electronic & Technology Co. Ltd","0025E2":"Everspring Industry Co. Ltd","0025E3":"Hanshinit Inc.","0025E4":"OMNI-WiFi, LLC","0025E5":"LG Electronics (Mobile Communications)","0025E6":"Belgian Monitoring Systems bvba","0025E7":"Sony Mobile Communications AB","0025E8":"Idaho Technology","0025E9":"i-mate Development, Inc.","0025EA":"Iphion BV","0025EB":"Reutech Radar Systems (Pty) Ltd","0025EC":"Humanware","0025ED":"NuVo Technologies LLC","0025EE":"Avtex Ltd","0025EF":"I-TEC Co. Ltd","0025F0":"Suga Electronics Limited","0025F1":"ARRIS Group, Inc.","0025F2":"ARRIS Group, Inc.","0025F3":"Nordwestdeutsche Z?hlerrevision","0025F4":"KoCo Connector AG","0025F5":"DVS Korea, Co. Ltd","0025F6":"netTALK.com, Inc.","0025F7":"Ansaldo STS USA","0025F9":"GMK electronic design GmbH","0025FA":"J&M Analytik AG","0025FB":"Tunstall Healthcare A/S","0025FC":"Enda Endustriyel Elektronik Ltd STI.","0025FD":"OBR Centrum Techniki Morskiej S.A.","0025FE":"Pilot Electronics Corporation","0025FF":"CreNova Multimedia Co. Ltd","002600":"TEAC Australia Pty Ltd","002601":"Cutera Inc","002602":"SMART Temps LLC","002603":"Shenzhen Wistar Technology Co. Ltd","002604":"Audio Processing Technology Ltd","002605":"CC Systems AB","002606":"RAUMFELD GmbH","002607":"Enabling Technology Pty Ltd","002608":"Apple","002609":"Phyllis Co. Ltd","00260A":"Cisco Systems Inc.","00260B":"Cisco Systems Inc.","00260C":"Dataram","00260D":"Mercury Systems, Inc.","00260E":"Ablaze Systems, LLC","00260F":"Linn Products Ltd","002610":"Apacewave Technologies","002611":"Licera AB","002612":"Space Exploration Technologies","002613":"Engel Axil S.L.","002614":"Ktnf","002615":"Teracom Limited","002616":"Rosemount Inc.","002617":"OEM Worldwide","002618":"ASUSTek Computer Inc.","002619":"FRC","00261A":"Femtocomm System Technology Corp.","00261B":"Laurel Bank Machines Co. Ltd","00261C":"Neovia Inc.","00261D":"CoP Security System Corp.","00261E":"Qingbang Elec(SZ) Co. Ltd","00261F":"SAE Magnetics (H.K.) Ltd","002620":"ISGUS GmbH","002621":"InteliCloud Technology Inc.","002622":"Compal Information (Kunshan) Co. Ltd","002623":"JRD Communication Inc","002624":"Thomson Inc.","002625":"MediaSputnik","002626":"Geophysical Survey Systems, Inc.","002627":"Truesell","002628":"Companytec automa??o e Controle Ltda.","002629":"Juphoon System Software Inc.","00262A":"Proxense, LLC","00262B":"Wongs Electronics Co. Ltd","00262C":"IKT Advanced Technologies s.r.o.","00262D":"Wistron Corporation","00262E":"Chengdu Jiuzhou Electronic Technology Inc","00262F":"Hamamatsu TOA Electronics","002630":"Acorel S.A.S","002631":"Commtact Ltd","002632":"Instrumentation Technologies d.d.","002633":"MIR - Medical International Research","002634":"Infineta Systems, Inc","002635":"Bluetechnix GmbH","002636":"ARRIS Group, Inc.","002637":"Samsung Electro Mechanics Co. Ltd","002638":"Xia Men Joyatech Co. Ltd","002639":"T.M. Electronics, Inc.","00263A":"Digitec Systems","00263B":"Onbnetech","00263C":"Bachmann Technology GmbH & Co. KG","00263D":"MIA Corporation","00263E":"Trapeze Networks","00263F":"LIOS Technology GmbH","002640":"Baustem Broadband Technologies Ltd","002641":"ARRIS Group, Inc.","002642":"ARRIS Group, Inc.","002643":"Alps Electric Co. Ltd","002644":"Thomson Telecom Belgium","002645":"Circontrol S.A.","002646":"Shenyang Tongfang Multimedia Technology Company Limited","002647":"WFE Technology Corp.","002648":"Emitech Corp.","00264A":"Apple","00264C":"Shanghai DigiVision Technology Co. Ltd","00264D":"Arcadyan Technology Corporation","00264E":"Rail & Road Protec GmbH","00264F":"Kr?ger &Gothe GmbH","002650":"2Wire Inc.","002651":"Cisco Systems Inc.","002652":"Cisco Systems Inc.","002653":"DaySequerra Corporation","002654":"3Com Corporation","002655":"Hewlett-Packard Company","002656":"Sansonic Electronics USA","002657":"OOO NPP Ekra","002658":"T-Platforms (Cyprus) Limited","002659":"Nintendo Co. Ltd","00265A":"D-Link Corporation","00265B":"Hitron Technologies. Inc","00265C":"Hon Hai Precision Ind. Co. Ltd","00265D":"Samsung Electronics Co. Ltd","00265E":"Hon Hai Precision Ind. Co. Ltd","00265F":"Samsung Electronics Co. Ltd","002660":"Logiways","002661":"Irumtek Co. Ltd","002662":"Actiontec Electronics, Inc","002663":"Shenzhen Huitaiwei Tech. Ltd, Co.","002664":"Core System Japan","002665":"ProtectedLogic Corporation","002666":"EFM Networks","002667":"Carecom Co. Ltd","002668":"Nokia Danmark A/S","002669":"Nokia Danmark A/S","00266A":"Essensium NV","00266B":"Shine Union Enterprise Limited","00266C":"INVENTEC Corporation","00266D":"MobileAccess Networks","00266E":"Nissho-denki Co. Ltd","00266F":"Coordiwise Technology Corp.","002670":"Cinch Connectors","002671":"AUTOVISION Co. Ltd","002672":"AAMP Of America","002673":"Ricoh Company Ltd","002674":"Electronic Solutions, Inc.","002675":"Aztech Electronics Pte Ltd","002676":"CoMMidt AS","002677":"Deif A/S","002678":"Logic Instrument SA","002679":"Euphonic Technologies, Inc.","00267A":"wuhan hongxin telecommunication technologies Co. Ltd","00267B":"GSI Helmholtzzentrum f?r Schwerionenforschung GmbH","00267C":"Metz-Werke GmbH & Co KG","00267D":"A-Max Technology Macao Commercial Offshore Company Limited","00267E":"Parrot SA","00267F":"Zenterio AB","002680":"SIL3 Pty.Ltd","002681":"Interspiro AB","002682":"Gemtek Technology Co. Ltd","002683":"Ajoho Enterprise Co. Ltd","002684":"Kisan System","002685":"Digital Innovation","002686":"Quantenna Communcations, Inc.","002687":"Corega K.K","002688":"Juniper Networks","002689":"General Dynamics Robotic Systems","00268A":"Terrier SC Ltd","00268B":"Guangzhou Escene Computer Technology Limited","00268C":"StarLeaf Ltd","00268D":"CellTel S.p.A.","00268E":"Alta Solutions, Inc.","00268F":"MTA SpA","002690":"I DO IT","002691":"Sagemcom Broadband SAS","002692":"Mitsubishi Electric Corporation","002693":"QVidium Technologies, Inc.","002694":"Senscient Ltd","002695":"ZT Group Int'l Inc","002696":"NOOLIX Co. Ltd","002697":"Alpha Technologies Inc.","002698":"Cisco Systems Inc.","002699":"Cisco Systems Inc.","00269A":"Carina System Co. Ltd","00269B":"SOKRAT Ltd","00269C":"Itus Japan Co. Ltd","00269D":"M2Mnet Co. Ltd","00269E":"Quanta Computer Inc.","00269F":"Private","0026A0":"moblic","0026A1":"Megger","0026A2":"Instrumentation Technology Systems","0026A3":"FQ Ingenieria Electronica S.A.","0026A4":"Novus Produtos Eletronicos Ltda","0026A5":"Microrobot.Co. Ltd","0026A6":"Trixell","0026A7":"Connect SRL","0026A8":"Daehap Hyper-Tech","0026A9":"Strong Technologies Pty Ltd","0026AA":"Kenmec Mechanical Engineering Co. Ltd","0026AB":"Seiko Epson Corporation","0026AC":"Shanghai LUSTER Teraband photonic Co. Ltd","0026AD":"Arada Systems, Inc.","0026AE":"Wireless Measurement Ltd","0026AF":"Duelco A/S","0026B0":"Apple","0026B1":"Navis Auto Motive Systems, Inc.","0026B2":"Setrix GmbH","0026B3":"Thales Communications Inc","0026B4":"Ford Motor Company","0026B5":"ICOMM Tele Ltd","0026B6":"Askey Computer Corp","0026B7":"Kingston Technology Company, Inc.","0026B8":"Actiontec Electronics, Inc","0026B9":"Dell Inc.","0026BA":"ARRIS Group, Inc.","0026BB":"Apple","0026BC":"General Jack Technology Ltd","0026BD":"JTEC Card & Communication Co. Ltd","0026BE":"Schoonderbeek Elektronica Systemen B.V.","0026BF":"ShenZhen Temobi Science&Tech Development Co. Ltd","0026C0":"EnergyHub","0026C1":"Artray Co. Ltd","0026C2":"SCDI Co. Ltd","0026C3":"Insightek Corp.","0026C4":"Cadmos microsystems S.r.l.","0026C5":"Guangdong Gosun Telecommunications Co. Ltd","0026C6":"Intel Corporation","0026C7":"Intel Corporation","0026C8":"System Sensor","0026C9":"Proventix Systems, Inc.","0026CA":"Cisco Systems Inc.","0026CB":"Cisco Systems Inc.","0026CC":"Nokia Danmark A/S","0026CD":"PurpleComm, Inc.","0026CE":"Kozumi USA Corp.","0026CF":"Deka R&D","0026D0":"Semihalf","0026D1":"S Squared Innovations Inc.","0026D2":"Pcube Systems, Inc.","0026D3":"Zeno Information System","0026D4":"IRCA SpA","0026D5":"Ory Solucoes em Comercio de Informatica Ltda.","0026D6":"Ningbo Andy Optoelectronic Co. Ltd","0026D7":"KM Electornic Technology Co. Ltd","0026D8":"Magic Point Inc.","0026D9":"ARRIS Group, Inc.","0026DA":"Universal Media Corporation /Slovakia/ s.r.o.","0026DB":"Ionics EMS Inc.","0026DC":"Optical Systems Design","0026DD":"Fival Science & Technology Co. Ltd","0026DE":"FDI Matelec","0026DF":"TaiDoc Technology Corp.","0026E0":"Asiteq","0026E1":"Stanford University, OpenFlow Group","0026E2":"LG Electronics (Mobile Communications)","0026E3":"DTI","0026E4":"Canal +","0026E5":"AEG Power Solutions","0026E6":"Visionhitech Co. Ltd","0026E7":"Shanghai ONLAN Communication Tech. Co. Ltd","0026E8":"Murata Manufacturing Co. Ltd","0026E9":"SP Corp","0026EA":"Cheerchip Electronic Technology (ShangHai) Co. Ltd","0026EB":"Advanced Spectrum Technology Co. Ltd","0026EC":"Legrand Home Systems, Inc","0026ED":"zte Corporation","0026EE":"TKM GmbH","0026EF":"Technology Advancement Group, Inc.","0026F0":"cTrixs International GmbH.","0026F1":"ProCurve Networking by HP","0026F2":"Netgear","0026F3":"SMC Networks","0026F4":"Nesslab","0026F5":"XRPLUS Inc.","0026F6":"Military Communication Institute","0026F7":"Nivetti Systems Pvt. Ltd","0026F8":"Golden Highway Industry Development Co. Ltd","0026F9":"S.E.M. srl","0026FA":"BandRich Inc.","0026FB":"AirDio Wireless, Inc.","0026FC":"AcSiP Technology Corp.","0026FD":"Interactive Intelligence","0026FE":"MKD Technology Inc.","0026FF":"BlackBerry RTS","002700":"Shenzhen Siglent Technology Co. Ltd","002701":"IncOstartec GmbH","002702":"SolarEdge Technologies","002703":"Testech Electronics Pte Ltd","002704":"Accelerated Concepts, Inc","002705":"Sectronic","002706":"Yoisys","002707":"Lift Complex DS, JSC","002708":"Nordiag ASA","002709":"Nintendo Co. Ltd","00270A":"IEE S.A.","00270B":"Adura Technologies","00270C":"Cisco Systems Inc.","00270D":"Cisco Systems Inc.","00270E":"Intel Corporation","00270F":"Envisionnovation Inc","002710":"Intel Corporation","002711":"LanPro Inc","002712":"MaxVision LLC","002713":"Universal Global Scientific Industrial Co. Ltd","002714":"Grainmustards, Co Ltd","002715":"Rebound Telecom. Co. Ltd","002716":"Adachi-Syokai Co. Ltd","002717":"CE Digital(Zhenjiang)Co. Ltd","002718":"Suzhou NEW SEAUNION Video Technology Co. Ltd","002719":"TP-Link Technologies Co. Ltd","00271A":"Geenovo Technology Ltd","00271B":"Alec Sicherheitssysteme GmbH","00271C":"Mercury Corporation","00271D":"Comba Telecom Systems (China) Ltd","00271E":"Xagyl Communications","00271F":"MIPRO Electronics Co. Ltd","002720":"NEW-SOL CoM","002721":"Shenzhen Baoan Fenda Industrial Co. Ltd","002722":"Ubiquiti Networks Inc.","002790":"Cisco Systems Inc.","0027E3":"Cisco Systems Inc.","0027F8":"Brocade Communications Systems, Inc.","00289F":"Semptian Co. Ltd","0028F8":"Intel Corporation","002926":"Applied Optoelectronics, Inc Taiwan Branch","002A10":"Cisco Systems Inc.","002A6A":"Cisco Systems Inc.","002AAF":"LARsys-Automation GmbH","002CC8":"Cisco Systems Inc.","002D76":"TITECH GmbH","002EC7":"Huawei Technologies Co. Ltd","002FD9":"Fiberhome Telecommunication Technologies Co. Ltd","003000":"Allwell Technology Corp.","003001":"SMP","003002":"Expand Networks","003003":"Phasys Ltd","003004":"Leadtek Research Inc.","003005":"Fujitsu Siemens Computers","003006":"Superpower Computer","003007":"Opti, Inc.","003008":"Avio Digital, Inc.","003009":"Tachion Networks, Inc.","00300A":"Aztech Electronics Pte Ltd","00300B":"mPHASE Technologies, Inc.","00300C":"Congruency Ltd","00300D":"MMC Technology, Inc.","00300E":"Klotz Digital AG","00300F":"IMT - Information Management T","003010":"Visionetics International","003011":"HMS Industrial Networks","003012":"Digital Engineering Ltd","003013":"NEC Corporation","003014":"Divio, Inc.","003015":"CP Clare Corp.","003016":"Ishida Co. Ltd","003017":"BlueArc UK Ltd","003018":"Jetway Information Co. Ltd","003019":"Cisco Systems Inc.","00301A":"Smartbridges PTE. Ltd","00301B":"Shuttle, Inc.","00301C":"Altvater Airdata Systems","00301D":"Skystream, Inc.","00301E":"3Com Europe Ltd","00301F":"Optical Networks, Inc.","003020":"TSI, Inc..","003021":"Hsing Tech. Enterprise Co. Ltd","003022":"Fong Kai Industrial Co. Ltd","003023":"Cogent Computer Systems, Inc.","003024":"Cisco Systems Inc.","003025":"Checkout Computer Systems Ltd","003026":"HeiTel Digital Video GmbH","003027":"Kerbango, Inc.","003028":"FASE Saldatura srl","003029":"Opicom","00302A":"Southern Information","00302B":"Inalp Networks, Inc.","00302C":"Sylantro Systems Corporation","00302D":"Quantum Bridge Communications","00302E":"Hoft & Wessel AG","00302F":"GE Aviation System","003030":"Harmonix Corporation","003031":"Lightwave Communications, Inc.","003032":"MagicRam, Inc.","003033":"Orient Telecom Co. Ltd","003034":"SET Engineering","003035":"Corning Incorporated","003036":"RMP Elektroniksysteme GmbH","003037":"Packard Bell Nec Services","003038":"XCP, Inc.","003039":"Softbook Press","00303A":"Maatel","00303B":"PowerCom Technology","00303C":"Onnto Corp.","00303D":"IVA Corporation","00303E":"Radcom Ltd","00303F":"TurboComm Tech Inc.","003040":"Cisco Systems Inc.","003041":"Saejin T & M Co. Ltd","003042":"DeTeWe-Deutsche Telephonwerke","003043":"Idream Technologies, PTE. Ltd","003044":"CradlePoint, Inc","003045":"Village Networks, Inc. (VNI)","003046":"Controlled Electronic Manageme","003047":"Nissei Electric Co. Ltd","003048":"Super Micro Computer, Inc.","003049":"Bryant Technology Ltd","00304A":"Fraunhofer IPMS","00304B":"Orbacom Systems, Inc.","00304C":"Appian Communications, Inc.","00304D":"ESI","00304E":"Bustec Production Ltd","00304F":"PLANET Technology Corporation","003050":"Versa Technology","003051":"Orbit Avionic & Communication","003052":"Elastic Networks","003053":"Basler AG","003054":"Castlenet Technology, Inc.","003055":"Renesas Technology America, Inc.","003056":"Beck IPC GmbH","003057":"QTelNet, Inc.","003058":"API Motion","003059":"Kontron Compact Computers AG","00305A":"Telgen Corporation","00305B":"Toko Inc.","00305C":"SMAR Laboratories Corp.","00305D":"Digitra Systems, Inc.","00305E":"Abelko Innovation","00305F":"Hasselblad","003060":"Powerfile, Inc.","003061":"MobyTEL","003062":"IP Video Networks Inc","003063":"Santera Systems, Inc.","003064":"Adlink Technology, Inc.","003065":"Apple","003066":"RFM","003067":"BIOSTAR Microtech Int'l Corp.","003068":"Cybernetics Tech. Co. Ltd","003069":"Impacct Technology Corp.","00306A":"Penta Media Co. Ltd","00306B":"Cmos Systems, Inc.","00306C":"Hitex Holding GmbH","00306D":"Lucent Technologies","00306E":"Hewlett-Packard Company","00306F":"Seyeon Tech. Co. Ltd","003070":"1Net Corporation","003071":"Cisco Systems Inc.","003072":"Intellibyte Inc.","003073":"International Microsystems, In","003074":"Equiinet Ltd","003075":"Adtech","003076":"Akamba Corporation","003077":"Onprem Networks","003078":"Cisco Systems Inc.","003079":"Cqos, Inc.","00307A":"Advanced Technology & Systems","00307B":"Cisco Systems Inc.","00307C":"Adid SA","00307D":"GRE America, Inc.","00307E":"Redflex Communication Systems","00307F":"Irlan Ltd","003080":"Cisco Systems Inc.","003081":"Altos C&C","003082":"Taihan Electric Wire Co. Ltd","003083":"Ivron Systems","003084":"Allied Telesyn Internaional","003085":"Cisco Systems Inc.","003086":"Transistor Devices, Inc.","003087":"Vega Grieshaber KG","003088":"Ericsson","003089":"Spectrapoint Wireless, LLC","00308A":"Nicotra Sistemi S.P.A","00308B":"Brix Networks","00308C":"Quantum Corporation","00308D":"Pinnacle Systems, Inc.","00308E":"Cross Match Technologies, Inc.","00308F":"MICRILOR, Inc.","003090":"Cyra Technologies, Inc.","003091":"Taiwan First Line Elec. Corp.","003092":"ModuNORM GmbH","003093":"Sonnet Technologies, Inc","003094":"Cisco Systems Inc.","003095":"Procomp Informatics Ltd","003096":"Cisco Systems Inc.","003097":"AB Regin","003098":"Global Converging Technologies","003099":"Boenig UND Kallenbach OHG","00309A":"Astro Terra Corp.","00309B":"Smartware","00309C":"Timing Applications, Inc.","00309D":"Nimble Microsystems, Inc.","00309E":"Workbit Corporation.","00309F":"Amber Networks","0030A0":"Tyco Submarine Systems Ltd","0030A1":"WEBGATE Inc.","0030A2":"Lightner Engineering","0030A3":"Cisco Systems Inc.","0030A4":"Woodwind Communications System","0030A5":"Active Power","0030A6":"Vianet Technologies Ltd","0030A7":"Schweitzer Engineering","0030A8":"OL'E Communications, Inc.","0030A9":"Netiverse, Inc.","0030AA":"Axus Microsystems, Inc.","0030AB":"Delta Networks, Inc.","0030AC":"Systeme Lauer GmbH & Co. Ltd","0030AD":"Shanghai Communication","0030AE":"Times N System, Inc.","0030AF":"Honeywell GmbH","0030B0":"Convergenet Technologies","0030B1":"TrunkNet","0030B2":"L-3 Sonoma EO","0030B3":"San Valley Systems, Inc.","0030B4":"Intersil Corp.","0030B5":"Tadiran Microwave Networks","0030B6":"Cisco Systems Inc.","0030B7":"Teletrol Systems, Inc.","0030B8":"RiverDelta Networks","0030B9":"Ectel","0030BA":"AC&T System Co. Ltd","0030BB":"CacheFlow, Inc.","0030BC":"Optronic AG","0030BD":"Belkin Components","0030BE":"City-Net Technology, Inc.","0030BF":"Multidata GmbH","0030C0":"Lara Technology, Inc.","0030C1":"Hewlett-Packard Company","0030C2":"Comone","0030C3":"Flueckiger Elektronik AG","0030C4":"Canon Imaging Systems Inc.","0030C5":"Cadence Design Systems, Inc.","0030C6":"Control Solutions, Inc.","0030C7":"Macromate Corp.","0030C8":"GAD Line Ltd","0030C9":"LuxN, N","0030CA":"Discovery Com","0030CB":"Omni Flow Computers, Inc.","0030CC":"Tenor Networks, Inc.","0030CD":"Conexant Systems, Inc.","0030CE":"Zaffire","0030CF":"TWO Technologies, Inc.","0030D0":"Tellabs","0030D1":"Inova Corporation","0030D2":"WIN Technologies, Co. Ltd","0030D3":"Agilent Technologies, Inc.","0030D4":"AAE Systems, Inc.","0030D5":"DResearch GmbH","0030D6":"MSC Vertriebs GmbH","0030D7":"Innovative Systems, L.L.C.","0030D8":"Sitek","0030D9":"Datacore Software Corp.","0030DA":"Comtrend Corporation","0030DB":"Mindready Solutions, Inc.","0030DC":"Rightech Corporation","0030DD":"Indigita Corporation","0030DE":"WAGO Kontakttechnik GmbH","0030DF":"KB/TEL Telecomunicaciones","0030E0":"Oxford Semiconductor Ltd","0030E1":"Network Equipment Technologies, Inc.","0030E2":"Garnet Systems Co. Ltd","0030E3":"Sedona Networks Corp.","0030E4":"Chiyoda System Riken","0030E5":"Amper Datos S.A.","0030E6":"Draeger Medical Systems, Inc.","0030E7":"CNF Mobile Solutions, Inc.","0030E8":"Ensim Corp.","0030E9":"GMA Communication Manufact'G","0030EA":"TeraForce Technology Corporation","0030EB":"Turbonet Communications, Inc.","0030EC":"Borgardt","0030ED":"Expert Magnetics Corp.","0030EE":"DSG Technology, Inc.","0030EF":"Neon Technology, Inc.","0030F0":"Uniform Industrial Corp.","0030F1":"Accton Technology Corp","0030F2":"Cisco Systems Inc.","0030F3":"At Work Computers","0030F4":"Stardot Technologies","0030F5":"Wild Lab. Ltd","0030F6":"Securelogix Corporation","0030F7":"Ramix Inc.","0030F8":"Dynapro Systems, Inc.","0030F9":"Sollae Systems Co. Ltd","0030FA":"Telica, Inc.","0030FB":"AZS Technology AG","0030FC":"Terawave Communications, Inc.","0030FD":"Integrated Systems Design","0030FE":"DSA GmbH","0030FF":"DataFab Systems Inc.","003146":"Juniper Networks","00323A":"so-logic","00336C":"SynapSense Corporation","0034DA":"LG Electronics (Mobile Communications)","0034F1":"Radicom Research, Inc.","0034FE":"Huawei Technologies Co. Ltd","00351A":"Cisco Systems Inc.","003532":"Electro-Metrics Corporation","003560":"Rosen Aviation","003676":"ARRIS Group, Inc.","0036F8":"Conti Temic microelectronic GmbH","0036FE":"SuperVision","00376D":"Murata Manufacturing Co. Ltd","0037B7":"Sagemcom Broadband SAS","0038DF":"Cisco Systems Inc.","003A7D":"Cisco Systems Inc.","003A98":"Cisco Systems Inc.","003A99":"Cisco Systems Inc.","003A9A":"Cisco Systems Inc.","003A9B":"Cisco Systems Inc.","003A9C":"Cisco Systems Inc.","003A9D":"NEC Platforms Ltd","003AAF":"BlueBit Ltd","003C10":"Cisco Systems Inc.","003CC5":"WONWOO Engineering Co. Ltd","003D41":"Hatteland Computer AS","003DE8":"LG Electronics (Mobile Communications)","003EE1":"Apple","004000":"PCI Componentes DA Amzonia Ltd","004001":"Zero One Technology Co. Ltd","004002":"Perle Systems Limited","004003":"Emerson Process Management Power & Water Solutions, Inc.","004004":"ICM Co. Ltd","004005":"ANI Communications Inc.","004006":"Sampo Technology Corporation","004007":"Telmat Informatique","004008":"A Plus Info Corporation","004009":"Tachibana Tectron Co. Ltd","00400A":"Pivotal Technologies, Inc.","00400B":"Cisco Systems Inc.","00400C":"General Micro Systems, Inc.","00400D":"Lannet Data Communications Ltd","00400E":"Memotec, Inc.","00400F":"Datacom Technologies","004010":"Sonic Systems, Inc.","004011":"Andover Controls Corporation","004012":"Windata, Inc.","004013":"NTT Data Comm. Systems Corp.","004014":"Comsoft GmbH","004015":"Ascom Infrasys AG","004016":"ADC - Global Connectivity Solutions Division","004017":"Silex Technology America","004018":"Adobe Systems, Inc.","004019":"Aeon Systems, Inc.","00401A":"Fuji Electric Co. Ltd","00401B":"Printer Systems Corp.","00401C":"AST Research, Inc.","00401D":"Invisible Software, Inc.","00401E":"ICC","00401F":"Colorgraph Ltd","004020":"CommScope Inc","004021":"Raster Graphics","004022":"Klever Computers, Inc.","004023":"Logic Corporation","004024":"Compac Inc.","004025":"Molecular Dynamics","004026":"Buffalo.Inc","004027":"SMC Massachusetts, Inc.","004028":"Netcomm Limited","004029":"Compex","00402A":"Canoga Perkins Corporation","00402B":"Trigem Computer, Inc.","00402C":"Isis Distributed Systems, Inc.","00402D":"Harris Adacom Corporation","00402E":"Precision Software, Inc.","00402F":"Xlnt Designs Inc.","004030":"GK Computer","004031":"Kokusai Electric Co. Ltd","004032":"Digital Communications","004033":"Addtron Technology Co. Ltd","004034":"Bustek Corporation","004035":"Opcom","004036":"Zoom Telephonics, Inc","004037":"SEA-Ilan, Inc.","004038":"Talent Electric Incorporated","004039":"Optec Daiichi Denko Co. Ltd","00403A":"Impact Technologies","00403B":"Synerjet International Corp.","00403C":"Forks, Inc.","00403D":"Teradata Corporation","00403E":"Raster OPS Corporation","00403F":"Ssangyong Computer Systems","004040":"Ring Access, Inc.","004041":"Fujikura Ltd","004042":"N.A.T. GmbH","004043":"Nokia Siemens Networks GmbH & Co. KG.","004044":"Qnix Computer Co. Ltd","004045":"Twinhead Corporation","004046":"UDC Research Limited","004047":"Wind River Systems","004048":"SMD Informatica S.A.","004049":"Roche Diagnostics International Ltd","00404A":"West Australian Department","00404B":"Maple Computer Systems","00404C":"Hypertec Pty Ltd","00404D":"Telecommunications Techniques","00404E":"Fluent, Inc.","00404F":"Space & Naval Warfare Systems","004050":"Ironics, Incorporated","004051":"Gracilis, Inc.","004052":"Star Technologies, Inc.","004053":"Ampro Computers","004054":"Connection Machines Services","004055":"Metronix GmbH","004056":"MCM Japan Ltd","004057":"Lockheed - Sanders","004058":"Kronos, Inc.","004059":"Yoshida Kogyo K. K.","00405A":"Goldstar Information & Comm.","00405B":"Funasset Limited","00405C":"Future Systems, Inc.","00405D":"Star-TEK, Inc.","00405E":"North Hills Israel","00405F":"AFE Computers Ltd","004060":"Comendec Ltd","004061":"Datatech Enterprises Co. Ltd","004062":"E-Systems, Inc./Garland Div.","004063":"VIA Technologies, Inc.","004064":"KLA Instruments Corporation","004065":"GTE Spacenet","004066":"APRESIA Systems Ltd","004067":"Omnibyte Corporation","004068":"Extended Systems","004069":"Lemcom Systems, Inc.","00406A":"Kentek Information Systems,Inc","00406B":"Sysgen","00406C":"Copernique","00406D":"Lanco, Inc.","00406E":"Corollary, Inc.","00406F":"Sync Research Inc.","004070":"Interware Co. Ltd","004071":"ATM Computer GmbH","004072":"Applied Innovation Inc.","004073":"Bass Associates","004074":"Cable AND Wireless","004075":"Tattile SRL","004076":"Sun Conversion Technologies","004077":"Maxton Technology Corporation","004078":"Wearnes Automation PTE Ltd","004079":"Juko Manufacture Company Ltd","00407A":"Societe D'Exploitation DU Cnit","00407B":"Scientific Atlanta","00407C":"Qume Corporation","00407D":"Extension Technology Corp.","00407E":"Evergreen Systems, Inc.","00407F":"FLIR Systems","004080":"Athenix Corporation","004081":"Mannesmann Scangraphic GmbH","004082":"Laboratory Equipment Corp.","004083":"TDA Industria de Produtos","004084":"Honeywell ACS","004085":"Saab Instruments AB","004086":"Michels & Kleberhoff Computer","004087":"Ubitrex Corporation","004088":"Mobius Technologies, Inc.","004089":"Meidensha Corporation","00408A":"TPS Teleprocessing Sys. GmbH","00408B":"Raylan Corporation","00408C":"Axis Communications AB","00408D":"THE Goodyear Tire & Rubber Co.","00408E":"Tattile SRL","00408F":"WM-Data Minfo AB","004090":"Ansel Communications","004091":"Procomp Industria Eletronica","004092":"ASP Computer Products, Inc.","004093":"Paxdata Networks Ltd","004094":"Shographics, Inc.","004095":"R.P.T. Intergroups Int'l Ltd","004096":"Cisco Systems Inc.","004097":"Datex Division Of","004098":"Dressler GmbH & Co.","004099":"Newgen Systems Corp.","00409A":"Network Express, Inc.","00409B":"HAL Computer Systems Inc.","00409C":"Transware","00409D":"Digiboard, Inc.","00409E":"Concurrent Technologies Ltd","00409F":"Telco Systems, Inc.","0040A0":"Goldstar Co. Ltd","0040A1":"Ergo Computing","0040A2":"Kingstar Technology Inc.","0040A3":"Microunity Systems Engineering","0040A4":"Rose Electronics","0040A5":"Clinicomp Intl.","0040A6":"Cray, Inc.","0040A7":"Itautec Philco S.A.","0040A8":"IMF International Ltd","0040A9":"Datacom Inc.","0040AA":"Valmet Automation","0040AB":"Roland DG Corporation","0040AC":"Super Workstation, Inc.","0040AD":"SMA Regelsysteme GmbH","0040AE":"Delta Controls, Inc.","0040AF":"Digital Products, Inc.","0040B0":"Bytex Corporation, Engineering","0040B1":"Codonics Inc.","0040B2":"Systemforschung","0040B3":"ParTech Inc.","0040B4":"Nextcom K.K.","0040B5":"Video Technology Computers Ltd","0040B6":"Computerm Corporation","0040B7":"Stealth Computer Systems","0040B8":"Idea Associates","0040B9":"Macq Electronique SA","0040BA":"Alliant Computer Systems Corp.","0040BB":"Goldstar Cable Co. Ltd","0040BC":"Algorithmics Ltd","0040BD":"Starlight Networks, Inc.","0040BE":"Boeing Defense & Space","0040BF":"Channel Systems Intern'L Inc.","0040C0":"Vista Controls Corporation","0040C1":"Bizerba-Werke Wilheim Kraut","0040C2":"Applied Computing Devices","0040C3":"Fischer AND Porter Co.","0040C4":"Kinkei System Corporation","0040C5":"Micom Communications Inc.","0040C6":"Fibernet Research, Inc.","0040C7":"Ruby Tech Corporation","0040C8":"Milan Technology Corporation","0040C9":"Ncube","0040CA":"First Internat'L Computer, Inc","0040CB":"Lanwan Technologies","0040CC":"Silcom Manuf'G Technology Inc.","0040CD":"Tera Microsystems, Inc.","0040CE":"NET-Source, Inc.","0040CF":"Strawberry Tree, Inc.","0040D0":"Mitac International Corp.","0040D1":"Fukuda Denshi Co. Ltd","0040D2":"Pagine Corporation","0040D3":"Kimpsion International Corp.","0040D4":"Gage Talker Corp.","0040D5":"Sartorius Mechatronics T&H GmbH","0040D6":"Locamation B.V.","0040D7":"Studio GEN Inc.","0040D8":"Ocean Office Automation Ltd","0040D9":"American Megatrends Inc.","0040DA":"Telspec Ltd","0040DB":"Advanced Technical Solutions","0040DC":"Tritec Electronic GmbH","0040DD":"Hong Technologies","0040DE":"Elsag Datamat spa","0040DF":"Digalog Systems, Inc.","0040E0":"Atomwide Ltd","0040E1":"Marner International, Inc.","0040E2":"Mesa Ridge Technologies, Inc.","0040E3":"Quin Systems Ltd","0040E4":"E-M Technology, Inc.","0040E5":"Sybus Corporation","0040E6":"C.A.E.N.","0040E7":"Arnos Instruments & Computer","0040E8":"Charles River Data Systems,Inc","0040E9":"Accord Systems, Inc.","0040EA":"Plain Tree Systems Inc","0040EB":"Martin Marietta Corporation","0040EC":"Mikasa System Engineering","0040ED":"Network Controls INT'Natl Inc.","0040EE":"Optimem","0040EF":"Hypercom, Inc.","0040F0":"MicroBrain,Inc.","0040F1":"Chuo Electronics Co. Ltd","0040F2":"Janich & Klass Computertechnik","0040F3":"Netcor","0040F4":"Cameo Communications, Inc.","0040F5":"OEM Engines","0040F6":"Katron Computers Inc.","0040F7":"Polaroid Corporation","0040F8":"Systemhaus Discom","0040F9":"Combinet","0040FA":"Microboards, Inc.","0040FB":"Cascade Communications","0040FC":"IBR Computer Technik GmbH","0040FD":"LXE","0040FE":"Symplex Communications","0040FF":"Telebit Corporation","0041B4":"Wuxi Zhongxing Optoelectronics Technology Co. Ltd","0041D2":"Cisco Systems Inc.","004252":"RLX Technologies","00425A":"Cisco Systems Inc.","004268":"Cisco Systems Inc.","0043FF":"Ketron S.R.L.","004501":"Versus Technology, Inc.","00464B":"Huawei Technologies Co. Ltd","004A77":"zte Corporation","004BF3":"Shenzhen Mercury Communication Technologies Co. Ltd","004D32":"Andon Health Co. Ltd","005000":"Nexo Communications, Inc.","005001":"Yamashita Systems Corp.","005002":"Omnisec AG","005003":"Xrite Inc","005004":"3Com Corporation","005006":"TAC AB","005007":"Siemens Telecommunication Systems Limited","005008":"Tiva Microcomputer Corp. (TMC)","005009":"Philips Broadband Networks","00500A":"Iris Technologies, Inc.","00500B":"Cisco Systems Inc.","00500C":"e-Tek Labs, Inc.","00500D":"Satori Electoric Co. Ltd","00500E":"Chromatis Networks, Inc.","00500F":"Cisco Systems Inc.","005010":"NovaNET Learning, Inc.","005012":"CBL - GmbH","005013":"Seagate Cloud Systems Inc","005014":"Cisco Systems Inc.","005015":"Bright Star Engineering","005016":"Molex Canada Ltd","005017":"RSR S.R.L.","005018":"AMIT, Inc.","005019":"Spring Tide Networks, Inc.","00501A":"IQinVision","00501B":"ABL Canada, Inc.","00501C":"Jatom Systems, Inc.","00501E":"Grass Valley, A Belden Brand","00501F":"MRG Systems Ltd","005020":"Mediastar Co. Ltd","005021":"EIS International, Inc.","005022":"Zonet Technology, Inc.","005023":"PG Design Electronics, Inc.","005024":"Navic Systems, Inc.","005026":"Cosystems, Inc.","005027":"Genicom Corporation","005028":"Aval Communications","005029":"1394 Printer Working Group","00502A":"Cisco Systems Inc.","00502B":"Genrad Ltd","00502C":"Soyo Computer, Inc.","00502D":"Accel, Inc.","00502E":"Cambex Corporation","00502F":"TollBridge Technologies, Inc.","005030":"Future Plus Systems","005031":"Aeroflex Laboratories, Inc.","005032":"Picazo Communications, Inc.","005033":"Mayan Networks","005036":"Netcam Ltd","005037":"Koga Electronics Co.","005038":"Dain Telecom Co. Ltd","005039":"Mariner Networks","00503A":"Datong Electronics Ltd","00503B":"Mediafire Corporation","00503C":"Tsinghua Novel Electronics","00503E":"Cisco Systems Inc.","00503F":"Anchor Games","005040":"Panasonic Electric Works Co. Ltd","005041":"Coretronic Corporation","005042":"SCI Manufacturing Singapore PTE Ltd","005043":"Marvell Semiconductor, Inc.","005044":"Asaca Corporation","005045":"Rioworks Solutions, Inc.","005046":"Menicx International Co. Ltd","005047":"Private","005048":"Infolibria","005049":"Arbor Networks Inc","00504A":"Elteco A.S.","00504B":"Barconet N.V.","00504C":"Galil Motion Control","00504D":"Tokyo Electron Device Limited","00504E":"Sierra Monitor Corp.","00504F":"Olencom Electronics","005050":"Cisco Systems Inc.","005051":"Iwatsu Electric Co. Ltd","005052":"Tiara Networks, Inc.","005053":"Cisco Systems Inc.","005054":"Cisco Systems Inc.","005055":"Doms A/S","005056":"VMware, Inc.","005057":"Broadband Access Systems","005058":"Sangoma Technologies","005059":"iBAHN","00505A":"Network Alchemy, Inc.","00505B":"Kawasaki LSI U.S.A., Inc.","00505C":"Tundo Corporation","00505E":"Digitek Micrologic S.A.","00505F":"Brand Innovators","005060":"Tandberg Telecom AS","005062":"Kouwell Electronics Corp. **","005063":"Oy Comsel System AB","005064":"CAE Electronics","005065":"TDK-Lambda Corporation","005066":"AtecoM GmbH advanced telecomunication modules","005067":"Aerocomm, Inc.","005068":"Electronic Industries Association","005069":"PixStream Incorporated","00506A":"Edeva, Inc.","00506B":"SPX-Ateg","00506C":"Beijer Electronics Products AB","00506D":"Videojet Systems","00506E":"Corder Engineering Corporation","00506F":"G-Connect","005070":"Chaintech Computer Co. Ltd","005071":"Aiwa Co. Ltd","005072":"Corvis Corporation","005073":"Cisco Systems Inc.","005074":"Advanced HI-Tech Corp.","005075":"Kestrel Solutions","005076":"IBM Corp","005077":"Prolific Technology, Inc.","005078":"Megaton House Ltd","005079":"Private","00507A":"Xpeed, Inc.","00507B":"Merlot Communications","00507C":"Videocon AG","00507D":"IFP","00507E":"Newer Technology","00507F":"DrayTek Corp.","005080":"Cisco Systems Inc.","005081":"Murata Machinery Ltd","005082":"Foresson Corporation","005083":"Gilbarco, Inc.","005084":"ATL Products","005086":"Telkom SA Ltd","005087":"Terasaki Electric Co. Ltd","005088":"Amano Corporation","005089":"Safety Management Systems","00508B":"Hewlett-Packard Company","00508C":"RSI Systems","00508D":"Abit Computer Corporation","00508E":"Optimation, Inc.","00508F":"Asita Technologies Int'l Ltd","005090":"Dctri","005091":"Netaccess, Inc.","005092":"Rigaku Corporation Osaka Plant","005093":"Boeing","005094":"ARRIS Group, Inc.","005095":"Peracom Networks","005096":"Salix Technologies, Inc.","005097":"MMC-EMBEDDED CoMPUTERTECHNIK GmbH","005098":"Globaloop Ltd","005099":"3Com Europe Ltd","00509A":"TAG Electronic Systems","00509B":"Switchcore AB","00509C":"Beta Research","00509D":"THE Industree B.V.","00509E":"Les Technologies SoftAcoustik Inc.","00509F":"Horizon Computer","0050A0":"Delta Computer Systems, Inc.","0050A1":"Carlo Gavazzi, Inc.","0050A2":"Cisco Systems Inc.","0050A3":"TransMedia Communications, Inc.","0050A4":"IO Tech, Inc.","0050A5":"Capitol Business Systems Ltd","0050A6":"Optronics","0050A7":"Cisco Systems Inc.","0050A8":"OpenCon Systems, Inc.","0050A9":"Moldat Wireless Technolgies","0050AA":"Konica Minolta Holdings, Inc.","0050AB":"NALTEC, Inc.","0050AC":"Maple Computer Corporation","0050AD":"CommUnique Wireless Corp.","0050AE":"FDK Co. Ltd","0050AF":"Intergon, Inc.","0050B0":"Technology Atlanta Corporation","0050B1":"Giddings & Lewis","0050B2":"BRODEL GmbH","0050B3":"Voiceboard Corporation","0050B4":"Satchwell Control Systems Ltd","0050B5":"Fichet Securite Electronique","0050B6":"Good WAY Ind. Co. Ltd","0050B7":"Boser Technology Co. Ltd","0050B8":"Inova Computers GmbH & Co. KG","0050B9":"Xitron Technologies, Inc.","0050BA":"D-Link Corporation","0050BB":"CMS Technologies","0050BC":"Hammer Storage Solutions","0050BD":"Cisco Systems Inc.","0050BE":"Fast Multimedia AG","0050BF":"Metalligence Technology Corp.","0050C0":"Gatan, Inc.","0050C1":"Gemflex Networks Ltd","0050C2":"IEEE Registration Authority","0050C4":"IMD","0050C5":"ADS Technologies, Inc","0050C6":"Loop Telecommunication International, Inc.","0050C7":"Private","0050C8":"Addonics Technologies, Inc.","0050C9":"Maspro Denkoh Corp.","0050CA":"NET TO NET Technologies","0050CB":"Jetter","0050CC":"Seagate Cloud Systems Inc","0050CD":"Digianswer A/S","0050CE":"LG International Corp.","0050CF":"Vanlink Communication Technology Research Institute","0050D0":"Minerva Systems","0050D1":"Cisco Systems Inc.","0050D2":"CMC Electronics Inc","0050D3":"Digital Audio Processing Pty. Ltd","0050D4":"Joohong Information &","0050D5":"AD Systems Corp.","0050D6":"Atlas Copco Tools AB","0050D7":"Telstrat","0050D8":"Unicorn Computer Corp.","0050D9":"ENGETRON-ENGENHARIA ELETRONICA Ind. e CoM. LtdA","0050DA":"3Com Corporation","0050DB":"Contemporary Control","0050DC":"TAS Telefonbau A. Schwabe GmbH & Co. KG","0050DD":"Serra Soldadura, S.A.","0050DE":"Signum Systems Corp.","0050DF":"AirFiber, Inc.","0050E1":"NS Tech Electronics SDN BHD","0050E2":"Cisco Systems Inc.","0050E3":"ARRIS Group, Inc.","0050E4":"Apple","0050E6":"Hakusan Corporation","0050E7":"Paradise Innovations (Asia)","0050E8":"Nomadix Inc.","0050EA":"XEL Communications, Inc.","0050EB":"Alpha-TOP Corporation","0050EC":"Olicom A/S","0050ED":"Anda Networks","0050EE":"TEK Digitel Corporation","0050EF":"SPE Systemhaus GmbH","0050F0":"Cisco Systems Inc.","0050F1":"Intel Corporation","0050F2":"Microsoft Corporation","0050F3":"GLOBAL NET InfORMATION Co. Ltd","0050F4":"Sigmatek GmbH & Co. KG","0050F6":"PAN-International Industrial Corp.","0050F7":"Venture Manufacturing (Singapore) Ltd","0050F8":"Entrega Technologies, Inc.","0050F9":"Sensormatic Electronics LLC","0050FA":"Oxtel Ltd","0050FB":"VSK Electronics","0050FC":"Edimax Technology Co. Ltd","0050FD":"Visioncomm Co. Ltd","0050FE":"PCTVnet ASA","0050FF":"Hakko Electronics Co. Ltd","005218":"Wuxi Keboda Electron Co.Ltd","00549F":"Avaya Inc","0054AF":"Continental Automotive Systems Inc.","0054BD":"Swelaser AB","0055DA":"IEEE Registration Authority","00562B":"Cisco Systems Inc.","0056CD":"Apple","0057D2":"Cisco Systems Inc.","00583F":"PC Aquarius","005907":"LenovoEMC Products USA, LLC","005979":"Networked Energy Services","0059AC":"KPN. B.V.","0059DC":"Cisco Systems Inc.","005A13":"Huawei Technologies Co. Ltd","005A39":"Shenzhen Fast Technologies Co. Ltd","005BA1":"shanghai huayuan chuangxin software Co. Ltd","005C86":"Shenzhen Fast Technologies Co. Ltd","005CB1":"Gospell DIGITAL TECHNOLOGY Co. Ltd","005D03":"Xilinx, Inc","005D73":"Cisco Systems Inc.","005F86":"Cisco Systems Inc.","006000":"Xycom Inc.","006001":"InnoSys, Inc.","006002":"Screen Subtitling Systems Ltd","006003":"Teraoka Weigh System PTE Ltd","006004":"Computadores Modulares SA","006005":"Feedback Data Ltd","006006":"Sotec Co. Ltd","006007":"Acres Gaming, Inc.","006008":"3Com Corporation","006009":"Cisco Systems Inc.","00600A":"Sord Computer Corporation","00600B":"LOGWARE GmbH","00600C":"Eurotech Inc.","00600D":"Digital Logic GmbH","00600E":"Wavenet International, Inc.","00600F":"Westell Technologies Inc.","006010":"Network Machines, Inc.","006011":"Crystal Semiconductor Corp.","006012":"Power Computing Corporation","006013":"Netstal Maschinen AG","006014":"Edec Co. Ltd","006015":"NET2NET Corporation","006016":"Clariion","006017":"Tokimec Inc.","006018":"Stellar ONE Corporation","006019":"Roche Diagnostics","00601A":"Keithley Instruments","00601B":"Mesa Electronics","00601C":"Telxon Corporation","00601D":"Lucent Technologies","00601E":"Softlab, Inc.","00601F":"Stallion Technologies","006020":"Pivotal Networking, Inc.","006021":"DSC Corporation","006022":"Vicom Systems, Inc.","006023":"Pericom Semiconductor Corp.","006024":"Gradient Technologies, Inc.","006025":"Active Imaging PLC","006026":"VIKING Modular Solutions","006027":"Superior Modular Products","006028":"Macrovision Corporation","006029":"Cary Peripherals Inc.","00602A":"Symicron Computer Communications Ltd","00602B":"Peak Audio","00602C":"LINX Data Terminals, Inc.","00602D":"Alerton Technologies, Inc.","00602E":"Cyclades Corporation","00602F":"Cisco Systems Inc.","006030":"Village Tronic Entwicklung","006031":"HRK Systems","006032":"I-Cube, Inc.","006033":"Acuity Imaging, Inc.","006034":"ROBERT BOSCH GmbH","006035":"Dallas Semiconductor, Inc.","006036":"AIT Austrian Institute Of Technology GmbH","006037":"NXP Semiconductors","006038":"Nortel Networks","006039":"SanCom Technology, Inc.","00603A":"Quick Controls Ltd","00603B":"AMTEC spa","00603C":"Hagiwara Sys-CoM Co. Ltd","00603D":"3CX","00603E":"Cisco Systems Inc.","00603F":"Patapsco Designs","006040":"Netro Corp.","006041":"Yokogawa Digital Computer Corporation","006042":"TKS (USA), Inc.","006043":"iDirect, Inc.","006044":"Litton/Poly-Scientific","006045":"Pathlight Technologies","006046":"Vmetro, Inc.","006047":"Cisco Systems Inc.","006048":"Dell EMC","006049":"Vina Technologies","00604A":"Saic Ideas Group","00604B":"Safe-Com GmbH & Co. KG","00604C":"Sagemcom Broadband SAS","00604D":"MMC Networks, Inc.","00604E":"Cycle Computer Corporation, Inc.","00604F":"Tattile SRL","006050":"Internix Inc.","006051":"Quality Semiconductor","006052":"PERIPHERALS ENTERPRISE Co. Ltd","006053":"Toyoda Machine Works Ltd","006054":"Controlware GmbH","006055":"Cornell University","006056":"Network Tools, Inc.","006057":"Murata Manufacturing Co. Ltd","006058":"Copper Mountain Communications, Inc.","006059":"Technical Communications Corp.","00605A":"Celcore, Inc.","00605B":"IntraServer Technology, Inc.","00605C":"Cisco Systems Inc.","00605D":"Scanivalve Corp.","00605E":"Liberty Technology Networking","00605F":"Nippon Unisoft Corporation","006060":"Data Innovations North America","006061":"Whistle Communications Corp.","006062":"Telesync, Inc.","006063":"Psion Dacom PLC.","006064":"Netcomm Limited","006065":"BERNECKER & RAINER IndUSTRIE-ELEKTRONIC GmbH","006066":"LACROIX Trafic","006067":"Acer Netxus Inc.","006068":"Dialogic Corporation","006069":"Brocade Communications Systems, Inc.","00606A":"Mitsubishi Wireless Communications. Inc.","00606B":"Synclayer Inc.","00606C":"Arescom","00606D":"Digital Equipment Corp.","00606E":"Davicom Semiconductor, Inc.","00606F":"Clarion Corporation Of America","006070":"Cisco Systems Inc.","006071":"Midas LAB, Inc.","006072":"VXL Instruments, Limited","006073":"Redcreek Communications, Inc.","006074":"QSC LLC","006075":"Pentek, Inc.","006076":"Schlumberger Technologies Retail Petroleum Systems","006077":"Prisa Networks","006078":"Power Measurement Ltd","006079":"Mainstream Data, Inc.","00607A":"DVS GmbH","00607B":"Fore Systems, Inc.","00607C":"WaveAccess Ltd","00607D":"Sentient Networks Inc.","00607E":"Gigalabs, Inc.","00607F":"Aurora Technologies, Inc.","006080":"Microtronix Datacom Ltd","006081":"TV/CoM International","006082":"Novalink Technologies, Inc.","006083":"Cisco Systems Inc.","006084":"Digital Video","006085":"Storage Concepts","006086":"Logic Replacement Tech. Ltd","006087":"Kansai Electric Co. Ltd","006088":"Analog Devices, Inc.","006089":"Xata","00608A":"Citadel Computer","00608B":"ConferTech International","00608C":"3Com Corporation","00608D":"Unipulse Corp.","00608E":"HE ELECTRONICS, TECHNOLOGIE & SysTEMTECHNIK GmbH","00608F":"Tekram Technology Co. Ltd","006090":"Artiza Networks Inc","006091":"First Pacific Networks, Inc.","006092":"Micro/Sys, Inc.","006093":"Varian","006094":"IBM Corp","006095":"Accu-Time Systems, Inc.","006096":"T.S. Microtech Inc.","006097":"3Com Corporation","006098":"HT Communications","006099":"SBE, Inc.","00609A":"NJK Techno Co.","00609B":"AstroNova, Inc","00609C":"Perkin-Elmer Incorporated","00609D":"PMI Food Equipment Group","00609E":"ASC X3 - Information Technology Standards Secretariats","00609F":"Phast Corporation","0060A0":"Switched Network Technologies, Inc.","0060A1":"VPNet, Inc.","0060A2":"Nihon Unisys Limited Co.","0060A3":"Continuum Technology Corp.","0060A4":"GEW Technologies (Pty)Ltd","0060A5":"Performance Telecom Corp.","0060A6":"Particle Measuring Systems","0060A7":"MICROSENS GmbH & Co. KG","0060A8":"Tidomat AB","0060A9":"Gesytec MBH","0060AA":"Intelligent Devices Inc. (IDI)","0060AB":"Larscom Incorporated","0060AC":"Resilience Corporation","0060AD":"MegaChips Corporation","0060AE":"Trio Information Systems AB","0060AF":"Pacific Micro Data, Inc.","0060B0":"Hewlett-Packard Company","0060B1":"Input/Output, Inc.","0060B2":"Process Control Corp.","0060B3":"Z-CoM, Inc.","0060B4":"Glenayre R&D Inc.","0060B5":"KEBA GmbH","0060B6":"Land Computer Co. Ltd","0060B7":"Channelmatic, Inc.","0060B8":"CoRELIS Inc.","0060B9":"NEC Platforms Ltd","0060BA":"Sahara Networks, Inc.","0060BB":"Cabletron Systems, Inc.","0060BC":"KeunYoung Electronics & Communication Co. Ltd","0060BD":"Enginuity Communications","0060BE":"Webtronics","0060BF":"Macraigor Systems, Inc.","0060C0":"Nera Networks AS","0060C1":"WaveSpan Corporation","0060C2":"MPL AG","0060C3":"Netvision Corporation","0060C4":"Soliton Systems K.K.","0060C5":"Ancot Corp.","0060C6":"DCS AG","0060C7":"Amati Communications Corp.","0060C8":"Kuka Welding Systems & Robots","0060C9":"ControlNet, Inc.","0060CA":"Harmonic Systems Incorporated","0060CB":"Hitachi Zosen Corporation","0060CC":"Emtrak, Incorporated","0060CD":"VideoServer, Inc.","0060CE":"Acclaim Communications","0060CF":"Alteon Networks, Inc.","0060D0":"Snmp Research Incorporated","0060D1":"Cascade Communications","0060D2":"Lucent Technologies Taiwan Telecommunications Co. Ltd","0060D3":"AT&T","0060D4":"Eldat Communication Ltd","0060D5":"AMADA MIYACHI Co. Ltd","0060D6":"NovAtel Inc.","0060D7":"Ecole Polytechnique Federale de Lausanne (Epfl)","0060D8":"Elmic Systems, Inc.","0060D9":"Transys Networks Inc.","0060DA":"Red Lion Controls, LP","0060DB":"NTP Elektronik A/S","0060DC":"NEC Magnus Communications Ltd","0060DD":"Myricom, Inc.","0060DE":"Kayser-Threde GmbH","0060DF":"Brocade Communications Systems, Inc.","0060E0":"Axiom Technology Co. Ltd","0060E1":"Orckit Communications Ltd","0060E2":"Quest Engineering & Development","0060E3":"Arbin Instruments","0060E4":"Compuserve, Inc.","0060E5":"Fuji Automation Co. Ltd","0060E6":"Shomiti Systems Incorporated","0060E7":"Randata","0060E8":"Hitachi Computer Products (America), Inc.","0060E9":"Atop Technologies, Inc.","0060EA":"StreamLogic","0060EB":"Fourthtrack Systems","0060EC":"Hermary Opto Electronics Inc.","0060ED":"Ricardo Test Automation Ltd","0060EE":"Apollo","0060EF":"Flytech Technology Co. Ltd","0060F0":"Johnson & Johnson Medical, Inc","0060F1":"EXP Computer, Inc.","0060F2":"Lasergraphics, Inc.","0060F3":"Performance Analysis Broadband, Spirent plc","0060F4":"ADVANCED CoMPUTER SOLUTIONS, Inc.","0060F5":"Icon West, Inc.","0060F6":"Nextest Communications Products, Inc.","0060F7":"Datafusion Systems","0060F8":"Loran International Technologies Inc.","0060F9":"Diamond Lane Communications","0060FA":"Educational Technology Resources, Inc.","0060FB":"Packeteer, Inc.","0060FC":"Conservation Through Innovation Ltd","0060FD":"NetICs, Inc.","0060FE":"Lynx System Developers, Inc.","0060FF":"QuVis, Inc.","006171":"Apple","0062EC":"Cisco Systems Inc.","006440":"Cisco Systems Inc.","0064A6":"Maquet CardioVascular","00664B":"Huawei Technologies Co. Ltd","006B8E":"Shanghai Feixun Communication Co. Ltd","006B9E":"Vizio, Inc","006BA0":"Shenzhen Universal Intellisys PTE Ltd","006BF1":"Cisco Systems Inc.","006CBC":"Cisco Systems Inc.","006CFD":"Sichuan Changhong Electric Ltd","006D52":"Apple","006DFB":"Vutrix Technologies Ltd","006F64":"Samsung Electronics Co. Ltd","0070B0":"M/A-CoM Inc. Companies","0070B3":"Data Recall Ltd","007147":"Amazon Technologies Inc.","0071C2":"Pegatron Corporation","0071CC":"Hon Hai Precision Ind. Co. Ltd","007263":"Netcore Technology Inc.","007278":"Cisco Systems Inc.","00738D":"Shenzhen TINNO Mobile Technology Corp.","0073E0":"Samsung Electronics Co. Ltd","00749C":"Ruijie Networks Co. Ltd","007532":"Inid BV","0075E1":"Ampt, LLC","007686":"Cisco Systems Inc.","0076B1":"Somfy-Protect By Myfox SAS","007888":"Cisco Systems Inc.","00789E":"Sagemcom Broadband SAS","0078CD":"Ignition Design Labs","007B18":"SENTRY Co. Ltd","007DFA":"Volkswagen Group Of America","007E56":"China Dragon Technology Limited","007F28":"Actiontec Electronics, Inc","008000":"Multitech Systems, Inc.","008001":"Periphonics Corporation","008002":"Satelcom (UK) Ltd","008003":"Hytec Electronics Ltd","008004":"Antlow Communications Ltd","008005":"Cactus Computer Inc.","008006":"Compuadd Corporation","008007":"Dlog NC-Systeme","008008":"Dynatech Computer Systems","008009":"Jupiter Systems, Inc.","00800A":"Japan Computer Corp.","00800B":"CSK Corporation","00800C":"Videcom Limited","00800D":"Vosswinkel F.U.","00800E":"Atlantix Corporation","00800F":"Standard Microsystems","008010":"Commodore International","008011":"Digital Systems Int'l. Inc.","008012":"Integrated Measurement Systems","008013":"Thomas-Conrad Corporation","008014":"Esprit Systems","008015":"Seiko Systems, Inc.","008016":"Wandel AND Goltermann","008017":"PFU Limited","008018":"Kobe Steel Ltd","008019":"Dayna Communications, Inc.","00801A":"Bell Atlantic","00801B":"Kodiak Technology","00801C":"Newport Systems Solutions","00801D":"Integrated Inference Machines","00801E":"Xinetron, Inc.","00801F":"Krupp Atlas Electronik GmbH","008020":"Network Products","008021":"Alcatel Canada Inc.","008022":"Scan-Optics","008023":"Integrated Business Networks","008024":"Kalpana, Inc.","008025":"Telit Wireless Solutions GmbH","008026":"Network Products Corporation","008027":"Adaptive Systems, Inc.","008028":"Tradpost (HK) Ltd","008029":"Eagle Technology, Inc.","00802A":"Test Systems & Simulations Inc","00802B":"Integrated Marketing Co","00802C":"THE Sage Group PLC","00802D":"Xylogics Inc","00802E":"Castle Rock Computing","00802F":"National Instruments Corp.","008030":"Nexus Electronics","008031":"Basys, Corp.","008032":"Access Co. Ltd","008033":"EMS Aviation, Inc.","008034":"SMT Goupil","008035":"Technology Works, Inc.","008036":"Reflex Manufacturing Systems","008037":"Ericsson Group","008038":"Data Research & Applications","008039":"Alcatel STC Australia","00803A":"Varityper, Inc.","00803B":"APT Communications, Inc.","00803C":"TVS Electronics Ltd","00803D":"Surigiken Co., Ltd","00803E":"Synernetics","00803F":"Tatung Company","008040":"John Fluke Manufacturing Co.","008041":"VEB Kombinat Robotron","008042":"Artesyn Embedded Technologies","008043":"Networld, Inc.","008044":"Systech Computer Corp.","008045":"Matsushita Electric Ind. Co","008046":"Tattile SRL","008047":"IN-NET Corp.","008048":"Compex Incorporated","008049":"Nissin Electric Co. Ltd","00804A":"PRO-LOG","00804B":"Eagle Technologies Pty.Ltd","00804C":"Contec Co. Ltd","00804D":"Cyclone Microsystems, Inc.","00804E":"Apex Computer Company","00804F":"Daikin Industries Ltd","008050":"Ziatech Corporation","008051":"Fibermux","008052":"Technically Elite Concepts","008053":"Intellicom, Inc.","008054":"Frontier Technologies Corp.","008055":"Fermilab","008056":"SPHINX Electronics GmbH & Co KG","008057":"Adsoft Ltd","008058":"Printer Systems Corp.","008059":"Stanley Electric Co. Ltd","00805A":"Tulip Computers Internat'L B.V","00805B":"Condor Systems, Inc.","00805C":"Agilis Corporation","00805D":"Canstar","00805E":"LSI Logic Corporation","00805F":"Hewlett-Packard Company","008060":"Network Interface Corporation","008061":"Litton Systems, Inc.","008062":"Interface Co.","008063":"Hirschmann Automation and Control GmbH","008064":"Wyse Technology LLC","008065":"Cybergraphic Systems Pty Ltd","008066":"Arcom Control Systems Ltd","008067":"Square D Company","008068":"Yamatech Scientific Ltd","008069":"Computone Systems","00806A":"ERI (Empac Research Inc.)","00806B":"Schmid Telecommunication","00806C":"Secure Systems & Services","00806D":"Century Systems Corp.","00806E":"Nippon Steel Corporation","00806F":"Onelan Ltd","008070":"Computadoras Micron","008071":"SAI Technology","008072":"Microplex Systems Ltd","008073":"DWB Associates","008074":"Fisher Controls","008075":"Parsytec GmbH","008076":"Mcnc","008077":"Brother Industries Ltd","008078":"Practical Peripherals, Inc.","008079":"Microbus Designs Ltd","00807A":"Aitech Systems Ltd","00807B":"Artel Communications Corp.","00807C":"Fibercom, Inc.","00807D":"Equinox Systems Inc.","00807E":"Southern Pacific Ltd","00807F":"DY-4 Incorporated","008080":"Datamedia Corporation","008081":"Kendall Square Research Corp.","008082":"PEP Modular Computers GmbH","008083":"Amdahl","008084":"THE Cloud Inc.","008085":"H-Three Systems Corporation","008086":"Computer Generation Inc.","008087":"OKI Electric Industry Co. Ltd","008088":"Victor Company Of Japan Ltd","008089":"Tecnetics (Pty) Ltd","00808A":"Summit Microsystems Corp.","00808B":"Dacoll Limited","00808C":"NetScout Systems, Inc.","00808D":"Westcoast Technology B.V.","00808E":"Radstone Technology","00808F":"C. Itoh Electronics, Inc.","008090":"Microtek International, Inc.","008091":"Tokyo Electric Co. Ltd","008092":"Silex Technology, Inc.","008093":"Xyron Corporation","008094":"Alfa Laval Automation AB","008095":"Basic Merton Handelsges.M.B.H.","008096":"Human Designed Systems, Inc.","008097":"Centralp Automatismes","008098":"TDK Corporation","008099":"Eaton Industries GmbH","00809A":"Novus Networks Ltd","00809B":"Justsystem Corporation","00809C":"Luxcom, Inc.","00809D":"Commscraft Ltd","00809E":"Datus GmbH","00809F":"ALE International","0080A0":"Hewlett-Packard Company","0080A1":"Microtest, Inc.","0080A2":"Creative Electronic Systems","0080A3":"Lantronix","0080A4":"Liberty Electronics","0080A5":"Speed International","0080A6":"Republic Technology, Inc.","0080A7":"Honeywell International Inc","0080A8":"Vitacom Corporation","0080A9":"Clearpoint Research","0080AA":"Maxpeed","0080AB":"Dukane Network Integration","0080AC":"Imlogix, Division Of Genesys","0080AD":"Cnet Technology, Inc.","0080AE":"Hughes Network Systems","0080AF":"Allumer Co. Ltd","0080B0":"Advanced Information","0080B1":"Softcom A/S","0080B2":"Network Equipment Technologies","0080B3":"Aval Data Corporation","0080B4":"Sophia Systems","0080B5":"United Networks Inc.","0080B6":"Themis Computer","0080B7":"Stellar Computer","0080B8":"DMG Mori B.U.G. Co. Ltd","0080B9":"Arche Technoligies Inc.","0080BA":"Specialix (Asia) PTE Ltd","0080BB":"Hughes LAN Systems","0080BC":"Hitachi Engineering Co. Ltd","0080BD":"THE Furukawa Electric Co. Ltd","0080BE":"Aries Research","0080BF":"Takaoka Electric MFG. Co. Ltd","0080C0":"Penril Datacomm","0080C1":"Lanex Corporation","0080C2":"IEEE 802.1 Working Group","0080C3":"Bicc Information Systems & SVC","0080C4":"Document Technologies, Inc.","0080C5":"Novellco de Mexico","0080C6":"National Datacomm Corporation","0080C7":"Xircom","0080C8":"D-Link Systems, Inc.","0080C9":"Alberta Microelectronic Centre","0080CA":"Netcom Research Incorporated","0080CB":"Falco Data Products","0080CC":"Microwave Bypass Systems","0080CD":"Micronics Computer, Inc.","0080CE":"Broadcast Television Systems","0080CF":"Embedded Performance Inc.","0080D0":"Computer Peripherals, Inc.","0080D1":"Kimtron Corporation","0080D2":"Shinnihondenko Co. Ltd","0080D3":"Shiva Corp.","0080D4":"Chase Research Ltd","0080D5":"Cadre Technologies","0080D6":"Nuvotech, Inc.","0080D7":"Fantum Engineering","0080D8":"Network Peripherals Inc.","0080D9":"EMK Elektronik GmbH & Co. KG","0080DA":"Bruel & Kjaer Sound & Vibration Measurement A/S","0080DB":"Graphon Corporation","0080DC":"Picker International","0080DD":"GMX Inc/Gimix","0080DE":"Gipsi S.A.","0080DF":"ADC Codenoll Technology Corp.","0080E0":"XTP Systems, Inc.","0080E1":"STMicroelectronics SRL","0080E2":"T.D.I. Co. Ltd","0080E3":"Coral Network Corporation","0080E4":"Northwest Digital Systems, Inc","0080E5":"NetApp","0080E6":"Peer Networks, Inc.","0080E7":"Leonardo Tactical Systems.","0080E8":"Cumulus Corporatiion","0080E9":"Madge Ltd","0080EA":"ADVA Optical Networking Ltd","0080EB":"Compcontrol B.V.","0080EC":"Supercomputing Solutions, Inc.","0080ED":"IQ Technologies, Inc.","0080EE":"Thomson CSF","0080EF":"Rational","0080F0":"Panasonic Communications Co. Ltd","0080F1":"Opus Systems","0080F2":"Raycom Systems Inc","0080F3":"SUN Electronics Corp.","0080F4":"Telemecanique Electrique","0080F5":"Quantel Ltd","0080F6":"Synergy Microsystems","0080F7":"Zenith Electronics Corporation","0080F8":"Mizar, Inc.","0080F9":"Heurikon Corporation","0080FA":"RWT GmbH","0080FB":"BVM Limited","0080FC":"Avatar Corporation","0080FD":"Exsceed Corpration","0080FE":"Azure Technologies, Inc.","0080FF":"SOC. de Teleinformatique RTC","0081C4":"Cisco Systems Inc.","0081F9":"Texas Instruments","0084ED":"Private","00869C":"Palo Alto Networks","0086A0":"Private","008701":"Samsung Electronics Co. Ltd","008731":"Cisco Systems Inc.","008865":"Apple","008A96":"Cisco Systems Inc.","008B43":"Rftech","008BFC":"mixi,Inc.","008C10":"Black Box Corp.","008C54":"ADB Broadband Italia","008CFA":"INVENTEC Corporation","008D4E":"Cjsc NII STT","008DDA":"Link One Co. Ltd","008E73":"Cisco Systems Inc.","008EF2":"Netgear","009000":"Diamond Multimedia","009001":"Nishimu Electronics Industries Co. Ltd","009002":"Allgon AB","009003":"Aplio","009004":"3Com Europe Ltd","009005":"Protech Systems Co. Ltd","009006":"Hamamatsu Photonics K.K.","009007":"Domex Technology Corp.","009008":"HanA Systems Inc.","009009":"I Controls, Inc.","00900A":"Proton Electronic Industrial Co. Ltd","00900B":"Lanner Electronics, Inc.","00900C":"Cisco Systems Inc.","00900D":"Overland Storage Inc.","00900E":"Handlink Technologies, Inc.","00900F":"Kawasaki Heavy Industries Ltd","009010":"Simulation Laboratories, Inc.","009011":"WAVTrace, Inc.","009012":"Globespan Semiconductor, Inc.","009013":"Samsan Corp.","009014":"Rotork Instruments Ltd","009015":"Centigram Communications Corp.","009016":"ZAC","009017":"Zypcom, Inc","009018":"ITO Electric Industry Co Ltd","009019":"Hermes Electronics Co. Ltd","00901A":"Unisphere Solutions","00901B":"Digital Controls","00901C":"mps Software GmbH","00901D":"PEC (NZ) Ltd","00901E":"Selesta Ingegneria S.p.A.","00901F":"Adtec Productions, Inc.","009020":"Philips Analytical X-RAY B.V.","009021":"Cisco Systems Inc.","009022":"Ivex","009023":"Zilog Inc.","009024":"Pipelinks, Inc.","009025":"BAE Systems Australia (Electronic Systems) Pty Ltd","009026":"Advanced Switching Communications, Inc.","009027":"Intel Corporation","009028":"Nippon Signal Co. Ltd","009029":"Crypto AG","00902A":"Communication Devices, Inc.","00902B":"Cisco Systems Inc.","00902C":"Data & Control Equipment Ltd","00902D":"Data Electronics (Aust.) Pty Ltd","00902E":"Namco Limited","00902F":"Netcore Systems, Inc.","009030":"Honeywell-Dating","009031":"Mysticom Ltd","009032":"Pelcombe Group Ltd","009033":"Innovaphone AG","009034":"Imagic, Inc.","009035":"Alpha Telecom, Inc.","009036":"ens, Inc.","009037":"Acucomm, Inc.","009038":"Fountain Technologies, Inc.","009039":"Shasta Networks","00903A":"Nihon Media Tool Inc.","00903B":"TriEMS Research Lab, Inc.","00903C":"Atlantic Network Systems","00903D":"Biopac Systems, Inc.","00903E":"N.V. Philips Industrial Activities","00903F":"Aztec Radiomedia","009040":"Siemens Network Convergence LLC","009041":"Applied Digital Access","009042":"ECCS, Inc.","009043":"Tattile SRL","009044":"Assured Digital, Inc.","009045":"Marconi Communications","009046":"Dexdyne Ltd","009047":"Giga Fast E. Ltd","009048":"Zeal Corporation","009049":"Entridia Corporation","00904A":"Concur System Technologies","00904B":"Gemtek Technology Co. Ltd","00904C":"Epigram, Inc.","00904D":"Spec S.A.","00904E":"Delem BV","00904F":"ABB Power T&D Company, Inc.","009050":"Teleste Corporation","009051":"Ultimate Technology Corp.","009052":"Selcom Elettronica S.R.L.","009053":"Daewoo Electronics Co. Ltd","009054":"Innovative Semiconductors, Inc","009055":"Parker Hannifin Corporation Compumotor Division","009056":"Telestream, Inc.","009057":"AANetcom, Inc.","009058":"Ultra Electronics Command & Control Systems","009059":"Telecom Device K.K.","00905A":"Dearborn Group, Inc.","00905B":"Raymond AND LAE Engineering","00905C":"Edmi","00905D":"Netcom Sicherheitstechnik GmbH","00905E":"Rauland-Borg Corporation","00905F":"Cisco Systems Inc.","009060":"System Create Corp.","009061":"Pacific Research & Engineering Corporation","009062":"ICP VORTEX CoMPUTERSYSTEME GmbH","009063":"Coherent Communications Systems Corporation","009064":"Thomson Inc.","009065":"Finisar Corporation","009066":"Troika Networks, Inc.","009067":"WalkAbout Computers, Inc.","009068":"DVT Corp.","009069":"Juniper Networks","00906A":"Turnstone Systems, Inc.","00906B":"Applied Resources, Inc.","00906C":"Sartorius Hamburg GmbH","00906D":"Cisco Systems Inc.","00906E":"Praxon, Inc.","00906F":"Cisco Systems Inc.","009070":"NEO Networks, Inc.","009071":"Applied Innovation Inc.","009072":"Simrad AS","009073":"Gaio Technology","009074":"Argon Networks, Inc.","009075":"NEC DO Brasil S.A.","009076":"FMT Aircraft Gate Support Systems AB","009077":"Advanced Fibre Communications","009078":"MER Telemanagement Solutions Ltd","009079":"ClearOne, Inc.","00907A":"Spectralink, Inc","00907B":"E-Tech, Inc.","00907C":"Digitalcast, Inc.","00907D":"Lake Communications","00907E":"Vetronix Corp.","00907F":"WatchGuard Technologies, Inc.","009080":"NOT Limited, Inc.","009081":"Aloha Networks, Inc.","009082":"Force Institute","009083":"Turbo Communication, Inc.","009084":"Atech System","009085":"Golden Enterprises, Inc.","009086":"Cisco Systems Inc.","009087":"Itis","009088":"Baxall Security Ltd","009089":"Softcom Microsystems, Inc.","00908A":"Bayly Communications, Inc.","00908B":"Tattile SRL","00908C":"Etrend Electronics, Inc.","00908D":"Vickers Electronics Systems","00908E":"Nortel Networks Broadband Access","00908F":"Audio Codes Ltd","009090":"I-BUS","009091":"DigitalScape, Inc.","009092":"Cisco Systems Inc.","009093":"Nanao Corporation","009094":"Osprey Technologies, Inc.","009095":"Universal Avionics","009096":"Askey Computer Corp","009097":"Sycamore Networks","009098":"SBC Designs, Inc.","009099":"Allied Telesis, K.K.","00909A":"ONE World Systems, Inc.","00909B":"Markem-Imaje","00909C":"ARRIS Group, Inc.","00909D":"NovaTech Process Solutions, LLC","00909E":"Critical IO, LLC","00909F":"Digi-Data Corporation","0090A0":"8X8 Inc.","0090A1":"Flying Pig Systems/High End Systems Inc.","0090A2":"CyberTAN Technology Inc.","0090A3":"Corecess Inc.","0090A4":"Altiga Networks","0090A5":"Spectra Logic","0090A6":"Cisco Systems Inc.","0090A7":"Clientec Corporation","0090A8":"NineTiles Networks Ltd","0090A9":"Western Digital","0090AA":"Indigo Active Vision Systems Limited","0090AB":"Cisco Systems Inc.","0090AC":"Optivision, Inc.","0090AD":"Aspect Electronics, Inc.","0090AE":"ITALTEL S.p.A/RF-UP-I","0090AF":"J. Morita MFG. Corp.","0090B0":"Vadem","0090B1":"Cisco Systems Inc.","0090B2":"Avici Systems Inc.","0090B3":"Agranat Systems","0090B4":"Willowbrook Technologies","0090B5":"Nikon Corporation","0090B6":"Fibex Systems","0090B7":"Digital Lightwave, Inc.","0090B8":"Rohde & Schwarz GmbH & Co. KG","0090B9":"Beran Instruments Ltd","0090BA":"Valid Networks, Inc.","0090BB":"TAINET CoMMUNICATION SysTEM Corp.","0090BC":"Telemann Co. Ltd","0090BD":"Omnia Communications, Inc.","0090BE":"IBC/Integrated Business Computers","0090BF":"Cisco Systems Inc.","0090C0":"K.J. LAW Engineers, Inc.","0090C1":"Peco II, Inc.","0090C2":"JK microsystems, Inc.","0090C3":"Topic Semiconductor Corp.","0090C4":"Javelin Systems, Inc.","0090C5":"Internet Magic, Inc.","0090C6":"Optim Systems, Inc.","0090C7":"Icom Inc.","0090C8":"Waverider Communications (Canada) Inc.","0090C9":"DPAC Technologies","0090CA":"Accord Video Telecommunications Ltd","0090CB":"Wireless OnLine, Inc.","0090CC":"Planex Communications Inc.","0090CD":"ENT-Empresa Nacional de Telecommunicacoes, S.A.","0090CE":"TETRA GmbH","0090CF":"Nortel Networks","0090D0":"Thomson Telecom Belgium","0090D1":"Leichu Enterprise Co. Ltd","0090D2":"Artel Video Systems","0090D3":"GIESECKE & DEVRIENT GmbH","0090D4":"BindView Development Corp.","0090D5":"Euphonix, Inc.","0090D6":"Crystal Group, Inc.","0090D7":"NetBoost Corp.","0090D8":"Whitecross Systems","0090D9":"Cisco Systems Inc.","0090DA":"Dynarc, Inc.","0090DB":"Next Level Communications","0090DC":"Teco Information Systems","0090DD":"MIHARU CoMMUNICATIONS Inc","0090DE":"Cardkey Systems, Inc.","0090DF":"Mitsubishi Chemical America, Inc.","0090E0":"Systran Corp.","0090E1":"Telena S.P.A.","0090E2":"Distributed Processing Technology","0090E3":"Avex Electronics Inc.","0090E4":"NEC America, Inc.","0090E5":"Teknema, Inc.","0090E6":"ALi Corporation","0090E7":"Horsch Elektronik AG","0090E8":"Moxa Technologies Corp. Ltd","0090E9":"Janz Computer AG","0090EA":"Alpha Technologies, Inc.","0090EB":"Sentry Telecom Systems","0090EC":"Pyrescom","0090ED":"Central System Research Co. Ltd","0090EE":"Personal Communications Technologies","0090EF":"Integrix, Inc.","0090F0":"Harmonic Video Systems Ltd","0090F1":"Seagate Cloud Systems Inc","0090F2":"Cisco Systems Inc.","0090F3":"Aspect Communications","0090F4":"Lightning Instrumentation","0090F5":"Clevo Co.","0090F6":"Escalate Networks, Inc.","0090F7":"Nbase Communications Ltd","0090F8":"Mediatrix Telecom","0090F9":"Imagine Communications","0090FA":"Emulex Corporation","0090FB":"Portwell, Inc.","0090FC":"Network Computing Devices","0090FD":"CopperCom, Inc.","0090FE":"Elecom Co. Ltd (Laneed Div.)","0090FF":"Tellus Technology Inc.","0091D6":"Crystal Group, Inc.","0091FA":"Synapse Product Development","0092FA":"Shenzhen Wisky Technology Co. Ltd","009363":"Uni-Link Technology Co. Ltd","0094A1":"F5 Networks, Inc.","009569":"LSD Science and Technology Co. Ltd","0097FF":"Heimann Sensor GmbH","009ACD":"Huawei Technologies Co. Ltd","009AD2":"Cisco Systems Inc.","009C02":"Hewlett-Packard Company","009D8E":"Cardiac Recorders, Inc.","009E1E":"Cisco Systems Inc.","009EC8":"Xiaomi Communications Co Ltd","00A000":"Centillion Networks, Inc.","00A001":"DRS Signal Solutions","00A002":"Leeds & Northrup Australia Pty Ltd","00A003":"Siemens Switzerland Ltd, I B T HVP","00A004":"Netpower, Inc.","00A005":"Daniel Instruments Ltd","00A006":"Image Data Processing System Group","00A007":"Apexx Technology, Inc.","00A008":"Netcorp","00A009":"Whitetree Network","00A00A":"Airspan","00A00B":"Computex Co. Ltd","00A00C":"Kingmax Technology, Inc.","00A00D":"THE Panda Project","00A00E":"NetScout Systems, Inc.","00A00F":"Broadband Technologies","00A010":"Syslogic Datentechnik AG","00A011":"Mutoh Industries Ltd","00A012":"Telco Systems, Inc.","00A013":"Teltrend Ltd","00A014":"Csir","00A015":"Wyle","00A016":"Micropolis Corp.","00A017":"J B M Corporation","00A018":"Creative Controllers, Inc.","00A019":"Nebula Consultants, Inc.","00A01A":"Binar Elektronik AB","00A01B":"Premisys Communications, Inc.","00A01C":"Nascent Networks Corporation","00A01D":"Red Lion Controls, LP","00A01E":"EST Corporation","00A01F":"Tricord Systems, Inc.","00A020":"Citicorp/TTI","00A021":"General Dynamics Mission Systems","00A022":"Centre FOR Development Of Advanced Computing","00A023":"Applied Creative Technology, Inc.","00A024":"3Com Corporation","00A025":"Redcom Labs Inc.","00A026":"Teldat, S.A.","00A027":"Firepower Systems, Inc.","00A028":"Conner Peripherals","00A029":"Coulter Corporation","00A02A":"Trancell Systems","00A02B":"Transitions Research Corp.","00A02C":"interWAVE Communications","00A02D":"1394 Trade Association","00A02E":"Brand Communications Ltd","00A02F":"ADB Broadband Italia","00A030":"Captor NV/SA","00A031":"Hazeltine Corporation, MS 1-17","00A032":"GES Singapore PTE. Ltd","00A033":"imc MeBsysteme GmbH","00A034":"Axel","00A035":"Cylink Corporation","00A036":"Applied Network Technology","00A037":"Mindray DS USA, Inc.","00A038":"Email Electronics","00A039":"Ross Technology, Inc.","00A03A":"Kubotek Corporation","00A03B":"Toshin Electric Co. Ltd","00A03C":"EG&G Nuclear Instruments","00A03D":"Opto-22","00A03E":"ATM Forum","00A03F":"Computer Society Microprocessor & Microprocessor Standards C","00A040":"Apple","00A041":"Inficon","00A042":"Spur Products Corp.","00A043":"American Technology Labs, Inc.","00A044":"NTT IT Co. Ltd","00A045":"PHOENIX CoNTACT Electronics GmbH","00A046":"Scitex Corp. Ltd","00A047":"Integrated Fitness Corp.","00A048":"Questech Ltd","00A049":"Digitech Industries, Inc.","00A04A":"Nisshin Electric Co. Ltd","00A04B":"TFL LAN Inc.","00A04C":"Innovative Systems & Technologies, Inc.","00A04D":"EDA Instruments, Inc.","00A04E":"Voelker Technologies, Inc.","00A04F":"Ameritec Corp.","00A050":"Cypress Semiconductor","00A051":"Angia Communications. Inc.","00A052":"Stanilite Electronics Pty. Ltd","00A053":"Compact Devices, Inc.","00A054":"Private","00A055":"Data Device Corporation","00A056":"Micropross","00A057":"LANCOM Systems GmbH","00A058":"Glory Ltd","00A059":"Hamilton Hallmark","00A05A":"Kofax Image Products","00A05B":"Marquip, Inc.","00A05C":"Inventory Conversion, Inc./","00A05D":"CS CoMPUTER SysTEME GmbH","00A05E":"Myriad Logic Inc.","00A05F":"BTG Electronics Design BV","00A060":"Acer Peripherals, Inc.","00A061":"Puritan Bennett","00A062":"AES Prodata","00A063":"JRL Systems, Inc.","00A064":"KVB/Analect","00A065":"Symantec Corporation","00A066":"ISA Co. Ltd","00A067":"Network Services Group","00A068":"BHP Limited","00A069":"Symmetricom, Inc.","00A06A":"Verilink Corporation","00A06B":"DMS Dorsch Mikrosystem GmbH","00A06C":"Shindengen Electric MFG. Co. Ltd","00A06D":"Mannesmann Tally Corporation","00A06E":"Austron, Inc.","00A06F":"Color Sentinel Systems, LLC","00A070":"Coastcom","00A071":"Video Lottery Technologies,Inc","00A072":"Ovation Systems Ltd","00A073":"CoM21, Inc.","00A074":"Perception Technology","00A075":"Micron Technology, Inc.","00A076":"Cardware LAB, Inc.","00A077":"Fujitsu Nexion, Inc.","00A078":"Marconi Communications","00A079":"Alps Electric (USA), Inc.","00A07A":"Advanced Peripherals Technologies, Inc.","00A07B":"Dawn Computer Incorporation","00A07C":"Tonyang Nylon Co. Ltd","00A07D":"Seeq Technology, Inc.","00A07E":"Avid Technology, Inc.","00A07F":"GSM-Syntel Ltd","00A080":"Tattile SRL","00A081":"Alcatel Data Networks","00A082":"NKT Elektronik A/S","00A083":"Asimmphony Turkey","00A084":"Dataplex Pty Ltd","00A085":"Private","00A086":"Amber Wave Systems, Inc.","00A087":"Microsemi Corporation","00A088":"Essential Communications","00A089":"Xpoint Technologies, Inc.","00A08A":"Brooktrout Technology, Inc.","00A08B":"Aston Electronic Designs Ltd","00A08C":"MultiMedia LANs, Inc.","00A08D":"Jacomo Corporation","00A08E":"Check Point Software Technologies","00A08F":"Desknet Systems, Inc.","00A090":"TimeStep Corporation","00A091":"Applicom International","00A092":"H. Bollmann Manufacturers Ltd","00A093":"B/E AEROSPACE, Inc.","00A094":"Comsat Corporation","00A095":"Acacia Networks, Inc.","00A096":"Mitsumi Electric Co. Ltd","00A097":"JC Information Systems","00A098":"NetApp","00A099":"K-NET Ltd","00A09A":"Nihon Kohden America","00A09B":"Qpsx Communications Ltd","00A09C":"Xyplex, Inc.","00A09D":"Johnathon Freeman Technologies","00A09E":"Ictv","00A09F":"Commvision Corp.","00A0A0":"Compact Data Ltd","00A0A1":"Epic Data Inc.","00A0A2":"Digicom S.P.A.","00A0A3":"Reliable Power Meters","00A0A4":"Oracle Corporation","00A0A5":"Teknor Microsysteme, Inc.","00A0A6":"M.I. Systems, K.K.","00A0A7":"Vorax Corporation","00A0A8":"Renex Corporation","00A0A9":"Navtel Communications Inc.","00A0AA":"Spacelabs Medical","00A0AB":"Netcs Informationstechnik GmbH","00A0AC":"Gilat Satellite Networks Ltd","00A0AD":"Marconi SPA","00A0AE":"Nucom Systems, Inc.","00A0AF":"WMS Industries","00A0B0":"I-O Data Device, Inc.","00A0B1":"First Virtual Corporation","00A0B2":"Shima Seiki","00A0B3":"Zykronix","00A0B4":"Texas Microsystems, Inc.","00A0B5":"3H Technology","00A0B6":"Sanritz Automation Co. Ltd","00A0B7":"Cordant, Inc.","00A0B8":"NetApp","00A0B9":"Eagle Technology, Inc.","00A0BA":"Patton Electronics Co.","00A0BB":"Hilan GmbH","00A0BC":"Viasat, Incorporated","00A0BD":"I-Tech Corp.","00A0BE":"Integrated Circuit Systems, Inc. Communications Group","00A0BF":"Wireless Data Group Motorola","00A0C0":"Digital Link Corp.","00A0C1":"Ortivus Medical AB","00A0C2":"R.A. Systems Co. Ltd","00A0C3":"Unicomputer GmbH","00A0C4":"Cristie Electronics Ltd","00A0C5":"ZyXEL Communications Corp","00A0C6":"Qualcomm Inc.","00A0C7":"Tadiran Telecommunications","00A0C8":"Adtran Inc","00A0C9":"Intel Corporation","00A0CA":"Fujitsu Denso Ltd","00A0CB":"ARK Telecommunications, Inc.","00A0CC":"Lite-ON Communications, Inc.","00A0CD":"DR. JOHANNES HEIDENHAIN GmbH","00A0CE":"Ecessa","00A0CF":"Sotas, Inc.","00A0D0":"TEN X Technology, Inc.","00A0D1":"Inventec Corporation","00A0D2":"Allied Telesis International Corporation","00A0D3":"Instem Computer Systems Ltd","00A0D4":"Radiolan, Inc.","00A0D5":"Sierra Wireless Inc","00A0D6":"SBE, Inc.","00A0D7":"Kasten Chase Applied Research","00A0D8":"Spectra - TEK","00A0D9":"Convex Computer Corporation","00A0DA":"INTEGRATED SysTEMS Technology, Inc.","00A0DB":"Fisher & Paykel Production","00A0DC":"O.N. Electronic Co. Ltd","00A0DD":"Azonix Corporation","00A0DE":"Yamaha Corporation","00A0DF":"STS Technologies, Inc.","00A0E0":"Tennyson Technologies Pty Ltd","00A0E1":"Westport Research Associates, Inc.","00A0E2":"Keisokugiken Corporation","00A0E3":"XKL Systems Corp.","00A0E4":"Optiquest","00A0E5":"NHC Communications","00A0E6":"Dialogic Corporation","00A0E7":"Central Data Corporation","00A0E8":"Reuters Holdings PLC","00A0E9":"Electronic Retailing Systems International","00A0EA":"Ethercom Corp.","00A0EB":"Encore Networks, Inc.","00A0EC":"Transmitton Ltd","00A0ED":"Brooks Automation, Inc.","00A0EE":"Nashoba Networks","00A0EF":"Lucidata Ltd","00A0F0":"Toronto Microelectronics Inc.","00A0F1":"MTI","00A0F2":"Infotek Communications, Inc.","00A0F3":"Staubli","00A0F4":"GE","00A0F5":"Radguard Ltd","00A0F6":"AutoGas Systems Inc.","00A0F7":"V.I Computer Corp.","00A0F8":"Zebra Technologies Inc","00A0F9":"Bintec Communications GmbH","00A0FA":"Marconi Communication GmbH","00A0FB":"Toray Engineering Co. Ltd","00A0FC":"Image Sciences, Inc.","00A0FD":"Scitex Digital Printing, Inc.","00A0FE":"Boston Technology, Inc.","00A0FF":"Tellabs Operations, Inc.","00A1DE":"ShenZhen ShiHua Technology Co. Ltd","00A289":"Cisco Systems Inc.","00A2DA":"INAT GmbH","00A2EE":"Cisco Systems Inc.","00A2F5":"Guangzhou Yuanyun Network Technology Co. Ltd","00A2FF":"abatec group AG","00A38E":"Cisco Systems Inc.","00A3D1":"Cisco Systems Inc.","00A509":"WigWag Inc.","00A6CA":"Cisco Systems Inc.","00A742":"Cisco Systems Inc.","00A784":"ITX security","00AA00":"Intel Corporation","00AA01":"Intel Corporation","00AA02":"Intel Corporation","00AA3C":"Olivetti Telecom SPA (Olteco)","00AA70":"LG Electronics (Mobile Communications)","00ACE0":"ARRIS Group, Inc.","00AECD":"Pensando Systems","00AEFA":"Murata Manufacturing Co. Ltd","00AF1F":"Cisco Systems Inc.","00B009":"Grass Valley, A Belden Brand","00B017":"InfoGear Technology Corp.","00B019":"UTC CCS","00B01C":"Westport Technologies","00B01E":"Rantic Labs, Inc.","00B02A":"ORSYS GmbH","00B02D":"ViaGate Technologies, Inc.","00B033":"OAO Izhevskiy radiozavod","00B03B":"HiQ Networks","00B048":"Marconi Communications Inc.","00B04A":"Cisco Systems Inc.","00B052":"Atheros Communications","00B064":"Cisco Systems Inc.","00B069":"Honewell Oy","00B06D":"Jones Futurex Inc.","00B080":"Mannesmann Ipulsys B.V.","00B086":"LocSoft Limited","00B08E":"Cisco Systems Inc.","00B091":"Transmeta Corp.","00B094":"Alaris, Inc.","00B09A":"Morrow Technologies Corp.","00B09D":"Point Grey Research Inc.","00B0AC":"SIAE-Microelettronica S.p.A.","00B0AE":"Symmetricom","00B0B3":"Xstreamis PLC","00B0C2":"Cisco Systems Inc.","00B0C7":"Tellabs Operations, Inc.","00B0CE":"Viveris Technologies","00B0D0":"Dell Inc.","00B0DB":"Nextcell, Inc.","00B0DF":"Starboard Storage Systems","00B0E1":"Cisco Systems Inc.","00B0E7":"British Federal Ltd","00B0EC":"Eacem","00B0EE":"Ajile Systems, Inc.","00B0F0":"Caly Networks","00B0F5":"NetWorth Technologies, Inc.","00B338":"Kontron Design Manufacturing Services (M) Sdn. Bhd","00B342":"MacroSAN Technologies Co. Ltd","00B362":"Apple","00B56D":"David Electronics Co. Ltd","00B5D6":"Omnibit Inc.","00B69F":"Latch","00B78D":"Nanjing Shining Electric Automation Co. Ltd","00B9F6":"Shenzhen Super Rich Electronics Co. Ltd","00BAC0":"Biometric Access Company","00BB01":"Octothorpe Corp.","00BB3A":"Private","00BB8E":"HME Co. Ltd","00BBC1":"Canon Inc.","00BBF0":"Ungermann-Bass Inc.","00BD27":"Exar Corp.","00BD3A":"Nokia Corporation","00BD82":"Shenzhen YOUHUA Technology Co. Ltd","00BE3B":"Huawei Technologies Co. Ltd","00BE75":"Cisco Systems Inc.","00BE9E":"Fiberhome Telecommunication Technologies Co. Ltd","00BF15":"Genetec Inc.","00BF61":"Samsung Electronics Co. Ltd","00BF77":"Cisco Systems Inc.","00C000":"Lanoptics Ltd","00C001":"Diatek Patient Managment","00C002":"Sercomm Corporation","00C003":"Globalnet Communications","00C004":"Japan Business Computer Co.Ltd","00C005":"Livingston Enterprises, Inc.","00C006":"Nippon Avionics Co. Ltd","00C007":"Pinnacle Data Systems, Inc.","00C008":"Seco SRL","00C009":"KT Technology (S) PTE Ltd","00C00A":"Micro Craft","00C00B":"Norcontrol A.S.","00C00C":"Relia Technolgies","00C00D":"Advanced Logic Research, Inc.","00C00E":"Psitech, Inc.","00C00F":"Quantum Software Systems Ltd","00C010":"Hirakawa Hewtech Corp.","00C011":"Interactive Computing Devices","00C012":"Netspan Corporation","00C013":"Netrix","00C014":"Telematics Calabasas Int'l,Inc","00C015":"NEW Media Corporation","00C016":"Electronic Theatre Controls","00C017":"NetScout Systems, Inc.","00C018":"Lanart Corporation","00C019":"Leap Technology, Inc.","00C01A":"Corometrics Medical Systems","00C01B":"Socket Communications, Inc.","00C01C":"Interlink Communications Ltd","00C01D":"Grand Junction Networks, Inc.","00C01E":"LA Francaise DES Jeux","00C01F":"S.E.R.C.E.L.","00C020":"Arco Electronic, Control Ltd","00C021":"Netexpress","00C022":"Lasermaster Technologies, Inc.","00C023":"Tutankhamon Electronics","00C024":"Eden Sistemas de Computacao SA","00C025":"Dataproducts Corporation","00C026":"Lans Technology Co. Ltd","00C027":"Cipher Systems, Inc.","00C028":"Jasco Corporation","00C029":"Nexans Deutschland GmbH - ANS","00C02A":"Ohkura Electric Co. Ltd","00C02B":"Gerloff Gesellschaft FUR","00C02C":"Centrum Communications, Inc.","00C02D":"Fuji Photo Film Co. Ltd","00C02E":"Netwiz","00C02F":"Okuma Corporation","00C030":"Integrated Engineering B. V.","00C031":"Design Research Systems, Inc.","00C032":"I-Cubed Limited","00C033":"Telebit Communications APS","00C034":"Transaction Network","00C035":"Quintar Company","00C036":"Raytech Electronic Corp.","00C037":"Dynatem","00C038":"Raster Image Processing System","00C039":"Teridian Semiconductor Corporation","00C03A":"MEN-Mikro Elektronik GmbH","00C03B":"Multiaccess Computing Corp.","00C03C":"Tower Tech S.R.L.","00C03D":"Wiesemann & Theis GmbH","00C03E":"FA. Gebr. Heller GmbH","00C03F":"Stores Automated Systems, Inc.","00C040":"Ecci","00C041":"Digital Transmission Systems","00C042":"Datalux Corp.","00C043":"Stratacom","00C044":"Emcom Corporation","00C045":"Isolation Systems Ltd","00C046":"Blue Chip Technology Ltd","00C047":"Unimicro Systems, Inc.","00C048":"BAY Technical Associates","00C049":"U.S. Robotics, Inc.","00C04A":"Group 2000 AG","00C04B":"Creative Microsystems","00C04C":"Department Of Foreign Affairs","00C04D":"Mitec, Inc.","00C04E":"Comtrol Corporation","00C04F":"Dell Inc.","00C050":"Toyo Denki Seizo K.K.","00C051":"Advanced Integration Research","00C052":"Burr-Brown","00C053":"Aspect Software Inc.","00C054":"Network Peripherals Ltd","00C055":"Modular Computing Technologies","00C056":"Somelec","00C057":"Myco Electronics","00C058":"Dataexpert Corp.","00C059":"Denso Corporation","00C05A":"Semaphore Communications Corp.","00C05B":"Networks Northwest, Inc.","00C05C":"Elonex PLC","00C05D":"L&N Technologies","00C05E":"Vari-Lite, Inc.","00C05F":"Fine-PAL Company Limited","00C060":"ID Scandinavia AS","00C061":"Solectek Corporation","00C062":"Impulse Technology","00C063":"Morning Star Technologies, Inc","00C064":"General Datacomm LLC","00C065":"Scope Communications, Inc.","00C066":"Docupoint, Inc.","00C067":"United Barcode Industries","00C068":"HME Clear-Com Ltd","00C069":"Axxcelera Broadband Wireless","00C06A":"Zahner-Elektrik GmbH & Co. KG","00C06B":"OSI Plus Corporation","00C06C":"Svec Computer Corp.","00C06D":"Boca Research, Inc.","00C06E":"Haft Technology, Inc.","00C06F":"Komatsu Ltd","00C070":"Sectra Secure-Transmission AB","00C071":"Areanex Communications, Inc.","00C072":"KNX Ltd","00C073":"Xedia Corporation","00C074":"Toyoda Automatic Loom","00C075":"Xante Corporation","00C076":"I-Data International A-S","00C077":"Daewoo Telecom Ltd","00C078":"Computer Systems Engineering","00C079":"Fonsys Co. Ltd","00C07A":"Priva B.V.","00C07B":"Ascend Communications, Inc.","00C07C":"Hightech Information","00C07D":"Risc Developments Ltd","00C07E":"Kubota Corporation Electronic","00C07F":"Nupon Computing Corp.","00C080":"Netstar, Inc.","00C081":"Metrodata Ltd","00C082":"Moore Products Co.","00C083":"Trace Mountain Products, Inc.","00C084":"Data Link Corp. Ltd","00C085":"Electronics FOR Imaging, Inc.","00C086":"THE Lynk Corporation","00C087":"Uunet Technologies, Inc.","00C088":"EKF Elektronik GmbH","00C089":"Telindus Distribution","00C08A":"Lauterbach GmbH","00C08B":"Risq Modular Systems, Inc.","00C08C":"Performance Technologies, Inc.","00C08D":"Tronix Product Development","00C08E":"Network Information Technology","00C08F":"Panasonic Electric Works Co. Ltd","00C090":"Praim S.R.L.","00C091":"Jabil Circuit, Inc.","00C092":"Mennen Medical Inc.","00C093":"Alta Research Corp.","00C094":"VMX Inc.","00C095":"ZNYX Networks, Inc.","00C096":"Tamura Corporation","00C097":"Archipel SA","00C098":"Chuntex Electronic Co. Ltd","00C099":"Yoshiki Industrial Co. Ltd","00C09A":"Photonics Corporation","00C09B":"Reliance Comm/TEC, R-TEC","00C09C":"Hioki E.E. Corporation","00C09D":"Distributed Systems Int'l, Inc","00C09E":"Cache Computers, Inc.","00C09F":"Quanta Computer Inc.","00C0A0":"Advance Micro Research, Inc.","00C0A1":"Tokyo Denshi Sekei Co.","00C0A2":"Intermedium A/S","00C0A3":"Dual Enterprises Corporation","00C0A4":"Unigraf Oy","00C0A5":"Dickens Data Systems","00C0A6":"Exicom Australia Pty. Ltd","00C0A7":"Seel Ltd","00C0A8":"GVC Corporation","00C0A9":"Barron Mccann Ltd","00C0AA":"Silicon Valley Computer","00C0AB":"Telco Systems, Inc.","00C0AC":"Gambit Computer Communications","00C0AD":"Marben Communication Systems","00C0AE":"Towercom Co. Inc. DBA PC House","00C0AF":"Teklogix Inc.","00C0B0":"GCC Technologies,Inc.","00C0B1":"Genius NET Co.","00C0B2":"Norand Corporation","00C0B3":"Comstat Datacomm Corporation","00C0B4":"Myson Technology, Inc.","00C0B5":"Corporate Network Systems,Inc.","00C0B6":"Overland Storage, Inc.","00C0B7":"American Power Conversion Corp","00C0B8":"Fraser'S Hill Ltd","00C0B9":"Funk Software, Inc.","00C0BA":"Netvantage","00C0BB":"Forval Creative, Inc.","00C0BC":"Telecom Australia/Cssc","00C0BD":"Inex Technologies, Inc.","00C0BE":"Alcatel - SEL","00C0BF":"Technology Concepts Ltd","00C0C0":"Shore Microsystems, Inc.","00C0C1":"Quad/Graphics, Inc.","00C0C2":"Infinite Networks Ltd","00C0C3":"Acuson Computed Sonography","00C0C4":"Computer Operational","00C0C5":"SID Informatica","00C0C6":"Personal Media Corp.","00C0C7":"Sparktrum Microsystems, Inc.","00C0C8":"Micro Byte Pty. Ltd","00C0C9":"Elsag Bailey Process","00C0CA":"Alfa, Inc.","00C0CB":"Control Technology Corporation","00C0CC":"Telesciences Co Systems, Inc.","00C0CD":"Comelta, S.A.","00C0CE":"CEI Systems & Engineering PTE","00C0CF":"Imatran Voima Oy","00C0D0":"Ratoc System Inc.","00C0D1":"Comtree Technology Corporation","00C0D2":"Syntellect, Inc.","00C0D3":"Olympus Image Systems, Inc.","00C0D4":"Axon Networks, Inc.","00C0D5":"Werbeagentur J?rgen Siebert","00C0D6":"J1 Systems, Inc.","00C0D7":"Taiwan Trading Center DBA","00C0D8":"Universal Data Systems","00C0D9":"Quinte Network Confidentiality","00C0DA":"Nice Systems Ltd","00C0DB":"IPC Corporation (PTE) Ltd","00C0DC":"EOS Technologies, Inc.","00C0DD":"QLogic Corporation","00C0DE":"Zcomm, Inc.","00C0DF":"KYE Systems Corp.","00C0E0":"DSC Communication Corp.","00C0E1":"Sonic Solutions","00C0E2":"Calcomp, Inc.","00C0E3":"Ositech Communications, Inc.","00C0E4":"Siemens Building","00C0E5":"Gespac, S.A.","00C0E6":"Verilink Corporation","00C0E7":"Fiberdata AB","00C0E8":"Plexcom, Inc.","00C0E9":"OAK Solutions Ltd","00C0EA":"Array Technology Ltd","00C0EB":"SEH Computertechnik GmbH","00C0EC":"Dauphin Technology","00C0ED":"US Army Electronic","00C0EE":"KYOCERA Display Corporation","00C0EF":"Abit Corporation","00C0F0":"Kingston Technology Company, Inc.","00C0F1":"Shinko Electric Co. Ltd","00C0F2":"Transition Networks","00C0F3":"Network Communications Corp.","00C0F4":"Interlink System Co. Ltd","00C0F5":"Metacomp, Inc.","00C0F6":"Celan Technology Inc.","00C0F7":"Engage Communication, Inc.","00C0F8":"About Computing Inc.","00C0F9":"Artesyn Embedded Technologies","00C0FA":"Canary Communications, Inc.","00C0FB":"Advanced Technology Labs","00C0FC":"Elastic Reality, Inc.","00C0FD":"Prosum","00C0FE":"Aptec Computer Systems, Inc.","00C0FF":"Seagate Cloud Systems Inc","00C14F":"DDL Co,.Ltd","00C164":"Cisco Systems Inc.","00C1B1":"Cisco Systems Inc.","00C2C6":"Intel Corporation","00C5DB":"Datatech Sistemas Digitales Avanzados SL","00C610":"Apple","00C88B":"Cisco Systems Inc.","00CAE5":"Cisco Systems Inc.","00CB00":"Private","00CBB4":"Shenzhen Ateko Photoelectricity Co. Ltd","00CBBD":"Cambridge Broadband Networks Ltd","00CCFC":"Cisco Systems Inc.","00CD90":"MAS Elektronik AG","00CDFE":"Apple","00CF1C":"Communication Machinery Corporation","00CFC0":"China Mobile Group Device Co. Ltd","00D000":"Ferran Scientific, Inc.","00D001":"VST Technologies, Inc.","00D002":"Ditech Corporation","00D003":"Comda Enterprises Corp.","00D004":"Pentacom Ltd","00D005":"ZHS Zeitmanagementsysteme","00D006":"Cisco Systems Inc.","00D007":"MIC Associates, Inc.","00D008":"Mactell Corporation","00D009":"Hsing Tech. Enterprise Co. Ltd","00D00A":"Lanaccess Telecom S.A.","00D00B":"RHK Technology, Inc.","00D00C":"Snijder Micro Systems","00D00D":"Micromeritics Instrument","00D00E":"Pluris, Inc.","00D00F":"Speech Design GmbH","00D010":"Convergent Networks, Inc.","00D011":"Prism Video, Inc.","00D012":"Gateworks Corp.","00D013":"Primex Aerospace Company","00D014":"Root, Inc.","00D015":"Univex Microtechnology Corp.","00D016":"SCM Microsystems, Inc.","00D017":"Syntech Information Co. Ltd","00D018":"Qwes. CoM, Inc.","00D019":"Dainippon Screen Corporate","00D01A":"Urmet TLC S.P.A.","00D01B":"Mimaki Engineering Co. Ltd","00D01C":"SBS Technologies,","00D01D":"Furuno Electric Co. Ltd","00D01E":"Pingtel Corp.","00D01F":"Senetas Corporation Ltd","00D020":"AIM System, Inc.","00D021":"Regent Electronics Corp.","00D022":"Incredible Technologies, Inc.","00D023":"Infortrend Technology, Inc.","00D024":"Cognex Corporation","00D025":"Xrosstech, Inc.","00D026":"Hirschmann Austria GmbH","00D027":"Applied Automation, Inc.","00D028":"Harmonic, Inc","00D029":"Wakefern Food Corporation","00D02A":"Voxent Systems Ltd","00D02B":"Jetcell, Inc.","00D02C":"Campbell Scientific, Inc.","00D02D":"Ademco","00D02E":"Communication Automation Corp.","00D02F":"Vlsi Technology Inc.","00D030":"Safetran Systems Corp","00D031":"Industrial Logic Corporation","00D032":"Yano Electric Co. Ltd","00D033":"Dalian Daxian Network","00D034":"Ormec Systems Corp.","00D035":"Behavior Tech. Computer Corp.","00D036":"Technology Atlanta Corp.","00D037":"ARRIS Group, Inc.","00D038":"Fivemere Ltd","00D039":"Utilicom, Inc.","00D03A":"Zoneworx, Inc.","00D03B":"Vision Products Pty. Ltd","00D03C":"Vieo, Inc.","00D03D":"Galileo Technology Ltd","00D03E":"Rocketchips, Inc.","00D03F":"American Communication","00D040":"Sysmate Co. Ltd","00D041":"Amigo Technology Co. Ltd","00D042":"Mahlo GmbH & Co. UG","00D043":"Zonal Retail Data Systems","00D044":"Alidian Networks, Inc.","00D045":"Kvaser AB","00D046":"Dolby Laboratories, Inc.","00D047":"XN Technologies","00D048":"Ecton, Inc.","00D049":"Impresstek Co. Ltd","00D04A":"Presence Technology GmbH","00D04B":"LA CIE Group S.A.","00D04C":"Eurotel Telecom Ltd","00D04D":"Div Of Research & Statistics","00D04E":"Logibag","00D04F":"Bitronics, Inc.","00D050":"Iskratel","00D051":"O2 Micro, Inc.","00D052":"Ascend Communications, Inc.","00D053":"Connected Systems","00D054":"SAS Institute Inc.","00D055":"Kathrein-Werke KG","00D056":"Somat Corporation","00D057":"Ultrak, Inc.","00D058":"Cisco Systems Inc.","00D059":"Ambit Microsystems Corp.","00D05A":"Symbionics Ltd","00D05B":"Acroloop Motion Control","00D05C":"KATHREIN TechnoTrend GmbH","00D05D":"Intelliworxx, Inc.","00D05E":"Stratabeam Technology, Inc.","00D05F":"Valcom, Inc.","00D060":"Panasonic Europe Ltd","00D061":"Tremon Enterprises Co. Ltd","00D062":"Digigram","00D063":"Cisco Systems Inc.","00D064":"Multitel","00D065":"Toko Electric","00D066":"Wintriss Engineering Corp.","00D067":"Campio Communications","00D068":"Iwill Corporation","00D069":"Technologic Systems","00D06A":"Linkup Systems Corporation","00D06B":"SR Telecom Inc.","00D06C":"Sharewave, Inc.","00D06D":"Acrison, Inc.","00D06E":"Trendview Recorders Ltd","00D06F":"KMC Controls","00D070":"Long Well Electronics Corp.","00D071":"Echelon Corp.","00D072":"Broadlogic","00D073":"ACN Advanced Communications","00D074":"Taqua Systems, Inc.","00D075":"Alaris Medical Systems, Inc.","00D076":"Bank Of America","00D077":"Lucent Technologies","00D078":"Eltex Of Sweden AB","00D079":"Cisco Systems Inc.","00D07A":"Amaquest Computer Corp.","00D07B":"Comcam International Inc","00D07C":"Koyo Electronics Inc. Co. Ltd","00D07D":"Cosine Communications","00D07E":"Keycorp Ltd","00D07F":"Strategy & Technology, Limited","00D080":"Exabyte Corporation","00D081":"RTD Embedded Technologies, Inc.","00D082":"Iowave Inc.","00D083":"Invertex, Inc.","00D084":"Nexcomm Systems, Inc.","00D085":"Otis Elevator Company","00D086":"Foveon, Inc.","00D087":"Microfirst Inc.","00D088":"ARRIS Group, Inc.","00D089":"Dynacolor, Inc.","00D08A":"Photron USA","00D08B":"ADVA Optical Networking Ltd","00D08C":"Genoa Technology, Inc.","00D08D":"Phoenix Group, Inc.","00D08E":"Grass Valley, A Belden Brand","00D08F":"Ardent Technologies, Inc.","00D090":"Cisco Systems Inc.","00D091":"Smartsan Systems, Inc.","00D092":"Glenayre Western Multiplex","00D093":"TQ - Components GmbH","00D094":"Seeion Control LLC","00D095":"Alcatel-Lucent Enterprise","00D096":"3Com Europe Ltd","00D097":"Cisco Systems Inc.","00D098":"Photon Dynamics Canada Inc.","00D099":"Elcard Wireless Systems Oy","00D09A":"Filanet Corporation","00D09B":"Spectel Ltd","00D09C":"Kapadia Communications","00D09D":"Veris Industries","00D09E":"2Wire Inc.","00D09F":"Novtek Test Systems","00D0A0":"Mips Denmark","00D0A1":"Oskar Vierling GmbH + Co. KG","00D0A2":"Integrated Device","00D0A3":"Vocal Data, Inc.","00D0A4":"Alantro Communications","00D0A5":"American Arium","00D0A6":"Lanbird Technology Co. Ltd","00D0A7":"Tokyo Sokki Kenkyujo Co. Ltd","00D0A8":"Network Engines, Inc.","00D0A9":"Shinano Kenshi Co. Ltd","00D0AA":"Chase Communications","00D0AB":"Deltakabel Telecom CV","00D0AC":"Commscope, Inc","00D0AD":"TL Industries","00D0AE":"Oresis Communications, Inc.","00D0AF":"Cutler-Hammer, Inc.","00D0B0":"Bitswitch Ltd","00D0B1":"Omega Electronics SA","00D0B2":"Xiotech Corporation","00D0B3":"DRS Technologies Canada Ltd","00D0B4":"Katsujima Co. Ltd","00D0B5":"IPricot formerly DotCom","00D0B6":"Crescent Networks, Inc.","00D0B7":"Intel Corporation","00D0B8":"Iomega Corporation","00D0B9":"Microtek International, Inc.","00D0BA":"Cisco Systems Inc.","00D0BB":"Cisco Systems Inc.","00D0BC":"Cisco Systems Inc.","00D0BD":"Lattice Semiconductor Corp. (LPA)","00D0BE":"Emutec Inc.","00D0BF":"Pivotal Technologies","00D0C0":"Cisco Systems Inc.","00D0C1":"Harmonic Data Systems Ltd","00D0C2":"Balthazar Technology AB","00D0C3":"Vivid Technology PTE Ltd","00D0C4":"Teratech Corporation","00D0C5":"Computational Systems, Inc.","00D0C6":"Thomas & Betts Corp.","00D0C7":"Pathway, Inc.","00D0C8":"Prevas A/S","00D0C9":"Advantech Co. Ltd","00D0CA":"Intrinsyc Software International Inc.","00D0CB":"Dasan Co. Ltd","00D0CC":"Technologies Lyre Inc.","00D0CD":"Atan Technology Inc.","00D0CE":"iSystem Labs","00D0CF":"Moreton BAY","00D0D0":"Zhongxing Telecom Ltd","00D0D1":"Sycamore Networks","00D0D2":"Epilog Corporation","00D0D3":"Cisco Systems Inc.","00D0D4":"V-Bits, Inc.","00D0D5":"Grundig AG","00D0D6":"Aethra Telecomunicazioni","00D0D7":"B2C2, Inc.","00D0D8":"3Com Corporation","00D0D9":"Dedicated Microcomputers","00D0DA":"Taicom Data Systems Co. Ltd","00D0DB":"Mcquay International","00D0DC":"Modular Mining Systems, Inc.","00D0DD":"Sunrise Telecom, Inc.","00D0DE":"Philips Multimedia Network","00D0DF":"Kuzumi Electronics, Inc.","00D0E0":"Dooin Electronics Co.","00D0E1":"Avionitek Israel Inc.","00D0E2":"MRT Micro, Inc.","00D0E3":"ELE-Chem Engineering Co. Ltd","00D0E4":"Cisco Systems Inc.","00D0E5":"Solidum Systems Corp.","00D0E6":"Ibond Inc.","00D0E7":"Vcon Telecommunication Ltd","00D0E8":"MAC System Co. Ltd","00D0E9":"Advantage Century Telecommunication Corp.","00D0EA":"Nextone Communications, Inc.","00D0EB":"Lightera Networks, Inc.","00D0EC":"NAKAYO Inc","00D0ED":"Xiox","00D0EE":"Dictaphone Corporation","00D0EF":"IGT","00D0F0":"Convision Technology GmbH","00D0F1":"Sega Enterprises Ltd","00D0F2":"Monterey Networks","00D0F3":"Solari DI Udine SPA","00D0F4":"Carinthian Tech Institute","00D0F5":"Orange Micro, Inc.","00D0F6":"Nokia","00D0F7":"Next Nets Corporation","00D0F8":"Fujian Star Terminal","00D0F9":"Acute Communications Corp.","00D0FA":"Thales e-Security Ltd","00D0FB":"TEK Microsystems, Incorporated","00D0FC":"Granite Microsystems","00D0FD":"Optima Tele.com, Inc.","00D0FE":"Astral Point","00D0FF":"Cisco Systems Inc.","00D11C":"Acetel","00D318":"SPG Controls","00D38D":"Hotel Technology Next Generation","00D632":"GE Energy","00D78F":"Cisco Systems Inc.","00D9D1":"Sony Interactive Entertainment Inc.","00DA55":"Cisco Systems Inc.","00DB1E":"Albedo Telecom SL","00DB45":"Thamway Co. Ltd","00DB70":"Apple","00DBDF":"Intel Corporation","00DD00":"Ungermann-Bass Inc.","00DD01":"Ungermann-Bass Inc.","00DD02":"Ungermann-Bass Inc.","00DD03":"Ungermann-Bass Inc.","00DD04":"Ungermann-Bass Inc.","00DD05":"Ungermann-Bass Inc.","00DD06":"Ungermann-Bass Inc.","00DD07":"Ungermann-Bass Inc.","00DD08":"Ungermann-Bass Inc.","00DD09":"Ungermann-Bass Inc.","00DD0A":"Ungermann-Bass Inc.","00DD0B":"Ungermann-Bass Inc.","00DD0C":"Ungermann-Bass Inc.","00DD0D":"Ungermann-Bass Inc.","00DD0E":"Ungermann-Bass Inc.","00DD0F":"Ungermann-Bass Inc.","00DEFB":"Cisco Systems Inc.","00E000":"Fujitsu Limited","00E001":"Strand Lighting Limited","00E002":"Crossroads Systems, Inc.","00E003":"Nokia Wireless Business Commun","00E004":"PMC-Sierra, Inc.","00E005":"Technical Corp.","00E006":"Silicon Integrated Sys. Corp.","00E007":"Avaya ECS Ltd","00E008":"Amazing Controls! Inc.","00E009":"Stratus Technologies","00E00A":"Diba, Inc.","00E00B":"Rooftop Communications Corp.","00E00C":"Motorola","00E00D":"Radiant Systems","00E00E":"Avalon Imaging Systems, Inc.","00E00F":"Shanghai Baud Data Communication Co. Ltd","00E010":"HESS SB-AUTOMATENBAU GmbH","00E011":"Uniden Corporation","00E012":"Pluto Technologies International Inc.","00E013":"Eastern Electronic Co. Ltd","00E014":"Cisco Systems Inc.","00E015":"Heiwa Corporation","00E016":"Rapid City Communications","00E017":"EXXACT GmbH","00E018":"ASUSTek Computer Inc.","00E019":"ING. Giordano Elettronica","00E01A":"Comtec Systems. Co. Ltd","00E01B":"Sphere Communications, Inc.","00E01C":"Cradlepoint, Inc","00E01D":"WebTV NETWORKS, Inc.","00E01E":"Cisco Systems Inc.","00E01F":"AVIDIA Systems, Inc.","00E020":"Tecnomen Oy","00E021":"Freegate Corp.","00E022":"Analog Devices, Inc.","00E023":"Telrad","00E024":"Gadzoox Networks","00E025":"dit Co. Ltd","00E026":"Redlake MASD LLC","00E027":"DUX, Inc.","00E028":"Aptix Corporation","00E029":"Standard Microsystems Corp.","00E02A":"Tandberg Television AS","00E02B":"Extreme Networks, Inc.","00E02C":"AST Computer","00E02D":"InnoMediaLogic, Inc.","00E02E":"SPC Electronics Corporation","00E02F":"Mcns Holdings, L.P.","00E030":"Melita International Corp.","00E031":"Hagiwara Electric Co. Ltd","00E032":"Misys Financial Systems Ltd","00E033":"E.E.P.D. GmbH","00E034":"Cisco Systems Inc.","00E035":"Artesyn Embedded Technologies","00E036":"Pioneer Corporation","00E037":"Century Corporation","00E038":"Proxima Corporation","00E039":"Paradyne Corp.","00E03A":"Cabletron Systems, Inc.","00E03B":"Prominet Corporation","00E03C":"AdvanSys","00E03D":"Focon Electronic Systems A/S","00E03E":"Alfatech, Inc.","00E03F":"Jaton Corporation","00E040":"DeskStation Technology, Inc.","00E041":"Cspi","00E042":"Pacom Systems Ltd","00E043":"VitalCom","00E044":"Lsics Corporation","00E045":"Touchwave, Inc.","00E046":"Bently Nevada Corp.","00E047":"Infocus Corporation","00E048":"SDL Communications, Inc.","00E049":"MICROWI ELECTRONIC GmbH","00E04A":"ZX Technologies, Inc","00E04B":"JUMP IndUSTRIELLE CoMPUTERTECHNIK GmbH","00E04C":"Realtek Semiconductor Corp.","00E04D":"Internet Initiative Japan, Inc","00E04E":"Sanyo Denki Co. Ltd","00E04F":"Cisco Systems Inc.","00E050":"Executone Information Systems, Inc.","00E051":"Talx Corporation","00E052":"Brocade Communications Systems, Inc.","00E053":"Cellport Labs, Inc.","00E054":"Kodai Hitec Co. Ltd","00E055":"Ingenieria Electronica Comercial Inelcom S.A.","00E056":"Holontech Corporation","00E057":"HAN Microtelecom. Co. Ltd","00E058":"Phase ONE Denmark A/S","00E059":"Controlled Environments Ltd","00E05A":"Galea Network Security","00E05B":"West END Systems Corp.","00E05C":"Panasonic Healthcare Co. Ltd","00E05D":"Unitec Co. Ltd","00E05E":"Japan Aviation Electronics Industry Ltd","00E05F":"e-Net, Inc.","00E060":"Sherwood","00E061":"EdgePoint Networks, Inc.","00E062":"Host Engineering","00E063":"Cabletron Systems, Inc.","00E064":"Samsung Electronics","00E065":"Optical Access International","00E066":"ProMax Systems, Inc.","00E067":"eac AUTOMATION-CoNSULTING GmbH","00E068":"Merrimac Systems Inc.","00E069":"Jaycor","00E06A":"Kapsch AG","00E06B":"W&G Special Products","00E06C":"Ultra Electronics Command & Control Systems","00E06D":"Compuware Corporation","00E06E":"FAR SysTEMS S.p.A.","00E06F":"ARRIS Group, Inc.","00E070":"DH Technology","00E071":"Epis Microcomputer","00E072":"Lynk","00E073":"National Amusement Network, Inc.","00E074":"Tiernan Communications, Inc.","00E075":"Verilink Corporation","00E076":"Development Concepts, Inc.","00E077":"Webgear, Inc.","00E078":"Berkeley Networks","00E079":"A.T.N.R.","00E07A":"Mikrodidakt AB","00E07B":"BAY Networks","00E07C":"Mettler-Toledo, Inc.","00E07D":"Netronix, Inc.","00E07E":"Walt Disney Imagineering","00E07F":"LOGISTISTEM s.r.l.","00E080":"Control Resources Corporation","00E081":"Tyan Computer Corp.","00E082":"Anerma","00E083":"Jato Technologies, Inc.","00E084":"Compulite R&D","00E085":"Global Maintech, Inc.","00E086":"Emerson Network Power, Avocent Division","00E087":"LeCroy - Networking Productions Division","00E088":"LTX-Credence CoRPORATION","00E089":"ION Networks, Inc.","00E08A":"GEC Avery Ltd","00E08B":"QLogic Corporation","00E08C":"Neoparadigm Labs, Inc.","00E08D":"Pressure Systems, Inc.","00E08E":"Utstarcom","00E08F":"Cisco Systems Inc.","00E090":"Beckman LAB. Automation Div.","00E091":"LG Electronics","00E092":"Admtek Incorporated","00E093":"Ackfin Networks","00E094":"Osai SRL","00E095":"Advanced-Vision Technolgies Corp.","00E096":"Shimadzu Corporation","00E097":"Carrier Access Corporation","00E098":"AboCom","00E099":"Samson AG","00E09A":"Positron Inc.","00E09B":"Engage Networks, Inc.","00E09C":"MII","00E09D":"Sarnoff Corporation","00E09E":"Quantum Corporation","00E09F":"Pixel Vision","00E0A0":"Wiltron Co.","00E0A1":"HIMA PAUL HILDEBRANDT GmbH Co. KG","00E0A2":"Microslate Inc.","00E0A3":"Cisco Systems Inc.","00E0A4":"ESAOTE S.p.A.","00E0A5":"ComCore Semiconductor, Inc.","00E0A6":"Telogy Networks, Inc.","00E0A7":"IPC Information Systems, Inc.","00E0A8":"SAT GmbH & Co.","00E0A9":"Funai Electric Co. Ltd","00E0AA":"Electrosonic Ltd","00E0AB":"Dimat S.A.","00E0AC":"Midsco, Inc.","00E0AD":"EES Technology Ltd","00E0AE":"Xaqti Corporation","00E0AF":"General Dynamics Information Systems","00E0B0":"Cisco Systems Inc.","00E0B1":"Alcatel-Lucent Enterprise","00E0B2":"Telmax Communications Corp.","00E0B3":"EtherWAN Systems, Inc.","00E0B4":"Techno Scope Co. Ltd","00E0B5":"Ardent Communications Corp.","00E0B6":"Entrada Networks","00E0B7":"PI Group Ltd","00E0B8":"Gateway 2000","00E0B9":"Byas Systems","00E0BA":"BERGHOF AUTOMATIONSTECHNIK GmbH","00E0BB":"NBX Corporation","00E0BC":"Symon Communications, Inc.","00E0BD":"Interface Systems, Inc.","00E0BE":"Genroco International, Inc.","00E0BF":"Torrent Networking Technologies Corp.","00E0C0":"Seiwa Electric MFG. Co. Ltd","00E0C1":"Memorex Telex Japan Ltd","00E0C2":"NECSY S.p.A.","00E0C3":"Sakai System Development Corp.","00E0C4":"Horner Electric, Inc.","00E0C5":"Bcom Electronics Inc.","00E0C6":"LINK2IT, L.L.C.","00E0C7":"Eurotech SRL","00E0C8":"Virtual Access Ltd","00E0C9":"AutomatedLogic Corporation","00E0CA":"Best Data Products","00E0CB":"Reson, Inc.","00E0CC":"Hero Systems Ltd","00E0CD":"Saab Sensis Corporation","00E0CE":"ARN","00E0CF":"Integrated Device","00E0D0":"Netspeed, Inc.","00E0D1":"Telsis Limited","00E0D2":"Versanet Communications, Inc.","00E0D3":"DATENTECHNIK GmbH","00E0D4":"Excellent Computer","00E0D5":"Emulex Corporation","00E0D6":"Computer & Communication Research LAB.","00E0D7":"Sunshine Electronics, Inc.","00E0D8":"LANBit Computer, Inc.","00E0D9":"Tazmo Co. Ltd","00E0DA":"Alcatel-Lucent Enterprise","00E0DB":"ViaVideo Communications, Inc.","00E0DC":"Nexware Corp.","00E0DD":"Zenith Electronics Corporation","00E0DE":"Datax NV","00E0DF":"KEYMILE GmbH","00E0E0":"SI Electronics Ltd","00E0E1":"G2 Networks, Inc.","00E0E2":"Innova Corp.","00E0E3":"SK-Elektronik GmbH","00E0E4":"FANUC ROBOTICS NORTH AMERICA, Inc.","00E0E5":"Cinco Networks, Inc.","00E0E6":"IncAA Computers","00E0E7":"Raytheon E-Systems, Inc.","00E0E8":"GRETACODER Data Systems AG","00E0E9":"Data Labs, Inc.","00E0EA":"Innovat Communications, Inc.","00E0EB":"Digicom Systems, Incorporated","00E0EC":"Celestica Inc.","00E0ED":"Silicom Ltd","00E0EE":"Marel HF","00E0EF":"Dionex","00E0F0":"Abler Technology, Inc.","00E0F1":"That Corporation","00E0F2":"Arlotto Comnet, Inc.","00E0F3":"WebSprint Communications, Inc.","00E0F4":"INSIDE Technology A/S","00E0F5":"Teles AG","00E0F6":"Decision Europe","00E0F7":"Cisco Systems Inc.","00E0F8":"Dicna Control AB","00E0F9":"Cisco Systems Inc.","00E0FA":"TRL Technology Ltd","00E0FB":"Leightronix, Inc.","00E0FC":"Huawei Technologies Co. Ltd","00E0FD":"A-Trend Technology Co. Ltd","00E0FE":"Cisco Systems Inc.","00E0FF":"SECURITY DYNAMICS TECHNOLOGIES, Inc.","00E16D":"Cisco Systems Inc.","00E175":"AK-Systems Ltd","00E18C":"Intel Corporation","00E3B2":"Samsung Electronics Co. Ltd","00E400":"Sichuan Changhong Electric Ltd","00E666":"ARIMA Communications Corp.","00E6D3":"Nixdorf Computer Corp.","00E6E8":"Netzin Technology Corporation,.Ltd","00E8AB":"Meggitt Training Systems, Inc.","00EB2D":"Sony Mobile Communications AB","00EBD5":"Cisco Systems Inc.","00EC0A":"Xiaomi Communications Co Ltd","00EEBD":"HTC Corporation","00F051":"KWB GmbH","00F22C":"Shanghai B-star Technology Co. Ltd","00F28B":"Cisco Systems Inc.","00F3DB":"WOO Sports","00F403":"Orbis Systems Oy","00F46F":"Samsung Electronics Co. Ltd","00F4B9":"Apple","00F663":"Cisco Systems Inc.","00F76F":"Apple","00F81C":"Huawei Technologies Co. Ltd","00F82C":"Cisco Systems Inc.","00F860":"PT. Panggung Electric Citrabuana","00F871":"DGS Denmark A/S","00FA3B":"Cloos Electronic GmbH","00FC58":"WebSilicon Ltd","00FC70":"Intrepid Control Systems, Inc.","00FC8B":"Amazon Technologies Inc.","00FC8D":"Hitron Technologies. Inc","00FD45":"Hewlett Packard Enterprise","00FD4C":"Nevatec","00FEC8":"Cisco Systems Inc.","020701":"Racal-Datacom","021C7C":"Perq Systems Corporation","026086":"Logic Replacement Tech. Ltd","02608C":"3Com Corporation","027001":"Racal-Datacom","0270B0":"M/A-CoM Inc. Companies","0270B3":"Data Recall Ltd","029D8E":"Cardiac Recorders, Inc.","02AA3C":"Olivetti Telecomm SPA (Olteco)","02BB01":"Octothorpe Corp.","02C08C":"3Com Corporation","02CF1C":"Communication Machinery Corporation","02E6D3":"Nixdorf Computer Corp.","04021F":"Huawei Technologies Co. Ltd","0402CA":"Shenzhen Vtsonic Co. Ltd","0403D6":"Nintendo Co. Ltd","0404EA":"Valens Semiconductor Ltd","040973":"Hewlett Packard Enterprise","040A83":"Alcatel-Lucent","040AE0":"Xmit AG Computer Networks","040CCE":"Apple","040EC2":"ViewSonic Mobile China Limited","041552":"Apple","04180F":"Samsung Electronics Co. Ltd","0418B6":"Private","0418D6":"Ubiquiti Networks Inc.","04197F":"Grasphere Japan","041A04":"WaveIP","041B6D":"LG Electronics (Mobile Communications)","041B94":"Host Mobility AB","041BBA":"Samsung Electronics Co. Ltd","041D10":"Dream Ware Inc.","041E64":"Apple","041E7A":"DSPWorks","04209A":"Panasonic Corporation AVC Networks Company","04214C":"Insight Energy Ventures LLC","042234":"Wireless Standard Extensions","0425C5":"Huawei Technologies Co. Ltd","042605":"GFR Gesellschaft f?r Regelungstechnik und Energieeinsparung mbH","042665":"Apple","042758":"Huawei Technologies Co. Ltd","042AE2":"Cisco Systems Inc.","042BBB":"PicoCELA, Inc.","042DB4":"First Property (Beijing) Co. Ltd Modern MOMA Branch","042F56":"ATOCS (Shenzhen) Ltd","043110":"Inspur Group Co. Ltd","0432F4":"Partron","043389":"Huawei Technologies Co. Ltd","043604":"Gyeyoung I&T","043A0D":"SM Optics S.r.l.","043D98":"ChongQing QingJia Electronics Co. Ltd","044169":"GoPro","0444A1":"Telecon Galicia,S.A.","044665":"Murata Manufacturing Co. Ltd","04489A":"Apple","044A50":"Ramaxel Technology (Shenzhen) limited Company","044BED":"Apple","044BFF":"GuangZhou Hedy Digital Technology Co. Ltd","044CEF":"Fujian Sanao Technology Co. Ltd","044E06":"Ericsson AB","044E5A":"ARRIS Group, Inc.","044EAF":"LG Innotek","044F17":"HUMAX Co. Ltd","044F4C":"Huawei Technologies Co. Ltd","044F8B":"Adapteva, Inc.","044FAA":"Ruckus Wireless","0450DA":"Qiku Internet Network Scientific (Shenzhen) Co. Ltd","0452C7":"Bose Corporation","0452F3":"Apple","0453D5":"Sysorex Global Holdings","045453":"Apple","0455CA":"BriView (Xiamen) Corp.","045604":"Gionee Communication Equipment Co. Ltd","04572F":"Sertel Electronics UK Ltd","04586F":"Sichuan Whayer Information Industry Co. Ltd","045A95":"Nokia Corporation","045C06":"Zmodo Technology Corporation","045C8E":"gosund GROUP Co. Ltd","045D4B":"Sony Corporation","045D56":"camtron Industrial Inc.","045FA7":"Shenzhen Yichen Technology Development Co. Ltd","046169":"Media Global Links Co. Ltd","046273":"Cisco Systems Inc.","0462D7":"Alstom Hydro France","0463E0":"Nome Oy","046565":"Testop","046785":"scemtec Hard- und Software fuer Mess- und Steuerungstechnik GmbH","0469F8":"Apple","046B1B":"SysDINE Co. Ltd","046C9D":"Cisco Systems Inc.","046D42":"Bryston Ltd","046E02":"OpenRTLS Group","046E49":"TaiYear Electronic Technology (Suzhou) Co. Ltd","0470BC":"Globalstar Inc.","04714B":"IEEE Registration Authority","0474A1":"Aligera Equipamentos Digitais Ltda","047503":"Huawei Technologies Co. Ltd","0475F5":"Csst","04766E":"Alps Electric Co. Ltd","047863":"Shanghai MXCHIP Information Technology Co. Ltd","047970":"Huawei Technologies Co. Ltd","047D50":"Shenzhen Kang Ying Technology Co.Ltd","047D7B":"Quanta Computer Inc.","047E4A":"moobox Co. Ltd","0481AE":"Clack Corporation","04848A":"7INOVA Technology Limited","04888C":"Eifelwerk Butler Systeme GmbH","0488E2":"Beats Electronics LLC","048A15":"Avaya Inc","048AE1":"Flextronics Manufacturing(Zhuhai)Co. Ltd","048B42":"Skspruce Technologies","048C03":"ThinPAD Technology (Shenzhen)Co. Ltd","048D38":"Netcore Technology Inc.","0492EE":"iway AG","04946B":"Tecno Mobile Limited","0494A1":"Catch THE Wind Inc","049573":"zte Corporation","0495E6":"Tenda Technology Co. LtdDongguan branch","049645":"Wuxi SKY Chip Interconnection Technology Co. Ltd","049790":"Lartech telecom LLC","0498F3":"Alps Electric Co. Ltd","0499E6":"Shenzhen Yoostar Technology Co. Ltd","049B9C":"Eadingcore Intelligent Technology Co. Ltd","049C62":"BMT Medical Technology s.r.o.","049F06":"Smobile Co. Ltd","049F81":"NetScout Systems, Inc.","049FCA":"Huawei Technologies Co. Ltd","04A151":"Netgear","04A316":"Texas Instruments","04A3F3":"Emicon","04A82A":"Nokia Corporation","04AC44":"Holtek Semiconductor Inc.","04B0E7":"Huawei Technologies Co. Ltd","04B167":"Xiaomi Communications Co Ltd","04B3B6":"Seamap (UK) Ltd","04B466":"BSP Co. Ltd","04B648":"Zenner","04BA36":"Li Seng Technology Ltd","04BBF9":"Pavilion Data Systems Inc","04BD70":"Huawei Technologies Co. Ltd","04BD88":"Aruba Networks","04BF6D":"ZyXEL Communications Corp","04BFA8":"ISB Corporation","04C05B":"Tigo Energy","04C06F":"Huawei Technologies Co. Ltd","04C09C":"Tellabs Inc.","04C103":"Clover Network, Inc.","04C1B9":"Fiberhome Telecommunication Technologies Co. Ltd","04C23E":"HTC Corporation","04C241":"Nokia","04C5A4":"Cisco Systems Inc.","04C880":"Samtec Inc","04C991":"Phistek Inc.","04C9D9":"Dish Technologies Corp","04CB1D":"Traka plc","04CE14":"Wilocity Ltd","04CF25":"Manycolors, Inc.","04D13A":"Xiaomi Communications Co Ltd","04D3B0":"Intel Corporation","04D3CF":"Apple","04D437":"ZNV","04D6AA":"Samsung Electro-Mechanics(Thailand)","04D783":"Y&H E&C Co. Ltd","04DAD2":"Cisco Systems Inc.","04DB56":"Apple","04DB8A":"Suntech International Ltd","04DD4C":"Velocytech","04DEDB":"Rockport Networks Inc","04DEF2":"Shenzhen ECOM Technology Co. Ltd","04DF69":"Car Connectivity Consortium","04E0B0":"Shenzhen YOUHUA Technology Co. Ltd","04E0C4":"Triumph-Adler AG","04E1C8":"IMS Solu??es em Energia Ltda.","04E229":"Qingdao Haier Technology Co. Ltd","04E2F8":"AEP Ticketing solutions srl","04E451":"Texas Instruments","04E536":"Apple","04E548":"Cohda Wireless Pty Ltd","04E662":"Acroname Inc.","04E676":"AMPAK Technology, Inc.","04E9E5":"Pjrc.com, LLC","04ECBB":"Fiberhome Telecommunication Technologies Co. Ltd","04EE91":"x-fabric GmbH","04F021":"Compex Systems Pte Ltd","04F128":"HMD Global Oy","04F13E":"Apple","04F17D":"Tarana Wireless","04F4BC":"Xena Networks","04F7E4":"Apple","04F8C2":"Flaircomm Microelectronics, Inc.","04F938":"Huawei Technologies Co. Ltd","04FA3F":"Opticore Inc.","04FA83":"Qingdao Haier Technology Co. Ltd","04FE31":"Samsung Electronics Co. Ltd","04FE7F":"Cisco Systems Inc.","04FE8D":"Huawei Technologies Co. Ltd","04FEA1":"Fihonest Communication Co. Ltd","04FF51":"Novamedia Innovision SP. Z O.O.","080001":"Computervision Corporation","080002":"Bridge Communications Inc.","080003":"Advanced Computer Comm.","080004":"Cromemco Incorporated","080005":"Symbolics Inc.","080006":"Siemens AG","080007":"Apple","080008":"Bolt Beranek AND Newman Inc.","080009":"Hewlett-Packard Company","08000A":"Nestar Systems Incorporated","08000B":"Unisys Corporation","08000C":"Miklyn Development Co.","08000D":"International Computers Ltd","08000E":"NCR Corporation","08000F":"Mitel Corporation","080011":"Tektronix Inc.","080012":"Bell Atlantic Integrated Syst.","080013":"Exxon","080014":"Excelan","080015":"STC Business Systems","080016":"Barrister Info Sys Corp","080017":"National Semiconductor","080018":"Pirelli Focom Networks","080019":"General Electric Corporation","08001A":"Tiara/ 10NET","08001B":"Dell EMC","08001C":"KDD-Kokusai Debnsin Denwa Co.","08001D":"Able Communications Inc.","08001E":"Apollo Computer Inc.","08001F":"Sharp Corporation","080020":"Oracle Corporation","080021":"3M Company","080022":"NBI Inc.","080023":"Panasonic Communications Co. Ltd","080024":"10NET Communications/DCA","080025":"Control Data","080026":"Norsk Data A.S.","080027":"PCS Systemtechnik GmbH","080028":"Texas Instruments","080029":"Megatek Corporation","08002A":"Mosaic Technologies Inc.","08002B":"Digital Equipment Corporation","08002C":"Britton LEE Inc.","08002D":"LAN-TEC Inc.","08002E":"Metaphor Computer Systems","08002F":"Prime Computer Inc.","080030":"Cern","080031":"Little Machines Inc.","080032":"Tigan Incorporated","080033":"Bausch & Lomb","080034":"Filenet Corporation","080035":"Microfive Corporation","080036":"Intergraph Corporation","080037":"Fuji-Xerox Co. Ltd","080038":"Bull S.A.S.","080039":"Spider Systems Limited","08003A":"Orcatech Inc.","08003B":"Torus Systems Limited","08003C":"Schlumberger Well Services","08003D":"Cadnetix Corporations","08003E":"Codex Corporation","08003F":"Fred Koschara Enterprises","080040":"Ferranti Computer Sys. Limited","080041":"Racal-Milgo Information Sys..","080042":"Japan Macnics Corp.","080043":"Pixel Computer Inc.","080044":"David Systems Inc.","080045":"Concurrent Computer Corp.","080046":"Sony Corporation","080047":"Sequent Computer Systems Inc.","080048":"Eurotherm Gauging Systems","080049":"Univation","08004A":"Banyan Systems Inc.","08004B":"Planning Research Corp.","08004C":"Hydra Computer Systems Inc.","08004D":"Corvus Systems Inc.","08004E":"3Com Europe Ltd","08004F":"Cygnet Systems","080050":"Daisy Systems Corp.","080051":"ExperData","080052":"Insystec","080053":"Middle East Tech. University","080055":"Stanford Telecomm. Inc.","080056":"Stanford Linear Accel. Center","080057":"Evans & Sutherland","080058":"Systems Concepts","080059":"A/S Mycron","08005A":"IBM Corp","08005B":"VTA Technologies Inc.","08005C":"Four Phase Systems","08005D":"Gould Inc.","08005E":"Counterpoint Computer Inc.","08005F":"Saber Technology Corp.","080060":"Industrial Networking Inc.","080061":"Jarogate Ltd","080062":"General Dynamics","080063":"Plessey","080064":"Sitasys AG","080065":"Genrad Inc.","080066":"Agfa Corporation","080067":"ComDesign","080068":"Ridge Computers","080069":"Silicon Graphics Inc.","08006A":"AT&T","08006B":"Accel Technologies Inc.","08006C":"Suntek Technology Int'l","08006D":"Whitechapel Computer Works","08006E":"Masscomp","08006F":"Philips Apeldoorn B.V.","080070":"Mitsubishi Precision Co. Ltd","080071":"Matra (Dsie)","080072":"Xerox Corp Univ Grant Program","080073":"Tecmar Inc.","080074":"Casio Computer Co. Ltd","080075":"Dansk Data Electronik","080076":"PC LAN Technologies","080077":"TSL Communications Ltd","080078":"Accell Corporation","080079":"THE Droid Works","08007A":"Indata","08007B":"Sanyo Electric Co. Ltd","08007C":"Vitalink Communications Corp.","08007E":"Amalgamated Wireless(AUS) Ltd","08007F":"Carnegie-Mellon University","080080":"AES Data Inc.","080081":"Astech Inc.","080082":"Veritas Software","080083":"Seiko Instruments Inc.","080084":"Tomen Electronics Corp.","080085":"Elxsi","080086":"Konica Minolta Holdings, Inc.","080087":"Xyplex, Inc.","080088":"Brocade Communications Systems, Inc.","080089":"Kinetics","08008A":"PerfTech, Inc.","08008B":"Pyramid Technology Corp.","08008C":"Network Research Corporation","08008D":"Xyvision Inc.","08008E":"Tandem Computers","08008F":"Chipcom Corporation","080090":"Sonoma Systems","08010F":"Sichuan Tianyi Comheart Telecomco. Ltd","08028E":"Netgear","080371":"KRG Corporate","080581":"Roku, Inc.","0805CD":"DongGuang EnMai Electronic Product Co.Ltd","0808C2":"Samsung Electronics Co. Ltd","0808EA":"Amsc","0809B6":"Masimo Corp","080A4E":"Planet Bingo(R) -- 3rd Rock Gaming(R)","080C0B":"SysMik GmbH Dresden","080CC9":"Mission Technology Group, dba Magma","080D84":"GECO, Inc.","080EA8":"Velex s.r.l.","080FFA":"KSP Inc.","08115E":"Bitel Co. Ltd","081196":"Intel Corporation","081443":"Unibrain S.A.","08152F":"Samsung Electronics Co. Ltd ARTIK","081651":"Shenzhen SEA Star Technology Co. Ltd","081735":"Cisco Systems Inc.","0817F4":"IBM Corp","08181A":"zte Corporation","08184C":"A. S. Thomas, Inc.","0819A6":"Huawei Technologies Co. Ltd","081DC4":"Thermo Fisher Scientific Messtechnik GmbH","081DFB":"Shanghai Mexon Communication Technology Co. Ltd","081F3F":"WondaLink Inc.","081F71":"TP-Link Technologies Co. Ltd","081FEB":"BinCube","081FF3":"Cisco Systems Inc.","0821EF":"Samsung Electronics Co. Ltd","0823B2":"vivo Mobile Communication Co. Ltd","082522":"Advansee","082719":"APS Systems/electronic AG","0827CE":"Nagano Keiki Co. Ltd","082AD0":"SRD Innovations Inc.","082CB0":"Network Instruments","082E5F":"Hewlett-Packard Company","08306B":"Palo Alto Networks","083571":"CASwell Inc.","0835B2":"CoreEdge Networks Co. Ltd","08373D":"Samsung Electronics Co. Ltd","08379C":"Topaz Co. Ltd","0838A5":"Funkwerk plettac electronic GmbH","083A5C":"Junilab, Inc.","083AB8":"Shinoda Plasma Co. Ltd","083D88":"Samsung Electronics Co. Ltd","083E0C":"ARRIS Group, Inc.","083E5D":"Sagemcom Broadband SAS","083E8E":"Hon Hai Precision Ind. Co. Ltd","083F3E":"WSH GmbH","083F76":"Intellian Technologies, Inc.","083FBC":"zte Corporation","084027":"Gridstore Inc.","0840F3":"Tenda Technology Co. LtdDongguan branch","084656":"VEO-Labs","08482C":"Raycore Taiwan Co. Ltd","084ACF":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","084E1C":"H2A Systems, LLC","084EBF":"Broad Net Mux Corporation","085114":"Qingdao Topscomm Communication Co. Ltd","08512E":"Orion Diagnostica Oy","085240":"EbV Elektronikbau- und Vertriebs GmbH","085700":"TP-Link Technologies Co. Ltd","085AE0":"Recovision Technology Co. Ltd","085B0E":"Fortinet, Inc.","085BDA":"CliniCare Ltd","085DDD":"Mercury Corporation","08606E":"ASUSTek Computer Inc.","086266":"ASUSTek Computer Inc.","086361":"Huawei Technologies Co. Ltd","08661F":"Palo Alto Networks","086698":"Apple","08674E":"Hisense broadband multimedia technology Co. Ltd","0868D0":"Japan System Design","0868EA":"Eito Electronics Co. Ltd","086A0A":"Askey Computer Corp","086D41":"Apple","086DF2":"Shenzhen MIMOWAVE Technology Co. Ltd","087045":"Apple","087402":"Apple","0874F6":"Winterhalter Gastronom GmbH","087572":"Obelux Oy","087618":"ViE Technologies Sdn. Bhd.","087695":"Auto Industrial Co. Ltd","0876FF":"Thomson Telecom Belgium","087808":"Samsung Electronics Co. Ltd","087999":"AIM GmbH","087A4C":"Huawei Technologies Co. Ltd","087BAA":"Svyazkomplektservice, LLC","087CBE":"Quintic Corp.","087D21":"Altasec technology Corporation","088039":"Cisco SPVTG","0881BC":"HongKong Ipro Technology Co., Limited","0881F4":"Juniper Networks","088466":"Novartis Pharma AG","088620":"Tecno Mobile Limited","08863B":"Belkin International Inc.","088C2C":"Samsung Electronics Co. Ltd","088DC8":"Ryowa Electronics Co. Ltd","088E4F":"SF Software Solutions","088F2C":"Hills Sound Vision & Lighting","0894EF":"Wistron Infocomm (Zhongshan) Corporation","08952A":"Technicolor CH USA Inc.","0896AD":"Cisco Systems Inc.","0896D7":"AVM GmbH","089734":"Hewlett Packard Enterprise","089758":"Shenzhen Strong Rising Electronics Co. Ltd DongGuan Subsidiary","089B4B":"iKuai Networks","089E01":"Quanta Computer Inc.","089E08":"Google, Inc.","089F97":"Leroy Automation","08A12B":"ShenZhen EZL Technology Co. Ltd","08A5C8":"Sunnovo International Limited","08A8A1":"Cyclotronics Power Concepts, Inc","08A95A":"Azurewave Technologies Inc.","08ACA5":"Benu Video, Inc.","08AED6":"Samsung Electronics Co. Ltd","08AF78":"Totus Solutions, Inc.","08B258":"Juniper Networks","08B2A3":"Cynny Italia S.r.L.","08B4CF":"Abicom International","08B738":"Lite-On Technogy Corp.","08B7EC":"Wireless Seismic","08BA22":"Swaive Corporation","08BBCC":"AK-NORD EDV VERTRIEBSGES. mbH","08BC20":"Hangzhou Royal Cloud Technology Co. Ltd","08BD43":"Netgear","08BE09":"Astrol Electronic AG","08BE77":"Green Electronics","08BEAC":"Edimax Technology Co. Ltd","08C021":"Huawei Technologies Co. Ltd","08C6B3":"Qtech LLC","08CA45":"Toyou Feiji Electronics Co. Ltd","08CC68":"Cisco Systems Inc.","08CCA7":"Cisco Systems Inc.","08CD9B":"samtec automotive electronics & software GmbH","08D09F":"Cisco Systems Inc.","08D0B7":"Qingdao Hisense Communications Co. Ltd","08D29A":"Proformatique","08D34B":"Techman Electronics (Changshu) Co. Ltd","08D40C":"Intel Corporation","08D42B":"Samsung Electronics Co. Ltd","08D5C0":"Seers Technology Co. Ltd","08D833":"Shenzhen RF Technology Co. Ltd","08DF1F":"Bose Corporation","08DFCB":"Systrome Networks","08E5DA":"Nanjing Fujitsu Computer Products Co. Ltd","08E672":"Jebsee Electronics Co. Ltd","08E689":"Apple","08E84F":"Huawei Technologies Co. Ltd","08EA40":"Shenzhen Bilian Electronic Co. Ltd","08EA44":"Aerohive Networks Inc.","08EB29":"Jiangsu Huitong Group Co. Ltd","08EB74":"HUMAX Co. Ltd","08EBED":"World Elite Technology Co. Ltd","08ECA9":"Samsung Electronics Co. Ltd","08ED02":"IEEE Registration Authority","08EDB9":"Hon Hai Precision Ind. Co. Ltd","08EE8B":"Samsung Electronics Co. Ltd","08EF3B":"MCS Logic Inc.","08EFAB":"Sayme Wireless Sensor Network","08F1B7":"Towerstream Corpration","08F2F4":"Net One Partners Co. Ltd","08F4AB":"Apple","08F69C":"Apple","08F6F8":"GET Engineering","08F728":"GLOBO Multimedia Sp. z o.o. Sp.k.","08FAE0":"Fohhn Audio AG","08FC52":"OpenXS BV","08FC88":"Samsung Electronics Co. Ltd","08FD0E":"Samsung Electronics Co. Ltd","0C0227":"Technicolor CH USA Inc.","0C0400":"Jantar d.o.o.","0C0535":"Juniper Systems","0C08B4":"HUMAX Co. Ltd","0C1105":"Ringslink (Xiamen) Network Communication Technologies Co. Ltd","0C1167":"Cisco Systems Inc.","0C1262":"zte Corporation","0C130B":"Uniqoteq Ltd","0C1420":"Samsung Electronics Co. Ltd","0C1539":"Apple","0C15C5":"SDTEC Co. Ltd","0C17F1":"Telecsys","0C191F":"Inform Electronik","0C1A10":"Acoustic Stream","0C1C20":"Kakao Corp","0C1DAF":"Xiaomi Communications Co Ltd","0C1DC2":"SeAH Networks","0C2026":"noax Technologies AG","0C2138":"Hengstler GmbH","0C2369":"Honeywell SPS","0C2576":"Longcheer Telecommunication Limited","0C2724":"Cisco Systems Inc.","0C2755":"Valuable Techologies Limited","0C2A69":"electric imp, Incorporated","0C2AE7":"Beijing General Research Institute Of Mining and Metallurgy","0C2C54":"Huawei Technologies Co. Ltd","0C2D89":"QiiQ Communications Inc.","0C3021":"Apple","0C3747":"zte Corporation","0C37DC":"Huawei Technologies Co. Ltd","0C383E":"Fanvil Technology Co. Ltd","0C3956":"Observator instruments","0C3C65":"Dome Imaging Inc","0C3CCD":"Universal Global Scientific Industrial Co. Ltd","0C3E9F":"Apple","0C413E":"Microsoft Corporation","0C41E9":"Huawei Technologies Co. Ltd","0C45BA":"Huawei Technologies Co. Ltd","0C469D":"MS Sedco","0C473D":"Hitron Technologies. Inc","0C47C9":"Amazon Technologies Inc.","0C4885":"LG Electronics (Mobile Communications)","0C4933":"Sichuan Jiuzhou Electronic Technology Co. Ltd","0C4B54":"TP-Link Technologies Co. Ltd","0C4C39":"MitraStar Technology Corp.","0C4DE9":"Apple","0C4F5A":"ASA-RT s.r.l.","0C5101":"Apple","0C51F7":"Chauvin Arnoux","0C5203":"AGM Group Limited","0C5415":"Intel Corporation","0C54A5":"Pegatron Corporation","0C54B9":"Nokia","0C5521":"Axiros GmbH","0C565C":"HyBroad Vision (Hong Kong) Technology Co Ltd","0C57EB":"Mueller Systems","0C5842":"DME Micro","0C5A19":"Axtion Sdn Bhd","0C5A9E":"Wi-SUN Alliance","0C5CD8":"DOLI Elektronik GmbH","0C5F35":"Niagara Video Corporation","0C6076":"Hon Hai Precision Ind. Co. Ltd","0C6111":"Anda Technologies SAC","0C6127":"Actiontec Electronics, Inc","0C61CF":"Texas Instruments","0C62A6":"Hui Zhou Gaoshengda Technology Co. Ltd","0C63FC":"Nanjing Signway Technology Co. Ltd","0C6803":"Cisco Systems Inc.","0C6ABC":"Fiberhome Telecommunication Technologies Co. Ltd","0C6AE6":"Stanley Security Solutions","0C6E4F":"PrimeVOLT Co. Ltd","0C6F9C":"Shaw Communications Inc.","0C704A":"Huawei Technologies Co. Ltd","0C715D":"Samsung Electronics Co. Ltd","0C722C":"TP-Link Technologies Co. Ltd","0C72D9":"zte Corporation","0C73BE":"Dongguan Haimai Electronie Technology Co. Ltd","0C73EB":"IEEE Registration Authority","0C74C2":"Apple","0C7523":"Beijing Gehua Catv Network Co. Ltd","0C756C":"Anaren Microwave, Inc.","0C75BD":"Cisco Systems Inc.","0C771A":"Apple","0C7D7C":"Kexiang Information Technology Co Ltd","0C8063":"TP-Link Technologies Co. Ltd","0C8112":"Private","0C8230":"Shenzhen Magnus Technologies Co. Ltd","0C8268":"TP-Link Technologies Co. Ltd","0C826A":"Wuhan Huagong Genuine Optics Technology Co. Ltd","0C8411":"A.O. Smith Water Products","0C8484":"Zenovia Electronics Inc.","0C84DC":"Hon Hai Precision Ind. Co. Ltd","0C8525":"Cisco Systems Inc.","0C8610":"Juniper Networks","0C8910":"Samsung Electronics Co. Ltd","0C8A87":"AgLogica Holdings, Inc","0C8BD3":"Itel Mobile Limited","0C8BFD":"Intel Corporation","0C8C8F":"Kamo Technology Limited","0C8CDC":"Suunto Oy","0C8D98":"TOP Eight Ind Corp","0C8DDB":"Cisco Meraki","0C8FFF":"Huawei Technologies Co. Ltd","0C9160":"Hui Zhou Gaoshengda Technology Co. Ltd","0C924E":"Rice Lake Weighing Systems","0C9301":"PT. Prasimax Inovasi Teknologi","0C93FB":"BNS Solutions","0C96BF":"Huawei Technologies Co. Ltd","0C9838":"Xiaomi Communications Co Ltd","0C9B13":"Shanghai Magic Mobile Telecommunication Co.Ltd","0C9D56":"Consort Controls Ltd","0C9E91":"Sankosha Corporation","0CA138":"Blinq Wireless Inc.","0CA2F4":"Chameleon Technology (UK) Limited","0CA402":"Alcatel-Lucent IPD","0CA42A":"OB Telecom Electronic Technology Co. Ltd","0CA694":"Sunitec Enterprise Co. Ltd","0CA8A7":"Samsung Electronics Co. Ltd","0CAC05":"Unitend Technologies Inc.","0CAE7D":"Texas Instruments","0CAF5A":"Genus Power Infrastructures Limited","0CB2B7":"Texas Instruments","0CB319":"Samsung Electronics Co. Ltd","0CB34F":"Shenzhen Xiaoqi Intelligent Technology Co. Ltd","0CB459":"Marketech International Corp.","0CB4EF":"Digience Co. Ltd","0CB5DE":"Alcatel Lucent","0CB912":"JM-DATA GmbH","0CB937":"Ubee Interactive Co., Limited","0CBC9F":"Apple","0CBD51":"TCT mobile Ltd","0CBF15":"Genetec Inc.","0CBF3F":"Shenzhen Lencotion Technology Co. Ltd","0CC0C0":"Magneti Marelli Sistemas Electronicos Mexico","0CC3A7":"Meritec","0CC47A":"Super Micro Computer, Inc.","0CC47E":"EUCAST Co. Ltd","0CC655":"Wuxi YSTen Technology Co. Ltd","0CC66A":"Nokia Corporation","0CC6AC":"Dags","0CC6CC":"Huawei Technologies Co. Ltd","0CC731":"Currant, Inc.","0CC81F":"Summer Infant, Inc.","0CC9C6":"Samwin Hong Kong Limited","0CCB8D":"ASCO Numatics GmbH","0CCC26":"Airenetworks","0CCDD3":"Eastriver Technology Co. Ltd","0CCDFB":"EDIC Systems Inc.","0CCEF6":"Guizhou Fortuneship Technology Co. Ltd","0CCFD1":"SPRINGWAVE Co. Ltd","0CD292":"Intel Corporation","0CD2B5":"Binatone Telecommunication Pvt. Ltd","0CD502":"Westell Technologies Inc.","0CD696":"Amimon Ltd","0CD6BD":"Huawei Technologies Co. Ltd","0CD746":"Apple","0CD7C2":"Axium Technologies, Inc.","0CD86C":"Shenzhen Fast Technologies Co. Ltd","0CD996":"Cisco Systems Inc.","0CD9C1":"Visteon Corporation","0CDA41":"Hangzhou H3C Technologies Co., Limited","0CDCCC":"Inala Technologies","0CDDEF":"Nokia Corporation","0CDFA4":"Samsung Electronics Co. Ltd","0CE0E4":"Plantronics, Inc.","0CE5D3":"DH electronics GmbH","0CE709":"Fox Crypto B.V.","0CE725":"Microsoft Corporation","0CE82F":"Bonfiglioli Vectron GmbH","0CE936":"ELIMOS srl","0CEAC9":"ARRIS Group, Inc.","0CEEE6":"Hon Hai Precision Ind. Co. Ltd","0CEF7C":"AnaCom Inc","0CEFAF":"IEEE Registration Authority","0CF019":"Malgn Technology Co. Ltd","0CF0B4":"Globalsat International Technology Ltd","0CF346":"Xiaomi Communications Co Ltd","0CF361":"Java Information","0CF3EE":"EM Microelectronic","0CF405":"Beijing Signalway Technologies Co. Ltd","0CF4D5":"Ruckus Wireless","0CF5A4":"Cisco Systems Inc.","0CF893":"ARRIS Group, Inc.","0CF9C0":"BSkyB Ltd","0CFC83":"Airoha Technology Corp.,","0CFD37":"SUSE Linux GmbH","0CFE45":"Sony Interactive Entertainment Inc.",100000:"Private","10005A":"IBM Corp","1000E8":"National Semiconductor","1000FD":"LaonPeople","1001CA":"Ashley Butterworth","1002B5":"Intel Corporation",100501:"Pegatron Corporation","1005B1":"ARRIS Group, Inc.","1005CA":"Cisco Systems Inc.",100723:"IEEE Registration Authority","1007B6":"Samsung Electronics Co. Ltd","1008B1":"Hon Hai Precision Ind. Co. Ltd","10090C":"Janome Sewing Machine Co. Ltd","100BA9":"Intel Corporation","100C24":"pomdevices, LLC","100D2F":"Online Security Pty. Ltd","100D32":"Embedian, Inc.","100D7F":"Netgear","100E2B":"NEC CASIO Mobile Communications","100E7E":"Juniper Networks","100F18":"Fu Gang Electronic(KunShan)Co. Ltd","1010B6":"McCain Inc",101212:"Vivo International Corporation Pty Ltd",101218:"Korins Inc.",101248:"ITG, Inc.",101250:"Integrated Device Technology (Malaysia) Sdn. Bhd.",101331:"Technicolor","1013EE":"Justec International Technology Inc.","10189E":"Elmo Motion Control","101B54":"Huawei Technologies Co. Ltd","101C0C":"Apple","101D51":"8Mesh Networks Limited","101DC0":"Samsung Electronics Co. Ltd","101F74":"Hewlett-Packard Company",102279:"ZeroDesktop, Inc.","1027BE":"Tvip",102831:"Morion Inc.","102AB3":"Xiaomi Communications Co Ltd","102C83":"Ximea","102D96":"Looxcie Inc.","102EAF":"Texas Instruments","102F6B":"Microsoft Corporation",103034:"Cara Systems",103047:"Samsung Electronics Co. Ltd",103378:"FLECTRON Co. Ltd",103711:"Simlink AS","103B59":"Samsung Electronics Co. Ltd","103DEA":"HFC Technology (Beijing) Ltd Co.","1040F3":"Apple","10417F":"Apple",104369:"Soundmax Electronic Limited",104400:"Huawei Technologies Co. Ltd","10445A":"Shaanxi Hitech Electronic Co. Ltd","1045BE":"Norphonic AS","1045F8":"LNT-Automation GmbH","1046B4":"FormericaOE",104780:"Huawei Technologies Co. Ltd","1048B1":"Beijing Duokan Technology Limited",104963:"Harting K.K.","104A7D":"Intel Corporation","104B46":"Mitsubishi Electric Corporation","104D77":"Innovative Computer Engineering","104E07":"Shanghai Genvision Industries Co. Ltd","104E89":"Garmin International","104FA8":"Sony Corporation",105172:"Huawei Technologies Co. Ltd",105611:"ARRIS Group, Inc.","1056CA":"Peplink International Ltd",105887:"Fiberhome Telecommunication Technologies Co. Ltd","105AF7":"ADB Italia","105C3B":"Perma-Pipe, Inc.","105CBF":"DuroByte Inc","105F06":"Actiontec Electronics, Inc","105F49":"Cisco SPVTG","10604B":"Hewlett-Packard Company","1062C9":"Adatis GmbH & Co. KG","1062D0":"Technicolor CH USA Inc.","1062EB":"D-Link International","1064E2":"ADFweb.com s.r.l.",106530:"Dell Inc.","1065A3":"Core Brands LLC","1065CF":"Iqsim",106682:"NEC Platforms Ltd","10683F":"LG Electronics (Mobile Communications)","106F3F":"Buffalo.Inc","106FEF":"Ad-Sol Nissin Corp","1071F9":"Cloud Telecomputers, LLC",107223:"Tellescom Industria E Comercio EM Telecomunicacao","10768A":"EoCell","1077B0":"Fiberhome Telecommunication Technologies Co. Ltd","1077B1":"Samsung Electronics Co. Ltd","10785B":"Actiontec Electronics, Inc",107873:"Shenzhen Jinkeyi Communication Co. Ltd","1078CE":"Hanvit SI, Inc.","1078D2":"Elitegroup Computer Systems Co. Ltd","107A86":"U&U Engineering Inc.","107B44":"ASUSTek Computer Inc.","107BEF":"ZyXEL Communications Corp","107D1A":"Dell Inc.","1083D2":"Microseven Systems, LLC","10868C":"ARRIS Group, Inc.","10880F":"Daruma Telecomunica??es e Inform?tica S.A.","1088CE":"Fiberhome Telecommunication Technologies Co. Ltd","108A1B":"RAONIX Inc.","108CCF":"Cisco Systems Inc.",109266:"Samsung Electronics Co. Ltd","1093E9":"Apple","1094BB":"Apple","10954B":"Megabyte Ltd",109836:"Dell Inc.","109AB9":"Tosibox Oy","109ADD":"Apple","109FA9":"Actiontec Electronics, Inc","10A13B":"Fujikura Rubber Ltd","10A4B9":"Baidu Online Network Technology (Beijing) Co. Ltd","10A4BE":"Shenzhen Bilian Electronic Co. Ltd","10A5D0":"Murata Manufacturing Co. Ltd","10A659":"Mobile Create Co. Ltd","10A743":"SK Mtek Limited","10A932":"Beijing Cyber Cloud Technology Co. Ltd","10AE60":"Private","10AF78":"Shenzhen ATUE Technology Co. Ltd","10B1F8":"Huawei Technologies Co. Ltd","10B26B":"base Co. Ltd","10B36F":"Bowei Technology Company Limited","10B713":"Private","10B7F6":"Plastoform Industries Ltd","10B9FE":"Lika srl","10BAA5":"Gana I&C Co. Ltd","10BD18":"Cisco Systems Inc.","10BD55":"Q-Lab Corporation","10BEF5":"D-Link International","10BF48":"ASUSTek Computer Inc.","10C07C":"Blu-ray Disc Association","10C25A":"Technicolor CH USA Inc.","10C2BA":"UTT Co. Ltd","10C37B":"ASUSTek Computer Inc.","10C586":"BIO Sound LAB Co. Ltd","10C60C":"Domino UK Ltd","10C61F":"Huawei Technologies Co. Ltd","10C67E":"Shenzhen Juchin Technology Co. Ltd","10C6FC":"Garmin International","10C73F":"Midas Klark Teknik Ltd","10CA81":"Precia","10CC1B":"Liverock technologies,Inc","10CCDB":"Aximum Produits Electroniques","10CD6E":"Fisys","10CDAE":"Avaya Inc","10CDB6":"Essential Products, Inc.","10CEA9":"Texas Instruments","10D07A":"AMPAK Technology, Inc.","10D0AB":"zte Corporation","10D1DC":"INSTAR Deutschland GmbH","10D38A":"Samsung Electronics Co. Ltd","10D542":"Samsung Electronics Co. Ltd","10DA43":"Netgear","10DDB1":"Apple","10DDF4":"Maxway Electronics Co. Ltd","10DEE4":"automationNEXT GmbH","10DF8B":"Shenzhen CareDear Communication Technology Co. Ltd","10E2D5":"Qi Hardware Inc.","10E3C7":"Seohwa Telecom","10E4AF":"APR, LLC","10E68F":"Kwangsung Electronics Korea Co. Ltd","10E6AE":"Source Technologies, LLC","10E7C6":"Hewlett-Packard Company","10E878":"Nokia","10E8EE":"PhaseSpace","10EA59":"Cisco SPVTG","10EED9":"Canoga Perkins Corporation","10F005":"Intel Corporation","10F163":"TNK Co. Ltd","10F1F2":"LG Electronics (Mobile Communications)","10F311":"Cisco Systems Inc.","10F3DB":"Gridco Systems, Inc.","10F49A":"T3 Innovation","10F681":"vivo Mobile Communication Co. Ltd","10F96F":"LG Electronics (Mobile Communications)","10F9EB":"Industria Fueguina de Relojer?a Electr?nica s.a.","10F9EE":"Nokia Corporation","10FACE":"Reacheng Communication Technology Co. Ltd","10FBF0":"KangSheng Ltd","10FC54":"Shany Electronic Co. Ltd","10FCB6":"mirusystems Co. Ltd","10FEED":"TP-Link Technologies Co. Ltd","1100AA":"Private",111111:"Private","1402EC":"Hewlett Packard Enterprise",140467:"SNK Technologies Co. Ltd",140708:"Private","1407E0":"Abrantix AG","1409DC":"Huawei Technologies Co. Ltd","140C5B":"PLNetworks","140C76":"Freebox SAS","140D4F":"Flextronics International","14109F":"Apple",141330:"Anakreon UK LLP",141357:"ATP Electronics, Inc.","14144B":"Ruijie Networks Co. Ltd","1414E6":"Ningbo Sanhe Digital Co. Ltd","14157C":"Tokyo Cosmos Electric Co. Ltd",141877:"Dell Inc.","141A51":"Treetech Sistemas Digitais","141AA3":"Motorola Mobility LLC, a Lenovo Company","141BBD":"Volex Inc.","141BF0":"Intellimedia Systems Ltd","141F78":"Samsung Electronics Co. Ltd","141FBA":"IEEE Registration Authority","14205E":"Apple","1422DB":"eero Inc.","1423D7":"Eutronix Co. Ltd",142882:"Midicom Electronics Co.Ltd",142971:"Nemoa Electronics (HK) Co. Ltd","142BD2":"Armtel Ltd","142BD6":"Guangdong Appscomm Co. Ltd","142D27":"Hon Hai Precision Ind. Co. Ltd","142D8B":"Incipio Technologies, Inc","142DF5":"Amphitech","142FFD":"LT Security Inc",143004:"Huawei Technologies Co. Ltd","14307A":"Avermetrics","1430C6":"Motorola Mobility LLC, a Lenovo Company","1432D1":"Samsung Electronics Co. Ltd",143365:"TEM Mobile Limited","14358B":"Mediabridge Products, LLC.","1435B3":"Future Designs, Inc.",143605:"Nokia Corporation","1436C6":"Lenovo Mobile Communication Technology Ltd","14373B":"PROCOM Systems","143AEA":"Dynapower Company LLC","143DF2":"Beijing Shidai Hongyuan Network Communication Co. Ltd","143E60":"Nokia","143EBF":"zte Corporation","143F27":"Noccela Oy",144146:"Honeywell (China) Co. Ltd","1441E2":"Monaco Enterprises, Inc.",144319:"Creative&Link Technology Limited","14444A":"Apollo Seiko Ltd","1446E4":"Avistel","14488B":"Shenzhen Doov Technology Co. Ltd",144978:"Digital Control Incorporated","1449E0":"Samsung Electro-Mechanics(Thailand)","144C1A":"Max Communication GmbH","144D67":"Zioncom Electronics (Shenzhen) Ltd","144E34":"Remote Solution","144FD7":"IEEE Registration Authority",145412:"Entis Co. Ltd",145645:"Savitech Corp.","14568E":"Samsung Electronics Co. Ltd","1458D0":"Hewlett-Packard Company","145A05":"Apple","145A83":"Logi-D Inc","145BD1":"ARRIS Group, Inc.","145BE1":"nyantec GmbH","145E45":"Kaleao Limited","145F94":"Huawei Technologies Co. Ltd",146080:"zte Corporation",146102:"Alpine Electronics, Inc.","14612F":"Avaya Inc",146308:"Jabil Circuit (Shanghai) Ltd","146A0B":"Cypress Electronics Limited","146B72":"Shenzhen Fortune Ship Technology Co. Ltd","146B9C":"Shenzhen Bilian Electronic Co. Ltd","146E0A":"Private",147373:"Tubitak Uekae",147411:"RIM",147590:"TP-Link Technologies Co. Ltd","14780B":"Varex Imaging Deutschland AG","1479F3":"China Mobile Group Device Co. Ltd","147DB3":"JOA Telecom.Co. Ltd","147DC5":"Murata Manufacturing Co. Ltd","14825B":"Hefei Radio Communication Technology Co. Ltd",148692:"TP-Link Technologies Co. Ltd","14893E":"Vixtel Technologies Limted",148951:"LCFC(HeFei) Electronics Technology Co. Ltd","1489FD":"Samsung Electronics Co. Ltd","148A70":"ADS GmbH","148F21":"Garmin International","148FC6":"Apple",149090:"KongTop Industrial(shen zhen)Co. Ltd",149182:"Belkin International Inc.",149346:"PNI sensor Corporation",149448:"BLU Castle S.A.","14987D":"Technicolor CH USA Inc.","1499E2":"Apple","149A10":"Microsoft Corporation","149B2F":"JiangSu ZhongXie Intelligent Technology Co. Ltd","149D09":"Huawei Technologies Co. Ltd","149ECF":"Dell Inc.","149F3C":"Samsung Electronics Co. Ltd","149FB6":"Guangdong Genius Technology Co. Ltd","149FE8":"Lenovo Mobile Communication Technology Ltd","14A0F8":"Huawei Technologies Co. Ltd","14A364":"Samsung Electronics Co. Ltd","14A51A":"Huawei Technologies Co. Ltd","14A62C":"S.M. Dezac S.A.","14A72B":"currentoptronics Pvt.Ltd","14A78B":"Zhejiang Dahua Technology Co. Ltd","14A86B":"ShenZhen Telacom Science&Technology Co. Ltd","14A9E3":"MST Corporation","14ABC5":"Intel Corporation","14ABF0":"ARRIS Group, Inc.","14AEDB":"VTech Telecommunications Ltd","14B126":"Industrial Software Co","14B1C8":"InfiniWing, Inc.","14B31F":"Dell Inc.","14B370":"Gigaset Digital Technology (Shenzhen) Co. Ltd","14B484":"Samsung Electronics Co. Ltd","14B73D":"ARCHEAN Technologies","14B7F8":"Technicolor CH USA Inc.","14B837":"Shenzhen YOUHUA Technology Co. Ltd","14B968":"Huawei Technologies Co. Ltd","14BB6E":"Samsung Electronics Co. Ltd","14BD61":"Apple","14C089":"Dune HD Ltd","14C126":"Nokia Corporation","14C1FF":"ShenZhen QianHai Comlan Communication Co. Ltd","14C21D":"Sabtech Industries","14C3C2":"K.A. Schmersal GmbH & Co. KG","14C913":"LG Electronics","14CC20":"TP-Link Technologies Co. Ltd","14CF8D":"Ohsung","14CF92":"TP-Link Technologies Co. Ltd","14CFE2":"ARRIS Group, Inc.","14D11F":"Huawei Technologies Co. Ltd","14D4FE":"ARRIS Group, Inc.","14D64D":"D-Link International","14D76E":"CoNCH ELECTRONIC Co. Ltd","14DAE9":"ASUSTek Computer Inc.","14DB85":"S NET Media","14DDA9":"ASUSTek Computer Inc.","14DDE5":"Mpmkvvcl","14E4EC":"mLogic LLC","14E6E4":"TP-Link Technologies Co. Ltd","14E7C8":"Integrated Device Technology (Malaysia) Sdn. Bhd.","14EB33":"BSMediasoft Co. Ltd","14EDA5":"Wa?chter GmbH Sicherheitssysteme","14EDBB":"2Wire Inc.","14EDE4":"Kaiam Corporation","14EE9D":"AirNav Systems LLC","14F0C5":"Xtremio Ltd","14F28E":"ShenYang ZhongKe-Allwin Technology Co.Ltd","14F42A":"Samsung Electronics Co. Ltd","14F65A":"Xiaomi Communications Co Ltd","14F893":"Wuhan FiberHome Digital Technology Co. Ltd","14FEAF":"Sagittar Limited","14FEB5":"Dell Inc.","18002D":"Sony Mobile Communications AB","1800DB":"Fitbit Inc.","18017D":"Harbin Arteor technology Co. Ltd","1801E3":"Bittium Wireless Ltd",180373:"Dell Inc.","1803FA":"IBT Interfaces",180675:"Dilax Intelcom GmbH","1806FF":"Acer Computer(Shanghai) Limited.","180B52":"Nanotron Technologies GmbH","180C14":"iSonea Limited","180C77":"Westinghouse Electric Company, LLC","180CAC":"Canon Inc.","180F76":"D-Link International","18104E":"Cedint-UPM",181212:"Cepton Technologies",181420:"TEB SAS",181456:"Nokia Corporation","1816C9":"Samsung Electronics Co. Ltd",181714:"Daewoois",181725:"Cameo Communications, Inc.","18193F":"Tamtron Oy","181BEB":"Actiontec Electronics, Inc","181E78":"Sagemcom Broadband SAS","181EB0":"Samsung Electronics Co. Ltd",182012:"Aztech Associates Inc.",182032:"Apple","18204C":"Kummler+Matter AG","1820A6":"Sage Co. Ltd",182195:"Samsung Electronics Co. Ltd","18227E":"Samsung Electronics Co. Ltd",182666:"Samsung Electronics Co. Ltd",182861:"AirTies Wireless Networks","182A7B":"Nintendo Co. Ltd","182B05":"8D Technologies","182C91":"Concept Development, Inc.","182CB4":"Nectarsoft Co. Ltd","182D98":"Jinwoo Industrial System",183009:"Woojin Industrial Systems Co. Ltd","1831BF":"ASUSTek Computer Inc.","1832A2":"Laon Technology Co. Ltd","18339D":"Cisco Systems Inc.",183451:"Apple","1835D1":"ARRIS Group, Inc.","1836FC":"Elecsys International Corporation",183825:"Wuhan Lingjiu High-tech Co. Ltd",183864:"CAP-Tech International Co. Ltd",183919:"Unicoi Systems","18396E":"Sunsea Telecommunications Co. Ltd","183A2D":"Samsung Electronics Co. Ltd","183BD2":"BYD Precision Manufacture Company Ltd","183DA2":"Intel Corporation","183F47":"Samsung Electronics Co. Ltd","1840A4":"Shenzhen Trylong Smart Science and Technology Co. Ltd","18421D":"Private","18422F":"Alcatel Lucent",184462:"Riava Networks, Inc.","1844E6":"zte Corporation",184617:"Samsung Electronics Co. Ltd","1848D8":"Fastback Networks","184A6F":"Alcatel-Lucent Shanghai Bell Co. Ltd","184C08":"Rockwell Automation","184E94":"Messoa Technologies Inc.","184F32":"Hon Hai Precision Ind. Co. Ltd","18502A":"Soarnex",185207:"Sichuan Tianyi Comheart Telecomco. Ltd",185253:"Pixord Corporation",185282:"Fiberhome Telecommunication Technologies Co. Ltd","1853E0":"Hanyang Digitech Co.Ltd","18550F":"Cisco SPVTG",185933:"Cisco SPVTG",185936:"Xiaomi Communications Co Ltd","185AE8":"Zenotech.Co. Ltd","185D9A":"BobjGear LLC","185E0F":"Intel Corporation",186024:"Hewlett-Packard Company","1861C7":"lemonbeat GmbH","18622C":"Sagemcom Broadband SAS",186472:"Aruba Networks",186571:"Top Victory Electronics (Taiwan) Co. Ltd",186590:"Apple","1866DA":"Dell Inc.","1866E3":"Veros Systems, Inc.","18673F":"Hanover Displays Limited",186751:"KOMEG Industrielle Messtechnik GmbH","1867B0":"Samsung Electronics Co. Ltd","18686A":"zte Corporation",186882:"Beward R&D Co. Ltd","1868CB":"Hangzhou Hikvision Digital Technology Co. Ltd","186D99":"Adanis Inc.",187117:"eta plus electronic GmbH","18742E":"Amazon Technologies Inc.",187532:"Sichuan Tianyi Comheart Telecomco. Ltd","1879A2":"GMJ Electric Limited","187A93":"AMICCOM Electronics Corporation","187C81":"Valeo Vision Systems","187ED5":"shenzhen kaism technology Co. Ltd",188090:"Cisco Systems Inc.","1880CE":"Barberry Solutions Ltd","1880F5":"Alcatel-Lucent Shanghai Bell Co. Ltd",188219:"Alibaba Cloud Computing Ltd",188331:"Samsung Electronics Co. Ltd","1883BF":"Arcadyan Technology Corporation",188410:"CoreTrust Inc.","18863A":"Digital ART System","1886AC":"Nokia Danmark A/S",188796:"HTC Corporation",188857:"Beijing Jinhong Xi-Dian Information Technology Corp.","18895B":"Samsung Electronics Co. Ltd","1889DF":"CerebrEX Inc.","188B15":"ShenZhen ZhongRuiJing Technology Co. Ltd","188B45":"Cisco Systems Inc.","188B9D":"Cisco Systems Inc.","188ED5":"TP Vision Belgium N.V. - innovation site Brugge","188EF9":"G2C Co. Ltd","1890D8":"Sagemcom Broadband SAS","18922C":"Virtual Instruments","1893D7":"Texas Instruments","1894C6":"ShenZhen Chenyee Technology Co. Ltd","1897FF":"TechFaith Wireless Technology Limited","1899F5":"Sichuan Changhong Electric Ltd","189A67":"CSE-Servelec Limited","189BA5":"IEEE Registration Authority","189C5D":"Cisco Systems Inc.","189EFC":"Apple","18A28A":"Essel-T Co. Ltd","18A3E8":"Fiberhome Telecommunication Technologies Co. Ltd","18A6F7":"TP-Link Technologies Co. Ltd","18A905":"Hewlett-Packard Company","18A958":"Provision Thai Co. Ltd","18A99B":"Dell Inc.","18AA45":"Fon Technology","18ABF5":"Ultra Electronics Electrics","18AD4D":"Polostar Technology Corporation","18AEBB":"Siemens Convergence Creators GmbH&Co.KG","18AF61":"Apple","18AF8F":"Apple","18AF9F":"DIGITRONIC Automationsanlagen GmbH","18B169":"Sonicwall","18B209":"Torrey Pines Logic, Inc","18B3BA":"Netlogic AB","18B430":"Nest Labs Inc.","18B591":"I-Storm","18B79E":"Invoxia","18B81F":"ARRIS Group, Inc.","18BC5A":"Zhejiang Tmall Technology Co. Ltd","18BDAD":"L-Tech Corporation","18C086":"Broadcom","18C19D":"Integrated Device Technology (Malaysia) Sdn. Bhd.","18C451":"Tucson Embedded Systems","18C501":"Shenzhen Gongjin Electronics Co.,LT","18C58A":"Huawei Technologies Co. Ltd","18C8E7":"Shenzhen Hualistone Technology Co. Ltd","18CC23":"Philio Technology Corporation","18CC88":"Hitachi Johnson Controls Air","18CF5E":"Liteon Technology Corporation","18D071":"Dasan Co. Ltd","18D225":"Fiberhome Telecommunication Technologies Co. Ltd","18D276":"Huawei Technologies Co. Ltd","18D5B6":"SMG Holdings LLC","18D66A":"Inmarsat","18D6C7":"TP-Link Technologies Co. Ltd","18D6CF":"Kurth Electronic GmbH","18D949":"Qvis Labs, LLC","18DBF2":"Dell Inc.","18DC56":"Yulong Computer Telecommunication Scientific (Shenzhen) Co. Ltd","18DED7":"Huawei Technologies Co. Ltd","18E288":"STT Condigi","18E29F":"vivo Mobile Communication Co. Ltd","18E2C2":"Samsung Electronics Co. Ltd","18E3BC":"TCT mobile Ltd","18E728":"Cisco Systems Inc.","18E7F4":"Apple","18E80F":"Viking Electronics Inc.","18E8DD":"Moduletek","18EE69":"Apple","18EF63":"Cisco Systems Inc.","18F0E4":"Xiaomi Communications Co Ltd","18F145":"NetComm Wireless Limited","18F1D8":"Apple","18F292":"Shannon Systems","18F46A":"Hon Hai Precision Ind. Co. Ltd","18F643":"Apple","18F650":"Multimedia Pacific Limited","18F76B":"Zhejiang Winsight Technology Co. Ltd","18F87A":"i3 International Inc.","18FA6F":"ISC applied Systems Corp","18FB7B":"Dell Inc.","18FC9F":"Changhe Electronics Co. Ltd","18FE34":"Espressif Inc.","18FF0F":"Intel Corporation","18FF2E":"Shenzhen Rui Ying Da Technology Co. Ltd","1C0042":"NARI Technology Co. Ltd","1C0656":"IDY Corporation","1C08C1":"Lg Innotek","1C0B52":"Epicom S.A","1C0FAF":"Lucid Vision Labs","1C0FCF":"Sypro Optics GmbH","1C1161":"Ciena Corporation","1C11E1":"Wartsila Finland Oy","1C129D":"IEEE PES Psrc/SUB","1C1448":"ARRIS Group, Inc.","1C14B3":"Airwire Technologies","1C151F":"Huawei Technologies Co. Ltd","1C17D3":"Cisco Systems Inc.","1C184A":"ShenZhen RicherLink Technologies Co. Ltd","1C19DE":"eyevis GmbH","1C1AC0":"Apple","1C1B0D":"Giga-Byte Technology Co. Ltd","1C1B68":"ARRIS Group, Inc.","1C1CFD":"Dalian Hi-Think Computer Technology, Corp","1C1D67":"Huawei Technologies Co. Ltd","1C1D86":"Cisco Systems Inc.","1C1EE3":"Hui Zhou Gaoshengda Technology Co. Ltd","1C1FD4":"LifeBEAM Technologies Ltd","1C21D1":"IEEE Registration Authority","1C232C":"Samsung Electronics Co. Ltd","1C234F":"EDMI Europe Ltd","1C25E1":"China Mobile IOT Company Limited","1C27DD":"Datang Gohighsec(zhejiang)Information Technology Co. Ltd","1C330E":"PernixData","1C334D":"ITS Telecom","1C3477":"Innovation Wireless","1C35F1":"NEW Lift Neue Elektronische Wege Steuerungsbau GmbH","1C36BB":"Apple","1C37BF":"Cloudium Systems Ltd","1C3947":"Compal Information (Kunshan) Co. Ltd","1C398A":"Fiberhome Telecommunication Technologies Co. Ltd","1C3A4F":"AccuSpec Electronics, LLC","1C3ADE":"Samsung Electronics Co. Ltd","1C3DE7":"Sigma Koki Co. Ltd","1C3E84":"Hon Hai Precision Ind. Co. Ltd","1C4024":"Dell Inc.","1C40E8":"Shenzhen Progress&WIN Technology Co. Ltd","1C4158":"Gemalto M2M GmbH","1C43EC":"Japan Circuit Co. Ltd","1C4419":"TP-Link Technologies Co. Ltd","1C4593":"Texas Instruments","1C4840":"IMS Messsysteme GmbH","1C48CE":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","1C48F9":"GN Netcom A/S","1C497B":"Gemtek Technology Co. Ltd","1C4AF7":"Amon Inc","1C4BB9":"SMG Enterprise, LLC","1C4BD6":"Azurewave Technologies Inc.","1C4D70":"Intel Corporation","1C51B5":"Techaya Ltd","1C5216":"Dongguan Hele Electronics Co. Ltd","1C52D6":"Flat Display Technology Corporation","1C553A":"QianGua Corp.","1C56FE":"Motorola Mobility LLC, a Lenovo Company","1C57D8":"Kraftway Corporation PLC","1C5A0B":"Tegile Systems","1C5A3E":"Samsung Electronics Co. Ltd","1C5A6B":"Philips Electronics Nederland BV","1C5C55":"PRIMA Cinema, Inc","1C5C60":"Shenzhen Belzon Technology Co. Ltd","1C5CF2":"Apple","1C5F2B":"D-Link International","1C5FFF":"Beijing Ereneben Information Technology Co. Ltd Shenzhen Branch","1C60DE":"Shenzhen Mercury Communication Technologies Co. Ltd","1C62B8":"Samsung Electronics Co. Ltd","1C63B7":"OpenProducts 237 AB","1C659D":"Liteon Technology Corporation","1C666D":"Hon Hai Precision Ind. Co. Ltd","1C66AA":"Samsung Electronics Co. Ltd","1C6758":"Huawei Technologies Co. Ltd","1C69A5":"BlackBerry RTS","1C6A7A":"Cisco Systems Inc.","1C6BCA":"Mitsunami Co. Ltd","1C6E4C":"Logistic Service & Engineering Co. Ltd","1C6E76":"Quarion Technology Inc","1C6F65":"Giga-Byte Technology Co. Ltd","1C7022":"Murata Manufacturing Co. Ltd","1C7328":"Connected Home","1C7370":"Neotech","1C740D":"ZyXEL Communications Corp","1C7508":"Compal Information (Kunshan) Co. Ltd","1C76CA":"Terasic Technologies Inc.","1C77F6":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","1C7839":"Shenzhen Tencent Computer System Co. Ltd","1C7B21":"Sony Mobile Communications AB","1C7B23":"Qingdao Hisense Communications Co. Ltd","1C7C11":"EID","1C7C45":"Vitek Industrial Video Products, Inc.","1C7CC7":"Coriant GmbH","1C7D22":"Fuji Xerox Co. Ltd","1C7E51":"3bumen.com","1C7EE5":"D-Link International","1C8341":"Hefei Bitland Information Technology Co.Ltd","1C83B0":"Linked IP GmbH","1C8464":"Formosa Wireless Communication Corp.","1C86AD":"MCT Co. Ltd","1C872C":"ASUSTek Computer Inc.","1C8E5C":"Huawei Technologies Co. Ltd","1C8E8E":"DB Communication & Systems Co. Ltd","1C8F8A":"Phase Motion Control SpA","1C9148":"Apple","1C9179":"Integrated System Technologies Ltd","1C9492":"RUAG Schweiz AG","1C955D":"I-LAX Electronics Inc.","1C959F":"Veethree Electronics And Marine LLC","1C965A":"Weifang GoerTek Technology Co. Ltd","1C973D":"PRICOM Design","1C98EC":"Hewlett Packard Enterprise","1C994C":"Murata Manufacturing Co. Ltd","1C9C26":"Zoovel Technologies","1C9D3E":"Integrated Device Technology (Malaysia) Sdn. Bhd.","1C9E46":"Apple","1C9ECB":"Beijing Nari Smartchip Microelectronics Company Limited","1CA0B8":"Hon Hai Precision Ind. Co. Ltd","1CA0D3":"IEEE Registration Authority","1CA2B1":"ruwido austria GmbH","1CA532":"Shenzhen Gongjin Electronics Co.,LT","1CA770":"Shenzhen Chuangwei-RGB Electronics Co. Ltd","1CAA07":"Cisco Systems Inc.","1CAB01":"Innovolt","1CAB34":"New H3C Technologies Co. Ltd","1CABA7":"Apple","1CABC0":"Hitron Technologies. Inc","1CADD1":"Bosung Electronics Co. Ltd","1CAF05":"Samsung Electronics Co. Ltd","1CAFF7":"D-Link International","1CB044":"Askey Computer Corp","1CB094":"HTC Corporation","1CB17F":"NEC Platforms Ltd","1CB243":"TDC A/S","1CB72C":"ASUSTek Computer Inc.","1CB857":"Becon Technologies Co,.Ltd","1CB9C4":"Ruckus Wireless","1CBA8C":"Texas Instruments","1CBBA8":"OJSC Ufimskiy Zavod Promsvyaz","1CBD0E":"Amplified Engineering Pty Ltd","1CBDB9":"D-Link International","1CC035":"Planex Communications Inc.","1CC0E1":"IEEE Registration Authority","1CC11A":"Wavetronix","1CC1DE":"Hewlett-Packard Company","1CC316":"MileSight Technology Co. Ltd","1CC586":"Absolute Acoustics","1CC63C":"Arcadyan Technology Corporation","1CC72D":"Shenzhen Huapu Digital Co. Ltd","1CCAE3":"IEEE Registration Authority","1CCB99":"TCT mobile Ltd","1CCDE5":"Shanghai Wind Technologies Co. Ltd","1CD40C":"Kriwan Industrie-Elektronik GmbH","1CD6BD":"Leedarson Lighting Co. Ltd","1CDA27":"vivo Mobile Communication Co. Ltd","1CDDEA":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","1CDEA7":"Cisco Systems Inc.","1CDF0F":"Cisco Systems Inc.","1CDF52":"Texas Instruments","1CE165":"Marshal Corporation","1CE192":"Qisda Corporation","1CE2CC":"Texas Instruments","1CE62B":"Apple","1CE6C7":"Cisco Systems Inc.","1CE85D":"Cisco Systems Inc.","1CEA1B":"Nokia","1CEEC9":"Elo touch solutions","1CEEE8":"Ilshin Elecom","1CEFCE":"bebro electronic GmbH","1CF03E":"Wearhaus Inc.","1CF061":"SCAPS GmbH","1CF4CA":"Private","1CF5E7":"Turtle Industry Co. Ltd","1CFA68":"TP-Link Technologies Co. Ltd","1CFCBB":"Realfiction ApS","1CFEA7":"IDentytech Solutins Ltd","20014F":"Linea Research Ltd","2002AF":"Murata Manufacturing Co. Ltd","20040F":"Dell Inc.",200505:"Radmax Communication Private Limited","2005E8":"OOO InProMedia","2008ED":"Huawei Technologies Co. Ltd","200A5E":"Xiangshan Giant Eagle Technology Developing Co. Ltd","200BC7":"Huawei Technologies Co. Ltd","200CC8":"Netgear","200E95":"IEC - TC9 WG43","200F70":"Foxtech","20107A":"Gemtek Technology Co. Ltd",201257:"Most Lucky Trading Ltd","2012D5":"Scientech Materials Corporation","2013E0":"Samsung Electronics Co. Ltd","2016B9":"Intel Corporation","2016D8":"Liteon Technology Corporation","20180E":"Shenzhen Sunchip Technology Co. Ltd","201A06":"Compal Information (Kunshan) Co. Ltd","201D03":"Elatec GmbH","2021A5":"LG Electronics (Mobile Communications)",202564:"Pegatron Corporation",202598:"Teleview","2028BC":"Visionscape Co,. Ltd","202BC1":"Huawei Technologies Co. Ltd","202CB7":"Kong Yue Electronics & Information Industry (Xinhui) Ltd","202D07":"Samsung Electronics Co. Ltd","202D23":"Collinear Networks Inc.","202DF8":"Digital Media Cartridge Ltd","2031EB":"Hdsn","20365B":"Megafone Limited",203706:"Cisco Systems Inc.","2037BC":"Kuipers Electronic Engineering BV","203A07":"Cisco Systems Inc.","203AEF":"Sivantos GmbH","203CAE":"Apple","203D66":"ARRIS Group, Inc.","203DB2":"Huawei Technologies Co. Ltd",204005:"feno GmbH","20415A":"Smarteh d.o.o.","20443A":"Schneider Electric Asia Pacific Ltd","2046A1":"VECOW Co. Ltd","2046F9":"Advanced Network Devices (dba:AND)",204747:"Dell Inc.","2047DA":"Xiaomi Communications Co Ltd","2047ED":"BSkyB Ltd","204AAA":"Hanscan Spain S.A.","204C03":"Aruba Networks","204C6D":"Hugo Brennenstuhl GmbH & Co. KG.","204C9E":"Cisco Systems Inc.","204E6B":"Axxana(israel) Ltd","204E71":"Juniper Networks","204E7F":"Netgear","2053CA":"Risk Technology Ltd",205476:"Sony Mobile Communications AB","2054FA":"Huawei Technologies Co. Ltd",205531:"Samsung Electronics Co. Ltd",205532:"Gotech International Technology Limited",205721:"Salix Technology Co. Ltd","2057AF":"Shenzhen FH-NET OPTOELECTRONICS Co. Ltd","2059A0":"Paragon Technologies Inc.","205A00":"Coval","205B2A":"Private","205B5E":"Shenzhen Wonhe Technology Co. Ltd","205CFA":"Yangzhou ChangLian Network Technology Co Ltd","205D47":"vivo Mobile Communication Co. Ltd","205EF7":"Samsung Electronics Co. Ltd",206274:"Microsoft Corporation","20635F":"Abeeway",206432:"Samsung Electro Mechanics Co. Ltd","20677C":"Hewlett Packard Enterprise","2067B1":"Pluto Inc.","20689D":"Liteon Technology Corporation","206A8A":"Wistron Infocomm (Zhongshan) Corporation","206AFF":"Atlas Elektronik UK Limited","206BE7":"TP-Link Technologies Co. Ltd","206C8A":"Aerohive Networks Inc.","206E9C":"Samsung Electronics Co. Ltd","206FEC":"Braemac CA LLC","20719E":"SF Technology Co. Ltd",207355:"ARRIS Group, Inc.","2074CF":"Shenzhen Voxtech Co. Ltd",207600:"Actiontec Electronics, Inc","20768F":"Apple",207693:"Lenovo (Beijing) Limited.","20780B":"Delta Faucet Company",207852:"Nokia","2078F0":"Apple","207C8F":"Quanta Microsystems,Inc.","207D74":"Apple","2082C0":"Xiaomi Communications Co Ltd","20858C":"Assa",208756:"Siemens AG","2087AC":"AES motomation","20896F":"Fiberhome Telecommunication Technologies Co. Ltd",208984:"Compal Information (Kunshan) Co. Ltd",208986:"zte Corporation","208B37":"Skyworth Digital Technology(Shenzhen) Co. Ltd","20906F":"Shenzhen Tencent Computer System Co. Ltd",209148:"Texas Instruments","20918A":"Profalux","2091D9":"I'M SPA","20934D":"Fujian Star-NET Communication Co. Ltd","209AE9":"Volacomm Co. Ltd","209BA5":"JIAXING GLEAD Electronics Co. Ltd","209BCD":"Apple","20A2E4":"Apple","20A2E7":"Lee-Dickens Ltd","20A680":"Huawei Technologies Co. Ltd","20A6CD":"Hewlett Packard Enterprise","20A783":"miControl GmbH","20A787":"Bointec Taiwan Corporation Limited","20A8B9":"Siemens","20A90E":"TCT mobile Ltd","20A99B":"Microsoft Corporation","20AA25":"IP-NET LLC","20AA4B":"Cisco-Linksys LLC","20AB37":"Apple","20B0F7":"Enclustra GmbH","20B399":"Enterasys","20B5C6":"Mimosa Networks","20B7C0":"OMICRON electronics GmbH","20BB76":"CoL GIOVANNI PAOLO SpA","20BBC0":"Cisco Systems Inc.","20BBC6":"Jabil Circuit Hungary Ltd","20BFDB":"DVL","20C047":"Verizon","20C06D":"Shenzhen Spacetek Technology Co. Ltd","20C1AF":"i Wit Digital Co., Limited","20C38F":"Texas Instruments","20C3A4":"RetailNext","20C60D":"Shanghai annijie Information technology Co. Ltd","20C6EB":"Panasonic Corporation AVC Networks Company","20C8B3":"Shenzhen BUL-Tech Co. Ltd","20C9D0":"Apple","20CD39":"Texas Instruments","20CEC4":"Peraso Technologies","20CF30":"ASUSTek Computer Inc.","20D160":"Private","20D21F":"Wincal Technology Corp.","20D25F":"SmartCap Technologies","20D390":"Samsung Electronics Co. Ltd","20D5AB":"Korea Infocom Co. Ltd","20D5BF":"Samsung Electronics Co. Ltd","20D607":"Nokia Corporation","20D75A":"Posh Mobile Limited","20D906":"Iota, Inc.","20DBAB":"Samsung Electronics Co. Ltd","20DC93":"Cheetah Hi-Tech, Inc.","20DCE6":"TP-Link Technologies Co. Ltd","20DF3F":"Nanjing SAC Power Grid Automation Co. Ltd","20DFB9":"Google, Inc.","20E09C":"Nokia","20E407":"Spark srl","20E52A":"Netgear","20E564":"ARRIS Group, Inc.","20E791":"Siemens Healthcare Diagnostics, Inc","20EAC7":"Shenzhen Riopine Electronics Co. Ltd","20ED74":"Ability enterprise Co. Ltd","20EE28":"Apple","20EEC6":"Elefirst Science & Tech Co . Ltd","20F002":"MTData Developments Pty. Ltd","20F17C":"Huawei Technologies Co. Ltd","20F19E":"ARRIS Group, Inc.","20F3A3":"Huawei Technologies Co. Ltd","20F41B":"Shenzhen Bilian electronic Co. Ltd","20F452":"Shanghai IUV Software Development Co. Ltd","20F510":"Codex Digital Limited","20F543":"Hui Zhou Gaoshengda Technology Co. Ltd","20F85E":"Delta Electronics","20FABB":"Cambridge Executive Limited","20FDF1":"3Com Europe Ltd","20FECD":"System In Frontier Inc.","20FEDB":"M2M Solution S.A.S.","2400BA":"Huawei Technologies Co. Ltd","2401C7":"Cisco Systems Inc.","24050F":"MTN Electronic Co. Ltd","2405F5":"Integrated Device Technology (Malaysia) Sdn. Bhd.",240917:"Devlin Electronics Limited",240995:"Huawei Technologies Co. Ltd","240A11":"TCT mobile Ltd","240A63":"ARRIS Group, Inc.","240A64":"Azurewave Technologies Inc.","240AC4":"Espressif Inc.","240B0A":"Palo Alto Networks","240B2A":"Viettel Group","240BB1":"KOSTAL Industrie Elektrik GmbH","240D65":"Shenzhen Vsun Communication Technology Co. Ltd","240D6C":"Smnd","240DC2":"TCT mobile Ltd",241064:"Shenzhen Ecsino Tecnical Co. Ltd",241125:"Hutek Co. Ltd",241148:"Entropix, LLC","2411D0":"Chongqing Ehs Science and Technology Development Co. Ltd","24181D":"Samsung Electro-Mechanics(Thailand)","241A8C":"Squarehead Technology AS","241B13":"Shanghai Nutshell Electronic Co. Ltd","241B44":"Hangzhou Tuners Electronics Co. Ltd","241C04":"Shenzhen Jehe Technology Development Co. Ltd","241EEB":"Apple","241F2C":"Calsys, Inc.","241FA0":"Huawei Technologies Co. Ltd","2420C7":"Sagemcom Broadband SAS","2421AB":"Sony Mobile Communications AB","24240E":"Apple",242642:"Sharp Corporation.","2429FE":"KYOCERA Corporation","242E02":"Huawei Technologies Co. Ltd","242FFA":"Toshiba Global Commerce Solutions",243184:"Sharp Corporation","24336C":"Private","2435CC":"Zhongshan Scinan Internet Of Things Co. Ltd","24374C":"Cisco SPVTG","2437EF":"EMC Electronic Media Communication SA","243C20":"Dynamode Group","2442BC":"Alinco,Incorporated",244427:"Huawei Technologies Co. Ltd",244597:"GEMUE Gebr. Mueller Apparatebau","24470E":"PentronicAB","24497B":"Innovative Converged Devices Inc","244B03":"Samsung Electronics Co. Ltd","244B81":"Samsung Electronics Co. Ltd","244C07":"Huawei Technologies Co. Ltd","244E7B":"IEEE Registration Authority","244F1D":"iRule LLC",245880:"Vizeo","24590B":"White Sky Inc. Limited","245BA7":"Apple","245BF0":"Liteon, Inc.","245CBF":"Ncse","245CCB":"AXIe Consortium, Inc.","245EBE":"QNAP Systems, Inc.","245FDF":"Kyocera Corporation",246081:"razberi technologies","24615A":"China Mobile Group Device Co. Ltd",246278:"Sysmocom - Systems for mobile Communications GmbH","2464EF":"CYG Sunri Co. Ltd",246511:"AVM GmbH",246880:"Braveridge.Co. Ltd","24693E":"innodisk Corporation","24694A":"Jasmine Systems Inc.",246968:"TP-Link Technologies Co. Ltd","2469A5":"Huawei Technologies Co. Ltd","246AAB":"IT-IS International","246C8A":"YUKAI Engineering","246E96":"Dell Inc.",247189:"Texas Instruments",247260:"IOTTECH Corp",247656:"Shanghai Net Miles Fiber Optics Technology Co. Ltd","24767D":"Cisco SPVTG",247703:"Intel Corporation","24792A":"Ruckus Wireless","247C4C":"Herman Miller","247E12":"Cisco Systems Inc.","247F20":"Sagemcom Broadband SAS","247F3C":"Huawei Technologies Co. Ltd",248000:"Westcontrol AS","2481AA":"KSH International Co. Ltd","24828A":"Prowave Technologies Ltd","2486F4":"Ctek, Inc.",248707:"SEnergy Corporation",248894:"shenzhen lensun Communication Technology Ltd","248A07":"Mellanox Technologies, Inc.","248BE0":"Sichuan Tianyi Comheart Telecomco. Ltd","24920E":"Samsung Electronics Co. Ltd","2493CA":"Voxtronic Technology Computer-Systeme GmbH",249442:"Open Road Solutions , Inc.",249504:"SFR","2497ED":"Techvision Intelligent Technology Limited","249EAB":"Huawei Technologies Co. Ltd","24A074":"Apple","24A2E1":"Apple","24A42C":"KOUKAAM a.s.","24A43C":"Ubiquiti Networks Inc.","24A495":"Thales Canada Inc.","24A534":"SynTrust Tech International Ltd","24A7DC":"BSkyB Ltd","24A87D":"Panasonic Automotive Systems Asia Pacific(Thailand)Co. Ltd","24A937":"PURE Storage","24AB81":"Apple","24AF4A":"Alcatel-Lucent IPD","24AF54":"NEXGEN Mediatech Inc.","24B0A9":"Shanghai Mobiletek Communication Ltd","24B209":"Avaya Inc","24B2DE":"Espressif Inc.","24B657":"Cisco Systems Inc.","24B6B8":"Friem SPA","24B6FD":"Dell Inc.","24B88C":"Crenus Co. Ltd","24B8D2":"Opzoon Technology Co. Ltd","24BA13":"Riso Kagaku Corporation","24BA30":"Technical Consumer Products, Inc.","24BBC1":"Absolute Analysis","24BC82":"Dali Wireless, Inc.","24BCF8":"Huawei Technologies Co. Ltd","24BE05":"Hewlett-Packard Company","24BF74":"Private","24C0B3":"RSF","24C1BD":"Crrc Dalian R&D Co. Ltd","24C3F9":"Securitas Direct AB","24C42F":"Philips Lifeline","24C44A":"zte Corporation","24C696":"Samsung Electronics Co. Ltd","24C848":"mywerk Portal GmbH","24C86E":"Chaney Instrument Co.","24C9A1":"Ruckus Wireless","24C9DE":"Genoray","24CACB":"Fiberhome Telecommunication Technologies Co. Ltd","24CBE7":"MYK, Inc.","24CF21":"Shenzhen State Micro Technology Co. Ltd","24D13F":"Mexus Co. Ltd","24D2CC":"SmartDrive Systems Inc.","24D51C":"Zhongtian broadband technology Co. Ltd","24D921":"Avaya Inc","24DA11":"NO NDA Inc","24DA9B":"Motorola Mobility LLC, a Lenovo Company","24DAB6":"Sistemas de Gesti?n Energ?tica S.A. de C.V","24DBAC":"Huawei Technologies Co. Ltd","24DBAD":"ShopperTrak RCT Corporation","24DBED":"Samsung Electronics Co. Ltd","24DEC6":"Aruba Networks","24DF6A":"Huawei Technologies Co. Ltd","24E124":"Xiamen Ursaconn Technology Co. Ltd","24E271":"Qingdao Hisense Communications Co. Ltd","24E314":"Apple","24E43F":"Wenzhou Kunmei Communication Technology Co. Ltd","24E5AA":"Philips Oral Healthcare, Inc.","24E6BA":"JSC Zavod im. Kozitsky","24E9B3":"Cisco Systems Inc.","24EA40":"Helmholz GmbH & Co. KG","24EB65":"SAET I.S. S.r.l.","24EC99":"Askey Computer Corp","24ECD6":"CSG Science & Technology Co. LtdHefei","24EE3A":"Chengdu Yingji Electronic Hi-tech Co Ltd","24F094":"Apple","24F0FF":"GHT Co. Ltd","24F128":"Telstra","24F27F":"Hewlett Packard Enterprise","24F2DD":"Radiant Zemax LLC","24F57E":"HWH Co. Ltd","24F5A2":"Belkin International Inc.","24F5AA":"Samsung Electronics Co. Ltd","24F677":"Apple","24FD52":"Liteon Technology Corporation","24FD5B":"SmartThings, Inc.","2802D8":"Samsung Electronics Co. Ltd","2804E0":"Fermax Electronica S.A.U.","28061E":"Ningbo Global Useful Electric Co. Ltd","28068D":"ITL, LLC","28070D":"Guangzhou Winsound Information Technology Co. Ltd","280B5C":"Apple","280C28":"Unigen DataStorage Corporation","280CB8":"Mikrosay Yazilim ve Elektronik A.S.","280DFC":"Sony Interactive Entertainment Inc.","280E8B":"Beijing Spirit Technology Development Co. Ltd","28101B":"MagnaCom","28107B":"D-Link International",281471:"Lantis Co. Ltd","28162E":"2Wire Inc.","2816A8":"Microsoft Corporation","2816AD":"Intel Corporation","2817CE":"Omnisense Ltd",281878:"Microsoft Corporation","2818FD":"Aditya Infotech Ltd",282246:"Beijing Sinoix Communication Co. Ltd",282373:"Digita","2824FF":"Wistron Neweb Corporation",282536:"Shenzhen Holatek Co. Ltd","2826A6":"PBR electronics GmbH","2827BF":"Samsung Electronics Co. Ltd","28285D":"ZyXEL Communications Corp",282986:"APC by Schneider Electric","2829CC":"Corsa Technology Incorporated","2829D9":"GlobalBeiMing technology (Beijing)Co. Ltd","282C02":"IEEE Registration Authority","282CB2":"TP-Link Technologies Co. Ltd","282FC2":"Automotive Data Solutions","2830AC":"Frontiir Co. Ltd",283152:"Huawei Technologies Co. Ltd","2832C5":"HUMAX Co. Ltd",283410:"Enigma Diagnostics Limited","2834A2":"Cisco Systems Inc.",283545:"Shenzhen Chuangwei-RGB Electronics Co. Ltd",283638:"IEEE Registration Authority",283713:"Shenzhen 3Nod Digital Technology Co. Ltd",283737:"Apple","2838CF":"Gen2wave","28395E":"Samsung Electronics Co. Ltd","2839E7":"Preceno Technology Pte.Ltd","283B82":"D-Link International","283B96":"Cool Control Ltd","283CE4":"Huawei Technologies Co. Ltd","283F69":"Sony Mobile Communications AB","28401A":"C8 MediSensors, Inc.",284121:"OptiSense Network, LLC",284430:"GenesisTechnical Systems (UK) Ltd","2847AA":"Nokia Corporation",284846:"GridCentric Inc.","284C53":"Intune Networks","284D92":"Luminator","284ED7":"OutSmart Power Systems, Inc.","284FCE":"Liaoning Wontel Science and Technology Development Co. Ltd",285132:"Shenzhen Prayfly Technology Co. Ltd",285261:"Cisco Systems Inc.","2852E0":"Layon international Electronic & Telecom Co. Ltd","28565A":"Hon Hai Precision Ind. Co. Ltd","2856C1":"Harman International",285767:"Dish Technologies Corp","2857BE":"Hangzhou Hikvision Digital Technology Co. Ltd","285AEB":"Apple","285F2F":"RNware Co. Ltd","285FDB":"Huawei Technologies Co. Ltd",286046:"Lantech Communications Global, Inc.",286094:"Capelec",286336:"Siemens AG - Industrial Automation - EWA","28656B":"Keystone Microtech Corporation","286AB8":"Apple","286ABA":"Apple","286C07":"XIAOMI Electronics,Co. Ltd","286D97":"SAMJIN Co. Ltd","286ED4":"Huawei Technologies Co. Ltd","286F7F":"Cisco Systems Inc.",287184:"Spire Payments","2872C5":"Smartmatic Corp","2872F0":"Athena",287610:"IgniteNet","2876CD":"Funshion Online Technologies Co. Ltd",287994:"Realplay Digital Technology(Shenzhen) Co. Ltd","287AEE":"ARRIS Group, Inc.","287B09":"zte Corporation","287CDB":"Hefei Toycloud Technology Co. Ltd",288023:"Hewlett-Packard Company","2880A2":"Novatel Wireless Solutions, Inc.",288335:"Samsung Electronics Co. Ltd","28840E":"silicon valley immigration service","2884FA":"Sharp Corporation","28852D":"Touch Networks",288915:"CashGuard Sverige AB","288A1C":"Juniper Networks","288CB8":"zte Corporation","2891D0":"Stage Tec Entwicklungsgesellschaft f?r professionelle Audiotechnik mbH","28924A":"Hewlett-Packard Company","2893FE":"Cisco Systems Inc.","28940F":"Cisco Systems Inc.","2894AF":"Samhwa Telecom","28987B":"Samsung Electronics Co. Ltd","28993A":"Arista Networks","289A4B":"SteelSeries ApS","289AFA":"TCT mobile Ltd","289EDF":"Danfoss Turbocor Compressors, Inc","28A02B":"Apple","28A183":"Alps Electric Co. Ltd","28A186":"enblink","28A192":"GERP Solution","28A1EB":"Etek Technology (Shenzhen) Co. Ltd","28A241":"exlar Corp","28A24B":"Juniper Networks","28A574":"Miller Electric Mfg. Co.","28A5EE":"Shenzhen SDGI CATV Co. Ltd","28A6AC":"seca GmbH & Co. kg","28A6DB":"Huawei Technologies Co. Ltd","28AC67":"Mach Power, Rappresentanze Internazionali s.r.l.","28AC9E":"Cisco Systems Inc.","28AD3E":"Shenzhen TONG BO WEI Technology Co. Ltd","28AF0A":"Sirius XM Radio Inc","28B0CC":"Xenya d.o.o.","28B2BD":"Intel Corporation","28B3AB":"Genmark Automation","28B448":"Huawei Technologies Co. Ltd","28B9D9":"Radisys Corporation","28BA18":"NextNav, LLC","28BAB5":"Samsung Electronics Co. Ltd","28BB59":"RNET Technologies, Inc.","28BC18":"SourcingOverseas Co. Ltd","28BC56":"EMAC, Inc.","28BE03":"TCT mobile Ltd","28BE9B":"Technicolor CH USA Inc.","28BF89":"Fiberhome Telecommunication Technologies Co. Ltd","28C0DA":"Juniper Networks","28C13C":"Hon Hai Precision Ind. Co. Ltd","28C2DD":"Azurewave Technologies Inc.","28C63F":"Intel Corporation","28C671":"Yota Devices Oy","28C68E":"Netgear","28C718":"Altierre","28C7CE":"Cisco Systems Inc.","28C825":"DellKing Industrial Co. Ltd","28C87A":"ARRIS Group, Inc.","28C914":"Taimag Corporation","28CA09":"ThyssenKrupp Elevators (Shanghai) Co. Ltd","28CBEB":"One","28CC01":"Samsung Electronics Co. Ltd","28CCFF":"Corporacion Empresarial Altra SL","28CD1C":"Espotel Oy","28CD4C":"Individual Computers GmbH","28CD9C":"Shenzhen Dynamax Software Development Co. Ltd","28CF08":"Essys","28CFDA":"Apple","28CFE9":"Apple","28D1AF":"Nokia Corporation","28D244":"LCFC(HeFei) Electronics Technology Co. Ltd","28D436":"Jiangsu dewosi electric Co. Ltd","28D576":"Premier Wireless, Inc.","28D93E":"Telecor Inc.","28D98A":"Hangzhou Konke Technology Co. Ltd","28D997":"Yuduan Mobile Co. Ltd","28DB81":"Shanghai Guao Electronic Technology Co. Ltd","28DEF6":"bioMerieux Inc.","28E02C":"Apple","28E14C":"Apple","28E297":"Shanghai InfoTM Microelectronics Co. Ltd","28E31F":"Xiaomi Communications Co Ltd","28E347":"Liteon Technology Corporation","28E476":"Pi-Coral","28E608":"Tokheim","28E6E9":"SIS Sat Internet Services GmbH","28E794":"Microtime Computer Inc.","28E7CF":"Apple","28ED58":"JAG Jakob AG","28ED6A":"Apple","28EDE0":"AMPAK Technology, Inc.","28EE2C":"Frontline Test Equipment","28EE52":"TP-Link Technologies Co. Ltd","28EED3":"Shenzhen Super D Technology Co. Ltd","28EF01":"Private","28F076":"Apple","28F10E":"Dell Inc.","28F358":"2C - Trifonov & Co","28F366":"Shenzhen Bilian electronic Co. Ltd","28F532":"ADD-Engineering BV","28F537":"IEEE Registration Authority","28F606":"Syes srl","28FAA0":"vivo Mobile Communication Co. Ltd","28FBD3":"Ragentek Technology Group","28FC51":"The Electric Controller and Manufacturing Co., LLC","28FCF6":"Shenzhen Xin KingBrand enterprises Co. Ltd","28FD80":"IEEE Registration Authority","28FECD":"Lemobile Information Technology (Beijing) Co. Ltd","28FEDE":"CoMESTA, Inc.","28FF3C":"Apple","28FF3E":"zte Corporation","2C002C":"Unowhy","2C0033":"EControls, LLC","2C00F7":"XOS","2C010B":"NASCENT Technology, LLC - RemKon","2C029F":"3ALogics","2C0623":"Win Leader Inc.","2C073C":"Devline Limited","2C081C":"OVH","2C088C":"HUMAX Co. Ltd","2C094D":"Raptor Engineering, LLC","2C09CB":"Cobs AB","2C0BE9":"Cisco Systems Inc.","2C0E3D":"Samsung Electro-Mechanics(Thailand)","2C10C1":"Nintendo Co. Ltd","2C18AE":"Trend Electronics Co. Ltd","2C1984":"IDN Telecom, Inc.","2C1A31":"Electronics Company Limited","2C1BC8":"Hunan Topview Network System Co. Ltd","2C1DB8":"ARRIS Group, Inc.","2C1EEA":"Aerodev","2C1F23":"Apple","2C200B":"Apple","2C2131":"Juniper Networks","2C2172":"Juniper Networks","2C21D7":"IMAX Corporation","2C228B":"CTR SRL","2C233A":"Hewlett-Packard Company","2C245F":"Babolat VS","2C2617":"Oculus VR, LLC","2C265F":"IEEE Registration Authority","2C26C5":"zte Corporation","2C279E":"IEEE Registration Authority","2C27D7":"Hewlett-Packard Company","2C282D":"BBK Educational Electronics Corp. Ltd","2C28B7":"Hangzhou Ruiying technology Co. Ltd","2C2997":"Microsoft Corporation","2C2D48":"bct electronic GesmbH","2C3033":"Netgear","2C3068":"Pantech Co. Ltd","2C3124":"Cisco Systems Inc.","2C3311":"Cisco Systems Inc.","2C3361":"Apple","2C337A":"Hon Hai Precision Ind. Co. Ltd","2C3427":"Erco & Gener","2C3557":"ELLIY Power Co..Ltd","2C36A0":"Capisco Limited","2C36F8":"Cisco Systems Inc.","2C3731":"Shenzhen Yifang Digital Technology Co. Ltd","2C3796":"Cybo Co. Ltd","2C37C5":"Qingdao Haier Intelligent Home Appliance Technology Co. Ltd","2C3996":"Sagemcom Broadband SAS","2C39C1":"Ciena Corporation","2C3A28":"Fagor Electr?nica","2C3AE8":"Espressif Inc.","2C3BFD":"Netstor Technology Co. Ltd","2C3ECF":"Cisco Systems Inc.","2C3F38":"Cisco Systems Inc.","2C3F3E":"Alge-Timing GmbH","2C402B":"Smart iBlue Technology Limited","2C4053":"Samsung Electronics Co. Ltd","2C4138":"Hewlett-Packard Company","2C41A1":"Bose Corporation","2C4205":"Lytx","2C431A":"Shenzhen YOUHUA Technology Co. Ltd","2C4401":"Samsung Electronics Co. Ltd","2C441B":"Spectrum Medical Limited","2C44FD":"Hewlett-Packard Company","2C4D54":"ASUSTek Computer Inc.","2C4D79":"Weifang GoerTek Technology Co. Ltd","2C5089":"Shenzhen Kaixuan Visual Technology Co.,Limited","2C534A":"Shenzhen Winyao Electronic Limited","2C542D":"Cisco Systems Inc.","2C5491":"Microsoft Corporation","2C54CF":"LG Electronics (Mobile Communications)","2C553C":"Gainspeed, Inc.","2C55D3":"Huawei Technologies Co. Ltd","2C56DC":"ASUSTek Computer Inc.","2C5731":"Wingtech Group (HongKong)Limited","2C598A":"LG Electronics (Mobile Communications)","2C59E5":"Hewlett-Packard Company","2C5A05":"Nokia Corporation","2C5A0F":"Cisco Systems Inc.","2C5A8D":"SysTRONIK Elektronik u. Systemtechnik GmbH","2C5AA3":"Promate Electronic Co.Ltd","2C5BB8":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","2C5BE1":"Centripetal Networks, Inc","2C5D93":"Ruckus Wireless","2C5FF3":"Pertronic Industries","2C600C":"Quanta Computer Inc.","2C61F6":"Apple","2C625A":"Finest Security Systems Co. Ltd","2C6289":"Regenersis (Glenrothes) Ltd","2C6373":"Sichuan Tianyi Comheart Telecomco. Ltd","2C6798":"IntalTech Ltd","2C67FB":"ShenZhen Zhengjili Electronics Co. Ltd","2C69BA":"RF Controls, LLC","2C6A6F":"IEEE Registration Authority","2C6B7D":"Texas Instruments","2C6BF5":"Juniper Networks","2C6E85":"Intel Corporation","2C6FC9":"Hon Hai Precision Ind. Co. Ltd","2C7155":"HiveMotion","2C72C3":"Soundmatters","2C7360":"Earda Technologies Co Ltd","2C750F":"Shanghai Dongzhou-Lawton Communication Technology Co. Ltd","2C768A":"Hewlett-Packard Company","2C7B5A":"Milper Ltd","2C7B84":"OOO Petr Telegin","2C7E81":"ARRIS Group, Inc.","2C7ECF":"Onzo Ltd","2C8065":"HARTING Inc. Of North America","2C8158":"Hon Hai Precision Ind. Co. Ltd","2C86D2":"Cisco Systems Inc.","2C8A72":"HTC Corporation","2C8BF2":"Hitachi Metals America Ltd","2C9127":"Eintechno Corporation","2C922C":"Kishu Giken Kogyou Company Ltd,.","2C9464":"Cincoze Co. Ltd","2C9569":"ARRIS Group, Inc.","2C957F":"zte Corporation","2C9662":"Invenit BV","2C9717":"I.C.Y. B.V.","2C9924":"ARRIS Group, Inc.","2C9AA4":"Eolo SpA","2C9D1E":"Huawei Technologies Co. Ltd","2C9E5F":"ARRIS Group, Inc.","2C9EEC":"Jabil Circuit Penang","2C9EFC":"Canon Inc.","2CA157":"acromate, Inc.","2CA17D":"ARRIS Group, Inc.","2CA2B4":"Fortify Technologies, LLC","2CA30E":"Power Dragon Development Limited","2CA539":"Parallel Wireless, Inc","2CA780":"True Technologies Inc.","2CA835":"RIM","2CAB00":"Huawei Technologies Co. Ltd","2CAB25":"Shenzhen Gongjin Electronics Co.,LT","2CABA4":"Cisco SPVTG","2CABEB":"Cisco Systems Inc.","2CAC44":"Conextop","2CAD13":"Shenzhen Zhilu Technology Co. Ltd","2CAE2B":"Samsung Electronics Co. Ltd","2CB05D":"Netgear","2CB0DF":"Soliton Technologies Pvt Ltd","2CB115":"Integrated Device Technology (Malaysia) Sdn. Bhd.","2CB21A":"Phicomm (Shanghai) Co. Ltd","2CB43A":"Apple","2CB693":"Radware","2CB69D":"RED Digital Cinema","2CB8ED":"SonicWall","2CBABA":"Samsung Electronics Co. Ltd","2CBE08":"Apple","2CBE97":"Ingenieurbuero Bickele und Buehler GmbH","2CC260":"Oracle Corporation","2CC548":"IAdea Corporation","2CC5D3":"Ruckus Wireless","2CCC15":"Nokia Corporation","2CCD27":"Precor Inc","2CCD43":"Summit Technology Group","2CCD69":"Aqavi.com","2CCF58":"Huawei Technologies Co. Ltd","2CD02D":"Cisco Systems Inc.","2CD05A":"Liteon Technology Corporation","2CD141":"IEEE Registration Authority","2CD1DA":"Sanjole, Inc.","2CD2E7":"Nokia Corporation","2CD444":"Fujitsu Limited","2CD974":"Hui Zhou Gaoshengda Technology Co. Ltd","2CDCAD":"Wistron Neweb Corporation","2CDD0C":"Discovergy GmbH","2CDD95":"Taicang T&W Electronics","2CDDA3":"Point Grey Research Inc.","2CE2A8":"DeviceDesign","2CE412":"Sagemcom Broadband SAS","2CE6CC":"Ruckus Wireless","2CE871":"Alert Metalguard ApS","2CEDEB":"Alpheus Digital Company Limited","2CEE26":"Petroleum Geo-Services","2CF0A2":"Apple","2CF0EE":"Apple","2CF203":"Emko Elektronik SAN VE TIC AS","2CF4C5":"Avaya Inc","2CF7F1":"Seeed Technology Inc.","2CFAA2":"Alcatel-Lucent Enterprise","2CFCE4":"CTEK Sweden AB","2CFD37":"Blue Calypso, Inc.","2CFDA1":"ASUSTek Computer Inc.","2CFDAB":"Motorola (Wuhan) Mobility Technologies Communication Co. Ltd","2CFF65":"Oki Electric Industry Co. Ltd","30053F":"JTI Co. Ltd","30055C":"Brother Industries Ltd","30074D":"Samsung Electro-Mechanics(Thailand)","300AC5":"Ruio telecommunication technologies Co., Limited","300B9C":"Delta Mobile Systems, Inc.","300C23":"zte Corporation","300D2A":"Zhejiang Wellcom Technology Co. Ltd","300D43":"Microsoft Mobile Oy","300ED5":"Hon Hai Precision Ind. Co. Ltd","300EE3":"Aquantia Corporation","3010B3":"Liteon Technology Corporation","3010E4":"Apple","30142D":"Piciorgros GmbH","30144A":"Wistron Neweb Corporation",301518:"Ubiquitous Communication Co. Ltd","30168D":"ProLon","3017C8":"Sony Mobile Communications AB","3018CF":"DEOS Control Systems GmbH",301966:"Samsung Electronics Co. Ltd","301A28":"Mako Networks Ltd","301F9A":"IEEE Registration Authority","30215B":"Shenzhen Ostar Display Electronic Co. Ltd","3029BE":"Shanghai MRDcom Co. Ltd","302DE8":"JDA, LLC (JDA Systems)",303294:"W-IE-NE-R Plein & Baus GmbH","3032D4":"Hanilstm Co. Ltd",303335:"Boosty","3034D2":"Availink, Inc.","3035AD":"Apple","3037A6":"Cisco Systems Inc.",303855:"Nokia Corporation",303926:"Sony Mobile Communications AB",303955:"Shenzhen Jinhengjia Electronic Co. Ltd","3039F2":"ADB Broadband Italia","303A64":"Intel Corporation","303D08":"Glintt TES S.A.","303EAD":"Sonavox Canada Inc",304174:"Altec Lansing LLC",304225:"Burg-W?Chter KG",304449:"PLATH GmbH",304487:"Hefei Radio Communication Technology Co. Ltd","3044A1":"Shanghai Nanchao Information Technology",304511:"Texas Instruments","30469A":"Netgear","30493B":"Nanjing Z-Com Wireless Co. Ltd","304C7E":"Panasonic Electric Works Automation Controls Techno Co. Ltd","304EC3":"Tianjin Techua Technology Co. Ltd","3051F8":"BYK-Gardner GmbH","30525A":"NST Co. Ltd","3052CB":"Liteon Technology Corporation","3055ED":"Trex Network LLC","3057AC":"Irlab Ltd",305890:"Frontier Silicon Ltd","30595B":"streamnow AG","3059B7":"Microsoft Corporation","305A3A":"ASUSTek Computer Inc.","305D38":"Beissbarth",306023:"ARRIS Group, Inc.",306112:"PAV GmbH",306118:"Paradom Inc.","30636B":"Apple","3065EC":"Wistron (ChongQing)","30688C":"Reach Technology Inc.","30694B":"RIM","306A85":"Samsung Electronics Co. Ltd","306CBE":"Skymotion Technology (HK) Limited","306E5C":"Validus Technologies","3071B2":"Hangzhou Prevail Optoelectronic Equipment Co. Ltd",307350:"Inpeco SA",307496:"Huawei Technologies Co. Ltd",307512:"Sony Mobile Communications AB","30766F":"LG Electronics (Mobile Communications)","3077CB":"Maike Industry(Shenzhen)Co. Ltd","30785C":"Partow Tamas Novin (Parman)","30786B":"TIANJIN Golden Pentagon Electronics Co. Ltd","3078C2":"Innowireless / QUCELL Networks","307BAC":"New H3C Technologies Co. Ltd","307C30":"RIM","307C5E":"Juniper Networks","307CB2":"Anov France","307ECB":"SFR",308454:"Guangdong Oppo Mobile Telecommunications Corp. Ltd","3085A9":"ASUSTek Computer Inc.",308730:"Huawei Technologies Co. Ltd","3087D9":"Ruckus Wireless",308976:"Dalian Lamba Technology Co. Ltd",308999:"Guangdong East Power Co.,","3089D3":"Hongkong Ucloudlink Network Technology Limited","308CFB":"Dropcam","308D99":"Hewlett-Packard Company","3090AB":"Apple","30918F":"Technicolor","3092F6":"Shanghai Sunmon Communication Technogy Co. Ltd","3095E3":"Shanghai Simcom Limited","3096FB":"Samsung Electronics Co. Ltd",309935:"zte Corporation","309BAD":"BBK Educational Electronics Corp. Ltd","309C23":"Micro-Star INTL Co. Ltd","309FFB":"Ardomus Networks Corporation","30A220":"ARG Telecom","30A243":"Shenzhen Prifox Innovation Technology Co. Ltd","30A8DB":"Sony Mobile Communications AB","30A9DE":"LG Innotek","30AABD":"Shanghai Reallytek Information Technology Co. Ltd","30AE7B":"Deqing Dusun Electron Co. Ltd","30AEA4":"Espressif Inc.","30AEF6":"Radio Mobile Access","30B164":"Power Electronics International Inc.","30B216":"ABB AG - Power Grids - Grid Automation","30B3A2":"Shenzhen Heguang Measurement & Control Technology Co. Ltd","30B49E":"TP-Link Technologies Co. Ltd","30B4B8":"LG Electronics","30B5C2":"TP-Link Technologies Co. Ltd","30B5F1":"Aitexin Technology Co. Ltd","30B62D":"Mojo Networks, Inc.","30B64F":"Juniper Networks","30B7D4":"Hitron Technologies. Inc","30C01B":"Shenzhen Jingxun Software Telecommunication Technology Co. Ltd","30C3D9":"Alps Electric Co. Ltd","30C507":"ECI Telecom Ltd","30C750":"MIC Technology Group","30C7AE":"Samsung Electronics Co. Ltd","30C82A":"WI-BIZ srl","30CBF8":"Samsung Electronics Co. Ltd","30CDA7":"Samsung Electronics Co. Ltd","30D17E":"Huawei Technologies Co. Ltd","30D32D":"devolo AG","30D357":"Logosol, Inc.","30D386":"zte Corporation","30D46A":"Autosales Incorporated","30D587":"Samsung Electronics Co. Ltd","30D6C9":"Samsung Electronics Co. Ltd","30D9D9":"Apple","30DE86":"Cedac Software S.r.l.","30E090":"Linctronix Ltd,","30E171":"Hewlett-Packard Company","30E37A":"Intel Corporation","30E48E":"Vodafone UK","30E4DB":"Cisco Systems Inc.","30EB1F":"Skylab M&C Technology Co. Ltd","30EB25":"Intek Digital","30EFD1":"Alstom Strongwish (Shenzhen) Co. Ltd","30F31D":"zte Corporation","30F335":"Huawei Technologies Co. Ltd","30F33A":"+plugg srl","30F42F":"ESP","30F6B9":"Ecocentric Energy","30F70D":"Cisco Systems Inc.","30F772":"Hon Hai Precision Ind. Co. Ltd","30F77F":"S Mobile Devices Limited","30F7C5":"Apple","30F7D7":"Thread Technology Co. Ltd","30F9ED":"Sony Corporation","30FAB7":"Tunai Creative","30FB94":"Shanghai Fangzhiwei Information Technology Co. Ltd","30FC68":"TP-Link Technologies Co. Ltd","30FD11":"Macrotech (USA) Inc.","30FD38":"Google, Inc.","30FE31":"Nokia","30FFF6":"HangZhou KuoHeng Technology Co. Ltd","34008A":"IEEE Registration Authority","3400A3":"Huawei Technologies Co. Ltd",340286:"Intel Corporation","34029B":"CloudBerry Technologies Private Limited","3403DE":"Texas Instruments","34049E":"IEEE Registration Authority","34074F":"AccelStor, Inc.","3407FB":"Ericsson AB",340804:"D-Link Corporation","3408BC":"Apple","340A22":"TOP-Access Electronics Co Ltd","340AFF":"Qingdao Hisense Communications Co. Ltd","340B40":"Mios Elettronica SRL","340CED":"Moduel AB",341290:"Treeview Co. Ltd",341298:"Apple","3413A8":"Mediplan Limited","3413E8":"Intel Corporation","34145F":"Samsung Electronics Co. Ltd",341513:"Texas Instruments","34159E":"Apple","3417EB":"Dell Inc.","341A35":"Fiberhome Telecommunication Technologies Co. Ltd","341A4C":"Shenzhen Weibu Electronics Co. Ltd","341B22":"Grandbeing Technology Co. Ltd","341E6B":"Huawei Technologies Co. Ltd","341FE4":"ARRIS Group, Inc.",342109:"Jensen Scandinavia AS",342387:"Hon Hai Precision Ind. Co. Ltd","3423BA":"Samsung Electro-Mechanics(Thailand)","34255D":"Shenzhen Loadcom Technology Co. Ltd",342606:"CarePredict, Inc.","3428F0":"ATN International Limited","34298F":"IEEE Registration Authority","3429EA":"MCD Electronics SP. Z O.O.","342AF1":"Texas Instruments","342D0D":"Samsung Electronics Co. Ltd","342F6E":"Anywire Corporation",343111:"Samsung Electronics Co. Ltd","3431C4":"AVM GmbH","3432E6":"Panasonic Industrial Devices Europe GmbH","34363B":"Apple",343759:"zte Corporation","3438AF":"Inlab Software GmbH","3438B7":"HUMAX Co. Ltd","343D98":"JinQianMao Technology Co. Ltd","343DC4":"Buffalo.Inc","3440B5":"IBM","34415D":"Intel Corporation","34466F":"HiTEM Engineering","344B3D":"Fiberhome Telecommunication Technologies Co. Ltd","344B50":"zte Corporation","344CA4":"amazipoint technology Ltd","344CC8":"Echodyne Corp","344DEA":"zte Corporation","344DF7":"LG Electronics (Mobile Communications)","344F3F":"IO-Power Technology Co. Ltd","344F5C":"R&M AG","344F69":"Ekinops SAS","3451AA":"JID Global","3451C9":"Apple","34543C":"Takaoka Toko Co. Ltd","3456FE":"Cisco Meraki",345760:"MitraStar Technology Corp.","345A06":"Sharp Corporation","345B11":"EVI Heat AB","345BBB":"GD Midea Air-Conditioning Equipment Co. Ltd","345C40":"Cargt Holdings LLC","345D10":"Wytek",346178:"The Boeing Company",346288:"Cisco Systems Inc.","3464A9":"Hewlett-Packard Company","34684A":"Teraworks Co. Ltd",346895:"Hon Hai Precision Ind. Co. Ltd",346987:"zte Corporation","346AC2":"Huawei Technologies Co. Ltd","346B46":"Sagemcom Broadband SAS","346BD3":"Huawei Technologies Co. Ltd","346C0F":"Pramod Telecom Pvt. Ltd","346E8A":"Ecosense","346E9D":"Ericsson AB","346F90":"Cisco Systems Inc.","346F92":"White Rodgers Division","346FED":"Enovation Controls","3475C7":"Avaya Inc","3476C5":"I-O Data Device, Inc.",347877:"O-Net Communications (Shenzhen) Limited","3478D7":"Gionee Communication Equipment Co. Ltd","347A60":"ARRIS Group, Inc.","347C25":"Apple","347E39":"Nokia Danmark A/S","347E5C":"Sonos, Inc.","347ECA":"Nextwill","3480B3":"Xiaomi Communications Co Ltd",348137:"Unicard SA","3481C4":"AVM GmbH","3481F4":"SST Taiwan Ltd","3482DE":"Kiio Inc",348302:"iFORCOM Co. Ltd",348446:"Ericsson AB",348584:"Aerohive Networks Inc.","34862A":"Heinz Lackmann GmbH & Co KG","34873D":"Quectel Wireless Solution Co. Ltd","34885D":"Logitech Far East","348A7B":"Samsung Electronics Co. Ltd","348AAE":"Sagemcom Broadband SAS","348B75":"Lava International(H.K) Limited","348F27":"Ruckus Wireless","3495DB":"Logitec Corporation",349672:"TP-Link Technologies Co. Ltd","3497F6":"ASUSTek Computer Inc.","3497FB":"Advanced RF Technologies Inc","34996F":"VPI Engineering",349971:"Quanta Storage Inc.","3499D7":"Universal Flow Monitors, Inc.","349A0D":"ZBD Displays Ltd","349B5B":"Maquet GmbH","349D90":"Heinzmann GmbH & Co. KG","349E34":"Evervictory Electronic Co.Ltd","34A183":"AWare, Inc","34A2A2":"Huawei Technologies Co. Ltd","34A395":"Apple","34A3BF":"Terewave. Inc.","34A55D":"Technosoft International SRL","34A5E1":"Sensorist ApS","34A68C":"Shine Profit Development Limited","34A709":"Trevil srl","34A7BA":"Fischer International Systems Corporation","34A843":"KYOCERA Display Corporation","34A84E":"Cisco Systems Inc.","34AA8B":"Samsung Electronics Co. Ltd","34AA99":"Nokia","34AAEE":"Mikrovisatos Servisas UAB","34AB37":"Apple","34ADE4":"Shanghai Chint Power Systems Co. Ltd","34AF2C":"Nintendo Co. Ltd","34B1F7":"Texas Instruments","34B354":"Huawei Technologies Co. Ltd","34B571":"Plds","34B7FD":"Guangzhou Younghead Electronic Technology Co. Ltd","34BA38":"PAL Mohan Electronics PVT Ltd","34BA51":"Se-Kure Controls, Inc.","34BA75":"Tembo Systems, Inc.","34BA9A":"Asiatelco Technologies Co.","34BB1F":"BlackBerry RTS","34BB26":"Motorola Mobility LLC, a Lenovo Company","34BCA6":"Beijing Ding Qing Technology Ltd","34BDC8":"Cisco Systems Inc.","34BDF9":"Shanghai WDK Industrial Co. Ltd","34BDFA":"Cisco SPVTG","34BE00":"Samsung Electronics Co. Ltd","34BF90":"Fiberhome Telecommunication Technologies Co. Ltd","34C059":"Apple","34C0F9":"Rockwell Automation","34C3AC":"Samsung Electronics Co. Ltd","34C3D2":"FN-Link Technology Limited","34C5D0":"Hagleitner Hygiene International GmbH","34C69A":"Enecsys Ltd","34C731":"Alps Electric Co. Ltd","34C803":"Nokia Corporation","34C99D":"Eidolon Communications Technology Co. Ltd","34C9F0":"LM Technologies Ltd","34CC28":"Nexpring Co. Ltd,","34CD6D":"CommSky Technologies","34CDBE":"Huawei Technologies Co. Ltd","34CE00":"XIAOMI Electronics,Co. Ltd","34CE94":"Parsec (Pty) Ltd","34D09B":"MobilMAX Technology Inc.","34D0B8":"IEEE Registration Authority","34D270":"Amazon Technologies Inc.","34D2C4":"RENA GmbH Print Systeme","34D712":"Smartisan Digital Co. Ltd","34D7B4":"Tributary Systems, Inc.","34D954":"WiBotic Inc.","34DBFD":"Cisco Systems Inc.","34DE1A":"Intel Corporation","34DE34":"zte Corporation","34DF2A":"Fujikon Industrial Co.,Limited","34E0CF":"zte Corporation","34E0D7":"Dongguan Qisheng Electronics Industrial Co. Ltd","34E2FD":"Apple","34E380":"Genexis B.V.","34E42A":"Automatic Bar Controls Inc.","34E6AD":"Intel Corporation","34E6D7":"Dell Inc.","34E70B":"HAN Networks Co. Ltd","34E71C":"Shenzhen YOUHUA Technology Co. Ltd","34E894":"TP-Link Technologies Co. Ltd","34E911":"vivo Mobile Communication Co. Ltd","34EA34":"HangZhou Gubei Electronics Technology Co. Ltd","34ED0B":"Shanghai XZ-CoM.Co. Ltd","34EF44":"2Wire Inc.","34EF8B":"NTT Communications Corporation","34F0CA":"Shenzhen Linghangyuan Digital Technology Co. Ltd","34F39A":"Intel Corporation","34F39B":"WizLAN Ltd","34F62D":"Sharp Corporation","34F64B":"Intel Corporation","34F6D2":"Panasonic Taiwan Co. Ltd","34F968":"ATEK Products, LLC","34FA40":"Guangzhou Robustel Technologies Co., Limited","34FA9F":"Ruckus Wireless","34FC6F":"Alcea","34FCB9":"Hewlett Packard Enterprise","34FCEF":"LG Electronics (Mobile Communications)",380195:"Samsung Electronics Co. Ltd",380197:"TSST Global,Inc","38019F":"Shenzhen Fast Technologies Co. Ltd",380546:"Foctek Photonics, Inc.","3805AC":"Piller Group GmbH","3806B4":"A.D.C. GmbH","3807D4":"Zeppelin Systems GmbH","3808FD":"Silca Spa","3809A4":"Firefly Integrations","380A0A":"Sky-City Communication and Electronics Limited Company","380A94":"Samsung Electronics Co. Ltd","380AAB":"Formlabs","380B40":"Samsung Electronics Co. Ltd","380DD4":"Primax Electronics Ltd","380E4D":"Cisco Systems Inc.","380E7B":"V.P.S. Thai Co. Ltd","380F4A":"Apple","380FE4":"Dedicated Network Partners Oy","3810D5":"AVM Audiovisuelles Marketing und Computersysteme GmbH","3816D1":"Samsung Electronics Co. Ltd",381766:"Promzakaz Ltd","3817C3":"Hewlett Packard Enterprise","3817E1":"Technicolor CH USA Inc.","38192F":"Nokia Corporation","381C1A":"Cisco Systems Inc.","381C23":"Hilan Technology Co. Ltd","381C4A":"SIMCom Wireless Solutions Co. Ltd","381DD9":"FN-Link Technology Limited",382056:"Cisco Systems Inc.","3820A8":"ColorTokens, Inc.",382187:"Midea Group Co. Ltd","38229D":"ADB Broadband Italia","3822D6":"Hangzhou H3C Technologies Co., Limited","38256B":"Microsoft Mobile Oy","38262B":"UTran Technology","3826CD":"Andtek","3828EA":"Fujian Netcom Technology Co. Ltd","38295A":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","3829DD":"ONvocal Inc","382B78":"ECO Plugs Enterprise Co. Ltd","382C4A":"ASUSTek Computer Inc.","382DD1":"Samsung Electronics Co. Ltd","382DE8":"Samsung Electronics Co. Ltd","3831AC":"WEG","3835FB":"Sagemcom Broadband SAS","38378B":"Huawei Technologies Co. Ltd","383A21":"IEEE Registration Authority","383BC8":"2Wire Inc.","383F10":"DBL Technology Ltd",384233:"Wildeboer Bauteile GmbH","3842A6":"Ingenieurbuero Stahlkopf",384369:"Patrol Products Consortium LLC","38437D":"Compal Broadband Networks, Inc.","38454C":"Light Labs, Inc.","38458C":"MyCloud Technology Corporation",384608:"zte Corporation","38484C":"Apple","384B76":"AIRTAME ApS","384C4F":"Huawei Technologies Co. Ltd","384C90":"ARRIS Group, Inc.","384F49":"Juniper Networks","384FF0":"Azurewave Technologies Inc.","38521A":"Nokia",385610:"CANDY HOUSE, Inc.","38580C":"Panaccess Systems GmbH","3859F8":"MindMade Sp. z o.o.","3859F9":"Hon Hai Precision Ind. Co. Ltd","385AA8":"Beijing Zhongdun Security Technology Development Co.","385F66":"Cisco SPVTG","385FC3":"Yu Jeong System, Co.Ltd",386077:"Pegatron Corporation","3863BB":"Hewlett-Packard Company","3863F6":"3NOD Multimedia(Shenzhen)Co. Ltd",386645:"OOSIC Technology Co. Ltd","3866F0":"Apple",386793:"Asia Optical Co., Inc.","386B1C":"Shenzhen Mercury Communication Technologies Co. Ltd","386BBB":"ARRIS Group, Inc.","386C9B":"Ivy Biomedical","386E21":"Wasion Group Ltd","386EA2":"vivo Mobile Communication Co. Ltd","38700C":"ARRIS Group, Inc.","3871DE":"Apple","3872C0":"Comtrend Corporation","3873EA":"IEEE Registration Authority","3876CA":"Shenzhen Smart Intelligent Technology Co.Ltd","3876D1":"Euronda SpA",387862:"Sony Mobile Communications AB","387B47":"AKELA, Inc.","3880DF":"Motorola Mobility LLC, a Lenovo Company",388345:"TP-Link Technologies Co. Ltd",388602:"Flexoptix GmbH","38892C":"Apple","3889DC":"Opticon Sensors Europe B.V.","388AB7":"ITC Networks","388C50":"LG Electronics","388EE7":"Fanhattan LLC","3890A5":"Cisco Systems Inc.","3891D5":"Hangzhou H3C Technologies Co., Limited","3891FB":"Xenox Holding BV",389496:"Samsung Electronics Co. Ltd","3894E0":"Syrotech Networks. Ltd",389592:"Beijing Tendyron Corporation","3897D6":"Hangzhou H3C Technologies Co., Limited","3898D8":"Meritech Co. Ltd","389AF6":"Samsung Electronics Co. Ltd","389D92":"Seiko Epson Corporation","389F5A":"C-Kur TV Inc.","389F83":"OTN Systems N.V.","38A28C":"Shenzhen RF-Link Technology Co. Ltd","38A4ED":"Xiaomi Communications Co Ltd","38A53C":"CoMECER Netherlands","38A5B6":"Shenzhen Megmeet Electrical Co. Ltd","38A6CE":"BSkyB Ltd","38A851":"Moog, Ing","38A86B":"Orga BV","38A95F":"Actifio Inc","38AA3C":"Samsung Electro Mechanics Co. Ltd","38AC3D":"Nephos Inc","38AD8E":"New H3C Technologies Co. Ltd","38ADBE":"New H3C Technologies Co. Ltd","38AFD7":"Fujitsu Limited","38B12D":"Sonotronic Nagel GmbH","38B1DB":"Hon Hai Precision Ind. Co. Ltd","38B54D":"Apple","38B5BD":"E.G.O. Elektro-Ger","38B725":"Wistron Infocomm (Zhongshan) Corporation","38B74D":"Fijowave Limited","38B8EB":"IEEE Registration Authority","38BAF8":"Intel Corporation","38BB23":"OzVision America LLC","38BB3C":"Avaya Inc","38BC01":"Huawei Technologies Co. Ltd","38BC1A":"MEIZU Technology Co. Ltd","38BF2F":"Espec Corp.","38BF33":"NEC CASIO Mobile Communications","38C096":"Alps Electric Co. Ltd","38C70A":"WiFiSong","38C7BA":"CS Services Co. Ltd","38C85C":"Cisco SPVTG","38C986":"Apple","38C9A9":"SMART High Reliability Solutions, Inc.","38CA97":"Contour Design LLC","38CADA":"Apple","38CD07":"Beijing FaceCam Technology Co. Ltd","38D135":"EasyIO Corporation Sdn. Bhd.","38D269":"Texas Instruments","38D40B":"Samsung Electronics Co. Ltd","38D547":"ASUSTek Computer Inc.","38D620":"Limidea Concept Pte. Ltd","38D7CA":"7HUGS Labs","38D82F":"zte Corporation","38DBBB":"Sunbow Telecom Co. Ltd","38DE60":"Mohlenhoff GmbH","38DEAD":"Intel Corporation","38E08E":"Mitsubishi Electric Corporation","38E1AA":"zte Corporation","38E2DD":"zte Corporation","38E3C5":"Taicang T&W Electronics","38E595":"Shenzhen Gongjin Electronics Co.,LT","38E60A":"Xiaomi Communications Co Ltd","38E7D8":"HTC Corporation","38E8DF":"b GmbH medien + datenbanken","38E98C":"Reco S.p.A.","38EAA7":"Hewlett-Packard Company","38EC11":"Novatek Microelectronics Corp.","38ECE4":"Samsung Electronics Co. Ltd","38ED18":"Cisco Systems Inc.","38EE9D":"Anedo Ltd","38F098":"Vapor Stone Rail Systems","38F0C8":"Livestream","38F135":"SensorTec-Canada","38F23E":"Microsoft Mobile Oy","38F33F":"Tatsuno Corporation","38F554":"Hisense Electric Co. Ltd","38F557":"Jolata, Inc.","38F597":"home2net GmbH","38F708":"National Resource Management, Inc.","38F73D":"Amazon Technologies Inc.","38F7B2":"Seojun Electric","38F889":"Huawei Technologies Co. Ltd","38F8B7":"V2COM Participacoes S.A.","38F8CA":"OWIN Inc.","38FACA":"Skyworth Digital Technology(Shenzhen) Co. Ltd","38FDFE":"IEEE Registration Authority","38FEC5":"Ellips B.V.","38FF36":"Ruckus Wireless","3C02B1":"Creation Technologies LP","3C0461":"ARRIS Group, Inc.","3C04BF":"PRAVIS SysTEMS Co.Ltd,","3C0518":"Samsung Electronics Co. Ltd","3C05AB":"Product Creation Studio","3C0754":"Apple","3C0771":"Sony Corporation","3C081E":"Beijing Yupont Electric Power Technology Co. Ltd","3C08F6":"Cisco Systems Inc.","3C096D":"Powerhouse Dynamics","3C0C48":"Servergy, Inc.","3C0CDB":"Unionman Technology Co. Ltd","3C0E23":"Cisco Systems Inc.","3C0FC1":"KBC Networks","3C1040":"daesung network","3C106F":"Albahith Technologies","3C10E6":"PHAZR Inc.","3C11B2":"Fraunhofer FIT","3C15C2":"Apple","3C15EA":"Tescom Co. Ltd","3C15FB":"Huawei Technologies Co. Ltd","3C1710":"Sagemcom Broadband SAS","3C189F":"Nokia Corporation","3C18A0":"Luxshare Precision Industry Company Limited","3C1915":"GFI Chrono Time","3C197D":"Ericsson AB","3C1A0F":"ClearSky Data","3C1A57":"Cardiopulmonary Corp","3C1A79":"Huayuan Technology Co. Ltd","3C1CBE":"Jadak LLC","3C1E04":"D-Link International","3C1E13":"Hangzhou Sunrise Technology Co. Ltd","3C24F0":"IEEE Registration Authority","3C25D7":"Nokia Corporation","3C26D5":"Sotera Wireless","3C2763":"SLE quality engineering GmbH & Co. KG","3C2AF4":"Brother Industries Ltd","3C2C94":"??????????(HangZhou Delan Technology Co. Ltd)","3C2C99":"Edgecore Networks Corporation","3C2DB7":"Texas Instruments","3C2EF9":"Apple","3C2EFF":"Apple","3C2F3A":"SFORZATO Corp.","3C300C":"Dewar Electronics Pty Ltd","3C3178":"Qolsys Inc.","3C3300":"Shenzhen Bilian electronic Co. Ltd","3C3556":"Cognitec Systems GmbH","3C363D":"Nokia Corporation","3C36E4":"ARRIS Group, Inc.","3C3888":"ConnectQuest, llc","3C39C3":"JW Electronics Co. Ltd","3C39E7":"IEEE Registration Authority","3C3A73":"Avaya Inc","3C3F51":"2CRSI","3C404F":"Guangdong Pisen Electronics Co. Ltd","3C438E":"ARRIS Group, Inc.","3C46D8":"TP-Link Technologies Co. Ltd","3C4711":"Huawei Technologies Co. Ltd","3C479B":"Theissen Training Systems, Inc.","3C4937":"ASSMANN Electronic GmbH","3C4A92":"Hewlett-Packard Company","3C4C69":"Infinity System S.L.","3C4CD0":"Ceragon Networks","3C4E47":"Etronic A/S","3C5282":"Hewlett-Packard Company","3C574F":"China Mobile Group Device Co. Ltd","3C57BD":"Kessler Crane Inc.","3C57D5":"FiveCo","3C591E":"TCL King Electrical Appliances (Huizhou) Co. Ltd","3C5A37":"Samsung Electronics Co. Ltd","3C5AB4":"Google, Inc.","3C5CC3":"Shenzhen First Blue Chip Technology Ltd","3C5EC3":"Cisco Systems Inc.","3C5F01":"Synerchip Co. Ltd","3C6104":"Juniper Networks","3C6200":"Samsung Electronics Co. Ltd","3C6278":"Shenzhen Jetnet Technology Co. Ltd","3C6716":"Lily Robotics","3C672C":"Sciovid Inc.","3C678C":"Huawei Technologies Co. Ltd","3C6816":"VXi Corporation","3C6A7D":"Niigata Power Systems Co. Ltd","3C6A9D":"Dexatek Technology Ltd","3C6E63":"Mitron Oy","3C6F45":"Fiberpro Inc.","3C6FEA":"Panasonic India Pvt. Ltd","3C6FF7":"EnTek Systems, Inc.","3C7059":"MakerBot Industries","3C7437":"RIM","3C754A":"ARRIS Group, Inc.","3C77E6":"Hon Hai Precision Ind. Co. Ltd","3C7843":"Huawei Technologies Co. Ltd","3C7873":"Airsonics","3C7A8A":"ARRIS Group, Inc.","3C7DB1":"Texas Instruments","3C7F6F":"Telechips, Inc.","3C80AA":"Ransnet Singapore Pte Ltd","3C81D8":"Sagemcom Broadband SAS","3C831E":"CKD Corporation","3C8375":"Microsoft Corporation","3C83B5":"Advance Vision Electronics Co. Ltd","3C86A8":"Sangshin elecom .Co, Ltd","3C8970":"Neosfar","3C89A6":"Kapelse","3C8AB0":"Juniper Networks","3C8AE5":"Tensun Information Technology(Hangzhou) Co. Ltd","3C8BCD":"Alcatel-Lucent Shanghai Bell Co. Ltd","3C8BFE":"Samsung Electronics Co. Ltd","3C8C40":"Hangzhou H3C Technologies Co., Limited","3C8CF8":"TRENDnet, Inc.","3C9066":"SmartRG, Inc.","3C912B":"Vexata Inc","3C9157":"Yulong Computer Telecommunication Scientific (Shenzhen) Co. Ltd","3C9174":"Along Communication Technology","3C92DC":"Octopod Technology Co. Ltd","3C94D5":"Juniper Networks","3C9509":"Liteon Technology Corporation","3C970E":"Wistron InfoComm(Kunshan)Co. Ltd","3C977E":"IPS Technology Limited","3C98BF":"Quest Controls, Inc.","3C99F7":"Lansentechnology AB","3C9A77":"Technicolor CH USA Inc.","3C9F81":"Shenzhen CATIC Bit Communications Technology Co. Ltd","3CA067":"Liteon Technology Corporation","3CA10D":"Samsung Electronics Co. Ltd","3CA308":"Texas Instruments","3CA315":"Bless Information & Communications Co. Ltd","3CA31A":"Oilfind International LLC","3CA348":"vivo Mobile Communication Co. Ltd","3CA581":"vivo Mobile Communication Co. Ltd","3CA616":"vivo Mobile Communication Co. Ltd","3CA72B":"MRV Communications (Networks) Ltd","3CA82A":"Hewlett-Packard Company","3CA9F4":"Intel Corporation","3CAA3F":"iKey Ltd","3CAB8E":"Apple","3CAE69":"ESA Elektroschaltanlagen Grimma GmbH","3CB15B":"Avaya Inc","3CB17F":"Wattwatchers Pty Ld","3CB6B7":"vivo Mobile Communication Co. Ltd","3CB72B":"PLUMgrid Inc","3CB792":"Hitachi Maxell Ltd, Optronics Division","3CB87A":"Private","3CB9A6":"Belden Deutschland GmbH","3CBB73":"Shenzhen Xinguodu Technology Co. Ltd","3CBBFD":"Samsung Electronics Co. Ltd","3CBD3E":"Beijing Xiaomi Electronics Co. Ltd","3CBDD8":"LG Electronics Inc","3CBEE1":"Nikon Corporation","3CC079":"Shenzhen One-Nine Intelligent Electronic Science and Technology Co. Ltd","3CC0C6":"d&b audiotechnik GmbH","3CC12C":"AES Corporation","3CC1F6":"Melange Systems Pvt. Ltd","3CC243":"Nokia Corporation","3CC2E1":"Xinhua Control Engineering Co. Ltd","3CC99E":"Huiyang Technology Co. Ltd","3CCA87":"Iders Incorporated","3CCB7C":"TCT mobile Ltd","3CCD5A":"Technische Alternative GmbH","3CCD5D":"Huawei Technologies Co. Ltd","3CCD93":"LG Electronics Inc","3CCE15":"Mercedes-Benz USA, LLC","3CCE73":"Cisco Systems Inc.","3CCF5B":"Icomm HK Limited","3CD0F8":"Apple","3CD16E":"Telepower Communication Co. Ltd","3CD4D6":"WirelessWERX, Inc","3CD7DA":"SK Mtek microelectronics(shenzhen)limited","3CD92B":"Hewlett-Packard Company","3CD9CE":"Eclipse WiFi","3CDA2A":"zte Corporation","3CDCBC":"Samsung Electronics Co. Ltd","3CDD89":"Somo Holdings & Tech. Co. Ltd","3CDF1E":"Cisco Systems Inc.","3CDFA9":"ARRIS Group, Inc.","3CDFBD":"Huawei Technologies Co. Ltd","3CE072":"Apple","3CE1A1":"Universal Global Scientific Industrial Co. Ltd","3CE5A6":"Hangzhou H3C Technologies Co., Limited","3CE5B4":"Kidasen Industria E Comercio de Antenas Ltda","3CE624":"LG Display","3CE824":"Huawei Technologies Co. Ltd","3CEA4F":"2Wire Inc.","3CEAF9":"Jubixcoltd","3CEAFB":"NSE AG","3CEF8C":"Zhejiang Dahua Technology Co. Ltd","3CF392":"Virtualtek. Co. Ltd","3CF52C":"DSPECIALISTS GmbH","3CF591":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","3CF72A":"Nokia Corporation","3CF748":"Shenzhen Linsn Technology Development Co. Ltd","3CF7A4":"Samsung Electronics Co. Ltd","3CF808":"Huawei Technologies Co. Ltd","3CF862":"Intel Corporation","3CFA43":"Huawei Technologies Co. Ltd","3CFB5C":"Fiberhome Telecommunication Technologies Co. Ltd","3CFB96":"Emcraft Systems LLC","3CFDFE":"Intel Corporation","4000E0":"Derek(Shaoguan)Limited",400107:"Arista Corp","40017A":"Cisco Systems Inc.","4001C6":"3Com Europe Ltd","40040C":"A&T","4007C0":"Railtec Systems GmbH","400D10":"ARRIS Group, Inc.","400E67":"Tremol Ltd","400E85":"Samsung Electro-Mechanics(Thailand)","4011DC":"Sonance","4012E4":"Compass-EOS","4013D9":"Global ES",401597:"Protect America, Inc.","40163B":"Samsung Electronics Co. Ltd","40167E":"ASUSTek Computer Inc.","40169F":"TP-Link Technologies Co. Ltd","4016FA":"EKM Metering","4018B1":"Aerohive Networks Inc.","4018D7":"Smartronix, Inc.","401B5F":"Weifang GoerTek Technology Co. Ltd","401D59":"Biometric Associates, LP","4022ED":"Digital Projection Ltd","4025C2":"Intel Corporation","40270B":"Mobileeco Co. Ltd",402814:"RFI Engineering","402BA1":"Sony Mobile Communications AB","402CF4":"Universal Global Scientific Industrial Co. Ltd","402E28":"MiXTelematics",403004:"Apple",403067:"Conlog (Pty) Ltd","40331A":"Apple","40336C":"Godrej & Boyce Mfg. Co. Ltd","4037AD":"Macro Image Technology, Inc.","403CFC":"Apple","403DEC":"HUMAX Co. Ltd","403F8C":"TP-Link Technologies Co. Ltd",404022:"ZIV","40406B":"Icomera","4040A7":"Sony Mobile Communications AB",404229:"Layer3TV, Inc","4045DA":"Spreadtrum Communications (Shanghai) Co. Ltd","40476A":"AG Acquisition Corp. d.b.a. ASTRO Gaming","4048FD":"IEEE Registration Authority","40490F":"Hon Hai Precision Ind. Co. Ltd","40498A":"Synapticon GmbH","404A03":"ZyXEL Communications Corp","404A18":"Addrek Smart Solutions","404AD4":"Widex A/S","404D7F":"Apple","404D8E":"Huawei Technologies Co. Ltd","404E36":"HTC Corporation","404EEB":"Higher Way Electronic Co. Ltd","4050B5":"Shenzhen New Species Technology Co. Ltd","4050E0":"Milton Security Group LLC","40516C":"Grandex International Corporation","40520D":"Pico Technology","4054E4":"Wearsafe Labs Inc",405539:"Cisco Systems Inc.","40560C":"In Home Displays Ltd","40562D":"Smartron India Pvt Ltd","405A9B":"Anovo","405CFD":"Dell Inc.","405D82":"Netgear","405EE1":"Shenzhen H&T Intelligent Control Co. Ltd","405FBE":"RIM","405FC2":"Texas Instruments","40605A":"Hawkeye Tech Co. Ltd",406186:"Micro-Star International","40618E":"Stella-Green Co",406231:"Gifa","4062B6":"Tele System Communication","4064A4":"THE Furukawa Electric Co. Ltd","4065A3":"Sagemcom Broadband SAS","40667A":"mediola - Connected living AG",406826:"Thales UK Limited","406A8E":"Hangzhou Puwell OE Tech Ltd","406AAB":"RIM","406C8F":"Apple","406F2A":"BlackBerry RTS",407009:"ARRIS Group, Inc.","40704A":"Power Idea Technology Limited",407074:"Life Technology (China) Co. Ltd",407183:"Juniper Networks",407496:"aFUN TECHNOLOGY Inc.","40786A":"Motorola Mobility LLC, a Lenovo Company",407875:"IMBEL - Industria de Material Belico do Brasil","407A80":"Nokia Corporation","407B1B":"Mettle Networks Inc.","407C7D":"Nokia","407D0F":"Huawei Technologies Co. Ltd","407FE0":"Glory Star Technics (ShenZhen) Limited",408256:"Continental Automotive GmbH","40831D":"Apple","4083DE":"Zebra Technologies Inc",408493:"Clavister AB","40862E":"JDM Mobile Internet Solution Co. Ltd",408805:"Motorola Mobility LLC, a Lenovo Company","4088E0":"Beijing Ereneben Information Technology Limited Shenzhen Branch","408A9A":"TITENG Co. Ltd","408B07":"Actiontec Electronics, Inc","408BF6":"Shenzhen TCL New Technology Co. Ltd","408D5C":"Giga-Byte Technology Co. Ltd",409558:"Aisino Corporation","4095BD":"NTmore.Co. Ltd","4097D1":"BK Electronics cc","40984C":"Casacom Solutions AG","40984E":"Texas Instruments","40987B":"Aisino Corporation","4098AD":"Apple",409922:"Azurewave Technologies Inc.","409B0D":"Shenzhen Yourf Kwan Industrial Co. Ltd","409BCD":"D-Link International","409C28":"Apple","409F38":"Azurewave Technologies Inc.","409F87":"Jide Technology (Hong Kong) Limited","409FC7":"BAEKCHUN I&C Co. Ltd","40A3CC":"Intel Corporation","40A5EF":"Shenzhen Four Seas Global Link Network Technology Co. Ltd","40A677":"Juniper Networks","40A6A4":"PassivSystems Ltd","40A6D9":"Apple","40A6E8":"Cisco Systems Inc.","40A8F0":"Hewlett-Packard Company","40A93F":"Private","40AC8D":"Data Management, Inc.","40B034":"Hewlett-Packard Company","40B0FA":"LG Electronics (Mobile Communications)","40B2C8":"Nortel Networks","40B395":"Apple","40B3CD":"Chiyoda Electronics Co. Ltd","40B3FC":"Logital Co. Limited","40B4CD":"Amazon Technologies Inc.","40B4F0":"Juniper Networks","40B688":"LEGIC Identsystems AG","40B6B1":"SUNGSAM Co,.Ltd","40B7F3":"ARRIS Group, Inc.","40B837":"Sony Mobile Communications AB","40B89A":"Hon Hai Precision Ind. Co. Ltd","40B93C":"Hewlett Packard Enterprise","40BA61":"ARIMA Communications Corp.","40BC73":"Cronoplast S.L.","40BC8B":"itelio GmbH","40BD32":"Texas Instruments","40BD9E":"Physio-Control, Inc","40BF17":"Digistar Telecom. SA","40C245":"Shenzhen Hexicom Technology Co. Ltd","40C4D6":"ChongQing Camyu Technology Development Co. Ltd","40C62A":"Shanghai Jing Ren Electronic Technology Co. Ltd","40C729":"Sagemcom Broadband SAS","40C7C9":"Naviit Inc.","40C8CB":"AM Telecom Co. Ltd","40CBA8":"Huawei Technologies Co. Ltd","40CBC0":"Apple","40CD3A":"Z3 Technology","40CD7A":"Qingdao Hisense Communications Co. Ltd","40CE24":"Cisco Systems Inc.","40D28A":"Nintendo Co. Ltd","40D32D":"Apple","40D357":"Ison Technology Co. Ltd","40D3AE":"Samsung Electronics Co. Ltd","40D40E":"Biodata Ltd","40D559":"Micro S.E.R.I.","40D63C":"Equitech Industrial(DongGuan)Co. Ltd","40D855":"IEEE Registration Authority","40E230":"Azurewave Technologies Inc.","40E3D6":"Aruba Networks","40E730":"DEY Storage Systems, Inc.","40E793":"Shenzhen Siviton Technology Co. Ltd","40EACE":"Founder Broadband Network Service Co. Ltd","40ECF8":"Siemens AG","40ED98":"IEEE Registration Authority","40EF4C":"Fihonest Communication Co. Ltd","40F02F":"Liteon Technology Corporation","40F04E":"Integrated Device Technology (Malaysia) Sdn. Bhd.","40F14C":"ISE Europe SPRL","40F201":"Sagemcom Broadband SAS","40F2E9":"IBM","40F308":"Murata Manufacturing Co. Ltd","40F385":"IEEE Registration Authority","40F407":"Nintendo Co. Ltd","40F413":"Rubezh","40F420":"Sichuan Tianyi Comheart Telecomco. Ltd","40F4EC":"Cisco Systems Inc.","40F52E":"Leica Microsystems (Schweiz) AG","40FA7F":"Preh Car Connect GmbH","40FC89":"ARRIS Group, Inc.","40FE0D":"Maxio",440010:"Apple","44032C":"Intel Corporation","4403A7":"Cisco Systems Inc.",440444:"Guangdong Oppo Mobile Telecommunications Corp. Ltd","4409B8":"Salcomp (Shenzhen) Co. Ltd","440CFD":"NetMan Co. Ltd",441102:"EDMI Europe Ltd","4411C2":"Telegartner Karl Gartner GmbH",441319:"WKK Technology Ltd",441441:"AudioControl Inc.","44184F":"Fitview","4419B6":"Hangzhou Hikvision Digital Technology Co. Ltd","441CA8":"Hon Hai Precision Ind. Co. Ltd","441E91":"ARVIDA Intelligent Electronics Technology Co. Ltd","441E98":"Ruckus Wireless","441EA1":"Hewlett-Packard Company","4423AA":"Farmage Co. Ltd","4425BB":"Bamboo Entertainment Corporation",442938:"NietZsche enterprise Co.Ltd","442A60":"Apple","442AFF":"E3 Technology, Inc.","442B03":"Cisco Systems Inc.","442C05":"AMPAK Technology, Inc.",443192:"Hewlett-Packard Company","44322A":"Avaya Inc","4432C8":"Technicolor CH USA Inc.","44334C":"Shenzhen Bilian electronic Co. Ltd","44348F":"MXT Industrial Ltda","4434A7":"ARRIS Group, Inc.","44356F":"Neterix",443708:"MRV Comunications",443719:"2 Save Energy Ltd","44376F":"Young Electric Sign Co","4437E6":"Hon Hai Precision Ind. Co. Ltd",443839:"Cumulus Networks, Inc","4439C4":"Universal Global Scientific Industrial Co. Ltd","443C9C":"Pintsch Tiefenbach GmbH","443D21":"Nuvolt","443EB2":"DEOTRON Co. Ltd",444450:"OttoQ",444891:"HDMI Licensing, LLC","4448C1":"Hewlett Packard Enterprise","444A65":"Silverflare Ltd","444AB0":"Zhejiang Moorgen Intelligence Technology Co. Ltd","444C0C":"Apple","444CA8":"Arista Networks","444E1A":"Samsung Electronics Co. Ltd","444E6D":"AVM Audiovisuelles Marketing und Computersysteme GmbH","444F5E":"Pan Studios Co. Ltd","4451DB":"Raytheon BBN Technologies","4454C0":"Thompson Aerospace","4455B1":"Huawei Technologies Co. Ltd","44568D":"PNC Technologies Co. Ltd","4456B7":"Spawn Labs, Inc",445829:"Cisco SPVTG","44599F":"Criticare Systems, Inc","445ECD":"Razer Inc","445EF3":"Tonalite Holding B.V.","445F7A":"Shihlin Electric & Engineering Corp.","445F8C":"Intercel Group Limited",446132:"ecobee Inc","44619C":"FONsystem Co. Ltd",446246:"Comat AG","44650D":"Amazon Technologies Inc.","44656A":"Mega Video Electronic(HK) Industry Co. Ltd","44666E":"IP-Line","4466FC":"Guangdong Oppo Mobile Telecommunications Corp. Ltd",446755:"Orbit Irrigation","4468AB":"Juin Company, Limited","446A2E":"Huawei Technologies Co. Ltd","446AB7":"ARRIS Group, Inc.","446C24":"Reallin Electronic Co. Ltd","446D57":"Liteon Technology Corporation","446D6C":"Samsung Electronics Co. Ltd","446EE5":"Huawei Technologies Co. Ltd","44700B":"Iffu",447098:"Ming Hong Technology (Shen Zhen) Limited","4473D6":"Logitech","44746C":"Sony Mobile Communications AB","44783E":"Samsung Electronics Co. Ltd","447BBB":"Shenzhen YOUHUA Technology Co. Ltd","447BC4":"DualShine Technology(SZ)Co. Ltd","447C7F":"Innolight Technology Corporation","447DA5":"Vtion Information Technology (Fujian) Co. Ltd","447E76":"Trek Technology (S) Pte Ltd","447E95":"Alpha and Omega, Inc","447F77":"Connected Home","4480EB":"Motorola Mobility LLC, a Lenovo Company","4482E5":"Huawei Technologies Co. Ltd",448312:"Star-Net",448500:"Intel Corporation","4486C1":"Siemens Low Voltage & Products",448723:"Hoya Service Corporation","4487FC":"Elitegroup Computer Systems Co. Ltd","4488CB":"Camco Technologies NV","448A5B":"Micro-Star International","448C52":"KTIS Co. Ltd","448E12":"DT Research, Inc.","448E81":"VIG","448F17":"Samsung Electronics Co. Ltd ARTIK",449160:"Murata Manufacturing Co. Ltd","4491DB":"Shanghai Huaqin Telecom Technology Co. Ltd","4494FC":"Netgear","4495FA":"Qingdao Santong Digital Technology Co.Ltd","44962B":"Aidon Oy","44975A":"Shenzhen Fast Technologies Co. Ltd","449B78":"The Now Factory","449CB5":"Alcomp, Inc","449EF9":"vivo Mobile Communication Co. Ltd","449F7F":"DataCore Software Corporation","44A42D":"TCT mobile Ltd","44A689":"Promax Electronica SA","44A6E5":"Thinking Technology Co. Ltd","44A7CF":"Murata Manufacturing Co. Ltd","44A842":"Dell Inc.","44A8C2":"Sewoo Tech Co. Ltd","44AA27":"udworks Co. Ltd","44AA50":"Juniper Networks","44AAE8":"Nanotec Electronic GmbH & Co. KG","44AAF5":"ARRIS Group, Inc.","44AD19":"Xingfei (H.K)Limited","44ADD9":"Cisco Systems Inc.","44B32D":"TP-Link Technologies Co. Ltd","44B382":"Kuang-chi Institute Of Advanced Technology","44B412":"Sius AG","44BA46":"Sichuan Tianyi Comheart Telecomco. Ltd","44BFE3":"Shenzhen Longtech Electronics Co. Ltd","44C15C":"Texas Instruments","44C233":"Guangzhou Comet Technology Development Co.Ltd","44C306":"SIFROM Inc.","44C346":"Huawei Technologies Co. Ltd","44C39B":"OOO Rubezh NPO","44C4A9":"Opticom Communication, LLC","44C56F":"NGN Easy Satfinder (Tianjin) Electronic Co. Ltd","44C69B":"Wuhan Feng Tian Information Network Co. Ltd","44C874":"China Mobile Group Device Co. Ltd","44C9A2":"Greenwald Industries","44CD0E":"Flextronics Manufacturing(Zhuhai)Co. Ltd","44CE7D":"SFR","44D15E":"Shanghai Kingto Information Technology Ltd","44D1FA":"Shenzhen Yunlink Technology Co. Ltd","44D244":"Seiko Epson Corporation","44D2CA":"Anvia TV Oy","44D3CA":"Cisco Systems Inc.","44D437":"Inteno Broadband Technology AB","44D4E0":"Sony Mobile Communications AB","44D5A5":"AddOn Computer","44D63D":"Talari Networks","44D6E1":"Snuza International Pty. Ltd","44D832":"Azurewave Technologies Inc.","44D884":"Apple","44D9E7":"Ubiquiti Networks Inc.","44DC91":"Planex Communications Inc.","44DCCB":"Semindia Systems PVT Ltd","44E08E":"Cisco SPVTG","44E137":"ARRIS Group, Inc.","44E49A":"Omnitronics Pty Ltd","44E4D9":"Cisco Systems Inc.","44E8A5":"Myreka Technologies Sdn. Bhd.","44E9DD":"Sagemcom Broadband SAS","44EA4B":"Actlas Inc.","44EAD8":"Texas Instruments","44ED57":"Longicorn, Inc.","44EE02":"MTI Ltd","44EE30":"Budelmann Elektronik GmbH","44F034":"Kaonmedia Co. Ltd","44F436":"zte Corporation","44F459":"Samsung Electronics Co. Ltd","44F477":"Juniper Networks","44F849":"Union Pacific Railroad","44FB42":"Apple","44FDA3":"Everysight Ltd","44FFBA":"zte Corporation",480031:"Huawei Technologies Co. Ltd",480033:"Technicolor CH USA Inc.","48022A":"B-Link Electronic Limited",480362:"Desay Electronics(Huizhou)Co. Ltd","48066A":"Tempered Networks, Inc.","480BB2":"IEEE Registration Authority","480C49":"NAKAYO Inc","480EEC":"TP-Link Technologies Co. Ltd","480FCF":"Hewlett-Packard Company",481063:"NTT Innovation Institute, Inc.",481249:"Luxcom Technologies Inc.","48137E":"Samsung Electronics Co. Ltd","4813F3":"BBK Educational Electronics Corp. Ltd","48174C":"MicroPower technologies",481842:"Shanghai Winaas Co. Equipment Co. Ltd","4818FA":"Nocsys","481A84":"Pointer Telocation Ltd","481BD2":"Intron Scientific Co. Ltd","481D70":"Cisco SPVTG","4826E8":"Tek-Air Systems, Inc.","4827EA":"Samsung Electronics Co. Ltd","48282F":"zte Corporation","482CEA":"Motorola Inc Business Light Radios","4833DD":"Zennio Avance Y Tecnologia, S.L.","48343D":"IEP GmbH","48365F":"Wintecronics Ltd",483974:"Proware Technologies Co. Ltd","483B38":"Apple","483C0C":"Huawei Technologies Co. Ltd","483D32":"Syscor Controls & Automation","48435A":"Huawei Technologies Co. Ltd","48437C":"Apple",484487:"Cisco SPVTG","4844F7":"Samsung Electronics Co. Ltd",484520:"Intel Corporation","4846F1":"Uros Oy","4846FB":"Huawei Technologies Co. Ltd","4849C7":"Samsung Electronics Co. Ltd","484BAA":"Apple","484D7E":"Dell Inc.",485073:"Microsoft Corporation","4851B7":"Intel Corporation",485261:"Soreel",485415:"NET Rules Tecnologia Eireli","48555C":"Wu Qi Technologies,Inc.","48555F":"Fiberhome Telecommunication Technologies Co. Ltd","4857DD":"Facebook Inc",485929:"LG Electronics (Mobile Communications)","4859A4":"zte Corporation","485A3F":"Wisol","485AB6":"Hon Hai Precision Ind. Co. Ltd","485B39":"ASUSTek Computer Inc.","485D36":"Verizon","485D60":"Azurewave Technologies Inc.","48605F":"LG Electronics (Mobile Communications)","4860BC":"Apple","4861A3":"Concern Axion JSC",486276:"Huawei Technologies Co. Ltd","4865EE":"IEEE Registration Authority","486B2C":"BBK Educational Electronics Corp. Ltd","486B91":"Fleetwood Group Inc.","486DBB":"Vestel Elektronik San ve Tic. A.?.","486E73":"Pica8, Inc.","486EFB":"Davit System Technology Co. Ltd","486FD2":"StorSimple Inc",487119:"SGB Group Ltd","48746E":"Apple",487604:"Private","487A55":"ALE International","487ADA":"Hangzhou H3C Technologies Co., Limited","487B6B":"Huawei Technologies Co. Ltd","487D2E":"TP-Link Technologies Co. Ltd",488244:"Life Fitness / Div. Of Brunswick","4882F2":"Appel Elektronik GmbH","4883C7":"Sagemcom Broadband SAS","4886E8":"Microsoft Corporation",488803:"ManTechnology Inc.","4888CA":"Motorola (Wuhan) Mobility Technologies Communication Co. Ltd","488AD2":"Shenzhen Mercury Communication Technologies Co. Ltd","488D36":"Arcadyan Corporation","488E42":"DIGALOG GmbH","488EEF":"Huawei Technologies Co. Ltd",489153:"Weinmann Ger?te f?r Medizin GmbH + Co. KG","4891F6":"Shenzhen Reach software technology Co. Ltd","489A42":"Technomate Ltd","489BE2":"SCI Innovations Ltd","489D18":"Flashbay Limited","489D24":"BlackBerry RTS","48A195":"Apple","48A22D":"Shenzhen Huaxuchang Telecom Technology Co. Ltd","48A2B7":"Kodofon JSC","48A380":"Gionee Communication Equipment Co. Ltd","48A6D2":"GJsun Optical Science and Tech Co. Ltd","48A74E":"zte Corporation","48A91C":"Apple","48A9D2":"Wistron Neweb Corporation","48AA5D":"Store Electronic Systems","48AD08":"Huawei Technologies Co. Ltd","48B253":"Marketaxess Corporation","48B5A7":"Glory Horse Industries Ltd","48B620":"ROLI Ltd","48B8DE":"Homewins Technology Co. Ltd","48B977":"PulseOn Oy","48B9C2":"Teletics Inc.","48BA4E":"Hewlett-Packard Company","48BCA6":"ASUNG TECHNO Co. Ltd","48BD3D":"New H3C Technologies Co. Ltd","48BE2D":"Symanitron","48BF6B":"Apple","48BF74":"Baicells Technologies Co. Ltd","48C049":"Broad Telecom SA","48C093":"Xirrus, Inc.","48C1AC":"Plantronics, Inc.","48C58D":"Lear Corporation GmbH","48C663":"GTO Access Systems LLC","48C796":"Samsung Electronics Co. Ltd","48C862":"Simo Wireless,Inc.","48C8B6":"SysTec GmbH","48CB6E":"Cello Electronics (UK) Ltd","48D0CF":"Universal Electronics, Inc.","48D18E":"Metis Communication Co. Ltd","48D224":"Liteon Technology Corporation","48D343":"ARRIS Group, Inc.","48D35D":"Private","48D539":"Huawei Technologies Co. Ltd","48D54C":"Jeda Networks","48D6D5":"Google, Inc.","48D705":"Apple","48D7FF":"BLANKOM Antennentechnik GmbH","48D855":"Telvent","48D8FE":"ClarIDy Solutions, Inc.","48DA96":"Eddy Smart Home Solutions Inc.","48DB50":"Huawei Technologies Co. Ltd","48DCFB":"Nokia Corporation","48DF1C":"Wuhan NEC Fibre Optic Communications Industry Co. Ltd","48DF37":"Hewlett Packard Enterprise","48E1AF":"Vity","48E244":"Hon Hai Precision Ind. Co. Ltd","48E9F1":"Apple","48EA63":"Zhejiang Uniview Technologies Co. Ltd","48EB30":"Eterna Technology, Inc.","48EC5B":"Nokia","48ED80":"daesung eltec","48EE07":"Silver Palm Technologies LLC","48EE0C":"D-Link International","48EE86":"UTStarcom (China) Co. Ltd","48F07B":"Alps Electric Co. Ltd","48F230":"Ubizcore Co. Ltd","48F317":"Private","48F47D":"TechVision Holding Internation Limited","48F7C0":"Technicolor CH USA Inc.","48F7F1":"Nokia","48F8B3":"Cisco-Linksys LLC","48F8E1":"Nokia","48F925":"Maestronic","48F97C":"Fiberhome Telecommunication Technologies Co. Ltd","48FCB6":"Lava International(H.K) Limited","48FCB8":"Woodstream Corporation","48FD8E":"Huawei Technologies Co. Ltd","48FEEA":"Homa B.V.","4C0082":"Cisco Systems Inc.","4C022E":"CMR Korea Co. Ltd","4C0289":"LEX Computech Co. Ltd","4C068A":"Basler Electric Company","4C07C9":"CoMPUTER OfFICE Co. Ltd","4C09B4":"zte Corporation","4C09D4":"Arcadyan Technology Corporation","4C0B3A":"TCT mobile Ltd","4C0BBE":"Microsoft Corporation","4C0DEE":"Jabil Circuit (Shanghai) Ltd","4C0F6E":"Hon Hai Precision Ind. Co. Ltd","4C0FC7":"Earda Electronics Co. Ltd","4C11BF":"Zhejiang Dahua Technology Co. Ltd","4C1365":"Emplus Technologies","4C1480":"Noregon Systems, Inc","4C14A3":"TCL Technoly Electronics (Huizhou) Co. Ltd","4C1694":"shenzhen sibituo Technology Co. Ltd","4C16F1":"zte Corporation","4C16FC":"Juniper Networks","4C17EB":"Sagemcom Broadband SAS","4C189A":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","4C1A3A":"PRIMA Research And Production Enterprise Ltd","4C1A3D":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","4C1A95":"Novakon Co. Ltd","4C1FCC":"Huawei Technologies Co. Ltd","4C21D0":"Sony Mobile Communications AB","4C2258":"Cozybit, Inc.","4C2578":"Nokia Corporation","4C26E7":"Welgate Co. Ltd","4C2C80":"Beijing Skyway Technologies Co. Ltd","4C2C83":"Zhejiang KaNong Network Technology Co. Ltd","4C2F9D":"ICM Controls","4C3089":"Thales Transportation Systems GmbH","4C322D":"Teledata Networks","4C3275":"Apple","4C32D9":"M Rutty Holdings Pty. Ltd","4C334E":"Hightech","4C3488":"Intel Corporation","4C38D5":"Mitac Computing Technology Corporation","4C38D8":"ARRIS Group, Inc.","4C3909":"HPL Electric & Power Private Limited","4C3910":"Newtek Electronics Co. Ltd","4C3B74":"VOGTEC(H.K.) Co. Ltd","4C3C16":"Samsung Electronics Co. Ltd","4C48DA":"Beijing Autelan Technology Co. Ltd","4C49E3":"Xiaomi Communications Co Ltd","4C4B68":"Mobile Device, Inc.","4C4E03":"TCT mobile Ltd","4C4E35":"Cisco Systems Inc.","4C5262":"Fujitsu Technology Solutions GmbH","4C5427":"Linepro Sp. z o.o.","4C5499":"Huawei Technologies Co. Ltd","4C5585":"Hamilton Systems","4C55B8":"Turkcell Teknoloji","4C55CC":"Zentri Pty Ltd","4C57CA":"Apple","4C5DCD":"Oy Finnish Electric Vehicle Technologies Ltd","4C5E0C":"Routerboard.com","4C5FD2":"Alcatel-Lucent","4C60D5":"airPointe Of New Hampshire","4C60DE":"Netgear","4C6255":"Sanmina-SCI System de Mexico S.A. de C.V.","4C63EB":"Application Solutions (Electronics and Vision) Ltd","4C64D9":"Guangdong Leawin Group Co. Ltd","4C65A8":"IEEE Registration Authority","4C6641":"Samsung Electro-Mechanics(Thailand)","4C6E6E":"Comnect Technology Co. Ltd","4C72B9":"Pegatron Corporation","4C7367":"Genius Bytes Software Solutions GmbH","4C73A5":"Kove","4C7403":"BQ","4C7487":"Leader Phone Communication Technology Co. Ltd","4C74BF":"Apple","4C7625":"Dell Inc.","4C774F":"Embedded Wireless Labs","4C776D":"Cisco Systems Inc.","4C7872":"Cav. Uff. Giacomo Cimberio S.p.A.","4C7897":"Arrowhead Alarm Products Ltd","4C79BA":"Intel Corporation","4C7C5F":"Apple","4C7F62":"Nokia Corporation","4C804F":"Armstrong Monitoring Corp","4C8093":"Intel Corporation","4C8120":"Taicang T&W Electronics","4C82CF":"Dish Technologies Corp","4C83DE":"Cisco SPVTG","4C8B30":"Actiontec Electronics, Inc","4C8B55":"Grupo Digicon","4C8BEF":"Huawei Technologies Co. Ltd","4C8D79":"Apple","4C8ECC":"Silkan SA","4C8FA5":"Jastec","4C910C":"Lanix Internacional, S.A. de C.V.","4C9614":"Juniper Networks","4C98EF":"Zeo","4C9E80":"KYOKKO ELECTRIC Co. Ltd","4C9EE4":"Hanyang Navicom Co. Ltd","4C9EFF":"ZyXEL Communications Corp","4CA003":"T-21 Technologies LLC","4CA161":"Rain Bird Corporation","4CA515":"Baikal Electronics JSC","4CA56D":"Samsung Electronics Co. Ltd","4CA74B":"Alcatel Lucent","4CA928":"Insensi","4CAA16":"Azurewave Technologies Inc.","4CAB33":"KST technology","4CABFC":"zte Corporation","4CAC0A":"zte Corporation","4CAE1C":"SaiNXT Technologies LLP","4CAE31":"ShengHai Electronics (Shenzhen) Ltd","4CB008":"Shenzhen Gwelltimes Technology Co. Ltd","4CB0E8":"Beijing RongZhi xinghua technology Co. Ltd","4CB16C":"Huawei Technologies Co. Ltd","4CB199":"Apple","4CB21C":"Maxphotonics Co. Ltd","4CB44A":"NANOWAVE Technologies Inc.","4CB4EA":"HRD (S) PTE. Ltd","4CB76D":"Novi Security","4CB81C":"SAM Electronics GmbH","4CB82C":"Cambridge Mobile Telematics, Inc.","4CB8B5":"Shenzhen YOUHUA Technology Co. Ltd","4CB9C8":"Conet Co. Ltd","4CBAA3":"Bison Electronics Inc.","4CBB58":"Chicony Electronics Co. Ltd","4CBC42":"Shenzhen Hangsheng Electronics Co. Ltd","4CBCA5":"Samsung Electronics Co. Ltd","4CBD8F":"Hangzhou Hikvision Digital Technology Co. Ltd","4CC00A":"vivo Mobile Communication Co. Ltd","4CC206":"Somfy","4CC452":"Shang Hai Tyd. Electon Technology Ltd","4CC602":"Radios, Inc.","4CC681":"Shenzhen Aisat Electronic Co. Ltd","4CC94F":"Nokia","4CCA53":"Skyera, Inc.","4CCBF5":"zte Corporation","4CCC34":"Motorola Solutions Inc.","4CCC6A":"Micro-Star INTL Co. Ltd","4CD08A":"HUMAX Co. Ltd","4CD0CB":"Huawei Technologies Co. Ltd","4CD637":"Qsono Electronics Co. Ltd","4CD7B6":"Helmer Scientific","4CD9C4":"Magneti Marelli Automotive Electronics (Guangzhou) Co. Ltd","4CDD31":"Samsung Electronics Co. Ltd","4CDF3D":"Team Engineers Advance Technologies India PVT Ltd","4CE173":"IEEE Registration Authority","4CE1BB":"Zhuhai HiFocus Technology Co. Ltd","4CE2F1":"sclak srl","4CE676":"Buffalo.Inc","4CE933":"RailComm, LLC","4CEB42":"Intel Corporation","4CECEF":"Soraa, Inc.","4CEDDE":"Askey Computer Corp","4CEEB0":"SHC Netzwerktechnik GmbH","4CEFC0":"Amazon Technologies Inc.","4CF02E":"Vifa Denmark A/S","4CF2BF":"Cambridge Industries(Group) Co. Ltd","4CF45B":"Blue Clover Devices","4CF5A0":"Scalable Network Technologies Inc","4CF737":"SamJi Electronics Co. Ltd","4CF95D":"Huawei Technologies Co. Ltd","4CFACA":"Cambridge Industries(Group) Co. Ltd","4CFB45":"Huawei Technologies Co. Ltd","4CFF12":"Fuze Entertainment Co. Ltd","50008C":"Hong Kong Telecommunications (HKT) Limited","50016B":"Huawei Technologies Co. Ltd","5001BB":"Samsung Electronics Co. Ltd","5001D9":"Huawei Technologies Co. Ltd","5004B8":"Huawei Technologies Co. Ltd","50053D":"CyWee Group Ltd",500604:"Cisco Systems Inc.","5006AB":"Cisco Systems Inc.",500959:"Technicolor CH USA Inc.","500B32":"Foxda Technology Industrial(ShenZhen)Co. Ltd","500B91":"IEEE Registration Authority","500E6D":"TrafficCast International","500F80":"Cisco Systems Inc.","500FF5":"Tenda Technology Co. LtdDongguan branch","5011EB":"SilverNet Ltd",501479:"iRobot Corporation","5014B5":"Richfit Information Technology Co. Ltd","5017FF":"Cisco Systems Inc.","50184C":"Platina Systems Inc.","501AA5":"GN Netcom A/S","501AC5":"Microsoft Corporation","501CB0":"Cisco Systems Inc.","501CBF":"Cisco Systems Inc.","501D93":"Huawei Technologies Co. Ltd","501E2D":"StreamUnlimited Engineering GmbH","50206B":"Emerson Climate Technologies Transportation Solutions",502267:"PixeLINK","50252B":"Nethra Imaging Incorporated",502690:"Fujitsu Limited","5027C7":"TECHNART Co. Ltd","50294D":"Nanjing IOT Sensor Technology Co Ltd","502A7E":"Smart electronic GmbH","502A8B":"Telekom Research and Development Sdn Bhd","502B73":"Tenda Technology Co. LtdDongguan branch","502D1D":"Nokia Corporation","502DA2":"Intel Corporation","502DF4":"Phytec Messtechnik GmbH","502E5C":"HTC Corporation","502ECE":"Asahi Electronics Co. Ltd","5031AD":"ABB Global Industries and Services Private Limited",503237:"Apple",503275:"Samsung Electronics Co. Ltd","50338B":"Texas Instruments","5033F0":"Yichen (Shenzhen) Technology Co.Ltd",503955:"Cisco SPVTG","503A7D":"AlphaTech PLC Int'l Co. Ltd","503AA0":"Shenzhen Mercury Communication Technologies Co. Ltd","503CC4":"Lenovo Mobile Communication Technology Ltd","503CEA":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","503DA1":"Samsung Electronics Co. Ltd","503DE5":"Cisco Systems Inc.","503EAA":"TP-Link Technologies Co. Ltd","503F56":"Syncmold Enterprise Corp","503F98":"Cmitech",504061:"Nokia","5045F7":"Liuhe Intelligence Technology Ltd","50465D":"ASUSTek Computer Inc.","5048EB":"Beijing Haihejinsheng Network Technology Co. Ltd","504A5E":"Masimo Corporation","504A6E":"Netgear","504B5B":"CoNTROLtronic GmbH","504EDC":"Ping Communication","504F94":"Loxone Electronics GmbH","50502A":"Egardia",505065:"TAKT Corporation","5050CE":"Hangzhou Dianyixia Communication Technology Co. Ltd","5052D2":"Hangzhou Telin Technologies Co., Limited",505527:"LG Electronics (Mobile Communications)",505663:"Texas Instruments","5056A8":"Jolla Ltd","5056BF":"Samsung Electronics Co. Ltd","5057A8":"Cisco Systems Inc.",505800:"WyTec International, Inc.","50584F":"waytotec,Inc.","505AC6":"Guangdong Super Telecom Co. Ltd","505DAC":"Huawei Technologies Co. Ltd",506028:"Xirrus Inc.",506184:"Avaya Inc","5061D6":"Indu-Sol GmbH",506313:"Hon Hai Precision Ind. Co. Ltd","50642B":"XIAOMI Electronics,Co. Ltd",506441:"Greenlee",506583:"Texas Instruments","5065F3":"Hewlett-Packard Company",506787:"Planet Networks","5067AE":"Cisco Systems Inc.","5067F0":"ZyXEL Communications Corp","50680A":"Huawei Technologies Co. Ltd","506A03":"Netgear","506B4B":"Mellanox Technologies, Inc.","506B8D":"Nutanix","506CBE":"InnosiliconTechnology Ltd","506E92":"Innocent Technology Co. Ltd","506F77":"Huawei Technologies Co. Ltd","506F98":"Sehaj Synergy Technologies Private Limited","506F9A":"Wi-Fi Alliance","5070E5":"He Shan World Fair Electronics Technology Limited",507224:"Texas Instruments","50724D":"BEG Brueck Electronic GmbH",507691:"Tekpea, Inc.","5076A6":"Ecil Informatica Ind. Com. Ltda",507705:"Samsung Electronics Co. Ltd","50795B":"Interexport Telecomunicaciones S.A.","507A55":"Apple","507B9D":"LCFC(HeFei) Electronics Technology Co. Ltd","507D02":"Biodit","507E5D":"Arcadyan Technology Corporation","5082D5":"Apple",508569:"Samsung Electronics Co. Ltd",508789:"Cisco Systems Inc.","5087B8":"Nuvyyo Inc",508965:"Shenzhen Mercury Communication Technologies Co. Ltd","508A0F":"Shenzhen Fise Technology Holding Co. Ltd","508A42":"Uptmate Technology Co. Ltd","508ACB":"Shenzhen Maxmade Technology Co. Ltd","508C77":"DIRMEIER Schanktechnik GmbH &Co KG","508CB1":"Texas Instruments","508D6F":"CHAHOO Limited","508F4C":"Xiaomi Communications Co Ltd","5092B9":"Samsung Electronics Co. Ltd","50934F":"Gradual Tecnologia Ltda.",509551:"ARRIS Group, Inc.",509772:"Westinghouse Digital",509871:"Inventum Technologies Private Limited","5098F3":"Rheem Australia Pty Ltd","509A4C":"Dell Inc.","509EA7":"Samsung Electronics Co. Ltd","509F27":"Huawei Technologies Co. Ltd","509F3B":"OI Electric Co. Ltd","50A009":"Xiaomi Communications Co Ltd","50A054":"Actineon","50A0BF":"Alba Fiber Systems Inc.","50A4C8":"Samsung Electronics Co. Ltd","50A4D0":"IEEE Registration Authority","50A67F":"Apple","50A6E3":"David Clark Company","50A715":"Aboundi, Inc.","50A72B":"Huawei Technologies Co. Ltd","50A733":"Ruckus Wireless","50A83A":"S Mobile Devices Limited","50A9DE":"Smartcom - Bulgaria AD","50AB3E":"Qibixx AG","50ABBF":"Hoseo Telecom","50ADD5":"Dynalec Corporation","50AF73":"Shenzhen Bitland Information Technology Co. Ltd","50B363":"Digitron da Amazonia S/A","50B695":"Micropoint Biotechnologies,Inc.","50B7C3":"Samsung Electronics Co. Ltd","50B888":"wi2be Tecnologia S/A","50B8A2":"ImTech Technologies LLC,","50BC96":"Apple","50BD5F":"TP-Link Technologies Co. Ltd","50C006":"Carmanah Signs","50C271":"Securetech Inc","50C58D":"Juniper Networks","50C7BF":"TP-Link Technologies Co. Ltd","50C8E5":"Samsung Electronics Co. Ltd","50C971":"GN Netcom A/S","50C9A0":"Skipper AS","50CCF8":"Samsung Electro Mechanics Co. Ltd","50CD22":"Avaya Inc","50CD32":"NanJing Chaoran Science & Technology Co. Ltd","50CE75":"Measy Electronics Co. Ltd","50D213":"CviLux Corporation","50D274":"Steffes Corporation","50D37F":"Yu Fly Mikly Way Science and Technology Co. Ltd","50D59C":"Thai Habel Industrial Co. Ltd","50D6D7":"Takahata Precision","50D753":"CoNELCOM GmbH","50DA00":"Hangzhou H3C Technologies Co., Limited","50DCE7":"Amazon Technologies Inc.","50DD4F":"Automation Components, Inc","50DF95":"Lytx","50E0C7":"TurControlSystme AG","50E14A":"Private","50E549":"Giga-Byte Technology Co. Ltd","50E666":"Shenzhen Techtion Electronics Co. Ltd","50E971":"Jibo, Inc.","50EAD6":"Apple","50EB1A":"Brocade Communications Systems, Inc.","50ED78":"Changzhou Yongse Infotech Co. Ltd","50ED94":"Egatel SL","50F003":"Open Stack, Inc.","50F0D3":"Samsung Electronics Co. Ltd","50F14A":"Texas Instruments","50F43C":"Leeo Inc","50F520":"Samsung Electronics Co. Ltd","50F5DA":"Amazon Technologies Inc.","50F61A":"Kunshan JADE Technologies Co. Ltd","50F722":"Cisco Systems Inc.","50FA84":"TP-Link Technologies Co. Ltd","50FAAB":"L-tek d.o.o.","50FC30":"Treehouse Labs","50FC9F":"Samsung Electronics Co. Ltd","50FEF2":"Sify Technologies Ltd","50FF20":"Keenetic Limited","50FF99":"IEEE Registration Authority",540237:"Teltronic AG",540384:"Hangkong Nano IC Technologies Co. Ltd","5403F5":"EBN Technology Corp.",540496:"Gigawave Ltd","5404A6":"ASUSTek Computer Inc.",540536:"Vivago Oy","54055F":"Alcatel Lucent",540593:"WOORI ELEC Co. Ltd",540955:"zte Corporation","54098D":"deister electronic GmbH","5410EC":"Microchip Technology Inc.","54112F":"Sulzer Pump Solutions Finland Oy","54115F":"Atamo Pty Ltd",541379:"Hon Hai Precision Ind. Co. Ltd",541473:"Wingtech Group (HongKong)Limited","5414FD":"Orbbec 3D Technology International","5419C8":"vivo Mobile Communication Co. Ltd","541B5D":"Techno-Innov","541DFB":"Freestyle Energy Ltd","541E56":"Juniper Networks","541FD5":"Advantage Electronics",542018:"Tely Labs",542160:"Resolution Products","5422F8":"zte Corporation","5425EA":"Huawei Technologies Co. Ltd",542696:"Apple","54271E":"Azurewave Technologies Inc.",542758:"Motorola (Wuhan) Mobility Technologies Communication Co. Ltd","54276C":"Jiangsu Houge Technology Corp.","542A9C":"LSY Defense, LLC.","542AA2":"Alpha Networks Inc.","542B57":"Night Owl SP","542CEA":"Protectron","542F89":"Euclid Laboratories, Inc.","542F8A":"Tellescom Industria E Comercio EM Telecomunicacao",543131:"Raster Vision Ltd","5433CB":"Apple",543530:"Hon Hai Precision Ind. Co. Ltd","5435DF":"Symeo GmbH","54369B":"1Verge Internet Technology (Beijing) Co. Ltd",543968:"Edgewater Networks Inc","5439DF":"Huawei Technologies Co. Ltd","543B30":"duagon AG","543D37":"Ruckus Wireless","543E64":"Fiberhome Telecommunication Technologies Co. Ltd","5440AD":"Samsung Electronics Co. Ltd",544249:"Sony Corporation",544408:"Nokia Corporation","54466B":"Shenzhen CZTIC Electronic Technology Co. Ltd","54489C":"Cdoubles Electronics Co. Ltd","544A00":"Cisco Systems Inc.","544A05":"wenglor sensoric GmbH","544A16":"Texas Instruments","544B8C":"Juniper Networks","544E45":"Private","544E90":"Apple","54511B":"Huawei Technologies Co. Ltd",545146:"AMG Systems Ltd","5453ED":"Sony Corporation",545414:"Digital RF Corea, Inc","5454CF":"Probedigital Co. Ltd","545AA6":"Espressif Inc.","545EBD":"NL Technologies","545FA9":"Teracom Limited",546009:"Google, Inc.",546172:"Zodiac Aerospace SAS","5461EA":"Zaplox AB","5464D9":"Sagemcom Broadband SAS","5465DE":"ARRIS Group, Inc.","54666C":"Shenzhen YOUHUA Technology Co. Ltd",546751:"Compal Broadband Networks, Inc.","546C0E":"Texas Instruments","546D52":"Topview Optronics Corp.","54724F":"Apple",547398:"Toyo Electronics Corporation","5474E6":"Webtech Wireless",547595:"TP-Link Technologies Co. Ltd","5475D0":"Cisco Systems Inc.","54781A":"Cisco Systems Inc.",547975:"Nokia Corporation","547A52":"CTE International srl","547C69":"Cisco Systems Inc.","547DCD":"Texas Instruments","547F54":"Ingenico","547FA8":"TELCO Systems, s.r.o.","547FEE":"Cisco Systems Inc.","5481AD":"Eagle Research Corporation","54847B":"Digital Devices GmbH","54880E":"Samsung Electro-Mechanics(Thailand)",548922:"Zelfy Inc",548998:"Huawei Technologies Co. Ltd","548CA0":"Liteon Technology Corporation","5492BE":"Samsung Electronics Co. Ltd",549359:"Shenzhen Twowing Technologies Co. Ltd",549478:"Silvershore Technology Partners",549963:"Apple","549A11":"IEEE Registration Authority","549A16":"Uzushio Electric Co. Ltd","549A4C":"Guangdong Homecare Technology Co. Ltd","549B12":"Samsung Electronics Co. Ltd","549D85":"EnerAccess Inc","549F13":"Apple","549F35":"Dell Inc.","54A04F":"t-mac Technologies Ltd","54A050":"ASUSTek Computer Inc.","54A274":"Cisco Systems Inc.","54A31B":"Shenzhen Linkworld Technology Co,.Ltd","54A3FA":"BQT Solutions (Australia)Pty Ltd","54A51B":"Huawei Technologies Co. Ltd","54A54B":"NSC Communications Siberia Ltd","54A619":"Alcatel-Lucent Shanghai Bell Co. Ltd","54A65C":"Technicolor CH USA Inc.","54A9D4":"Minibar Systems","54AB3A":"Quanta Computer Inc.","54AE27":"Apple","54B121":"Huawei Technologies Co. Ltd","54B56C":"Xi'an NovaStar Tech Co. Ltd","54B620":"SUHDOL E&C Co.Ltd","54B753":"Hunan Fenghui Yinjia Science And Technology Co. Ltd","54B7E5":"Rayson Technology Co. Ltd","54B802":"Samsung Electronics Co. Ltd","54B80A":"D-Link International","54BD79":"Samsung Electronics Co. Ltd","54BE53":"zte Corporation","54BEF7":"Pegatron Corporation","54C415":"Hangzhou Hikvision Digital Technology Co. Ltd","54C57A":"Sunnovo International Limited","54C80F":"TP-Link Technologies Co. Ltd","54C9DF":"FN-Link Technology Limited","54CD10":"Panasonic Mobile Communications Co. Ltd","54CDA7":"Fujian Shenzhou Electronic Co. Ltd","54CDEE":"ShenZhen Apexis Electronic Co. Ltd","54D0B4":"Xiamen Four-Faith Communication Technology Co. Ltd","54D0ED":"AXIM Communications","54D163":"MAX-Tech,Inc","54D1B0":"Universal Laser Systems, Inc","54D272":"Nuki Home Solutions GmbH","54D46F":"Cisco SPVTG","54D751":"Proximus","54D9E4":"Brilliantts Co. Ltd","54DC1D":"Yulong Computer Telecommunication Scientific (Shenzhen) Co. Ltd","54DF00":"Ulterius Technologies, LLC","54DF24":"Fiberhome Telecommunication Technologies Co. Ltd","54DF63":"Intrakey technologies GmbH","54E032":"Juniper Networks","54E061":"Sichuan Tianyi Comheart Telecomco. Ltd","54E140":"Ingenico","54E1AD":"LCFC(HeFei) Electronics Technology Co. Ltd","54E2C8":"Dongguan Aoyuan Electronics Technology Co. Ltd","54E2E0":"ARRIS Group, Inc.","54E3B0":"JVL Industri Elektronik","54E3F6":"Alcatel-Lucent","54E43A":"Apple","54E4BD":"FN-Link Technology Limited","54E63F":"ShenZhen LingKeWeiEr Technology Co. Ltd","54E6FC":"TP-Link Technologies Co. Ltd","54EAA8":"Apple","54EDA3":"Navdy, Inc.","54EE75":"Wistron InfoComm(Kunshan)Co. Ltd","54EF92":"Shenzhen Elink Technology Co. Ltd","54EFFE":"Fullpower Technologies, Inc.","54F201":"Samsung Electronics Co. Ltd","54F5B6":"Oriental Pacific International Limited","54F666":"Berthold Technologies GmbH and Co.KG","54F6C5":"Fujian Star-NET Communication Co. Ltd","54F876":"ABB AG","54FA3E":"Samsung Electronics Co. Ltd","54FA96":"Nokia","54FB58":"WISEWARE, Lda","54FCF0":"Samsung Electronics Co. Ltd","54FDBF":"Scheidt & Bachmann GmbH","54FF82":"Davit Solution Co.","54FFCF":"Mopria Alliance","5800BB":"Juniper Networks","5800E3":"Liteon Technology Corporation",580454:"Icomm HK Limited","5804CB":"Tianjin Huisun Technology Co. Ltd",580528:"Labris Networks",580556:"Elettronica GF S.r.L.","5808FA":"Fiber Optic & telecommunication Inc.",580943:"Private","5809E5":"Kivic Inc.","580A20":"Cisco Systems Inc.","58108C":"Intelbras",581243:"AcSiP Technology Corp.",581626:"Avaya Inc","58170C":"Sony Mobile Communications AB","5819F8":"ARRIS Group, Inc.","581CBD":"Affinegy","581D91":"Advanced Mobile Telecom Co. Ltd","581F28":"Huawei Technologies Co. Ltd","581F67":"Open-m technology limited","581FAA":"Apple","581FEF":"Tuttnaer Ltd","5820B1":"Hewlett-Packard Company",582136:"KMB Systems, s.r.o.","5821E9":"Twpi","58238C":"Technicolor CH USA Inc.","582AF7":"Huawei Technologies Co. Ltd","582BDB":"Pax AB","582EFE":"Lighting Science Group","582F42":"Universal Electric Corporation",583112:"Drust",583277:"Reliance Communications LLC","58343B":"Glovast Technology Ltd","5835D9":"Cisco Systems Inc.",583879:"Ricoh Company Ltd","583BD9":"Fiberhome Telecommunication Technologies Co. Ltd","583CC6":"Omneality Ltd","583F54":"LG Electronics (Mobile Communications)","58404E":"Apple","5842E4":"Baxter International Inc",584498:"Xiaomi Communications Co Ltd","58468F":"Koncar Electronics and Informatics","5846E1":"Baxter International Inc",584704:"Shenzhen Webridge Technology Co. Ltd",584822:"Sony Mobile Communications AB","5848C0":"Coflec",584925:"E3 Enterprise","58493B":"Palo Alto Networks","5849BA":"Chitai Electronic Corp.","584C19":"Chongqing Guohong Technology Development Company Limited","584CEE":"Digital One Technologies, Limited",585076:"Linear Equipamentos Eletronicos SA","5850AB":"TLS Corporation","5850E6":"Best Buy Corporation","58528A":"Mitsubishi Electric Corporation","5853C0":"Beijing Guang Runtong Technology Development Company Co. Ltd","5855CA":"Apple","5856E8":"ARRIS Group, Inc.","58570D":"Danfoss Solar Inverters","58605F":"Huawei Technologies Co. Ltd",586163:"Quantum Networks (SG) Pte. Ltd",586356:"FN-Link Technology Limited","58639A":"TPL Systemes","5865E6":"Infomark Co. Ltd","5866BA":"Hangzhou H3C Technologies Co., Limited","58671A":"Barnes&Noble","58677F":"Clare Controls Inc.","58685D":"Tempo Australia Pty Ltd","58696C":"Ruijie Networks Co. Ltd","5869F9":"Fusion Transactive Ltd","586AB1":"Hangzhou H3C Technologies Co., Limited","586D8F":"Cisco-Linksys LLC","586ED6":"Private","5870C6":"Shanghai Xiaoyi Technology Co. Ltd",587521:"CJSC RTSoft",587675:"Beijing ECHO Technologies Co. Ltd","5876C5":"Digi I'S Ltd","587A4D":"Stonesoft Corporation","587A62":"Texas Instruments","587A6A":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","587BE9":"AirPro Technology India Pvt. Ltd","587E61":"Qingdao Hisense Communications Co. Ltd","587F57":"Apple","587F66":"Huawei Technologies Co. Ltd","587FB7":"Sonar Industrial Co. Ltd","587FC8":"S2M","58821D":"H. Schom?cker GmbH","5882A8":"Microsoft Corporation","5884E4":"IP500 Alliance e.V.","58856E":"QSC AG","58874C":"Lite-ON Clean Energy Technology Corp.","5887E2":"Shenzhen Coship Electronics Co. Ltd","588A5A":"Dell Inc.","588BF3":"ZyXEL Communications Corp","588D09":"Cisco Systems Inc.","588D64":"Xi'an Clevbee Technology Co. Ltd",589043:"Sagemcom Broadband SAS","5891CF":"Intel Corporation","58920D":"Kinetic Avionics Limited",589396:"Ruckus Wireless","58946B":"Intel Corporation","5894CF":"Vertex Standard LMR, Inc.","58971E":"Cisco Systems Inc.","5897BD":"Cisco Systems Inc.",589835:"Technicolor","58986F":"Revolution Display","589B0B":"Shineway Technologies, Inc.","589CFC":"FreeBSD Foundation","58A0CB":"TrackNet, Inc","58A2B5":"LG Electronics (Mobile Communications)","58A76F":"iD Corporation","58A839":"Intel Corporation","58AC78":"Cisco Systems Inc.","58B035":"Apple","58B0D4":"ZuniData Systems Inc.","58B3FC":"Shenzhen RF-Link Technology Co. Ltd","58B42D":"YSTen Technology Co. Ltd","58B633":"Ruckus Wireless","58B961":"SOLEM Electronique","58B9E1":"Crystalfontz America, Inc.","58BAD4":"Huawei Technologies Co. Ltd","58BC27":"Cisco Systems Inc.","58BC8F":"Cognitive Systems Corp.","58BDA3":"Nintendo Co. Ltd","58BDF9":"Sigrand","58BFEA":"Cisco Systems Inc.","58C17A":"Cambium Networks Limited","58C232":"NEC Corporation","58C38B":"Samsung Electronics Co. Ltd","58C583":"Itel Mobile Limited","58C5CB":"Samsung Electronics Co. Ltd","58C935":"Chiun Mai Communication Systems, Inc","58CF4B":"Lufkin Industries","58D071":"BW Broadcast","58D08F":"IEEE 1904.1 Working Group","58D67A":"TCPlink","58D6D3":"Dairy Cheq Inc","58D759":"Huawei Technologies Co. Ltd","58D9D5":"Tenda Technology Co. LtdDongguan branch","58DB15":"Tecno Mobile Limited","58DB8D":"Fast Co. Ltd","58DC6D":"Exceptional Innovation, Inc.","58E02C":"Micro Technic A/S","58E16C":"Ying Hua Information Technology (Shanghai)Co. Ltd","58E28F":"Apple","58E326":"Compass Technologies Inc.","58E476":"Centron Communications Technologies Fujian Co. Ltd","58E636":"EVRsafe Technologies","58E747":"Deltanet AG","58E808":"Autonics Corporation","58E876":"IEEE Registration Authority","58EB14":"Proteus Digital Health","58ECE1":"Newport Corporation","58EECE":"Icon Time Systems","58EF68":"Belkin International Inc.","58F102":"BLU Products Inc.","58F387":"Hccp","58F39C":"Cisco Systems Inc.","58F496":"Source Chain","58F67B":"Xia Men UnionCore Technology Ltd","58F6BF":"Kyoto University","58F987":"Huawei Technologies Co. Ltd","58F98E":"SECUDOS GmbH","58FB84":"Intel Corporation","58FC73":"Arria Live Media, Inc.","58FCDB":"IEEE Registration Authority","58FD20":"Bravida Sakerhet AB","5C0038":"Viasat Group S.p.A.","5C026A":"Applied Vision Corporation","5C0339":"Huawei Technologies Co. Ltd","5C076F":"Thought Creator","5C0947":"Apple","5C0979":"Huawei Technologies Co. Ltd","5C0A5B":"Samsung Electro Mechanics Co. Ltd","5C0C0E":"Guizhou Huaxintong Semiconductor Technology Co Ltd","5C0CBB":"CELIZION Inc.","5C0E8B":"Extreme Networks, Inc.","5C1193":"Seal One AG","5C1437":"Thyssenkrupp Aufzugswerke GmbH","5C1515":"Advan","5C15E1":"Aidc Technology (S) PTE Ltd","5C16C7":"Big Switch Networks","5C1737":"I-View Now, LLC.","5C17D3":"LGE","5C18B5":"Talon Communications","5C1A6F":"Cambridge Industries(Group) Co. Ltd","5C1DD9":"Apple","5C20D0":"Asoni Communication Co. Ltd","5C22C4":"DAE EUN Electronics Co. Ltd","5C2443":"O-Sung Telecom Co. Ltd","5C2479":"Baltech AG","5C254C":"Avire Global Pte Ltd","5C260A":"Dell Inc.","5C2AEF":"Open Access Pty Ltd","5C2BF5":"Vivint Wireless Inc.","5C2E59":"Samsung Electronics Co. Ltd","5C2ED2":"ABC(XiSheng) Electronics Co. Ltd","5C313E":"Texas Instruments","5C3327":"Spazio Italia srl","5C335C":"Swissphone Telecom AG","5C338E":"Alpha Networks Inc.","5C353B":"Compal Broadband Networks, Inc.","5C35DA":"There Corporation Oy","5C36B8":"TCL King Electrical Appliances (Huizhou) Co. Ltd","5C38E0":"Shanghai Super Electronics Technology Co. Ltd","5C3B35":"Gehirn Inc.","5C3C27":"Samsung Electronics Co. Ltd","5C4058":"Jefferson Audio Video Systems, Inc.","5C41E7":"Wiatec International Ltd","5C43D2":"Hazemeyer","5C4527":"Juniper Networks","5C4979":"AVM Audiovisuelles Marketing und Computersysteme GmbH","5C497D":"Samsung Electronics Co. Ltd","5C4A1F":"Sichuan Tianyi Comheart Telecomco. Ltd","5C4A26":"Enguity Technology Corp","5C4CA9":"Huawei Technologies Co. Ltd","5C5015":"Cisco Systems Inc.","5C514F":"Intel Corporation","5C5181":"Samsung Electronics Co. Ltd","5C5188":"Motorola Mobility LLC, a Lenovo Company","5C521E":"Nintendo Co. Ltd","5C546D":"Huawei Technologies Co. Ltd","5C56ED":"3pleplay Electronics Private Limited","5C571A":"ARRIS Group, Inc.","5C57C8":"Nokia Corporation","5C5819":"Jingsheng Technology Co. Ltd","5C5948":"Apple","5C5AEA":"Ford","5C5B35":"Mist Systems, Inc.","5C5BC2":"YIK Corporation","5C5EAB":"Juniper Networks","5C5F67":"Intel Corporation","5C63BF":"TP-Link Technologies Co. Ltd","5C6776":"IDS Imaging Development Systems GmbH","5C6984":"Nuvico","5C6A7D":"Kentkart EGE Elektronik SAN. VE TIC. Ltd STI.","5C6A80":"ZyXEL Communications Corp","5C6B32":"Texas Instruments","5C6B4F":"Hello Inc.","5C6D20":"Hon Hai Precision Ind. Co. Ltd","5C6F4F":"S.A. Sistel","5C70A3":"LG Electronics (Mobile Communications)","5C7757":"Haivision Network Video","5C7776":"TCT mobile Ltd","5C7D5E":"Huawei Technologies Co. Ltd","5C81A7":"Network Devices Pty Ltd","5C838F":"Cisco Systems Inc.","5C8486":"Brightsource Industries Israel Ltd","5C8613":"Beijing Zhoenet Technology Co. Ltd","5C864A":"Secret Labs LLC","5C865C":"Samsung Electronics Co. Ltd","5C86C1":"Dongguan Solum Electronics Co. Ltd","5C8778":"Cybertelbridge Co. Ltd","5C899A":"TP-Link Technologies Co. Ltd","5C89D4":"Beijing Banner Electric Co. Ltd","5C8A38":"Hewlett-Packard Company","5C8D2D":"Shanghai Wellpay Information Technology Co. Ltd","5C8D4E":"Apple","5C8FE0":"ARRIS Group, Inc.","5C93A2":"Liteon Technology Corporation","5C95AE":"Apple","5C9656":"Azurewave Technologies Inc.","5C966A":"Rtnet","5C969D":"Apple","5C97F3":"Apple","5C9960":"Samsung Electronics Co. Ltd","5C9AD8":"Fujitsu Limited","5CA176":"Sichuan Tianyi Comheart Telecomco. Ltd","5CA178":"TableTop Media (dba Ziosk)","5CA39D":"Samsung Electro Mechanics Co. Ltd","5CA3EB":"Lokel s.r.o.","5CA48A":"Cisco Systems Inc.","5CA86A":"Huawei Technologies Co. Ltd","5CA933":"Luma Home","5CAAFD":"Sonos, Inc.","5CAC4C":"Hon Hai Precision Ind. Co. Ltd","5CAD76":"Shenzhen TCL New Technology Co. Ltd","5CADCF":"Apple","5CAF06":"LG Electronics (Mobile Communications)","5CB066":"ARRIS Group, Inc.","5CB395":"Huawei Technologies Co. Ltd","5CB43E":"Huawei Technologies Co. Ltd","5CB524":"Sony Mobile Communications AB","5CB559":"CNEX Labs","5CB6CC":"NovaComm Technologies Inc.","5CB8CB":"Allis Communications","5CB901":"Hewlett-Packard Company","5CBA37":"Microsoft Corporation","5CBD9E":"Hongkong Miracle Eagle Technology(Group) Limited","5CC213":"Fr. Sauter AG","5CC307":"Huawei Technologies Co. Ltd","5CC5D4":"Intel Corporation","5CC6D0":"Skyworth Digital Technology(Shenzhen) Co. Ltd","5CC6E9":"Edifier International","5CC7D7":"Azroad Technology Company Limited","5CC9D3":"Palladium Energy Eletronica DA Amazonia Ltda","5CCA1A":"Microsoft Mobile Oy","5CCA32":"Theben AG","5CCCA0":"Gridwiz Inc.","5CCCFF":"Techroutes Network Pvt Ltd","5CCEAD":"CDYNE Corporation","5CCF7F":"Espressif Inc.","5CD135":"Xtreme Power Systems","5CD2E4":"Intel Corporation","5CD41B":"UCZOON Technology Co. Ltd","5CD4AB":"Zektor","5CD61F":"Qardio, Inc","5CD998":"D-Link Corporation","5CDAD4":"Murata Manufacturing Co. Ltd","5CDC96":"Arcadyan Technology Corporation","5CDD70":"Hangzhou H3C Technologies Co., Limited","5CE0C5":"Intel Corporation","5CE0CA":"FeiTian United (Beijing) System Technology Co. Ltd","5CE0F6":"NIC.br- Nucleo de Informacao e Coordenacao do Ponto BR","5CE223":"Delphin Technology AG","5CE286":"Nortel Networks","5CE28C":"ZyXEL Communications Corp","5CE2F4":"AcSiP Technology Corp.","5CE30E":"ARRIS Group, Inc.","5CE3B6":"Fiberhome Telecommunication Technologies Co. Ltd","5CE7BF":"New Singularity International Technical Development Co. Ltd","5CE8B7":"Oraimo Technology Limited","5CE8EB":"Samsung Electronics Co. Ltd","5CEA1D":"Hon Hai Precision Ind. Co. Ltd","5CEB4E":"R. STAHL HMI Systems GmbH","5CEB68":"Cheerstar Technology Co. Ltd","5CEE79":"Global Digitech Co Ltd","5CF207":"Speco Technologies","5CF286":"IEEE Registration Authority","5CF370":"CC&C Technologies, Inc","5CF3FC":"IBM Corp","5CF4AB":"ZyXEL Communications Corp","5CF50D":"Institute Of microelectronic applications","5CF5DA":"Apple","5CF6DC":"Samsung Electronics Co. Ltd","5CF7C3":"Syntech (HK) Technology Limited","5CF7E6":"Apple","5CF821":"Texas Instruments","5CF8A1":"Murata Manufacturing Co. Ltd","5CF938":"Apple","5CF96A":"Huawei Technologies Co. Ltd","5CF9DD":"Dell Inc.","5CF9F0":"Atomos Engineering P/L","5CFC66":"Cisco Systems Inc.","5CFF35":"Wistron Corporation","5CFFFF":"Shenzhen Kezhonglong Optoelectronic Technology Co. Ltd",600194:"Espressif Inc.",600292:"Pegatron Corporation","6002B4":"Wistron Neweb Corporation",600308:"Apple",600347:"Billion Electric Co. Ltd",600417:"Posbank Co. Ltd",600810:"Huawei Technologies Co. Ltd",600837:"ivvi Scientific(Nanchang)Co.Ltd","600B03":"Hangzhou H3C Technologies Co., Limited","600F77":"SilverPlus, Inc",601199:"Siama Systems Inc",601283:"TSB Real Time Location Systems S.L.","60128B":"Canon Inc.",601466:"zte Corporation","6014B3":"CyberTAN Technology Inc.","6015C7":"IdaTech",601803:"Daikin Air-Conditioning (Shanghai) Co. Ltd","60182E":"ShenZhen Protruly Electronic Ltd Co.",601888:"zte Corporation","60190C":"Rramac",601929:"Voltronic Power Technology(Shenzhen) Corp.",601970:"Huizhou Qiaoxing Electronics Technology Co. Ltd",601971:"ARRIS Group, Inc.","601D0F":"Midnite Solar","601E02":"EltexAlatau",602101:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",602103:"I4VINE, Inc","6021C0":"Murata Manufacturing Co. Ltd","6024C1":"Jiangsu Zhongxun Electronic Technology Co. Ltd","60271C":"VIDEOR E. Hartig GmbH","602A54":"CardioTek B.V.","602AD0":"Cisco SPVTG","602E20":"Huawei Technologies Co. Ltd","6030D4":"Apple","60313B":"Sunnovo International Limited",603197:"ZyXEL Communications Corp","6032F0":"Mplus technology","60334B":"Apple",603553:"Buwon Technology",603696:"The Sapling Company","6036DD":"Intel Corporation","60380E":"Alps Electric Co. Ltd","6038E0":"Belkin International Inc.","60391F":"ABB Ltd","603D26":"Technicolor CH USA Inc.","603E7B":"Gafachi, Inc.","603ECA":"Cambridge Medical Robotics Ltd","603FC5":"CoX Co. Ltd","60427F":"Shenzhen Chuangwei-RGB Electronics Co. Ltd","6044F5":"Easy Digital Ltd","60455E":"Liptel s.r.o.","6045BD":"Microsoft Corporation","6045CB":"ASUSTek Computer Inc.",604616:"Xiamen Vann Intelligent Co. Ltd",604762:"Beijing Sensoro Technology Co. Ltd","6047D4":"FORICS Electronic Technology Co. Ltd",604826:"Newbridge Technologies Int. Ltd","6049C1":"Avaya Inc","604A1C":"SUYIN Corporation","604BAA":"Private","6050C1":"Kinetek Sports","60512C":"TCT mobile Ltd","6052D0":"FACTS Engineering",605317:"Sandstone Technologies",605464:"Eyedro Green Solutions Inc.",605718:"Intel Corporation","605BB4":"Azurewave Technologies Inc.","605F8D":"eero Inc.","60601F":"SZ DJI Technology Co. Ltd","6063F9":"Ciholas, Inc.","6063FD":"Transcend Communication Beijing Co. Ltd",606405:"Texas Instruments",606453:"AOD Co. Ltd","6064A1":"RADiflow Ltd",606720:"Intel Corporation",606944:"Apple","60699B":"isepos GmbH","606BBD":"Samsung Electronics Co. Ltd","606BFF":"Nintendo Co. Ltd","606C66":"Intel Corporation","606D3C":"Luxshare Precision Industry Company Limited","606DC7":"Hon Hai Precision Ind. Co. Ltd","60720B":"BLU Products Inc","60735C":"Cisco Systems Inc.","6073BC":"zte Corporation","60748D":"Atmaca Elektronik",607688:"Velodyne","6077E2":"Samsung Electronics Co. Ltd","607EDD":"Microsoft Mobile Oy","60812B":"Custom Control Concepts","6081F9":"Helium Systems, Inc",608334:"Huawei Technologies Co. Ltd","6083B2":"GkWare e.K.","60843B":"Soladigm, Inc.","6084BD":"Buffalo.Inc",608645:"Avery Weigh-Tronix, LLC","60893C":"Thermo Fisher Scientific P.O.A.","6089B1":"Key Digital Systems","6089B7":"Kael M?Hend?SL?K Elektron?K T?Caret Sanay? L?M?TED ??Rket?","608C2B":"Hanson Technology","608CE6":"ARRIS Group, Inc.","608D17":"Sentrus Government Systems Division, Inc","608E08":"Samsung Electronics Co. Ltd","608F5C":"Samsung Electronics Co. Ltd",609084:"DSSD Inc","6091F3":"vivo Mobile Communication Co. Ltd",609217:"Apple",609620:"Private","6097DD":"MicroSys Electronics GmbH",609813:"Shanghai Visking Digital Technology Co. Ltd","6099D1":"Vuzix / Lenovo","609AA4":"GVI Security Inc.","609AC1":"Apple","609BC8":"Hipad Intelligent Technology Co. Ltd","609C9F":"Brocade Communications Systems, Inc.","609E64":"Vivonic GmbH","609F9D":"CloudSwitch","60A10A":"Samsung Electronics Co. Ltd","60A37D":"Apple","60A44C":"ASUSTek Computer Inc.","60A4D0":"Samsung Electronics Co. Ltd","60A8FE":"Nokia","60A9B0":"Merchandising Technologies, Inc","60ACC8":"KunTeng Inc.","60AF6D":"Samsung Electronics Co. Ltd","60B185":"ATH System","60B387":"Synergics Technologies GmbH","60B3C4":"Elber Srl","60B4F7":"Plume Design Inc","60B606":"Phorus","60B617":"Fiberhome Telecommunication Technologies Co. Ltd","60B933":"Deutron Electronics Corp.","60B982":"RO.VE.R. Laboratories S.p.A.","60BA18":"nextLAP GmbH","60BB0C":"Beijing HuaqinWorld Technology Co Ltd","60BC4C":"EWM Hightec Welding GmbH","60BD91":"Move Innovation","60BEB5":"Motorola Mobility LLC, a Lenovo Company","60C0BF":"ON Semiconductor","60C1CB":"Fujian Great Power PLC Equipment Co. Ltd","60C397":"2Wire Inc.","60C547":"Apple","60C5A8":"Beijing LT Honway Technology Co. Ltd","60C5AD":"Samsung Electronics Co. Ltd","60C658":"PHYTRONIX Co. Ltd","60C798":"Verifone","60C980":"Trymus","60CBFB":"AirScape Inc.","60CDA9":"Abloomy","60CDC5":"Taiwan Carol Electronics. Ltd","60D0A9":"Samsung Electronics Co. Ltd","60D1AA":"Vishal Telecommunications Pvt Ltd","60D262":"Tzukuri Pty Ltd","60D2B9":"Realand BIO Co. Ltd","60D30A":"Quatius Limited","60D7E3":"IEEE Registration Authority","60D819":"Hon Hai Precision Ind. Co. Ltd","60D9A0":"Lenovo Mobile Communication Technology Ltd","60D9C7":"Apple","60DA23":"Estech Co. Ltd","60DA83":"Hangzhou H3C Technologies Co., Limited","60DB2A":"HNS","60DE44":"Huawei Technologies Co. Ltd","60DEF3":"Huawei Technologies Co. Ltd","60E00E":"Shinsei Electronics Co Ltd","60E327":"TP-Link Technologies Co. Ltd","60E3AC":"LG Electronics (Mobile Communications)","60E6BC":"Sino-Telecom Technology Co. Ltd","60E701":"Huawei Technologies Co. Ltd","60E78A":"Unisem","60E956":"Ayla Networks, Inc","60EB69":"Quanta Computer Inc.","60EE5C":"Shenzhen Fast Technologies Co. Ltd","60EFC6":"Shenzhen Chima Technologies Co Limited","60F13D":"JABLOCOM s.r.o.","60F189":"Murata Manufacturing Co. Ltd","60F281":"Tranwo Technology Co. Ltd","60F2EF":"VisionVera International Co. Ltd","60F3DA":"Logic Way GmbH","60F445":"Apple","60F494":"Hon Hai Precision Ind. Co. Ltd","60F59C":"CRU-Dataport","60F673":"Terumo Corporation","60F677":"Intel Corporation","60F81D":"Apple","60FACD":"Apple","60FB42":"Apple","60FD56":"WOORISYSTEMS Co. Ltd","60FE1E":"China Palms Telecom.Ltd","60FE20":"2Wire Inc.","60FEC5":"Apple","60FEF9":"Thomas & Betts","60FFDD":"C.E. Electronics, Inc","64002D":"Powerlinq Co. Ltd","64006A":"Dell Inc.","6400F1":"Cisco Systems Inc.","6402CB":"ARRIS Group, Inc.","6405BE":"NEW Light LED","6405E9":"Shenzhen WayOS Technology Crop. Ltd","64094C":"Beijing Superbee Wireless Technology Co. Ltd",640980:"Xiaomi Communications Co Ltd","640B4A":"Digital Telecom Technology Limited","640DCE":"Shenzhen Mercury Communication Technologies Co. Ltd","640DE6":"Petra Systems","640E36":"Taztag","640E94":"Pluribus Networks, Inc.","640F28":"2Wire Inc.",641084:"HEXIUM Technical Development Co. Ltd",641225:"Cisco Systems Inc.",641269:"ARRIS Group, Inc.","64136C":"zte Corporation",641666:"Nest Labs Inc.","64167F":"Polycom","64168D":"Cisco Systems Inc.","6416F0":"Huawei Technologies Co. Ltd","641A22":"Heliospectra AB","641C67":"Digibras Industria DO Brasils/A","641CAE":"Samsung Electronics Co. Ltd","641CB0":"Samsung Electronics Co. Ltd","641E81":"Dowslake Microsystems","64200C":"Apple","64209F":"Tilgin AB",642184:"Nippon Denki Kagaku Co. Ltd",642216:"Shandong Taixin Electronic Co. Ltd",642400:"Xorcom Ltd",642737:"Hon Hai Precision Ind. Co. Ltd","642B8A":"ALL BEST Industrial Co. Ltd","642DB7":"Seungil Electronics",643150:"Hewlett-Packard Company","64317E":"Dexin Corporation","6432A8":"Intel Corporation",643409:"BITwave Pte Ltd","64351C":"e-CoN SysTEMS IndIA PVT Ltd","643AB1":"Sichuan Tianyi Comheart Telecomco. Ltd","643E8C":"Huawei Technologies Co. Ltd","643F5F":"Exablaze",644214:"Swisscom Energy Solutions AG",644346:"GuangDong Quick Network Computer Co. Ltd","6447E0":"Feitian Technologies Co. Ltd","644BC3":"Shanghai WOASiS Telecommunications Ltd, Co.","644BF0":"CalDigit, Inc","644D70":"dSPACE GmbH","644F74":"LENUS Co. Ltd","644FB0":"Hyunjin.com",645106:"Hewlett-Packard Company","64517E":"Long BEN (Dongguan) Electronic Technology Co. Ltd",645299:"The Chamberlain Group, Inc","64535D":"Frauscher Sensortechnik",645422:"Equinox Payments",645563:"Intelight Inc.","64557F":"NSFOCUS Information Technology Co. Ltd","6455B1":"ARRIS Group, Inc.",645601:"TP-Link Technologies Co. Ltd","6459F8":"Vodafone Omnitel B.V.","645A04":"Chicony Electronics Co. Ltd","645AED":"Apple","645D92":"Sichuan Tianyi Comheart Telecomco. Ltd","645DD7":"Shenzhen Lifesense Medical Electronics Co. Ltd","645EBE":"Yahoo! JAPAN","645FFF":"Nicolet Neuro",646184:"Velux",646223:"Cellient Co. Ltd","64649B":"Juniper Networks","6465C0":"Nuvon, Inc","6466B3":"TP-Link Technologies Co. Ltd",646707:"Beijing Omnific Technology Ltd","64680C":"Comtrend Corporation","6469BC":"Hytera Communications Co . Ltd","646A52":"Avaya Inc","646A74":"Auth-Servers, LLC","646CB2":"Samsung Electronics Co. Ltd","646E69":"Liteon Technology Corporation","646E6C":"Radio Datacom LLC","646EEA":"Iskratel d.o.o.",647002:"TP-Link Technologies Co. Ltd",647033:"Apple","6472D8":"GooWi Technology Co.,Limited","6473E2":"Arbiter Systems, Inc.","6474F6":"Shooter Detection Systems",647657:"Innovative Security Designs","6476BA":"Apple","64777D":"Hitron Technologies. Inc",647791:"Samsung Electronics Co. Ltd","6479A7":"Phison Electronics Corp.","647BD4":"Texas Instruments","647C34":"Ubee Interactive Co., Limited","647D81":"Yokota Industrial Co,.Ltd","647FDA":"TEKTELIC Communications Inc.","64808B":"VG Controls, Inc.",648099:"Intel Corporation",648125:"Alphatron Marine BV",648788:"Juniper Networks","6487D7":"ADB Broadband Italia","6488FF":"Sichuan Changhong Electric Ltd","64899A":"LG Electronics (Mobile Communications)","648D9E":"IVT Electronic Co. Ltd",649829:"Integrated Device Technology (Malaysia) Sdn. Bhd.","64995D":"LGE",649968:"Elentec","6499A0":"AG Elektronik AB","649A08":"Shenzhen SuperElectron Technology Co. Ltd","649A12":"P2 Mobile Technologies Limited","649ABE":"Apple","649B24":"V Technology Co. Ltd","649C81":"Qualcomm Inc.","649C8E":"Texas Instruments","649EF3":"Cisco Systems Inc.","649FF7":"Kone Oyj","64A0E7":"Cisco Systems Inc.","64A232":"OOO Samlight","64A341":"Wonderlan (Beijing) Technology Co. Ltd","64A3CB":"Apple","64A5C3":"Apple","64A651":"Huawei Technologies Co. Ltd","64A68F":"Zhongshan Readboy Electronics Co. Ltd","64A769":"HTC Corporation","64A7DD":"Avaya Inc","64A837":"Juni Korea Co. Ltd","64AE0C":"Cisco Systems Inc.","64AE88":"Polytec GmbH","64B0A6":"Apple","64B21D":"Chengdu Phycom Tech Co. Ltd","64B310":"Samsung Electronics Co. Ltd","64B370":"PowerComm Solutions LLC","64B473":"Xiaomi Communications Co Ltd","64B5C6":"Nintendo Co. Ltd","64B64A":"ViVOtech, Inc.","64B853":"Samsung Electronics Co. Ltd","64B9E8":"Apple","64BABD":"SDJ Technologies, Inc.","64BC0C":"LG Electronics (Mobile Communications)","64BC11":"CombiQ AB","64C354":"Avaya Inc","64C3D6":"Juniper Networks","64C5AA":"South African Broadcasting Corporation","64C667":"Barnes&Noble","64C6AF":"AXERRA Networks Ltd","64C944":"LARK Technologies, Inc","64CB5D":"SIA TeleSet","64CBA3":"Pointmobile","64CC2E":"Xiaomi Communications Co Ltd","64CFD9":"Texas Instruments","64D02D":"Next Generation Integration (NGI)","64D154":"Routerboard.com","64D1A3":"Sitecom Europe BV","64D241":"Keith & Koep GmbH","64D4BD":"Alps Electric Co. Ltd","64D4DA":"Intel Corporation","64D814":"Cisco Systems Inc.","64D912":"Solidica, Inc.","64D954":"Taicang T&W Electronics","64D989":"Cisco Systems Inc.","64DAA0":"Robert Bosch Smart Home GmbH","64DB18":"OpenPattern","64DB43":"Motorola (Wuhan) Mobility Technologies Communication Co. Ltd","64DB81":"Syszone Co. Ltd","64DB8B":"Hangzhou Hikvision Digital Technology Co. Ltd","64DBA0":"Select Comfort","64DC01":"Static Systems Group PLC","64DE1C":"Kingnetic Pte Ltd","64DFE9":"Ateme","64E161":"DEP Corp.","64E599":"EFM Networks","64E625":"Woxu Wireless Co. Ltd","64E682":"Apple","64E84F":"Serialway Communication Technology Co. Ltd","64E892":"Morio Denki Co. Ltd","64E8E6":"global moisture management System","64E950":"Cisco Systems Inc.","64EAC5":"SiboTech Automation Co. Ltd","64EB8C":"Seiko Epson Corporation","64ED57":"ARRIS Group, Inc.","64ED62":"WOORI SysTEMS Co. Ltd","64F242":"Gerdes Aktiengesellschaft","64F50E":"Kinion Technology Company Limited","64F69D":"Cisco Systems Inc.","64F88A":"China Mobile IOT Company Limited","64F970":"Kenade Electronics Technology Co. Ltd","64F987":"Avvasi Inc.","64FB50":"RoomReady/Zdi, Inc.","64FB81":"IEEE Registration Authority","64FC8C":"Zonar Systems",680235:"Konten Networks Inc.",680571:"Samsung Electronics Co. Ltd","6805CA":"Intel Corporation",680715:"Intel Corporation",680927:"Apple","680AD7":"Yancheng Kecheng Optoelectronic Technology Co. Ltd","68122D":"Special Instrument Development Co. Ltd",681295:"Lupine Lighting Systems GmbH",681401:"Hon Hai Precision Ind. Co. Ltd",681590:"Sagemcom Broadband SAS","6815D3":"Zaklady Elektroniki i Mechaniki Precyzyjnej R&G S.A.",681605:"Systems And Electronic Development FZCO",681729:"Intel Corporation","68193F":"Digital Airways","681AB2":"zte Corporation","681CA2":"Rosewill Inc.","681D64":"Sunwave Communications Co. Ltd","681DEF":"Shenzhen CYX Technology Co. Ltd","681E8B":"InfoSight Corporation","681F40":"Blu Wireless Technology Ltd","681FD8":"Siemens Industry, Inc.","68234B":"Nihon Dengyo Kousaku","68262A":"Sichuan Tianyi Comheart Telecomco. Ltd",682737:"Samsung Electronics Co. Ltd","6828BA":"Dejai","6828F6":"Vubiq Networks, Inc.","682C7B":"Cisco Systems Inc.","682DDC":"Wuhan Changjiang Electro-Communication Equipment Co. Ltd","6831FE":"Teladin Co. Ltd",683563:"Shenzhen Liown Electronics Co. Ltd","6836B5":"DriveScale, Inc.","6837E9":"Amazon Technologies Inc.","683B1E":"Countwise Ltd","683C7D":"Magic Intelligence Technology Limited","683E02":"SIEMENS AG, Digital Factory, Motion Control System","683E34":"MEIZU Technology Co. Ltd","683EEC":"Ereca",684352:"Bhuu Limited",684898:"Samsung Electronics Co. Ltd","684B88":"Galtronics Telemetry Inc.","684CA8":"Shenzhen Herotel Tech. Co. Ltd","6851B7":"PowerCloud Systems, Inc.","68536C":"SPnS Co. Ltd",685388:"P&S Technology","6854C1":"ColorTokens, Inc.","6854ED":"Alcatel-Lucent","6854F5":"enLighted Inc","6854FD":"Amazon Technologies Inc.","68572D":"Hangzhou Aixiangji Technology Co. Ltd","6858C5":"ZF TRW Automotive","68597F":"Alcatel Lucent","685ACF":"Samsung Electronics Co. Ltd","685B35":"Apple","685B36":"Powertech Industrial Co. Ltd","685D43":"Intel Corporation","685E6B":"PowerRay Co. Ltd",686359:"Advanced Digital Broadcast SA","68644B":"Apple","68692E":"Zycoo Co. Ltd",686975:"Angler Labs Inc","6869F2":"ComAp s.r.o.","686E23":"Wi3 Inc.","686E48":"Prophet Electronic Technology Corp. Ltd",687251:"Ubiquiti Networks Inc.","6872DC":"CETORY.TV Company Limited","68764F":"Sony Mobile Communications AB",687848:"Westunitis Co. Ltd","68784C":"Nortel Networks",687924:"ELS-GmbH & Co. KG","6879ED":"Sharp Corporation","687CC8":"Measurement Systems S. de R.L.","687CD5":"Y Soft Corporation, a.s.","687F74":"Cisco-Linksys LLC","68831A":"Pandora Mobility Corporation",688470:"eSSys Co. Ltd",688540:"IGI Mobile, Inc.","68856A":"OuterLink Corporation","6886A7":"Cisco Systems Inc.","6886E7":"Orbotix, Inc.","68876B":"INQ Mobile Limited",688975:"nuoxc","6889C1":"Huawei Technologies Co. Ltd","688AB5":"EDP Servicos","688AF0":"zte Corporation","688DB6":"Aetek Inc.","688F84":"Huawei Technologies Co. Ltd","6891D0":"IEEE Registration Authority",689234:"Ruckus Wireless",689361:"Integrated Device Technology (Malaysia) Sdn. Bhd.",689423:"Hon Hai Precision Ind. Co. Ltd","68967B":"Apple","68974B":"Shenzhen Costar Electronics Co. Ltd","6897E8":"Society Of Motion Picture & Television Engineers",689861:"Beacon Inc","6899CD":"Cisco Systems Inc.","689AB7":"Atelier Vision Corporation","689C5E":"AcSiP Technology Corp.","689C70":"Apple","689CE2":"Cisco Systems Inc.","689E19":"Texas Instruments","689FF0":"zte Corporation","68A0F6":"Huawei Technologies Co. Ltd","68A1B7":"Honghao Mingchuan Technology (Beijing) Co. Ltd","68A378":"Freebox SAS","68A3C4":"Liteon Technology Corporation","68A40E":"BSH Hausger?te GmbH","68A682":"Shenzhen YOUHUA Technology Co. Ltd","68A828":"Huawei Technologies Co. Ltd","68A86D":"Apple","68AAD2":"Datecs Ltd,","68AB1E":"Apple","68AB8A":"RF IDeas","68AE20":"Apple","68AF13":"Futura Mobility","68B094":"Inesa Electron Co. Ltd","68B35E":"Shenzhen Neostra Technology Co.Ltd","68B43A":"WaterFurnace International, Inc.","68B599":"Hewlett-Packard Company","68B6FC":"Hitron Technologies. Inc","68B8D9":"Act KDE, Inc.","68B983":"b-plus GmbH","68BC0C":"Cisco Systems Inc.","68BDAB":"Cisco Systems Inc.","68C44D":"Motorola Mobility LLC, a Lenovo Company","68C63A":"Espressif Inc.","68C90B":"Texas Instruments","68CA00":"Octopus Systems Limited","68CAE4":"Cisco Systems Inc.","68CC6E":"Huawei Technologies Co. Ltd","68CC9C":"Mine Site Technologies","68CD0F":"U Tek Company Limited","68CE4E":"L-3 Communications Infrared Products","68D1BA":"Shenzhen YOUHUA Technology Co. Ltd","68D1FD":"Shenzhen Trimax Technology Co. Ltd","68D247":"Portalis LC","68D482":"Shenzhen Gongjin Electronics Co.,LT","68D925":"ProSys Development Services","68D93C":"Apple","68DB54":"Phicomm (Shanghai) Co. Ltd","68DB67":"Nantong Coship Electronics Co. Ltd","68DB96":"OPWILL Technologies Co . Ltd","68DBCA":"Apple","68DCE8":"PacketStorm Communications","68DFDD":"Xiaomi Communications Co Ltd","68E166":"Private","68E41F":"Unglaube Identech GmbH","68E8EB":"Linktel Technologies Co. Ltd","68EBAE":"Samsung Electronics Co. Ltd","68EBC5":"Angstrem Telecom","68EC62":"YODO Technology Corp. Ltd","68ECC5":"Intel Corporation","68ED43":"BlackBerry RTS","68EDA4":"Shenzhen Seavo Technology Co. Ltd","68EE96":"Cisco SPVTG","68EF43":"Apple","68EFBD":"Cisco Systems Inc.","68F06D":"Along Industrial Co., Limited","68F0BC":"Shenzhen LiWiFi Technology Co. Ltd","68F125":"Data Controls Inc.","68F728":"LCFC(HeFei) Electronics Technology Co. Ltd","68F895":"Redflow Limited","68F956":"Objetivos y Servicio de Valor A?adido","68FB7E":"Apple","68FB95":"Generalplus Technology Inc.","68FCB3":"Next Level Security Systems, Inc.","68FEDA":"Fiberhome Telecommunication Technologies Co. Ltd","68FEF7":"Apple","6C0273":"Shenzhen Jin Yun Video Equipment Co. Ltd","6C0460":"RBH Access Technologies Inc.","6C05D5":"Ethertronics Inc","6C090A":"Gematica SRL","6C09D6":"Digiquest Electronics Ltd","6C0B84":"Universal Global Scientific Industrial Co. Ltd","6C0E0D":"Sony Mobile Communications AB","6C0EE6":"Chengdu Xiyida Electronic Technology Co,.Ltd","6C0F6A":"JDC Tech Co. Ltd","6C14F7":"Erhardt+Leimer GmbH","6C15F9":"Nautronix Limited","6C160E":"ShotTracker","6C1811":"Decatur Electronics","6C198F":"D-Link International","6C19C0":"Apple","6C1E70":"Guangzhou YBDS IT Co. Ltd","6C1E90":"Hansol Technics Co. Ltd","6C2056":"Cisco Systems Inc.","6C22AB":"Ainsworth Game Technology","6C23B9":"Sony Mobile Communications AB","6C2483":"Microsoft Mobile Oy","6C25B9":"BBK Educational Electronics Corp. Ltd","6C2779":"Microsoft Mobile Oy","6C2995":"Intel Corporation","6C2ACB":"Paxton Access Ltd","6C2C06":"OOO NPP Systemotechnika-NN","6C2E33":"Accelink Technologies Co. Ltd","6C2E72":"B&B Exporting Limited","6C2E85":"Sagemcom Broadband SAS","6C2F2C":"Samsung Electronics Co. Ltd","6C32DE":"Indieon Technologies Pvt. Ltd","6C33A9":"Magicjack LP","6C3838":"Marking System Technology Co. Ltd","6C38A1":"Ubee Interactive Co., Limited","6C391D":"Beijing ZhongHuaHun Network Information center","6C3A84":"Shenzhen Aero-Startech. Co.Ltd","6C3B6B":"Routerboard.com","6C3BE5":"Hewlett-Packard Company","6C3C53":"SoundHawk Corp","6C3E6D":"Apple","6C3E9C":"KE Knestel Elektronik GmbH","6C4008":"Apple","6C40C6":"Nimbus Data Systems, Inc.","6C416A":"Cisco Systems Inc.","6C4418":"Zappware","6C4598":"Antex Electronic Corp.","6C49C1":"o2ones Co. Ltd","6C4A39":"Bita","6C4B7F":"Vossloh-Schwabe Deutschland GmbH","6C4B90":"LiteON","6C4D73":"Apple","6C4E86":"Third Millennium Systems Ltd","6C504D":"Cisco Systems Inc.","6C54CD":"Lampex Electronics Limited","6C5697":"Amazon Technologies Inc.","6C5779":"Aclima, Inc.","6C5940":"Shenzhen Mercury Communication Technologies Co. Ltd","6C5976":"Shanghai Tricheer Technology Co. Ltd","6C5A34":"Shenzhen Haitianxiong Electronic Co. Ltd","6C5AB5":"TCL Technoly Electronics (Huizhou) Co. Ltd","6C5C14":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","6C5CDE":"SunReports, Inc.","6C5D63":"ShenZhen Rapoo Technology Co. Ltd","6C5E7A":"Ubiquitous Internet Telecom Co. Ltd","6C5F1C":"Lenovo Mobile Communication Technology Ltd","6C60EB":"ZHI Yuan Electronics Co., Limited","6C6126":"Rinicom Holdings","6C626D":"Micro-Star International","6C641A":"Penguin Computing","6C6EFE":"Core Logic Inc.","6C6F18":"Stereotaxis, Inc.","6C7039":"Novar GmbH","6C709F":"Apple","6C71BD":"Ezelink Telecom","6C71D9":"Azurewave Technologies Inc.","6C7220":"D-Link International","6C72E7":"Apple","6C750D":"WiFiSONG","6C7660":"Kyocera Corporation","6C81FE":"Mitsuba Corporation","6C8336":"Samsung Electronics Co. Ltd","6C8366":"Nanjing SAC Power Grid Automation Co. Ltd","6C8686":"Technonia","6C8814":"Intel Corporation","6C8B2F":"zte Corporation","6C8CDB":"Otus Technologies Ltd","6C8D65":"Wireless Glue Networks, Inc.","6C8DC1":"Apple","6C8FB5":"Microsoft Mobile Oy","6C90B1":"SanLogic Inc","6C92BF":"Inspur Electronic Information Industry Co. Ltd","6C9354":"Yaojin Technology (Shenzhen) Co. Ltd","6C94F8":"Apple","6C9522":"Scalys","6C96CF":"Apple","6C98EB":"Riverbed Technology, Inc.","6C9989":"Cisco Systems Inc.","6C9AC9":"Valentine Research, Inc.","6C9B02":"Nokia Corporation","6C9CE9":"Nimble Storage","6C9CED":"Cisco Systems Inc.","6CA100":"Intel Corporation","6CA682":"EDAM Information & Communications","6CA75F":"zte Corporation","6CA780":"Nokia Corporation","6CA7FA":"Youngbo Engineering Inc.","6CA849":"Avaya Inc","6CA858":"Fiberhome Telecommunication Technologies Co. Ltd","6CA906":"Telefield Ltd","6CA96F":"TransPacket AS","6CAAB3":"Ruckus Wireless","6CAB31":"Apple","6CAB4D":"Digital Payment Technologies","6CAC60":"Venetex Corp","6CAD3F":"Hubbell Building Automation, Inc.","6CADEF":"KZ Broadband Technologies Ltd","6CADF8":"Azurewave Technologies Inc.","6CAE8B":"IBM Corporation","6CB0CE":"Netgear","6CB227":"Sony Video & Sound Products Inc.","6CB2AE":"Cisco Systems Inc.","6CB311":"Shenzhen Lianrui Electronics Co. Ltd","6CB350":"Anhui Comhigher tech Co. Ltd","6CB4A7":"Landauer, Inc.","6CB56B":"HUMAX Co. Ltd","6CB6CA":"DivUS GmbH","6CB749":"Huawei Technologies Co. Ltd","6CB7F4":"Samsung Electronics Co. Ltd","6CB9C5":"Delta Networks, Inc.","6CBEE9":"Alcatel-Lucent IPD","6CBFB5":"Noon Technology Co. Ltd","6CC147":"Xiamen Hanin Electronic Technology Co. Ltd","6CC1D2":"ARRIS Group, Inc.","6CC217":"Hewlett-Packard Company","6CC26B":"Apple","6CC4D5":"HMD Global Oy","6CCA08":"ARRIS Group, Inc.","6CD032":"LG Electronics","6CD146":"Smartek d.o.o.","6CD1B0":"Wing Sing Electronics Hong Kong Limited","6CD68A":"LG Electronics (Mobile Communications)","6CDC6A":"Promethean Limited","6CDD30":"Cisco Systems Inc.","6CE01E":"Modcam AB","6CE0B0":"SOUND4","6CE3B6":"Nera Telecommunications Ltd","6CE4CE":"Villiger Security Solutions AG","6CE4DA":"NEC Platforms Ltd","6CE873":"TP-Link Technologies Co. Ltd","6CE907":"Nokia Corporation","6CE983":"Gastron Co. Ltd","6CEBB2":"Dongguan Sen DongLv Electronics Co. Ltd","6CEC5A":"Hon Hai Precision Ind. Co. Ltd","6CECA1":"Shenzhen Clou Electronics Co. Ltd","6CECEB":"Texas Instruments","6CEFC6":"Shenzhen Twowing Technologies Co. Ltd","6CF049":"Giga-Byte Technology Co. Ltd","6CF373":"Samsung Electronics Co. Ltd","6CF37F":"Aruba Networks","6CF5E8":"Mooredoll Inc.","6CF97C":"Nanoptix Inc.","6CF9D2":"Chengdu Goods for the Road Electronic Technology C","6CFA58":"Avaya Inc","6CFA89":"Cisco Systems Inc.","6CFAA7":"AMPAK Technology, Inc.","6CFDB9":"Proware Technologies Co Ltd","6CFFBE":"MPB Communications Inc.",700136:"FATEK Automation Corporation","7001B5":"Cisco Systems Inc.",700258:"01DB-Metravib",700514:"LG Electronics (Mobile Communications)","7006AC":"Eastcompeace Technology Co. Ltd","700BC0":"Dewav Technology Company","700FC7":"Shenzhen Ikinloop Technology Co. Ltd","700FEC":"Poindus Systems Corp.","70105C":"Cisco Systems Inc.","70106F":"Hewlett Packard Enterprise",701124:"Apple","7011AE":"Music Life Ltd",701404:"Limited Liability Company","7014A6":"Apple","70169F":"EtherCAT Technology Group","70188B":"Hon Hai Precision Ind. Co. Ltd","701A04":"Liteon Technology Corporation","701AED":"Advas Co. Ltd","701CE7":"Intel Corporation","701D08":"99IOT Shenzhen Co. Ltd","701D7F":"Comtech Technology Co. Ltd","701DC4":"NorthStar Battery Company, LLC","701F53":"Cisco Systems Inc.",702084:"Hon Hai Precision Ind. Co. Ltd",702393:"fos4X GmbH",702526:"Nokia",702559:"CyberTAN Technology Inc.",702605:"SONY Visual Products Inc.","70288B":"Samsung Electronics Co. Ltd",702900:"Shenzhen ChipTrip Technology Co Ltd","702A7D":"EpSpot AB","702B1D":"E-Domus International Limited","702C1F":"Wisol","702D84":"i4C Innovations","702DD1":"Newings Communication Co. Ltd","702E22":"zte Corporation","702F4B":"PolyVision Inc.","702F97":"Aava Mobile Oy",703018:"Avaya Inc","70305D":"Ubiquoss Inc","70305E":"Nanjing Zhongke Menglian Information Technology Co. Ltd",703187:"ACX GmbH","7032D5":"Athena Wireless Communications Inc",703811:"Invensys Rail","7038B4":"Low Tech Solutions","7038EE":"Avaya Inc","703A0E":"Aruba Networks","703A73":"Shenzhen Sundray Technologies Company Limited","703ACB":"Google, Inc.","703AD8":"Shenzhen Afoundry Electronic Co. Ltd","703C03":"RadiAnt Co. Ltd","703C39":"SEAWING Kft","703D15":"Hangzhou H3C Technologies Co., Limited","703EAC":"Apple","7041B7":"Edwards Lifesciences LLC",704642:"Chyng Hong Electronic Co. Ltd","7047E9":"vivo Mobile Communication Co. Ltd","70480F":"Apple","704AAE":"Xstream Flow (Pty) Ltd","704AE4":"Rinstrum Pty Ltd","704CA5":"Fortinet, Inc.","704CED":"TMRG, Inc.","704D7B":"ASUSTek Computer Inc.","704E01":"Kwangwon Tech Co. Ltd","704E66":"Shenzhen Fast Technologies Co. Ltd","704F57":"TP-Link Technologies Co. Ltd","7050AF":"BSkyB Ltd","7052C5":"Avaya Inc","70533F":"Alfa Instrumentos Eletronicos Ltda.","7054D2":"Pegatron Corporation","7054F5":"Huawei Technologies Co. Ltd","7055F8":"Cerebras Systems Inc",705681:"Apple",705812:"Panasonic Corporation AVC Networks Company",705896:"InShow Technology",705957:"Medallion Instrumentation Systems",705986:"OOO TTV","705A0F":"Hewlett-Packard Company","705A9E":"Technicolor CH USA Inc.","705AAC":"Samsung Electronics Co. Ltd","705AB6":"Compal Information (Kunshan) Co. Ltd","705B2E":"M2Communication Inc.","705CAD":"Konami Gaming Inc","705EAA":"Action Target, Inc.","7060DE":"LaVision GmbH",706173:"Calantec GmbH","7062B8":"D-Link International",706417:"Orbis Tecnologia Electrica S.A.",706582:"Suzhou Hanming Technologies Co. Ltd","7065A3":"Kandao lightforge Co. Ltd","70661B":"Sonova AG",706879:"Saijo Denki International Co. Ltd","70695A":"Cisco Systems Inc.","706BB9":"Cisco Systems Inc.","706DEC":"Wifi-soft LLC","706E6D":"Cisco Systems Inc.","706F81":"Private","70700D":"Apple","70704C":"Purple Communications, Inc","70708B":"Cisco Systems Inc.","7071B3":"Brain Corporation","7071BC":"Pegatron Corporation","70720D":"Lenovo Mobile Communication Technology Ltd","70723C":"Huawei Technologies Co. Ltd","7072CF":"EdgeCore Networks","7073CB":"Apple",707630:"ARRIS Group, Inc.","7076DD":"Oxyguard International A/S","7076F0":"LevelOne Communications (India) Private Limited","7076FF":"Kerlink",707781:"Hon Hai Precision Ind. Co. Ltd","70788B":"vivo Mobile Communication Co. Ltd",707938:"Wuxi Zhanrui Electronic Technology Co. Ltd",707990:"Huawei Technologies Co. Ltd","7079B3":"Cisco Systems Inc.","707BE8":"Huawei Technologies Co. Ltd","707C18":"ADATA Technology Co. Ltd","707C69":"Avaya Inc","707D95":"Shenzhen City LinwlanTechnology Co. Ltd","707DB9":"Cisco Systems Inc.","707E43":"ARRIS Group, Inc.","707EDE":"Nastec Ltd",708105:"Cisco Systems Inc.","7081EB":"Apple","70820E":"as electronics GmbH","70828E":"OleumTech Corporation","7085C2":"ASRock Incorporation","7085C6":"ARRIS Group, Inc.","7086C1":"Texas Instruments","70884D":"Japan Radio Co. Ltd","708A09":"Huawei Technologies Co. Ltd","708B78":"citygrow technology Co. Ltd","708BCD":"ASUSTek Computer Inc.","708D09":"Nokia Corporation","70918F":"Weber-Stephen Products LLC","7091F3":"Universal Electronics, Inc.",709383:"Intelligent Optical Network High Tech Co. Ltd","7093F8":"Space Monkey, Inc.",709756:"Happyelectronics Co. Ltd","70991C":"Shenzhen Honesty Electronics Co. Ltd","709A0B":"Italian Institute Of Technology","709BA5":"Shenzhen Y&D Electronics Co. Ltd","709BFC":"Bryton Inc.","709C8F":"Nero AG","709E29":"Sony Interactive Entertainment Inc.","709E86":"X6D Limited","709F2D":"zte Corporation","70A191":"Trendsetter Medical, LLC","70A2B3":"Apple","70A41C":"Advanced Wireless Dynamics S.L.","70A66A":"Prox Dynamics AS","70A84C":"MONAD., Inc.","70A8E3":"Huawei Technologies Co. Ltd","70AAB2":"BlackBerry RTS","70AD54":"Malvern Instruments Ltd","70AF24":"TP Vision Belgium NV","70AF25":"Nishiyama Industry Co. Ltd","70AF6A":"Shenzhen Fenglian Technology Co. Ltd","70B035":"Shenzhen Zowee Technology Co. Ltd","70B08C":"Shenou Communication Equipment Co. Ltd","70B14E":"ARRIS Group, Inc.","70B265":"Hiltron s.r.l.","70B3D5":"IEEE Registration Authority","70B599":"Embedded Technologies s.r.o.","70B7E2":"Jiangsu Miter Technology Co. Ltd","70B921":"Fiberhome Telecommunication Technologies Co. Ltd","70BAEF":"Hangzhou H3C Technologies Co., Limited","70BF3E":"Charles River Laboratories","70C6AC":"Bosch Automotive Aftermarket","70C76F":"Inno S","70C833":"Wirepas Oy","70C94E":"Liteon Technology Corporation","70CA4D":"Shenzhen lnovance Technology Co. Ltd","70CA9B":"Cisco Systems Inc.","70CD60":"Apple","70D081":"Beijing Netpower Technologies Inc.","70D379":"Cisco Systems Inc.","70D4F2":"RIM","70D57E":"Scalar Corporation","70D5E7":"Wellcore Corporation","70D6B6":"Metrum Technologies","70D880":"Upos System sp. z o.o.","70D923":"vivo Mobile Communication Co. Ltd","70D931":"Cambridge Industries(Group) Co. Ltd","70DA9C":"Tecsen","70DB98":"Cisco Systems Inc.","70DDA1":"Tellabs","70DEE2":"Apple","70DEF9":"FAI WAH International (Hong Kong) Limited","70DF2F":"Cisco Systems Inc.","70E027":"Hongyu Communication Technology Limited","70E139":"3view Ltd","70E1FD":"Flextronics","70E24C":"SAE IT-Systems GmbH & Co. KG","70E284":"Wistron Infocomm (Zhongshan) Corporation","70E422":"Cisco Systems Inc.","70E56E":"Texas Instruments","70E72C":"Apple","70E843":"Beijing C&W Optical Communication Technology Co. Ltd","70ECE4":"Apple","70EE50":"Netatmo","70EEA3":"Eoptolink Technology Inc. Ltd,","70EF00":"Apple","70F087":"Apple","70F11C":"Shenzhen Ogemray Technology Co. Ltd","70F176":"Data Modul AG","70F196":"Actiontec Electronics, Inc","70F1A1":"Liteon Technology Corporation","70F1E5":"Xetawave LLC","70F220":"Actiontec Electronics, Inc","70F35A":"Cisco Systems Inc.","70F395":"Universal Global Scientific Industrial Co. Ltd","70F8E7":"IEEE Registration Authority","70F927":"Samsung Electronics Co. Ltd","70F96D":"Hangzhou H3C Technologies Co., Limited","70FC8C":"OneAccess SA","70FF5C":"Cheerzing Communication(Xiamen)Technology Co. Ltd","70FF76":"Texas Instruments","7403BD":"Buffalo.Inc","74042B":"Lenovo Mobile Communication (Wuhan) Company Limited","740ABC":"LightwaveRF Technology Ltd","740EDB":"Optowiz Co. Ltd","7412BB":"Fiberhome Telecommunication Technologies Co. Ltd",741489:"SRT Wireless","7415E2":"Tri-Sen Systems Corporation",741865:"Shanghai DareGlobal Technologies Co. Ltd","7419F8":"IEEE Registration Authority","741AE0":"IEEE Registration Authority","741BB2":"Apple","741C27":"Itel Mobile Limited","741E93":"Fiberhome Telecommunication Technologies Co. Ltd","741F4A":"Hangzhou H3C Technologies Co., Limited",742344:"Xiaomi Communications Co Ltd","74258A":"Hangzhou H3C Technologies Co., Limited","7426AC":"Cisco Systems Inc.","74273C":"ChangYang Technology (Nanjing) Co. Ltd","7427EA":"Elitegroup Computer Systems Co. Ltd",742857:"Mayfield Robotics","7429AF":"Hon Hai Precision Ind. Co. Ltd","742B0F":"Infinidat Ltd","742B62":"Fujitsu Limited","742D0A":"Norfolk Elektronik AG","742EFC":"DirectPacket Research, Inc,","742F68":"Azurewave Technologies Inc.",743170:"Arcadyan Technology Corporation",743256:"NT-ware Systemprg GmbH","74372F":"Tongfang Shenzhen Cloudcomputing Technology Co. Ltd","74373B":"UNINET Co. Ltd",743889:"ANNAX Anzeigesysteme GmbH","743A65":"NEC Corporation","743E2B":"Ruckus Wireless","743ECB":"Gentrice tech","7440BB":"Hon Hai Precision Ind. Co. Ltd",744401:"Netgear","74458A":"Samsung Electronics Co. Ltd","7446A0":"Hewlett-Packard Company","744AA4":"zte Corporation","744BE9":"Explorer Hypertech Co. Ltd","744D79":"Arrive Systems Inc.","7451BA":"Xiaomi Communications Co Ltd",745327:"Commsen Co., Limited",745427:"Shenzhen Fast Technologies Co. Ltd","74547D":"Cisco SPVTG",745612:"ARRIS Group, Inc.",745798:"TRUMPF Laser GmbH + Co. KG","745AAA":"Huawei Technologies Co. Ltd","745C4B":"GN Audio A/S","745C9F":"TCT mobile Ltd","745E1C":"Pioneer Corporation","745F00":"Samsung Semiconductor Inc.","745FAE":"TSL PPL","74614B":"Chongqing Huijiatong Information Technology Co. Ltd","7463DF":"VTS GmbH","7465D1":"Atlinks",746630:"T:mi Ytti","7467F7":"Extreme Networks, Inc.","746A3A":"Aperi Corporation","746A89":"Rezolt Corporation","746A8F":"VS Vision Systems GmbH","746B82":"Movek","746EE4":"Asia Vital Components Co. Ltd","746F19":"Icarvisions (Shenzhen) Technology Co. Ltd","746F3D":"Contec GmbH","746FF7":"Wistron Neweb Corporation","7470FD":"Intel Corporation","74721E":"Edison Labs Inc.","7472B0":"Guangzhou Shiyuan Electronics Co. Ltd","7472F2":"Chipsip Technology Co. Ltd",747336:"MICRODIGTAL Inc",747548:"Amazon Technologies Inc.",747818:"Jurumani Solutions","747B7A":"ETH Inc.","747D24":"Phicomm (Shanghai) Co. Ltd","747DB6":"Aliwei Communications, Inc","747E1A":"Red Embedded Design Limited","747E2D":"Beijing Thomson CITIC Digital Technology Co. Ltd",748114:"Apple","74819A":"PT. Hartono Istana Teknologi","7483EF":"Arista Networks","74852A":"Pegatron Corporation","74860B":"Cisco Systems Inc.","74867A":"Dell Inc.","7487A9":"OCT Technology Co. Ltd","74882A":"Huawei Technologies Co. Ltd","74888B":"ADB Broadband Italia","748A69":"Korea Image Technology Co. Ltd","748D08":"Apple","748E08":"Bestek Corp.","748EF8":"Brocade Communications Systems, Inc.","748F1B":"MasterImage 3D","748F4D":"MEN Mikro Elektronik GmbH",749050:"Renesas Electronics Corporation","74911A":"Ruckus Wireless","7491BD":"Four Systems Co. Ltd","7493A4":"Zebra Technologies Corp.","74943D":"AgJunction","7495EC":"Alps Electric Co. Ltd",749637:"Todaair Electronic Co. Ltd",749781:"zte Corporation",749975:"IBM Corporation","749C52":"Huizhou Desay SV Automotive Co. Ltd","749CE3":"KodaCloud Canada, Inc","749D8F":"Huawei Technologies Co. Ltd","749DDC":"2Wire Inc.","749EAF":"Apple","74A02F":"Cisco Systems Inc.","74A063":"Huawei Technologies Co. Ltd","74A2E6":"Cisco Systems Inc.","74A34A":"Zimi Corporation","74A4A7":"QRS Music Technologies, Inc.","74A4B5":"Powerleader Science and Technology Co. Ltd","74A528":"Huawei Technologies Co. Ltd","74A722":"LG Electronics (Mobile Communications)","74A78E":"zte Corporation","74AC5F":"Qiku Internet Network Scientific (Shenzhen) Co. Ltd","74ADB7":"China Mobile Group Device Co. Ltd","74AE76":"iNovo Broadband, Inc.","74B00C":"Network Video Technologies, Inc","74B472":"Ciesse","74B57E":"zte Corporation","74B9EB":"JinQianMao Technology Co. Ltd","74BADB":"Longconn Electornics(shenzhen)Co. Ltd","74BBD3":"Shenzhen xeme Communication Co. Ltd","74BE08":"ATEK Products, LLC","74BFA1":"Hyunteck","74BFB7":"Nusoft Corporation","74C246":"Amazon Technologies Inc.","74C330":"Shenzhen Fast Technologies Co. Ltd","74C621":"Zhejiang Hite Renewable Energy Co. Ltd","74C63B":"Azurewave Technologies Inc.","74C99A":"Ericsson AB","74C9A3":"Fiberhome Telecommunication Technologies Co. Ltd","74CA25":"Calxeda, Inc.","74CC39":"Fiberhome Telecommunication Technologies Co. Ltd","74CD0C":"Smith Myers Communications Ltd","74CE56":"Packet Force Technology Limited Company","74D02B":"ASUSTek Computer Inc.","74D0DC":"Ericsson AB","74D21D":"Huawei Technologies Co. Ltd","74D435":"Giga-Byte Technology Co. Ltd","74D675":"WYMA Tecnologia","74D6EA":"Texas Instruments","74D7CA":"Panasonic Corporation Automotive","74D850":"Evrisko Systems","74DA38":"Edimax Technology Co. Ltd","74DADA":"D-Link International","74DAEA":"Texas Instruments","74DBD1":"Ebay Inc","74DE2B":"Liteon Technology Corporation","74DFBF":"Liteon Technology Corporation","74E06E":"Ergophone GmbH","74E14A":"IEEE Registration Authority","74E182":"Texas Instruments","74E19A":"Fiberhome Telecommunication Technologies Co. Ltd","74E1B6":"Apple","74E277":"Vizmonet Pte Ltd","74E28C":"Microsoft Corporation","74E2F5":"Apple","74E424":"Apiste Corporation","74E50B":"Intel Corporation","74E537":"Radspin","74E543":"Liteon Technology Corporation","74E5F9":"Intel Corporation","74E60F":"Tecno Mobile Limited","74E6E2":"Dell Inc.","74E7C6":"ARRIS Group, Inc.","74EA3A":"TP-Link Technologies Co. Ltd","74EAC8":"New H3C Technologies Co. Ltd","74EACB":"New H3C Technologies Co. Ltd","74EAE8":"ARRIS Group, Inc.","74ECF1":"Acumen","74F06D":"Azurewave Technologies Inc.","74F07D":"BnCOM Co. Ltd","74F102":"Beijing HCHCOM Technology Co. Ltd","74F413":"Maxwell Forest","74F612":"ARRIS Group, Inc.","74F61C":"HTC Corporation","74F661":"Schneider Electric Fire & Security Oy","74F726":"Neuron Robotics","74F85D":"Berkeley Nucleonics Corp","74F8DB":"IEEE Registration Authority","74F91A":"Onface","74FDA0":"Compupal (Group) Corporation","74FE48":"Advantech Co. Ltd","74FF4C":"Skyworth Digital Technology(Shenzhen) Co. Ltd","74FF7D":"Wren Sound Systems, LLC","78009E":"Samsung Electronics Co. Ltd","78028F":"Adaptive Spectrum and Signal Alignment (ASSIA), Inc.","7802B1":"Cisco Systems Inc.","7802B7":"ShenZhen Ultra Easy Technology Co. Ltd","7802F8":"Xiaomi Communications Co Ltd",780541:"Queclink Wireless Solutions Co. Ltd",780738:"Z.U.K. Elzab S.A.","780AC7":"Baofeng TV Co. Ltd","780CB8":"Intel Corporation","780F77":"HangZhou Gubei Electronics Technology Co. Ltd",781185:"NBS Payment Solutions Inc.","7811DC":"XIAOMI Electronics,Co. Ltd","7812B8":"Orantek Limited",781881:"Azurewave Technologies Inc.","78192E":"NASCENT Technology","7819F7":"Juniper Networks","781C5A":"Sharp Corporation","781D4A":"zte Corporation","781DBA":"Huawei Technologies Co. Ltd","781DFD":"Jabil Inc","781FDB":"Samsung Electronics Co. Ltd",782079:"ID Tech","78223D":"Affirmed Networks","7823AE":"ARRIS Group, Inc.","7824AF":"ASUSTek Computer Inc.",782544:"Omnima Limited","78257A":"LEO Innovation Lab","7825AD":"Samsung Electronics Co. Ltd","7828CA":"Sonos, Inc.","782BCB":"Dell Inc.","782D7E":"TRENDnet, Inc.","782EEF":"Nokia Corporation","78303B":"Stephen Technologies Co.,Limited","7830E1":"UltraClenz, LLC","78312B":"zte Corporation","7831C1":"Apple","78321B":"D-Link International","78324F":"Millennium Group, Inc.",783690:"Yulong Computer Telecommunication Scientific (Shenzhen) Co. Ltd","7836CC":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","783A84":"Apple","783CE3":"Kai-EE","783D5B":"TELNET Redes Inteligentes S.A.","783E53":"BSkyB Ltd","783F15":"EasySYNC Ltd","7840E4":"Samsung Electronics Co. Ltd",784405:"FUJITU(HONG KONG) ELECTRONIC Co. Ltd",784476:"Zioncom Electronics (Shenzhen) Ltd","7844FD":"TP-Link Technologies Co. Ltd",784501:"Biamp Systems",784561:"CyberTAN Technology Inc.","7845C4":"Dell Inc.","7846C4":"Daehap Hyper-Tech","78471D":"Samsung Electronics Co. Ltd",784859:"Hewlett-Packard Company","78491D":"The Will-Burt Company","784B08":"f.robotics acquisitions Ltd","784B87":"Murata Manufacturing Co. Ltd","784F43":"Apple","78510C":"LiveU Ltd","78521A":"Samsung Electronics Co. Ltd",785262:"Shenzhen Hojy Software Co. Ltd",785364:"SHIFT GmbH","7853F2":"ROXTON Ltd","78542E":"D-Link International",785517:"SankyuElectronics",785712:"Mobile Integration Workgroup",785860:"Huawei Technologies Co. Ltd","7858F3":"Vachen Co. Ltd","78593E":"RAFI GmbH & Co.KG","78595E":"Samsung Electronics Co. Ltd",785968:"Hon Hai Precision Ind. Co. Ltd","785C28":"Prime Motion Inc.","785C72":"Hioso Technology Co. Ltd","785DC8":"LG Electronics","785F4C":"Argox Information Co. Ltd","78617C":"Mitsumi Electric Co. Ltd",786256:"Huawei Technologies Co. Ltd","7864E6":"Green Motive Technology Limited","7866AE":"ZTEC Instruments, Inc.","7867D7":"Apple","7868F7":"YSTen Technology Co. Ltd","786A89":"Huawei Technologies Co. Ltd","786C1C":"Apple","786D94":"Palo Alto Networks","78719C":"ARRIS Group, Inc.","787B8A":"Apple","787D48":"Itel Mobile Limited","787E61":"Apple","787F62":"GiK mbH",788038:"Funai Electric Co. Ltd",788102:"Sercomm Corporation.","78818F":"Server Racks Australia Pty Ltd","78843C":"Sony Corporation","7884EE":"Indra Espacio S.A.","78870D":"Unifiedgateways India Private Limited","78886D":"Apple","78888A":"CDR Sp. z o.o. Sp. k.",788973:"CMC","788A20":"Ubiquiti Networks Inc.","788B77":"Standar Telecom","788C4D":"Indyme Solutions, LLC","788C54":"Ping Communication","788DF7":"Hitron Technologies. Inc","788E33":"Jiangsu SEUIC Technology Co. Ltd","78923E":"Nokia Corporation","78929C":"Intel Corporation","7894B4":"Sercomm Corporation.",789682:"zte Corporation",789684:"ARRIS Group, Inc.","7898FD":"Q9 Networks Inc.","78995C":"Nationz Technologies Inc",789966:"Musilab Electronics (DongGuan)Co. Ltd","78998F":"Mediline Italia SRL","789C85":"August Home, Inc.","789CE7":"Shenzhen Aikede Technology Co. Ltd","789ED0":"Samsung Electronics Co. Ltd","789F4C":"HOERBIGER Elektronik GmbH","789F70":"Apple","789F87":"Siemens AG I IA PP PRM","78A051":"iiNet Labs Pty Ltd","78A106":"TP-Link Technologies Co. Ltd","78A183":"Advidia","78A2A0":"Nintendo Co. Ltd","78A351":"Shenzhen Zhibotong Electronics Co. Ltd","78A3E4":"Apple","78A504":"Texas Instruments","78A5DD":"Shenzhen Smarteye Digital Electronics Co. Ltd","78A683":"Precidata","78A6BD":"DAEYEON Control&Instrument Co,.Ltd","78A6E1":"Brocade Communications Systems, Inc.","78A714":"Amphenol","78A873":"Samsung Electronics Co. Ltd","78AB60":"ABB Australia","78ABBB":"Samsung Electronics Co. Ltd","78ACBF":"Igneous Systems","78ACC0":"Hewlett-Packard Company","78AE0C":"Far South Networks","78AF58":"Gimasi SA","78B28D":"Beijing Tengling Technology Co.Ltd","78B3B9":"ShangHai sunup lighting Co. Ltd","78B3CE":"Elo touch solutions","78B5D2":"Ever Treasure Industrial Limited","78B6C1":"AOBO Telecom Co. Ltd","78B6EC":"Scuf Gaming International LLC","78B81A":"Inter Sales A/S","78B84B":"Sichuan Tianyi Comheart Telecomco. Ltd","78BAD0":"Shinybow Technology Co. Ltd","78BAF9":"Cisco Systems Inc.","78BC1A":"Cisco Systems Inc.","78BDBC":"Samsung Electronics Co. Ltd","78BEB6":"Enhanced Vision","78BEBD":"STULZ GmbH","78C1A7":"zte Corporation","78C2C0":"IEEE Registration Authority","78C3E9":"Samsung Electronics Co. Ltd","78C40E":"H&D Wireless","78C4AB":"Shenzhen Runsil Technology Co. Ltd","78C5E5":"Texas Instruments","78C6BB":"Innovasic, Inc.","78CA04":"Nokia Corporation","78CA39":"Apple","78CA5E":"Elno","78CA83":"IEEE Registration Authority","78CB33":"DHC Software Co. Ltd","78CB68":"Daehap Hyper-Tech","78CD8E":"SMC Networks Inc","78D004":"Neousys Technology Inc.","78D129":"Vicos","78D34F":"Pace-O-Matic, Inc.","78D38D":"Hongkong Yunlink Technology Limited","78D5B5":"Navielektro KY","78D66F":"Aristocrat Technologies Australia Pty. Ltd","78D6B2":"Toshiba","78D6F0":"Samsung Electro Mechanics Co. Ltd","78D752":"Huawei Technologies Co. Ltd","78D75F":"Apple","78D800":"IEEE Registration Authority","78D99F":"NuCom HK Ltd","78DA6E":"Cisco Systems Inc.","78DAB3":"GBO Technology","78DD08":"Hon Hai Precision Ind. Co. Ltd","78DDD6":"c-scape","78DDD9":"Guangzhou Shiyuan Electronics Co. Ltd","78DEE4":"Texas Instruments","78E103":"Amazon Technologies Inc.","78E3B5":"Hewlett-Packard Company","78E400":"Hon Hai Precision Ind. Co. Ltd","78E7D1":"Hewlett-Packard Company","78E8B6":"zte Corporation","78E980":"RainUs Co. Ltd","78EB14":"Shenzhen Fast Technologies Co. Ltd","78EB39":"Instituto Nacional de Tecnolog?a Industrial","78EC22":"Shanghai Qihui Telecom Technology Co. Ltd","78EC74":"Kyland-USA","78EF4C":"Unetconvergence Co. Ltd","78F29E":"Pegatron Corporation","78F557":"Huawei Technologies Co. Ltd","78F5E5":"BEGA Gantenbrink-Leuchten KG","78F5FD":"Huawei Technologies Co. Ltd","78F7BE":"Samsung Electronics Co. Ltd","78F7D0":"Silverbrook Research","78F882":"LG Electronics (Mobile Communications)","78F944":"Private","78F9B4":"Nokia","78FC14":"Family Zone Cyber Safety Ltd","78FD94":"Apple","78FE3D":"Juniper Networks","78FE41":"Socus networks","78FEE2":"Shanghai Diveo Technology Co. Ltd","78FF57":"Intel Corporation","78FFCA":"Tecno Mobile Limited","7C010A":"Texas Instruments","7C0187":"Curtis Instruments, Inc.","7C0191":"Apple","7C02BC":"Hansung Electronics Co. Ltd","7C034C":"Sagemcom Broadband SAS","7C03C9":"Shenzhen YOUHUA Technology Co. Ltd","7C03D8":"Sagemcom Broadband SAS","7C04D0":"Apple","7C0507":"Pegatron Corporation","7C051E":"Rafael Ltd","7C0623":"Ultra Electronics Sonar System Division","7C08D9":"Shanghai B-Star Technology Co","7C092B":"Bekey A/S","7C0A50":"J-MEX Inc.","7C0BC6":"Samsung Electronics Co. Ltd","7C0ECE":"Cisco Systems Inc.","7C1015":"Brilliant Home Technology, Inc.","7C11BE":"Apple","7C11CB":"Huawei Technologies Co. Ltd","7C11CD":"QianTang Technology","7C1476":"Damall Technologies SAS","7C160D":"Saia-Burgess Controls AG","7C18CD":"E-TRON Co. Ltd","7C1A03":"8Locations Co. Ltd","7C1AFC":"Dalian Co-Edifice Video Technology Co. Ltd","7C1C4E":"LG Innotek","7C1C68":"Samsung Electronics Co. Ltd","7C1CF1":"Huawei Technologies Co. Ltd","7C1DD9":"Xiaomi Communications Co Ltd","7C1E52":"Microsoft Corporation","7C1EB3":"2N TELEKOMUNIKACE a.s.","7C2048":"KoamTac","7C2064":"Alcatel-Lucent IPD","7C2586":"Juniper Networks","7C2587":"chaowifi.com","7C2634":"ARRIS Group, Inc.","7C2664":"Sagemcom Broadband SAS","7C2A31":"Intel Corporation","7C2BE1":"Shenzhen Ferex Electrical Co. Ltd","7C2CF3":"Secure Electrans Ltd","7C2E0D":"Blackmagic Design","7C2EDD":"Samsung Electronics Co. Ltd","7C2F80":"Gigaset Communications GmbH","7C336E":"MEG Electronics Inc.","7C3548":"Transcend Information","7C3866":"Texas Instruments","7C386C":"Real Time Logic","7C3920":"Ssoma Security","7C3953":"zte Corporation","7C3BD5":"Imago Group","7C3CB6":"Shenzhen Homecare Technology Co. Ltd","7C3E9D":"Patech","7C438F":"E-Band Communications Corp.","7C444C":"Entertainment Solutions, S.L.","7C4685":"Motorola (Wuhan) Mobility Technologies Communication Co. Ltd","7C477C":"IEEE Registration Authority","7C49B9":"Plexus Manufacturing Sdn Bhd","7C49EB":"XIAOMI Electronics,Co. Ltd","7C4A82":"Portsmith LLC","7C4AA8":"MindTree Wireless PVT Ltd","7C4B78":"Red Sun Synthesis Pte Ltd","7C4C58":"Scale Computing, Inc.","7C4CA5":"BSkyB Ltd","7C4F7D":"Sawwave","7C4FB5":"Arcadyan Technology Corporation","7C5049":"Apple","7C534A":"Metamako","7C55E7":"YSI, Inc.","7C574E":"CoBI GmbH","7C5A1C":"Sophos Ltd","7C5A67":"JNC Systems, Inc.","7C5CF8":"Intel Corporation","7C6097":"Huawei Technologies Co. Ltd","7C6193":"HTC Corporation","7C6456":"Samsung Electronics Co. Ltd","7C669D":"Texas Instruments","7C67A2":"Intel Corporation","7C69F6":"Cisco Systems Inc.","7C6AB3":"IBC Technologies Inc.","7C6AC3":"GatesAir, Inc","7C6ADB":"SafeTone Technology Co. Ltd","7C6AF3":"Integrated Device Technology (Malaysia) Sdn. Bhd.","7C6B33":"Tenyu Tech Co. Ltd","7C6B52":"Tigaro Wireless","7C6BF7":"NTI Co. Ltd","7C6C39":"Pixsys SRL","7C6C8F":"AMS Neve Ltd","7C6D62":"Apple","7C6DF8":"Apple","7C6F06":"Caterpillar Trimble Control Technologies","7C6FF8":"ShenZhen ACTO Digital Video Technology Co. Ltd","7C70BC":"IEEE Registration Authority","7C7176":"Wuxi iData Technology Company Ltd","7C72E4":"Unikey Technologies","7C738B":"Cocoon Alarm Ltd","7C7630":"Shenzhen YOUHUA Technology Co. Ltd","7C7635":"Intel Corporation","7C7668":"Huawei Technologies Co. Ltd","7C7673":"ENMAS GmbH","7C787E":"Samsung Electronics Co. Ltd","7C79E8":"PayRange Inc.","7C7A53":"Phytrex Technology Corp.","7C7A91":"Intel Corporation","7C7B8B":"Control Concepts, Inc.","7C7BE4":"Z'Sedai Kenkyusho Corporation","7C7D3D":"Huawei Technologies Co. Ltd","7C7D41":"Jinmuyu Electronics Co. Ltd","7C822D":"Nortec","7C8274":"Shenzhen Hikeen Technology Co. Ltd","7C8306":"Glen Dimplex Nordic as","7C8BCA":"TP-Link Technologies Co. Ltd","7C8D91":"Shanghai Hongzhuo Information Technology Co. Ltd","7C8EE4":"Texas Instruments","7C9122":"Samsung Electronics Co. Ltd","7C94B2":"Philips Healthcare PCCI","7C95B1":"Aerohive Networks Inc.","7C95F3":"Cisco Systems Inc.","7C9763":"Openmatics s.r.o.","7C9A9B":"VSE valencia smart energy","7CA15D":"GN ReSound A/S","7CA177":"Huawei Technologies Co. Ltd","7CA237":"King Slide Technology Co. Ltd","7CA23E":"Huawei Technologies Co. Ltd","7CA29B":"D.SignT GmbH & Co. KG","7CA61D":"MHL, LLC","7CA97D":"Objenious","7CAB25":"Mesmo Technology Inc.","7CACB2":"Bosch Software Innovations GmbH","7CAD74":"Cisco Systems Inc.","7CB03E":"OSRAM GmbH","7CB0C2":"Intel Corporation","7CB15D":"Huawei Technologies Co. Ltd","7CB177":"Satelco AG","7CB21B":"Cisco SPVTG","7CB232":"Hui Zhou Gaoshengda Technology Co. Ltd","7CB25C":"Acacia Communications","7CB542":"ACES Technology","7CB733":"Askey Computer Corp","7CB77B":"Paradigm Electronics Inc","7CB960":"Shanghai X-Cheng telecom Ltd","7CBACC":"IEEE Registration Authority","7CBB6F":"Cosco Electronics Co. Ltd","7CBB8A":"Nintendo Co. Ltd","7CBD06":"AE REFUsol","7CBF88":"Mobilicom Ltd","7CBFB1":"ARRIS Group, Inc.","7CC3A1":"Apple","7CC4EF":"Devialet","7CC537":"Apple","7CC6C4":"Kolff Computer Supplies b.v.","7CC709":"Shenzhen RF-Link Technology Co. Ltd","7CC8AB":"Acro Associates, Inc.","7CC8D0":"Tianjin Yaan Technology Co. Ltd","7CC8D7":"Damalisk","7CC95A":"Dell EMC","7CCB0D":"Antaira Technologies, LLC","7CCBE2":"IEEE Registration Authority","7CCC1F":"Sichuan Tianyi Comheart Telecomco. Ltd","7CCCB8":"Intel Corporation","7CCD11":"MS-Magnet","7CCD3C":"Guangzhou Juzing Technology Co. Ltd","7CCFCF":"Shanghai SEARI Intelligent System Co. Ltd","7CD1C3":"Apple","7CD30A":"INVENTEC Corporation","7CD762":"Freestyle Technology Pty Ltd","7CD844":"Enmotus Inc","7CD9FE":"New Cosmos Electric Co. Ltd","7CDA84":"Dongnian Networks Inc.","7CDD11":"Chongqing MAS SCI&TECH.Co. Ltd","7CDD20":"IOXOS Technologies S.A.","7CDD76":"Suzhou Hanming Technologies Co. Ltd","7CDD90":"Shenzhen Ogemray Technology Co. Ltd","7CE044":"NEON Inc","7CE1FF":"Computer Performance, Inc. DBA Digital Loggers, Inc.","7CE2CA":"Juniper Networks","7CE4AA":"Private","7CE524":"Quirky, Inc.","7CE56B":"ESEN Optoelectronics Technology Co. Ltd","7CE97C":"Itel Mobile Limited","7CE9D3":"Hon Hai Precision Ind. Co. Ltd","7CEB7F":"Dmet Products Corp.","7CEBAE":"Ridgeline Instruments","7CEBEA":"Asct","7CEC79":"Texas Instruments","7CED8D":"Microsoft Corporation","7CEF18":"Creative Product Design Pty. Ltd","7CEF8A":"Inhon International Ltd","7CF05F":"Apple","7CF098":"Bee Beans Technologies, Inc.","7CF0BA":"Linkwell Telesystems Pvt Ltd","7CF429":"NUUO Inc.","7CF854":"Samsung Electronics Co. Ltd","7CF90E":"Samsung Electronics Co. Ltd","7CF95C":"U.I. Lapp GmbH","7CFADF":"Apple","7CFC3C":"Visteon Corporation","7CFE28":"Salutron Inc.","7CFE4E":"Shenzhen Safe vision Technology Co. Ltd","7CFE90":"Mellanox Technologies, Inc.","7CFF4D":"AVM Audiovisuelles Marketing und Computersysteme GmbH","7CFF62":"Huizhou Super Electron Technology Co. Ltd","80000B":"Intel Corporation",800010:"AT&T","80006E":"Apple",800184:"HTC Corporation","8002DF":"ORA Inc.",800588:"Ruijie Networks Co. Ltd","8005DF":"Montage Technology Group Limited","8007A2":"Esson Technology Inc.",800902:"Keysight Technologies, Inc.","800A06":"CoMTEC Co. Ltd","800A80":"IEEE Registration Authority","800B51":"Chengdu XGimi Technology Co. Ltd","800DD7":"Latticework, Inc","800E24":"ForgetBox",801382:"Huawei Technologies Co. Ltd",801440:"Sunlit System Technology Corp","8014A8":"Guangzhou V-SOLUTION Electronic Technology Co. Ltd","8016B7":"Brunel University","80177D":"Nortel Networks",801844:"Dell Inc.","8018A7":"Samsung Electronics Co. Ltd",801934:"Intel Corporation",801967:"Shanghai Reallytek Information Technology Co. Ltd","8019FE":"JianLing Technology Co. Ltd","801DAA":"Avaya Inc","801F02":"Edimax Technology Co. Ltd","801F12":"Microchip Technology Inc.","8020AF":"Trade FIDES, a.s.",802275:"Beijing Beny Wave Technology Co Ltd",802689:"D-Link International",802994:"Technicolor CH USA Inc.","802AA8":"Ubiquiti Networks Inc.","802AFA":"Germaneers GmbH","802BF9":"Hon Hai Precision Ind. Co. Ltd","802DE1":"Solarbridge Technologies","802E14":"azeti Networks AG","802FDE":"Zurich Instruments AG","8030DC":"Texas Instruments",803457:"OT Systems Limited","8035C1":"Xiaomi Communications Co Ltd",803773:"Netgear",803896:"Sharp Corporation","8038BC":"Huawei Technologies Co. Ltd","8038FD":"LeapFrog Enterprises, Inc.","8039E5":"Patlite Corporation","803A0A":"Integrated Device Technology (Malaysia) Sdn. Bhd.","803A59":"AT&T","803B2A":"ABB Xiamen Low Voltage Equipment Co. Ltd","803B9A":"ghe-ces electronic ag","803BF6":"Look Easy International Limited","803F5D":"Winstars Technology Ltd","803FD6":"bytes at work AG",804126:"Huawei Technologies Co. Ltd","80414E":"BBK Educational Electronics Corp. Ltd","80427C":"Adolf Tedsen GmbH & Co. KG",804731:"Packet Design, Inc.","8048A5":"Sichuan Tianyi Comheart Telecomco. Ltd",804971:"Apple","804B20":"Ventilation Control","804E70":"Samsung Electronics Co. Ltd","804E81":"Samsung Electronics Co. Ltd","804F58":"ThinkEco, Inc.","80501B":"Nokia Corporation",805067:"W & D Technology Corporation","8056F2":"Hon Hai Precision Ind. Co. Ltd",805719:"Samsung Electronics Co. Ltd","8058C5":"NovaTec Kommunikationstechnik GmbH","8058F8":"Motorola Mobility LLC, a Lenovo Company","8059FD":"Noviga","805A04":"LG Electronics (Mobile Communications)","805E0C":"Yealink(Xiamen) Network Technology Co. Ltd","805EC0":"Yealink(Xiamen) Network Technology Co. Ltd",806007:"RIM","80615F":"Beijing Sinead Technology Co. Ltd","80618F":"Shenzhen sangfei Consumer Communications Co. Ltd",806459:"Nimbus Inc.","80656D":"Samsung Electronics Co. Ltd","8065E9":"BenQ Corporation",806629:"Prescope Technologies Co. Ltd","806AB0":"Shenzhen TINNO Mobile Technology Corp.","806C1B":"Motorola Mobility LLC, a Lenovo Company","806C8B":"Kaeser Kompressoren AG","806CBC":"NET New Electronic Technology GmbH","80711F":"Juniper Networks","80717A":"Huawei Technologies Co. Ltd","80739F":"Kyocera Corporation",807459:"K's Co. Ltd",807693:"Newag SA","8079AE":"ShanDong Tecsunrise Co. Ltd","807A7F":"ABB Genway Xiamen Electrical Equipment Co. Ltd","807ABF":"HTC Corporation","807B1E":"Corsair Components","807B85":"IEEE Registration Authority","807D1B":"Neosystem Co. Ltd","807DE3":"Chongqing Sichuan Instrument Microcircuit Co.Ltd","8081A5":"TONGQING CoMMUNICATION EQUIPMENT (SHENZHEN) Co. Ltd",808287:"ATCOM Technology Co.Ltd",808698:"Netronics Technologies Inc.","8086F2":"Intel Corporation",808917:"TP-Link Technologies Co. Ltd","808B5C":"Shenzhen Runhuicheng Technology Co. Ltd","808C97":"Kaonmedia Co. Ltd","808DB7":"Hewlett Packard Enterprise","80912A":"Lih Rong electronic Enterprise Co. Ltd","8091C0":"AgileMesh, Inc.","80929F":"Apple",809393:"Xapt GmbH","80946C":"Tokyo Radar Corporation","8096B1":"ARRIS Group, Inc.","8096CA":"Hon Hai Precision Ind. Co. Ltd","80971B":"Altenergy Power System,Inc.","809B20":"Intel Corporation","809FAB":"Fiberhome Telecommunication Technologies Co. Ltd","80A036":"Shanghai MXCHIP Information Technology Co. Ltd","80A1AB":"Intellisis","80A1D7":"Shanghai DareGlobal Technologies Co. Ltd","80A589":"Azurewave Technologies Inc.","80A85D":"Osterhout Design Group","80AAA4":"Usag","80ACAC":"Juniper Networks","80AD16":"Xiaomi Communications Co Ltd","80AD67":"Kasda Networks Inc","80B03D":"Apple","80B219":"Elektron Technology UK Limited","80B234":"Technicolor CH USA Inc.","80B289":"Forworld Electronics Ltd","80B32A":"Alstom Grid","80B686":"Huawei Technologies Co. Ltd","80B708":"Blue Danube Systems, Inc","80B709":"Viptela, Inc","80B95C":"ELFTECH Co. Ltd","80BAAC":"TeleAdapt Ltd","80BAE6":"Neets","80BBEB":"Satmap Systems Ltd","80BE05":"Apple","80C16E":"Hewlett-Packard Company","80C548":"Shenzhen Zowee Technology Co. Ltd","80C5E6":"Microsoft Corporation","80C5F2":"Azurewave Technologies Inc.","80C63F":"Remec Broadband Wireless , LLC","80C6AB":"Technicolor CH USA Inc.","80C6CA":"Endian s.r.l.","80C755":"Panasonic Appliances Company","80C7C5":"Fiberhome Telecommunication Technologies Co. Ltd","80C862":"Openpeak, Inc","80CE62":"Hewlett-Packard Company","80CEB1":"Theissen Training Systems GmbH","80CF41":"Lenovo Mobile Communication Technology Ltd","80D019":"Embed, Inc","80D09B":"Huawei Technologies Co. Ltd","80D160":"Integrated Device Technology (Malaysia) Sdn. Bhd.","80D18B":"Hangzhou I'Converge Technology Co. Ltd","80D21D":"Azurewave Technologies Inc.","80D433":"LzLabs GmbH","80D4A5":"Huawei Technologies Co. Ltd","80D605":"Apple","80D733":"QSR Automations, Inc.","80DB31":"Power Quotient International Co. Ltd","80E01D":"Cisco Systems Inc.","80E4DA":"IEEE Registration Authority","80E650":"Apple","80E86F":"Cisco Systems Inc.","80EA23":"Wistron Neweb Corporation","80EA96":"Apple","80EACA":"Dialog Semiconductor Hellas SA","80EB77":"Wistron Corporation","80ED2C":"Apple","80EE73":"Shuttle Inc.","80F25E":"Kyynel","80F503":"ARRIS Group, Inc.","80F593":"IRCO Sistemas de Telecomunicaci?n S.A.","80F62E":"Hangzhou H3C Technologies Co., Limited","80F8EB":"RayTight","80FA5B":"Clevo Co.","80FB06":"Huawei Technologies Co. Ltd","80FFA8":"Unidis","84002D":"Pegatron Corporation","8400D2":"Sony Mobile Communications AB","8401A7":"Greyware Automation Products, Inc","8404D2":"Kirale Technologies SL","840B2D":"Samsung Electro Mechanics Co. Ltd","840F45":"Shanghai GMT Digital Technologies Co. Ltd","84100D":"Motorola Mobility LLC, a Lenovo Company","84119E":"Samsung Electronics Co. Ltd","8416F9":"TP-Link Technologies Co. Ltd",841715:"GP Electronics (HK) Ltd",841766:"Weifang GoerTek Technology Co. Ltd",841826:"Osram GmbH","84183A":"Ruckus Wireless",841888:"Juniper Networks","841B38":"Shenzhen Excelsecu Data Technology Co. Ltd","841B5E":"Netgear","841E26":"KERNEL-I Co. Ltd",842096:"Shenzhen RF-Link Technology Co. Ltd",842141:"Shenzhen Ginwave Technologies Ltd","8421F1":"Huawei Technologies Co. Ltd","84248D":"Zebra Technologies Inc",842519:"Samsung Electronics","84253F":"silex technology, Inc.","8425A4":"Tariox Limited","8425DB":"Samsung Electronics Co. Ltd",842615:"ADB Broadband Italia","84262B":"Nokia",842690:"Beijing Thought Science Co. Ltd","8427CE":"Corporation Of the Presiding Bishop Of The Church Of Jesus Christ Of Latter-day Saints","84285A":"Saffron Solutions Inc",842914:"EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG",842999:"Apple","842B2B":"Dell Inc.","842B50":"Huria Co. Ltd","842BBC":"Modelleisenbahn GmbH","842C80":"Sichuan Changhong Electric Ltd","842E27":"Samsung Electronics Co. Ltd","842F75":"Innokas Group","8430E5":"SkyHawke Technologies, LLC","8432EA":"Anhui Wanzten P&T Co. Ltd",843497:"Hewlett-Packard Company",843611:"hyungseul Publishing networks",843835:"Apple",843838:"Samsung Electro-Mechanics(Thailand)","843A4B":"Intel Corporation","843DC6":"Cisco Systems Inc.","843F4E":"Tri-Tech Manufacturing, Inc.",844076:"Drivenets",844167:"Apple",844464:"ServerU Inc",844765:"Huawei Technologies Co. Ltd",844823:"WOXTER TECHNOLOGY Co. Ltd",844915:"vArmour Networks, Inc.","844BB7":"Beijing Sankuai Online Technology Co. Ltd","844BF5":"Hon Hai Precision Ind. Co. Ltd","844F03":"Ablelink Electronics Ltd","84509A":"Easy Soft TV Co. Ltd",845181:"Samsung Electronics Co. Ltd","8455A5":"Samsung Electronics Co. Ltd","84569C":"Coho Data, Inc.,",845787:"DVR C&C Co. Ltd","845A81":"ffly4u","845B12":"Huawei Technologies Co. Ltd","845C93":"Chabrier Services","845DD7":"Shenzhen Netcom Electronics Co. Ltd","8461A0":"ARRIS Group, Inc.",846223:"Shenzhen Coship Electronics Co. Ltd","8462A6":"EuroCB (Phils), Inc.","8463D6":"Microsoft Corporation","84683E":"Intel Corporation",846878:"Apple","846AED":"Wireless Tsukamoto.,Co.Ltd","846EB1":"Park Assist LLC",847207:"I&C Technology",847303:"Letv Mobile and Intelligent Information Technology (Beijing) Corporation Ltd","84742A":"zte Corporation",847460:"zte Corporation",847616:"Addat s.r.o.",847778:"Cochlear Limited","84788B":"Apple","8478AC":"Cisco Systems Inc.",847933:"profichip GmbH",847973:"Shanghai Baud Data Communication Co. Ltd","847A88":"HTC Corporation","847BEB":"Dell Inc.","847D50":"Holley Metering Limited","847E40":"Texas Instruments","84802D":"Cisco Systems Inc.","8482F4":"Beijing Huasun Unicreate Technology Co. Ltd",848319:"Hangzhou Zero Zero Technology Co. Ltd",848336:"Newrun",848371:"Avaya Inc",848433:"Paradox Engineering SA",848506:"Apple","84850A":"Hella Sonnen- und Wetterschutztechnik GmbH","8486F3":"Greenvity Communications","8489AD":"Apple","848D84":"Rajant Corporation","848DC7":"Cisco SPVTG","848E0C":"Apple","848E96":"Embertec Pty Ltd","848EDF":"Sony Mobile Communications AB","848F69":"Dell Inc.",849000:"Arnold & Richter Cine Technik","84930C":"Incoax Networks Europe AB","84948C":"Hitron Technologies. Inc",849681:"Cathay Communication Co. Ltd","8496D8":"ARRIS Group, Inc.","8497B8":"Memjet Inc.",849866:"Samsung Electronics Co. Ltd","849CA6":"Arcadyan Technology Corporation","849D64":"SMC Corporation","849DC5":"Centera Photonics Inc.","849FB5":"Huawei Technologies Co. Ltd","84A134":"Apple","84A1D1":"Sagemcom Broadband SAS","84A423":"Sagemcom Broadband SAS","84A466":"Samsung Electronics Co. Ltd","84A6C8":"Intel Corporation","84A783":"Alcatel Lucent","84A788":"Perples","84A8E4":"Huawei Technologies Co. Ltd","84A991":"Cyber Trans Japan Co. Ltd","84A9C4":"Huawei Technologies Co. Ltd","84AA9C":"MitraStar Technology Corp.","84ACA4":"Beijing Novel Super Digital TV Technology Co. Ltd","84ACFB":"Crouzet Automatismes","84AD58":"Huawei Technologies Co. Ltd","84AF1F":"Beat System Service Co,. Ltd","84AFEC":"Buffalo.Inc","84B153":"Apple","84B261":"Cisco Systems Inc.","84B517":"Cisco Systems Inc.","84B541":"Samsung Electronics Co. Ltd","84B59C":"Juniper Networks","84B802":"Cisco Systems Inc.","84BA3B":"Canon Inc.","84BE52":"Huawei Technologies Co. Ltd","84C0EF":"Samsung Electronics Co. Ltd","84C1C1":"Juniper Networks","84C2E4":"Jiangsu Qinheng Co. Ltd","84C3E8":"Vaillant GmbH","84C727":"Gnodal Ltd","84C7A9":"C3PO S.A.","84C7EA":"Sony Mobile Communications AB","84C8B1":"Incognito Software Systems Inc.","84C9B2":"D-Link International","84CD62":"ShenZhen IDWELL Technology Co. Ltd","84CFBF":"Fairphone","84D32A":"IEEE 1905.1","84D47E":"Aruba Networks","84D4C8":"Widex A/S","84D6D0":"Amazon Technologies Inc.","84D931":"Hangzhou H3C Technologies Co., Limited","84D9C8":"Unipattern Co.,","84DB2F":"Sierra Wireless Inc","84DB9E":"Aifloo AB","84DBAC":"Huawei Technologies Co. Ltd","84DBFC":"Nokia","84DD20":"Texas Instruments","84DDB7":"Cilag GmbH International","84DE3D":"Crystal Vision Ltd","84DF0C":"NET2GRID BV","84DF19":"Chuango Security Technology Corporation","84E058":"ARRIS Group, Inc.","84E0F4":"IEEE Registration Authority","84E323":"Green Wave Telecommunication SDN BHD","84E327":"Tailyn Technologies Inc","84E4D9":"Shenzhen NEED technology Ltd","84E629":"Bluwan SA","84E714":"Liang Herng Enterprise,Co.Ltd","84EA99":"Vieworks","84EB18":"Texas Instruments","84ED33":"BBMC Co. Ltd","84EF18":"Intel Corporation","84F129":"Metrascale Inc.","84F3EB":"Espressif Inc.","84F493":"OMS spol. s.r.o.","84F64C":"Cross Point BV","84F6FA":"Miovision Technologies Incorporated","84FCAC":"Apple","84FCFE":"Apple","84FE9E":"RTC Industries, Inc.","84FEDC":"Borqs Beijing Ltd","8801F2":"Vitec System Engineering Inc.",880355:"Arcadyan Technology Corporation","88074B":"LG Electronics (Mobile Communications)",880905:"MTMCommunications","8809AF":"Masimo Corporation","880F10":"Huami Information Technology Co. Ltd","880FB6":"Jabil Circuits India Pvt Ltd,-EHTP unit",881036:"Panodic(ShenZhen) Electronics Limted",881196:"Huawei Technologies Co. Ltd","88124E":"Qualcomm Inc.","88142B":"Protonic Holland",881544:"Cisco Meraki","8817A3":"Integrated Device Technology (Malaysia) Sdn. Bhd.","8818AE":"Tamron Co. Ltd",881908:"Apple","881B99":"Shenzhen XIN FEI JIA Electronic Co. Ltd","881DFC":"Cisco Systems Inc.","881FA1":"Apple",882012:"LMI Technologies","8821E3":"Nebusens, S.L.",882364:"Watchnet DVR Inc","8823FE":"TTTech Computertechnik AG","88252C":"Arcadyan Technology Corporation",882593:"TP-Link Technologies Co. Ltd","8828B3":"Huawei Technologies Co. Ltd",882950:"Netmoon Technology Co. Ltd","882BD7":"ADD?Nergie Technologies","882E5A":"storONE","88308A":"Murata Manufacturing Co. Ltd","88329B":"Samsung Electro-Mechanics(Thailand)",883314:"Texas Instruments","8833BE":"Ivenix, Inc.","88354C":"Transics",883612:"SRC Computers, LLC","88365F":"LG Electronics (Mobile Communications)","88366C":"EFM Networks","883B8B":"Cheering Connection Co. Ltd","883C1C":"Mercury Corporation","883D24":"Google, Inc.","883F4A":"Texas Instruments","883FD3":"Huawei Technologies Co. Ltd",884157:"Shenzhen Atsmart Technology Co. Ltd","8841C1":"Orbisat DA Amazonia Ind E Aerol SA","8841FC":"AirTies Wireless Networks","8843E1":"Cisco Systems Inc.",884477:"Huawei Technologies Co. Ltd","8844F6":"Nokia Corporation","88462A":"Telechips Inc.","884AEA":"Texas Instruments","884B39":"Siemens AG, Healthcare Sector","884CCF":"Pulzze Systems, Inc","8850DD":"Infiniband Trade Association","8851FB":"Hewlett-Packard Company","88532E":"Intel Corporation",885395:"Apple","8853D4":"Huawei Technologies Co. Ltd","88576D":"XTA Electronics Ltd","8857EE":"Buffalo.Inc","885A92":"Cisco Systems Inc.","885BDD":"Aerohive Networks Inc.","885C47":"Alcatel Lucent","885D90":"IEEE Registration Authority","885DFB":"zte Corporation","885FE8":"IEEE Registration Authority","88615A":"Siano Mobile Silicon Ltd","8863DF":"Apple",886639:"Huawei Technologies Co. Ltd","8866A5":"Apple","88685C":"Shenzhen ChuangDao & Perpetual Eternal Technology Co. Ltd","886AB1":"vivo Mobile Communication Co. Ltd","886AE3":"Alpha Networks Inc.","886B0F":"Bluegiga Technologies Oy","886B44":"Sunnovo International Limited","886B6E":"Apple","886B76":"China Hopeful Group Hopeful Electric Co. Ltd",887033:"Hangzhou Silan Microelectronic Inc","88708C":"Lenovo Mobile Communication Technology Ltd","8870EF":"SC Professional Trading Co. Ltd","8871E5":"Amazon Technologies Inc.",887384:"Toshiba",887398:"K2E Tekpoint",887556:"Cisco Systems Inc.",887598:"Samsung Electronics Co. Ltd",887873:"Intel Corporation","88789C":"Game Technologies SA","88795B":"Konka Group Co. Ltd","88797E":"Motorola Mobility LLC, a Lenovo Company","887A31":"Velankani Electronics Pvt. Ltd","887F03":"Comper Technology Investment Limited",888279:"Shenzhen RB-LINK Intelligent Technology Co.Ltd",888322:"Samsung Electronics Co. Ltd","88835D":"FN-Link Technology Limited",888603:"Huawei Technologies Co. Ltd","8886A0":"Simton Technologies Ltd","8886C2":"STABILO International GmbH",888717:"Canon Inc.","8887DD":"DarbeeVision Inc.",888914:"All Components Incorporated",888964:"GSI Electronics Inc.","888B5D":"Storage Appliance Corporation","888C19":"Brady Corp Asia Pacific Ltd","88908D":"Cisco Systems Inc.",889166:"Viewcooper Corp.","8891DD":"Racktivity",889471:"Brocade Communications Systems, Inc.","88947E":"Fiberhome Telecommunication Technologies Co. Ltd","8894F9":"Gemicom Technology, Inc.","8895B9":"Unified Packet Systems Crop","88964E":"ARRIS Group, Inc.",889676:"TTC MARCONI s.r.o.","8896B6":"Global Fire Equipment S.A.","8896F2":"Valeo Schalter und Sensoren GmbH","8897DF":"Entrypass Corporation Sdn. Bhd.",889821:"Teraon","889B39":"Samsung Electronics Co. Ltd","889CA6":"BTB Korea Inc","889FFA":"Hon Hai Precision Ind. Co. Ltd","88A084":"Formation Data Systems","88A25E":"Juniper Networks","88A2D7":"Huawei Technologies Co. Ltd","88A3CC":"Amatis Controls","88A5BD":"Qpcom Inc.","88A6C6":"Sagemcom Broadband SAS","88A73C":"Ragentek Technology Group","88A9A7":"IEEE Registration Authority","88ACC1":"Generiton Co. Ltd","88AD43":"Pegatron Corporation","88ADD2":"Samsung Electronics Co. Ltd","88AE07":"Apple","88AE1D":"Compal Information (Kunshan) Co. Ltd","88B111":"Intel Corporation","88B168":"Delta Control GmbH","88B1E1":"Mojo Networks, Inc.","88B362":"Nokia Shanghai Bell Co. Ltd)","88B4A6":"Motorola Mobility LLC, a Lenovo Company","88B627":"Gembird Europe BV","88B6EE":"Dish Technologies Corp","88B8D0":"Dongguan Koppo Electronic Co. Ltd","88BA7F":"Qfiednet Co. Ltd","88BD45":"Samsung Electronics Co. Ltd","88BD78":"Flaircomm Microelectronics,Inc.","88BFD5":"Simple Audio Ltd","88C242":"Poynt Co.","88C255":"Texas Instruments","88C36E":"Beijing Ereneben lnformation Technology Limited","88C3B3":"Sovico","88C626":"Logitech, Inc","88C663":"Apple","88C9D0":"LG Electronics (Mobile Communications)","88CB87":"Apple","88CBA5":"Suzhou Torchstar Intelligent Technology Co. Ltd","88CC45":"Skyworth Digital Technology(Shenzhen) Co. Ltd","88CEFA":"Huawei Technologies Co. Ltd","88CF98":"Huawei Technologies Co. Ltd","88D039":"TCL Technoly Electronics(Huizhou). Ltd","88D171":"Beghelli S.P.A","88D274":"zte Corporation","88D37B":"FirmTek, LLC","88D50C":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","88D7BC":"DEP Company","88D7F6":"ASUSTek Computer Inc.","88D962":"Canopus Systems US LLC","88DA1A":"Redpine Signals, Inc.","88DC96":"SENAO Networks, Inc.","88DD79":"Voltaire","88DEA9":"Roku, Inc.","88E0A0":"Shenzhen VisionSTOR Technologies Co. Ltd","88E0F3":"Juniper Networks","88E161":"Art Beijing Science and Technology Development Co. Ltd","88E3AB":"Huawei Technologies Co. Ltd","88E603":"Avotek Corporation","88E628":"Shenzhen Kezhonglong Optoelectronic Technology Co. Ltd","88E712":"Whirlpool Corporation","88E7A6":"iKnowledge Integration Corp.","88E87F":"Apple","88E8F8":"Yong TAI Electronic (Dongguan) Ltd","88E90F":"innomdlelab","88E917":"Tamaggo","88E9FE":"Apple","88ED1C":"Cudo Communication Co. Ltd","88F031":"Cisco Systems Inc.","88F077":"Cisco Systems Inc.","88F488":"cellon Communications technology(shenzhen)Co. Ltd","88F490":"Jetmobile Pte Ltd","88F7C7":"Technicolor CH USA Inc.","88FD15":"Lineeye Co. Ltd","88FED6":"ShangHai WangYong Software Co. Ltd","8C006D":"Apple","8C04FF":"Technicolor CH USA Inc.","8C0551":"Koubachi AG","8C078C":"Flow Data Inc","8C088B":"Remote Solution","8C09F4":"ARRIS Group, Inc.","8C0C90":"Ruckus Wireless","8C0CA3":"Amper","8C0D76":"Huawei Technologies Co. Ltd","8C0EE3":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","8C0F6F":"Pegatron Corporation","8C0F83":"Angie Hospitality LLC","8C10D4":"Sagemcom Broadband SAS","8C11CB":"ABUS Security-Center GmbH & Co. KG","8C147D":"IEEE Registration Authority","8C1645":"LCFC(HeFei) Electronics Technology Co. Ltd","8C18D9":"Shenzhen RF Technology Co. Ltd","8C192D":"IEEE Registration Authority","8C1ABF":"Samsung Electronics Co. Ltd","8C1F94":"RF Surgical System Inc.","8C210A":"TP-Link Technologies Co. Ltd","8C2505":"Huawei Technologies Co. Ltd","8C271D":"QuantHouse","8C278A":"Vocollect Inc","8C2937":"Apple","8C2DAA":"Apple","8C2F39":"IBA Dosimetry GmbH","8C2FA6":"Solid Optics B.V.","8C3330":"EmFirst Co. Ltd","8C3357":"HiteVision Digital Media Technology Co. Ltd","8C34FD":"Huawei Technologies Co. Ltd","8C395C":"Bit4id Srl","8C3AE3":"LG Electronics (Mobile Communications)","8C3BAD":"Netgear","8C3C07":"Skiva Technologies, Inc.","8C3C4A":"NAKAYO Inc","8C41F2":"RDA Technologies Ltd","8C4435":"Shanghai BroadMobi Communication Technology Co. Ltd","8C4500":"Murata Manufacturing Co. Ltd","8C4AEE":"Giga TMS Inc","8C4B59":"3D Imaging & Simulations Corp","8C4CAD":"Evoluzn Inc.","8C4CDC":"Planex Communications Inc.","8C4DB9":"Unmonday Ltd","8C4DEA":"Cerio Corporation","8C5105":"Shenzhen ireadygo Information Technology Co. Ltd","8C53F7":"A&D Engineering Co. Ltd","8C541D":"LGE","8C569D":"Imaging Solutions Group","8C56C5":"Nintendo Co. Ltd","8C579B":"Wistron Neweb Corporation","8C57FD":"LVX Western","8C5877":"Apple","8C5973":"ZyXEL Communications Corp","8C598B":"C Technologies AB","8C59C3":"ADB Italia","8C5AF0":"Exeltech Solar Products","8C5BF0":"ARRIS Group, Inc.","8C5CA1":"d-broad,Inc","8C5D60":"UCI Corporation Co. Ltd","8C5F48":"Continental Intelligent Transportation Systems LLC","8C5FDF":"Beijing Railway Signal Factory","8C604F":"Cisco Systems Inc.","8C60E7":"Mpgio Co. Ltd","8C6102":"Beijing Baofengmojing Technologies Co. Ltd","8C640B":"Beyond Devices d.o.o.","8C6422":"Sony Mobile Communications AB","8C6878":"Nortek-AS","8C6AE4":"Viogem Limited","8C6D50":"Shenzhen MTC Co Ltd","8C705A":"Intel Corporation","8C71F8":"Samsung Electronics Co. Ltd","8C736E":"Fujitsu Limited","8C76C1":"Goden Tech Limited","8C7712":"Samsung Electronics Co. Ltd","8C7716":"Longcheer Telecommunication Limited","8C78D7":"Shenzhen Fast Technologies Co. Ltd","8C7967":"zte Corporation","8C7B9D":"Apple","8C7C92":"Apple","8C7CB5":"Hon Hai Precision Ind. Co. Ltd","8C7CFF":"Brocade Communications Systems, Inc.","8C7EB3":"Lytro, Inc.","8C7F3B":"ARRIS Group, Inc.","8C82A8":"Insigma Technology Co. Ltd","8C839D":"Shenzhen Xinyupeng Electronic Technology Co. Ltd","8C8401":"Private","8C8580":"Smart Innovation LLC","8C8590":"Apple","8C873B":"Leica Camera AG","8C897A":"Augtek","8C89A5":"Micro-Star International","8C8A6E":"Estun Automation Technoloy Co. Ltd","8C8ABB":"Beijing Orient View Technology Co. Ltd","8C8B83":"Texas Instruments","8C8E76":"taskit GmbH","8C8EF2":"Apple","8C8FE9":"Apple","8C90D3":"Nokia","8C9109":"Toyoshima Electric Technoeogy(Suzhou) Co. Ltd","8C9236":"Aus.Linx Technology Co. Ltd","8C9351":"Jigowatts Inc.","8C94CF":"Encell Technology, Inc.","8C99E6":"TCT mobile Ltd","8C9F3B":"Qingdao Hisense Communications Co. Ltd","8CA048":"Beijing NeTopChip Technology Co. Ltd","8CA2FD":"Starry, Inc.","8CA5A1":"Oregano Systems - Design & Consulting GmbH","8CA6DF":"TP-Link Technologies Co. Ltd","8CA982":"Intel Corporation","8CAB8E":"Shanghai Feixun Communication Co. Ltd","8CAE4C":"Plugable Technologies","8CAE89":"Y-cam Solutions Ltd","8CB094":"Airtech I&C Co. Ltd","8CB64F":"Cisco Systems Inc.","8CB7F7":"Shenzhen UniStrong Science & Technology Co. Ltd","8CB82C":"IPitomy Communications","8CB864":"AcSiP Technology Corp.","8CBEBE":"Xiaomi Communications Co Ltd","8CBF9D":"Shanghai Xinyou Information Technology Ltd Co.","8CBFA6":"Samsung Electronics Co. Ltd","8CC121":"Panasonic Corporation AVC Networks Company","8CC5E1":"ShenZhen Konka Telecommunication Technology Co. Ltd","8CC661":"Current, powered by GE","8CC7AA":"Radinet Communications Inc.","8CC7D0":"zhejiang ebang Communication Co. Ltd","8CC8CD":"Samsung Electronics Co. Ltd","8CC8F4":"IEEE Registration Authority","8CCDA2":"ACTP, Inc.","8CCDE8":"Nintendo Co. Ltd","8CCF09":"Dell EMC","8CCF5C":"BEFEGA GmbH","8CD17B":"CG Mobile","8CD2E9":"Yokote Seiko Co. Ltd","8CD3A2":"VisSim AS","8CD48E":"Itel Mobile Limited","8CD628":"Ikor Metering","8CDB25":"ESG Solutions","8CDCD4":"Hewlett-Packard Company","8CDD8D":"Wifly-City System Inc.","8CDE52":"ISSC Technologies Corp.","8CDE99":"Comlab Inc.","8CDF9D":"NEC Corporation","8CE081":"zte Corporation","8CE117":"zte Corporation","8CE2DA":"Circle Media Inc","8CE38E":"Toshiba Memory Corporation","8CE748":"Private","8CE78C":"DK Networks","8CE7B3":"Sonardyne International Ltd","8CEA1B":"Edgecore Networks Corporation","8CEBC6":"Huawei Technologies Co. Ltd","8CEC4B":"Dell Inc.","8CEEC6":"Precepscion Pty. Ltd","8CF228":"Shenzhen Mercury Communication Technologies Co. Ltd","8CF5A3":"Samsung Electro-Mechanics(Thailand)","8CF710":"AMPAK Technology, Inc.","8CF773":"Nokia","8CF813":"Orange Polska","8CF945":"Power Automation pte Ltd","8CF957":"RuiXingHengFang Network (Shenzhen) Co. Ltd","8CF9C9":"MESADA Technology Co. Ltd","8CFABA":"Apple","8CFDF0":"Qualcomm Inc.","8CFEB4":"Vsoontech Electronics Co., Limited","90004E":"Hon Hai Precision Ind. Co. Ltd","9000DB":"Samsung Electronics Co. Ltd","90013B":"Sagemcom Broadband SAS","90028A":"Shenzhen Shidean Legrand Electronic Products Co. Ltd","9002A9":"Zhejiang Dahua Technology Co. Ltd",900325:"Huawei Technologies Co. Ltd",900372:"Longnan Junya Digital Technology Co. Ltd","9003B7":"Parrot SA",900628:"Samsung Electronics Co. Ltd",900917:"Far-sighted mobile","900A1A":"Taicang T&W Electronics","900A39":"Wiio, Inc.","900A3A":"PSG Plastic Service GmbH","900BC1":"Sprocomm Technologies Co. Ltd","900CB4":"Alinket Electronic Technology Co. Ltd","900D66":"Digimore Electronics Co. Ltd","900DCB":"ARRIS Group, Inc.","900E83":"Monico Monitoring, Inc.",901711:"Hagenuk Marinekommunikation GmbH","90179B":"Nanomegas","9017AC":"Huawei Technologies Co. Ltd","90185E":"Apex Tool Group GmbH & Co OHG","90187C":"Samsung Electro Mechanics Co. Ltd","9018AE":"Shanghai Meridian Technologies, Co. Ltd",901900:"SCS SA","901ACA":"ARRIS Group, Inc.","901B0E":"Fujitsu Technology Solutions GmbH","901D27":"zte Corporation","901EDD":"Great Computer Corporation","90203A":"BYD Precision Manufacture Co. Ltd",902083:"General Engine Management Systems Ltd",902106:"BSkyB Ltd",902155:"HTC Corporation",902181:"Shanghai Huaqin Telecom Technology Co. Ltd","9023EC":"Availink, Inc.","9027E4":"Apple","902B34":"Giga-Byte Technology Co. Ltd","902CC7":"C-MAX Asia Limited","902E1C":"Intel Corporation","902E87":"LabJack","9031CD":"Onyx Healthcare Inc.","90324B":"Hon Hai Precision Ind. Co. Ltd","90342B":"Gatekeeper Systems, Inc.","9034FC":"Hon Hai Precision Ind. Co. Ltd","90356E":"Vodafone Omnitel N.V.",903809:"Ericsson AB","9038DF":"Changzhou Tiannengbo System Co. Ltd","903A72":"Ruckus Wireless","903AA0":"Nokia","903AE6":"Parrot SA","903C92":"Apple","903CAE":"Yunnan KSEC Digital Technology Co. Ltd","903D5A":"Shenzhen Wision Technology Holding Limited","903D68":"G-Printec, Inc.","903D6B":"Zicon Technology Corp.","903DBD":"Secure Meters Limited","903EAB":"ARRIS Group, Inc.",904506:"Tokyo Boeki Medisys Inc.","9046A2":"Tedipay UK Ltd","9046B7":"Vadaro Pte Ltd",904716:"Rorze Corporation","90489A":"Hon Hai Precision Ind. Co. Ltd","9049FA":"Intel Corporation","904CE5":"Hon Hai Precision Ind. Co. Ltd","904D4A":"Sagemcom Broadband SAS","904E2B":"Huawei Technologies Co. Ltd","904E91":"IEEE Registration Authority","90505A":"unGlue, Inc","90507B":"Advanced PANMOBIL Systems GmbH & Co. KG","9050CA":"Hitron Technologies. Inc","90513F":"Elettronica Santerno SpA",905446:"TES Electronic Solutions","9055AE":"Ericsson, EAB/RWI/K",905682:"Lenbrook Industries Limited",905692:"Autotalks Ltd","9059AF":"Texas Instruments","905C44":"Compal Broadband Networks, Inc.","905F2E":"TCT mobile Ltd","905F8D":"modas GmbH","9060F1":"Apple","90610C":"Fida International (S) Pte Ltd","9061AE":"Intel Corporation",906717:"Alphion India Private Limited","90671C":"Huawei Technologies Co. Ltd","9067B5":"Alcatel-Lucent","9067F3":"Alcatel Lucent","9068C3":"Motorola Mobility LLC, a Lenovo Company","906CAC":"Fortinet, Inc.","906DC8":"DLG Automa??o Industrial Ltda","906EBB":"Hon Hai Precision Ind. Co. Ltd","906F18":"Private","906FA9":"Nanjing Putian Telecommunications Technology Co. Ltd",907025:"Garea Microsys Co. Ltd",907065:"Texas Instruments",907240:"Apple",907282:"Sagemcom Broadband SAS",907910:"Integrated Device Technology (Malaysia) Sdn. Bhd.",907990:"Benchmark Electronics Romania SRL","907A0A":"Gebr. Bode GmbH & Co KG","907A28":"Beijing Morncloud Information And Technology Co. Ltd","907AF1":"Wally","907EBA":"Utek Technology (Shenzhen) Co. Ltd","907F61":"Chicony Electronics Co. Ltd",908260:"IEEE 1904.1 Working Group","90834B":"Beijing Yunyi Times Technology Co,.Ltd","90837A":"General Electric Water & Process Technologies","90840D":"Apple","90842B":"LEGO System A/S","90848B":"HDR10+ Technologies, LLC",908674:"Sichuan Tianyi Comheart Telecomco. Ltd","9088A2":"Ionics Technology ME Ltda","908C09":"Total Phase","908C44":"H.K Zongmu Technology Co. Ltd","908C63":"GZ Weedong Networks Technology Co. Ltd","908D1D":"GH Technologies","908D6C":"Apple","908D78":"D-Link International","908FCF":"UNO System Co. Ltd","90903C":"Trison Technology Corporation",909060:"RSI Video Technologies","9092B4":"Diehl BGT Defence GmbH & Co. KG",909497:"Huawei Technologies Co. Ltd","9094E4":"D-Link International","9097D5":"Espressif Inc.","9097F3":"Samsung Electronics Co. Ltd",909864:"Impex-Sat GmbH&Co KG",909916:"ELVEES NeoTek OJSC","909D7D":"ARRIS Group, Inc.","909DE0":"Newland Design + Assoc. Inc.","909F33":"EFM Networks","909F43":"Accutron Instruments Inc.","90A210":"United Telecoms Ltd","90A2DA":"Gheo SA","90A365":"HMD Global Oy","90A46A":"Sisnet Co. Ltd","90A4DE":"Wistron Neweb Corporation","90A62F":"Naver","90A783":"JSW Pacific Corporation","90A7C1":"Pakedge Device and Software Inc.","90AC3F":"BrightSign LLC","90ADF7":"vivo Mobile Communication Co. Ltd","90AE1B":"TP-Link Technologies Co. Ltd","90B0ED":"Apple","90B11C":"Dell Inc.","90B134":"ARRIS Group, Inc.","90B1E0":"Beijing Nebula Link Technology Co. Ltd","90B21F":"Apple","90B686":"Murata Manufacturing Co. Ltd","90B8D0":"Joyent, Inc.","90B931":"Apple","90B97D":"Johnson Outdoors Marine Electronics d/b/a Minnkota","90C115":"Sony Mobile Communications AB","90C1C6":"Apple","90C35F":"Nanjing Jiahao Technology Co. Ltd","90C682":"IEEE Registration Authority","90C792":"ARRIS Group, Inc.","90C7D8":"zte Corporation","90C99B":"Recore Systems","90CC24":"Synaptics, Inc","90CDB6":"Hon Hai Precision Ind. Co. Ltd","90CF15":"Nokia Corporation","90CF6F":"Dlogixs Co Ltd","90CF7D":"Qingdao Hisense Communications Co. Ltd","90D11B":"Palomar Medical Technologies","90D74F":"Bookeen","90D7BE":"Wavelab Global Inc.","90D7EB":"Texas Instruments","90D852":"Comtec Co. Ltd","90D8F3":"zte Corporation","90D92C":"HUG-Witschi AG","90DA4E":"Avanu","90DA6A":"FOCUS H&S Co. Ltd","90DB46":"E-Lead Electronic Co. Ltd","90DD5D":"Apple","90DFB7":"s.m.s smart microwave sensors GmbH","90DFFB":"Homerider Systems","90E0F0":"IEEE 1722a Working Group","90E2BA":"Intel Corporation","90E6BA":"ASUSTek Computer Inc.","90E7C4":"HTC Corporation","90EA60":"SPI Lasers Ltd","90EC50":"C.O.B.O. SPA","90EED9":"Universal de Desarrollos Electr?Nicos, SA","90EF68":"ZyXEL Communications Corp","90F052":"MEIZU Technology Co. Ltd","90F1AA":"Samsung Electronics Co. Ltd","90F1B0":"Hangzhou Anheng Info&Tech Co. Ltd","90F278":"Radius Gateway","90F305":"HUMAX Co. Ltd","90F3B7":"Kirisun Communications Co. Ltd","90F4C1":"Rand McNally","90F652":"TP-Link Technologies Co. Ltd","90F72F":"Phillips Machine & Welding Co., Inc.","90FB5B":"Avaya Inc","90FBA6":"Hon Hai Precision Ind. Co. Ltd","90FD61":"Apple","90FD9F":"Silicon Laboratories","90FF79":"Metro Ethernet Forum",940006:"jinyoung",940070:"Nokia Corporation",940149:"AutoHotBox","9401C2":"Samsung Electronics Co. Ltd","94049C":"Huawei Technologies Co. Ltd","9405B6":"Liling FullRiver Electronics & Technology Ltd",940937:"HUMAX Co. Ltd","940B2D":"NetView Technologies(Shenzhen) Co. Ltd","940BD5":"Himax Technologies, Inc","940C6D":"TP-Link Technologies Co. Ltd","940E6B":"Huawei Technologies Co. Ltd","94103E":"Belkin International Inc.","9411DA":"ITF Fr?schl GmbH","94147A":"vivo Mobile Communication Co. Ltd",941673:"Point Core SARL",941882:"Hewlett Packard Enterprise","941D1C":"TLab West Systems AB",942053:"Nokia Corporation",942197:"Stalmart Technology Limited","94236E":"Shenzhen Junlan Electronic Ltd","94282E":"New H3C Technologies Co. Ltd","94290C":"Shenyang wisdom Foundation Technology Development Co. Ltd","942A3F":"Diversey Inc","942CB3":"HUMAX Co. Ltd","942E17":"Schneider Electric Canada Inc","942E63":"Fins?cur","94319B":"Alphatronics BV","9433DD":"Taco Inc","94350A":"Samsung Electronics Co. Ltd","9436E0":"Sichuan Bihong Broadcast & Television New Technologies Co. Ltd","9439E5":"Hon Hai Precision Ind. Co. Ltd","943AF0":"Nokia Corporation","943BB1":"Kaonmedia Co. Ltd","943DC9":"Asahi Net, Inc.","943FC2":"Hewlett Packard Enterprise","9440A2":"Anywave Communication Technologies, Inc.","9441C1":"Mini-Cam Limited",944444:"LG Innotek",944452:"Belkin International Inc.",944696:"BaudTec Corporation",944996:"WiSilica Inc","944A09":"BitWise Controls","944A0C":"Sercomm Corporation",945047:"Rechnerbetriebsgruppe",945089:"SimonsVoss Technologies GmbH",945103:"Samsung Electronics Co. Ltd","94513D":"iSmart Alarm, Inc.","9451BF":"Hyundai ESG",945330:"Hon Hai Precision Ind. Co. Ltd",945493:"Rigado, LLC","9457A5":"Hewlett-Packard Company",945907:"Shanghai HITE-BELDEN Network Technology Co. Ltd","94592D":"EKE Building Technology Systems Ltd","945B7E":"Trilobit Ltda.","94611E":"Wata Electronics Co. Ltd",946124:"Pason Systems",946269:"ARRIS Group, Inc.",946372:"vivo Mobile Communication Co. Ltd","9463D1":"Samsung Electronics Co. Ltd","94652D":"OnePlus Technology (Shenzhen) Co. Ltd","94659C":"Intel Corporation","9466E7":"WOM Engineering","946AB0":"Arcadyan Corporation","9470D2":"Winfirm Technology","9471AC":"TCT mobile Ltd","94756E":"QinetiQ North America","9476B7":"Samsung Electronics Co. Ltd","94772B":"Huawei Technologies Co. Ltd","947BBE":"Ubicquia","947BE7":"Samsung Electronics Co. Ltd","947C3E":"Polewall Norge AS","947EB9":"National Narrowband Network Communications Pty Ltd","9481A4":"Azuray Technologies","94857A":"Evantage Industries Corp","9486CD":"Seoul Electronics&Telecom","9486D4":"Surveillance Pro Corporation","94877C":"ARRIS Group, Inc.",948815:"Infinique Worldwide Inc",948854:"Texas Instruments","94885E":"Surfilter Network Technology Co. Ltd","948B03":"EAGET Innovation and Technology Co. Ltd","948BC1":"Samsung Electronics Co. Ltd","948D50":"Beamex Oy Ab","948DEF":"Oetiker Schweiz AG","948E89":"Industrias Unidas SA de CV","948FEE":"Verizon Telematics","9492BC":"Syntech(HK) Technology Limited",949426:"Apple","9495A0":"Google, Inc.","9498A2":"Shanghai LISTEN TECH.Ltd",949901:"Shenzhen YITOA Digital Appliance Co. Ltd",949990:"VTC Telecommunications","949AA9":"Microsoft Corporation","949BFD":"Trans New Technology, Inc.","949C55":"Alta Data Technologies","949D57":"Panasonic do Brasil Limitada","949F3E":"Sonos, Inc.","949F3F":"Optek Digital Technology Company limited","949FB4":"ChengDu JiaFaAnTai Technology Co. Ltd","94A04E":"Bostex Technology Co. Ltd","94A1A2":"AMPAK Technology, Inc.","94A7B7":"zte Corporation","94A7BC":"BodyMedia, Inc.","94AAB8":"Joview(Beijing) Technology Co. Ltd","94ABDE":"OMX Technology - FZE","94ACCA":"trivum technologies GmbH","94AE61":"Alcatel Lucent","94AEE3":"Belden Hirschmann Industries (Suzhou) Ltd","94B10A":"Samsung Electronics Co. Ltd","94B2CC":"Pioneer Corporation","94B40F":"Aruba Networks","94B819":"Nokia","94B86D":"Intel Corporation","94B8C5":"RuggedCom Inc.","94B9B4":"Aptos Technology","94BA31":"Visiontec da Amaz?nia Ltda.","94BA56":"Shenzhen Coship Electronics Co. Ltd","94BBAE":"Husqvarna AB","94BF1E":"eflow Inc. / Smart Device Planning and Development Division","94BF2D":"Apple","94BF95":"Shenzhen Coship Electronics Co. Ltd","94C014":"Sorter Sp. j. Konrad Grzeszczyk MichaA, Ziomek","94C038":"Tallac Networks","94C150":"2Wire Inc.","94C3E4":"SCA Schucker GmbH & Co KG","94C4E9":"PowerLayer Microsystems HongKong Limited","94C691":"EliteGroup Computer Systems Co. Ltd","94C6EB":"NOVA electronics, Inc.","94C7AF":"Raylios Technology","94C960":"Zhongshan B&T technology.Co. Ltd","94C962":"Teseq AG","94CA0F":"Honeywell Analytics","94CCB9":"ARRIS Group, Inc.","94CDAC":"Creowave Oy","94CE2C":"Sony Mobile Communications AB","94CE31":"CTS Limited","94D019":"Cydle Corp.","94D029":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","94D417":"GPI Korea Inc.","94D469":"Cisco Systems Inc.","94D60E":"shenzhen yunmao Information technologies Co. Ltd","94D723":"Shanghai DareGlobal Technologies Co. Ltd","94D771":"Samsung Electronics Co. Ltd","94D859":"TCT mobile Ltd","94D93C":"Enelps","94D9B3":"TP-Link Technologies Co. Ltd","94DB49":"Sitcorp","94DBC9":"Azurewave Technologies Inc.","94DBDA":"Huawei Technologies Co. Ltd","94DD3F":"A+V Link Technologies, Corp.","94DE0E":"SmartOptics AS","94DE80":"Giga-Byte Technology Co. Ltd","94DF4E":"Wistron InfoComm(Kunshan)Co. Ltd","94DF58":"IJ Electron Co. Ltd","94E0D0":"HealthStream Taiwan Inc.","94E1AC":"Hangzhou Hikvision Digital Technology Co. Ltd","94E226":"D. ORtiz Consulting, LLC","94E2FD":"Boge Kompressoren OTTO Boge GmbH & Co. KG","94E36D":"Texas Instruments","94E711":"Xirka Dama Persada PT","94E848":"Fylde Micro Ltd","94E8C5":"ARRIS Group, Inc.","94E96A":"Apple","94E979":"Liteon Technology Corporation","94E98C":"Nokia","94EB2C":"Google, Inc.","94EBCD":"BlackBerry RTS","94F128":"Hewlett Packard Enterprise","94F19E":"Huizhou Maorong Intelligent Technology Co. Ltd","94F278":"Elma Electronic","94F551":"Cadi Scientific Pte Ltd","94F665":"Ruckus Wireless","94F692":"Geminico Co. Ltd","94F6A3":"Apple","94F720":"Tianjin Deviser Electronics Instrument Co. Ltd","94FAE8":"Shenzhen Eycom Technology Co. Ltd","94FB29":"Zebra Technologies Inc.","94FBB2":"Shenzhen Gongjin Electronics Co.,LT","94FD1D":"WhereWhen Corp","94FD2E":"Shanghai Uniscope Technologies Co. Ltd","94FE22":"Huawei Technologies Co. Ltd","94FE9D":"Shenzhen Gongjin Electronics Co.,LT","94FEF4":"Sagemcom Broadband SAS",980074:"Raisecom Technology Co. Ltd","9800C1":"GuangZhou CREATOR Technology Co. Ltd(CHINA)","9800C6":"Apple","9801A7":"Apple",980284:"Theobroma Systems GmbH","9802D8":"IEEE Registration Authority","9803A0":"ABB n.v. Power Quality Products","9803D8":"Apple","98072D":"Texas Instruments","980C82":"Samsung Electro Mechanics Co. Ltd","980CA5":"Motorola (Wuhan) Mobility Technologies Communication Co. Ltd","980D2E":"HTC Corporation","980EE4":"Private",981094:"Shenzhen Vsun Communication technology Co. Ltd","9810E8":"Apple",981333:"zte Corporation","9814D2":"Avonic","9816EC":"IC Intracom","981DFA":"Samsung Electronics Co. Ltd","981E0F":"Jeelan (Shanghai Jeelan Technology Information Inc","981FB1":"Shenzhen Lemon Network Technology Co. Ltd","98208E":"Definium Technologies","9822EF":"Liteon Technology Corporation","98234E":"Micromedia AG","98262A":"Applied Research Associates, Inc","9828A6":"Compal Information (Kunshan) Co. Ltd","98291D":"Jaguar de Mexico, SA de CV","98293F":"Fujian Start Computer Equipment Co. Ltd","9829A6":"Compal Information (Kunshan) Co. Ltd","982CBE":"2Wire Inc.","982D56":"Resolution Audio","982D68":"Samsung Electronics Co. Ltd","982DBA":"Fibergate Inc.","982F3C":"Sichuan Changhong Electric Ltd",983000:"Beijing KEMACOM Technologies Co. Ltd",983071:"Daikyung Vascom","98349D":"Krauss Maffei Technologies GmbH",983571:"Sub10 Systems Ltd","9835B8":"Assembled Products Corporation",983713:"PT.Navicom Indonesia","98398E":"Samsung Electronics Co. Ltd","983B16":"AMPAK Technology, Inc.","983F9F":"China SSJ (Suzhou) Network Technology Inc.","9840BB":"Dell Inc.",984246:"SOL Industry PTE. Ltd","9843DA":"Intertech",984562:"Shanghai Baud Data Communication Co. Ltd","98473C":"Shanghai Sunmon Communication Technogy Co. Ltd","984A47":"CHG Hospital Beds","984B4A":"ARRIS Group, Inc.","984BE1":"Hewlett-Packard Company","984C04":"Zhangzhou Keneng Electrical Equipment Co Ltd","984CD3":"Mantis Deposition","984E97":"Starlight Marketing (H. K.) Ltd","984FEE":"Intel Corporation","9852B1":"Samsung Electronics Co. Ltd","98541B":"Intel Corporation","9857D3":"HON HAI-Ccpbg Precision Ind.Co. Ltd","98588A":"SysGRATION Ltd",985945:"Texas Instruments","985AEB":"Apple","985BB0":"Kmdata Inc.","985C93":"SBG Systems SAS","985D46":"PeopleNet Communication","985DAD":"Texas Instruments","985E1B":"ConversDigital Co. Ltd","985FD3":"Microsoft Corporation",986022:"EMW Co. Ltd","9866EA":"Industrial Control Communications, Inc.","986B3D":"ARRIS Group, Inc.","986C5C":"Jiangxi Gosun Guard Security Co. Ltd","986CF5":"zte Corporation","986D35":"IEEE Registration Authority","986DC8":"Toshiba Mitsubishi-Electric Industrial Systems Corporation","986F60":"Guangdong Oppo Mobile Telecommunications Corp. Ltd","9870E8":"Innatech SDN BHD","9873C4":"Sage Electronic Engineering LLC","98743D":"Shenzhen Jun Kai Hengye Technology Co. Ltd","9874DA":"Infinix mobility limited","9876B6":"Adafruit",987770:"Pep Digital Technology (Guangzhou) Co. Ltd","987BF3":"Texas Instruments","987E46":"Emizon Networks Limited",988217:"Disruptive Ltd",988389:"Samsung Electronics Co. Ltd","9884E3":"Texas Instruments","9886B1":"Flyaudio Corporation (China)",988744:"Wuxi Hongda Science and Technology Co. Ltd","9889ED":"Anadem Information Inc.","988B5D":"Sagemcom Broadband SAS","988BAD":"Corintech Ltd","988E34":"Zhejiang Boxsam Electronic Co. Ltd","988E4A":"Noxus(Beijing) Technology Co. Ltd","988EDD":"TE Connectivity Limerick",989080:"Linkpower Network System Inc Ltd",989096:"Dell Inc.","9893CC":"LG Electronics Inc",989449:"Skyworth Wireless Technology Ltd","9897D1":"MitraStar Technology Corp.","989C57":"Huawei Technologies Co. Ltd","989E63":"Apple","98A40E":"Snap, Inc.","98A7B0":"Mcst ZAO","98AA3C":"Will i-tech Co. Ltd","98AAD7":"Blue Wave Networking Co Ltd","98AAFC":"IEEE Registration Authority","98B039":"Nokia","98B6E9":"Nintendo Co. Ltd","98B8E3":"Apple","98BB1E":"BYD Precision Manufacture Company Ltd","98BC57":"SVA Technologies Co.Ltd","98BC99":"Edeltech Co. Ltd","98BE94":"IBM","98C0EB":"Global Regency Ltd","98C5DB":"Ericsson AB","98C845":"PacketAccess","98CA33":"Apple","98CB27":"Galore Networks Pvt. Ltd","98CDB4":"Virident Systems, Inc.","98CF53":"BBK Educational Electronics Corp. Ltd","98D293":"Google, Inc.","98D331":"Shenzhen Bolutek Technology Co. Ltd","98D3D2":"MEKRA Lang GmbH & Co. KG","98D686":"Chyi Lee Industry Co. Ltd","98D6BB":"Apple","98D6F7":"LG Electronics (Mobile Communications)","98D863":"Shanghai High-Flying Electronics Technology Co. Ltd","98D88C":"Nortel Networks","98DA92":"Vuzix Corporation","98DCD9":"UNITEC Co. Ltd","98DDEA":"Infinix mobility limited","98DED0":"TP-Link Technologies Co. Ltd","98E0D9":"Apple","98E165":"Accutome","98E476":"Zentan","98E79A":"Foxconn(NanJing) Communication Co. Ltd","98E7F4":"Hewlett-Packard Company","98E7F5":"Huawei Technologies Co. Ltd","98E848":"Axiim","98EC65":"Cosesy ApS","98EECB":"Wistron Infocomm (Zhongshan) Corporation","98EF9B":"Ohsung","98F058":"Lynxspring, Incl.","98F0AB":"Apple","98F170":"Murata Manufacturing Co. Ltd","98F199":"NEC Platforms Ltd","98F2B3":"Hewlett Packard Enterprise","98F428":"zte Corporation","98F537":"zte Corporation","98F5A9":"Ohsung","98F7D7":"ARRIS Group, Inc.","98F8C1":"IDT Technology Limited","98F8DB":"Marini Impianti Industriali s.r.l.","98FAE3":"Xiaomi Communications Co Ltd","98FB12":"Grand Electronics (HK) Ltd","98FC11":"Cisco-Linksys LLC","98FD74":"ACT.Co.Ltd","98FDB4":"Primax Electronics Ltd","98FE03":"Ericsson - North America","98FE94":"Apple","98FF6A":"OTEC(Shanghai)Technology Co. Ltd","98FFD0":"Lenovo Mobile Communication Technology Ltd","9C0111":"Shenzhen Newabel Electronic Co. Ltd","9C0298":"Samsung Electronics Co. Ltd","9C039E":"Beijing Winchannel Software Technology Co. Ltd","9C0473":"Tecmobile (International) Ltd","9C04EB":"Apple","9C061B":"Hangzhou H3C Technologies Co., Limited","9C066E":"Hytera Communications Corporation Limited","9C0DAC":"Tymphany HK Limited","9C0E4A":"Shenzhen Vastking Electronic Co. Ltd","9C13AB":"Chanson Water Co. Ltd","9C1465":"Edata Elektronik San. ve Tic. A.?.","9C1874":"Nokia Danmark A/S","9C1C12":"Aruba Networks","9C1D58":"Texas Instruments","9C1E95":"Actiontec Electronics, Inc","9C1FDD":"Accupix Inc.","9C207B":"Apple","9C216A":"TP-Link Technologies Co. Ltd","9C220E":"TASCAN Systems GmbH","9C2840":"Discovery Technology Ltd.","9C28BF":"Continental Automotive Czech Republic s.r.o.","9C28EF":"Huawei Technologies Co. Ltd","9C293F":"Apple","9C2A70":"Hon Hai Precision Ind. Co. Ltd","9C2A83":"Samsung Electronics Co. Ltd","9C2EA1":"Xiaomi Communications Co Ltd","9C305B":"Hon Hai Precision Ind. Co. Ltd","9C3066":"RWE Effizienz GmbH","9C3178":"Foshan Huadian Intelligent Communications Teachnologies Co. Ltd","9C31B6":"Kulite Semiconductor Products Inc","9C32A9":"Sichuan Tianyi Comheart Telecomco. Ltd","9C32CE":"Canon Inc.","9C3426":"ARRIS Group, Inc.","9C3583":"Nipro Diagnostics, Inc","9C35EB":"Apple","9C37F4":"Huawei Technologies Co. Ltd","9C3AAF":"Samsung Electronics Co. Ltd","9C3DCF":"Netgear","9C3EAA":"EnvyLogic Co. Ltd","9C417C":"Hame Technology Co., Limited","9C431E":"IEEE Registration Authority","9C443D":"Chengdu Xuguang Technology Co Ltd","9C44A6":"SwiftTest, Inc.","9C4563":"DIMEP Sistemas","9C4A7B":"Nokia Corporation","9C4CAE":"Mesa Labs","9C4E20":"Cisco Systems Inc.","9C4E36":"Intel Corporation","9C4E8E":"ALT Systems Ltd","9C4EBF":"BoxCast","9C4FCF":"TCT mobile Ltd","9C4FDA":"Apple","9C50EE":"Cambridge Industries(Group) Co. Ltd","9C52F8":"Huawei Technologies Co. Ltd","9C53CD":"ENGICAM s.r.l.","9C541C":"Shenzhen My-power Technology Co. Ltd","9C54CA":"Zhengzhou VCOM Science and Technology Co. Ltd","9C55B4":"I.S.E. S.r.l.","9C5711":"Feitian Xunda(Beijing) Aeronautical Information Technology Co. Ltd","9C57AD":"Cisco Systems Inc.","9C5B96":"NMR Corporation","9C5C8D":"Firemax Ind?Stria E CoM?Rcio de Produtos Eletr?Nicos Ltda","9C5C8E":"ASUSTek Computer Inc.","9C5CF9":"Sony Mobile Communications AB","9C5D12":"Aerohive Networks Inc.","9C5D95":"VTC Electronics Corp.","9C5E73":"Calibre UK Ltd","9C611D":"Omni-ID USA, Inc.","9C6121":"Sichuan Tianyi Comheart Telecomco. Ltd","9C62AB":"Sumavision Technologies Co. Ltd","9C63ED":"zte Corporation","9C645E":"Harman Consumer Group","9C65B0":"Samsung Electronics Co. Ltd","9C65EE":"DASAN Network Solutions","9C65F9":"AcSiP Technology Corp.","9C6650":"Glodio Technolies Co. Ltd Tianjin Branch","9C685B":"Octonion SA","9C6ABE":"QEES ApS.","9C6C15":"Microsoft Corporation","9C6F52":"zte Corporation","9C741A":"Huawei Technologies Co. Ltd","9C7514":"Wildix srl","9C77AA":"Nadasnv","9C79AC":"Suntec Software(Shanghai) Co. Ltd","9C7A03":"Ciena Corporation","9C7BD2":"NEOLAB Convergence","9C7DA3":"Huawei Technologies Co. Ltd","9C7F57":"DERA Co. Ltd","9C807D":"SysCABLE Korea Inc.","9C80DF":"Arcadyan Technology Corporation","9C83BF":"PRO-VISION, Inc.","9C84BF":"Apple","9C86DA":"Phoenix Geophysics Ltd","9C8888":"Simac Techniek NV","9C88AD":"Fiberhome Telecommunication Technologies Co. Ltd","9C8BA0":"Apple","9C8BF1":"The Warehouse Limited","9C8C6E":"Samsung Electronics Co. Ltd","9C8D1A":"INTEG process group Inc","9C8D7C":"Alps Electric Co. Ltd","9C8DD3":"Leonton Technologies","9C8E99":"Hewlett-Packard Company","9C8ECD":"Amcrest Technologies","9C8EDC":"Teracom Limited","9C934E":"Xerox Corporation","9C93E4":"Private","9C95F8":"SmartDoor Systems, LLC","9C9726":"Technicolor","9C9811":"Guangzhou Sunrise Electronics Development Co. Ltd","9C99A0":"Xiaomi Communications Co Ltd","9C9C1D":"Starkey Labs Inc.","9C9C40":"Sichuan Tianyi Comheart Telecomco. Ltd","9C9D5D":"Raden Inc","9CA10A":"Scle SFE","9CA134":"Nike, Inc.","9CA3A9":"Guangzhou Juan Optical and Electronical Tech Joint Stock Co. Ltd","9CA3BA":"SAKURA Internet Inc.","9CA577":"Osorno Enterprises Inc.","9CA5C0":"vivo Mobile Communication Co. Ltd","9CA615":"TP-Link Technologies Co. Ltd","9CA69D":"Whaley Technology Co.Ltd","9CA9E4":"zte Corporation","9CAC6D":"Universal Electronics, Inc.","9CAD97":"Hon Hai Precision Ind. Co. Ltd","9CADEF":"Obihai Technology, Inc.","9CAED3":"Seiko Epson Corporation","9CAF6F":"Itel Mobile Limited","9CAFCA":"Cisco Systems Inc.","9CB008":"Ubiquitous Computing Technology Corporation","9CB206":"Procentec","9CB2B2":"Huawei Technologies Co. Ltd","9CB654":"Hewlett-Packard Company","9CB6D0":"Rivet Networks","9CB70D":"Liteon Technology Corporation","9CB793":"Creatcomm Technology Inc.","9CBB98":"Shen Zhen RND Electronic Co. Ltd","9CBD9D":"SkyDisk, Inc.","9CBEE0":"Biosoundlab Co. Ltd","9CC077":"PrintCounts, LLC","9CC0D2":"Conductix-Wampfler GmbH","9CC172":"Huawei Technologies Co. Ltd","9CC7A6":"AVM GmbH","9CC7D1":"Sharp Corporation","9CC8AE":"Becton, Dickinson and Company","9CCAD9":"Nokia Corporation","9CCC83":"Juniper Networks","9CCD82":"Cheng UEI Precision Industry Co. Ltd","9CD21E":"Hon Hai Precision Ind. Co. Ltd","9CD24B":"zte Corporation","9CD332":"PLC Technology Ltd","9CD35B":"Samsung Electronics Co. Ltd","9CD36D":"Netgear","9CD48B":"Innolux Technology Europe BV","9CD643":"D-Link International","9CD917":"Motorola Mobility LLC, a Lenovo Company","9CD9CB":"Lesira Manufacturing Pty Ltd","9CDA3E":"Intel Corporation","9CDC71":"Hewlett Packard Enterprise","9CDD1F":"Intelligent Steward Co. Ltd","9CDF03":"Harman/Becker Automotive Systems GmbH","9CDFB1":"Shenzhen Crave Communication Co. Ltd","9CE063":"Samsung Electronics Co. Ltd","9CE10E":"NCTech Ltd","9CE1D6":"Junger Audio-Studiotechnik GmbH","9CE230":"Julong Co,.Ltd","9CE33F":"Apple","9CE374":"Huawei Technologies Co. Ltd","9CE635":"Nintendo Co. Ltd","9CE65E":"Apple","9CE6E7":"Samsung Electronics Co. Ltd","9CE7BD":"Winduskorea Co. Ltd","9CE82B":"vivo Mobile Communication Co. Ltd","9CE895":"New H3C Technologies Co. Ltd","9CE951":"Shenzhen Sang Fei Consumer Communications Ltd, Co.","9CEBE8":"BizLink (Kunshan) Co. Ltd","9CEFD5":"Panda Wireless, Inc.","9CF387":"Apple","9CF48E":"Apple","9CF61A":"UTC Fire and Security","9CF67D":"Ricardo Prague, s.r.o.","9CF8DB":"shenzhen eyunmei technology Co,.Ltd","9CF938":"AREVA NP GmbH","9CFBD5":"vivo Mobile Communication Co. Ltd","9CFBF1":"MESOMATIC GmbH & Co.KG","9CFC01":"Apple","9CFCD1":"Aetheris Technology (Shanghai) Co. Ltd","9CFEA1":"Fiberhome Telecommunication Technologies Co. Ltd","9CFFBE":"OTSL Inc.",A002DC:"Amazon Technologies Inc.",A00363:"Robert Bosch Healthcare GmbH",A0043E:"Parker Hannifin Manufacturing Germany GmbH & Co. KG",A00460:"Netgear",A00627:"NEXPA System",A00798:"Samsung Electronics Co. Ltd",A007B6:"Advanced Technical Support, Inc.",A0086F:"Huawei Technologies Co. Ltd",A0094C:"CenturyLink",A009ED:"Avaya Inc",A00ABF:"Wieson Technologies Co. Ltd",A00BBA:"Samsung Electro Mechanics Co. Ltd",A00CA1:"SKTB SKiT",A01081:"Samsung Electronics Co. Ltd",A01290:"Avaya Inc",A012DB:"Tabuchi Electric Co. Ltd",A0133B:"HiTi Digital, Inc.",A013CB:"Fiberhome Telecommunication Technologies Co. Ltd",A0143D:"Parrot SA",A0165C:"Triteka Ltd",A01828:"Apple",A01859:"Shenzhen Yidashi Electronics Co Ltd",A01917:"Bertel S.p.a.",A01B29:"Sagemcom Broadband SAS",A01C05:"Nimax Telecom Co. Ltd",A01D48:"Hewlett-Packard Company",A01E0B:"MINIX Technology Limited",A020A6:"Espressif Inc.",A02195:"Samsung Electronics Co. Ltd",A021B7:"Netgear",A0231B:"TeleComp R&D Corp.",A0239F:"Cisco Systems Inc.",A02BB8:"Hewlett-Packard Company",A02C36:"FN-Link Technology Limited",A02EF3:"United Integrated Services Co., Led.",A03299:"Lenovo (Beijing) Co. Ltd",A0341B:"TrackR, Inc",A0369F:"Intel Corporation",A036F0:"Comprehensive Power",A036FA:"Ettus Research LLC",A038F8:"OURA Health Oy",A039EE:"Sagemcom Broadband SAS",A039F7:"LG Electronics (Mobile Communications)",A03A75:"PSS Belgium N.V.",A03B1B:"Inspire Tech",A03BE3:"Apple",A03D6F:"Cisco Systems Inc.",A03E6B:"IEEE Registration Authority",A04025:"Actioncable, Inc.",A04041:"SAMWONFA Co. Ltd",A040A0:"Netgear",A0415E:"Opsens Solution Inc.",A041A7:"NL Ministry Of Defense",A0423F:"Tyan Computer Corp",A043DB:"Sitael S.p.A.",A0481C:"Hewlett-Packard Company",A04C5B:"Shenzhen TINNO Mobile Technology Corp.",A04CC1:"Helixtech Corp.",A04E01:"CENTRAL ENGINEERING Co. Ltd",A04E04:"Nokia Corporation",A04EA7:"Apple",A04FD4:"ADB Broadband Italia",A051C6:"Avaya Inc",A0554F:"Cisco Systems Inc.",A055DE:"ARRIS Group, Inc.",A056B2:"Harman/Becker Automotive Systems GmbH",A056F3:"Apple",A057E3:"Huawei Technologies Co. Ltd",A0593A:"V.D.S. Video Display Systems srl",A05AA4:"Grand Products Nevada, Inc.",A05B21:"ENVINET GmbH",A05DC1:"TMCT Co. Ltd",A05DE7:"DIRECTV, Inc.",A05E6B:"MELPER Co. Ltd",A06090:"Samsung Electronics Co. Ltd",A06391:"Netgear",A0648F:"Askey Computer Corp",A06518:"Vnpt Technology",A06610:"Fujitsu Limited",A067BE:"Sicon srl",A06986:"Wellav Technologies Ltd",A06A00:"Verilink Corporation",A06A44:"Vizio, Inc",A06CEC:"RIM",A06D09:"Intelcan Technosystems Inc.",A06E50:"Nanotek Elektronik Sistemler Ltd Sti.",A06FAA:"LG Innotek",A07099:"Beijing Huacan Electronics Co. Ltd",A071A9:"Nokia Corporation",A0722C:"HUMAX Co. Ltd",A072E4:"NJ System Co. Ltd",A07332:"Cashmaster International Limited",A073FC:"Rancore Technologies Private Limited",A07591:"Samsung Electronics Co. Ltd",A075EA:"BoxLock, Inc.",A07771:"Vialis BV",A078BA:"Pantech Co. Ltd",A0821F:"Samsung Electronics Co. Ltd",A082AC:"Linear DMS Solutions Sdn. Bhd.",A082C7:"P.T.I Co. Ltd",A084CB:"SonicSensory,Inc.",A0861D:"Chengdu Fuhuaxin Technology Co. Ltd",A086C6:"Xiaomi Communications Co Ltd",A086EC:"SAEHAN HITEC Co. Ltd",A08869:"Intel Corporation",A088B4:"Intel Corporation",A089E4:"Skyworth Digital Technology(Shenzhen) Co. Ltd",A08A87:"HuiZhou KaiYue Electronic Co. Ltd",A08C15:"Gerhard D. Wempe KG",A08C9B:"Xtreme Technologies Corp",A08CF8:"Huawei Technologies Co. Ltd",A08CFD:"Hewlett-Packard Company",A08D16:"Huawei Technologies Co. Ltd",A08E78:"Sagemcom Broadband SAS",A090DE:"Veedims,LLC",A09169:"LG Electronics (Mobile Communications)",A091C8:"zte Corporation",A09347:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",A0950C:"China Mobile IOTCompany Limited",A09805:"OpenVox Communication Co Ltd",A098ED:"Shandong Intelligent Optical Communication Development Co. Ltd",A0999B:"Apple",A09A5A:"Time Domain",A09BBD:"Total Aviation Solutions Pty Ltd",A09D86:"Alcatel-Lucent Shanghai Bell Co. Ltd",A09D91:"SoundBridge",A09DC1:"China Dragon Technology Limited",A09E1A:"Polar Electro Oy",A0A130:"DLI Taiwan Branch Office",A0A23C:"Gpms",A0A33B:"Huawei Technologies Co. Ltd",A0A3E2:"Actiontec Electronics, Inc",A0A65C:"Supercomputing Systems AG",A0A763:"Polytron Vertrieb GmbH",A0A8CD:"Intel Corporation",A0AAFD:"EraThink Technologies Corp.",A0AB1B:"D-Link International",A0ADA1:"JMR Electronics, Inc",A0AFBD:"Intel Corporation",A0B100:"ShenZhen Cando Electronics Co. Ltd",A0B3CC:"Hewlett-Packard Company",A0B437:"GD Mission Systems",A0B4A5:"Samsung Electronics Co. Ltd",A0B5DA:"HongKong THTF Co. Ltd",A0B662:"Acutvista Innovation Co. Ltd",A0B8F8:"Amgen U.S.A. Inc.",A0B9ED:"Skytap",A0BAB8:"Pixon Imaging",A0BB3E:"IEEE Registration Authority",A0BDCD:"BSkyB Ltd",A0BF50:"S.C. ADD-Production S.R.L.",A0BFA5:"Coresys",A0C2DE:"Costar Video Systems",A0C3DE:"Triton Electronic Systems Ltd",A0C4A5:"Sygn House Co. Ltd",A0C562:"ARRIS Group, Inc.",A0C589:"Intel Corporation",A0C5F2:"IEEE Registration Authority",A0C6EC:"ShenZhen ANYK Technology Co. Ltd",A0C9A0:"Murata Manufacturing Co. Ltd",A0CBFD:"Samsung Electronics Co. Ltd",A0CC2B:"Murata Manufacturing Co. Ltd",A0CEC8:"CE Link Limited",A0CF5B:"Cisco Systems Inc.",A0D12A:"AXPRO Technology Inc.",A0D37A:"Intel Corporation",A0D385:"AUMA Riester GmbH & Co. KG",A0D3C1:"Hewlett-Packard Company",A0D795:"Apple",A0D86F:"Private",A0DA92:"Nanjing Glarun Atten Technology Co. Ltd",A0DC04:"Becker-Antriebe GmbH",A0DD97:"PolarLink Technologies Ltd",A0DDE5:"Sharp Corporation",A0DE05:"JSC Irbis-T",A0E0AF:"Cisco Systems Inc.",A0E201:"AVTrace Ltd(China)",A0E25A:"Amicus SK, s.r.o.",A0E295:"DAT System Co. Ltd",A0E453:"Sony Mobile Communications AB",A0E4CB:"ZyXEL Communications Corp",A0E534:"Stratec Biomedical AG",A0E5E9:"enimai Inc",A0E617:"Matis",A0E6F8:"Texas Instruments",A0E9DB:"Ningbo FreeWings Technologies Co. Ltd",A0EB76:"AirCUVE Inc.",A0EC80:"zte Corporation",A0ECF9:"Cisco Systems Inc.",A0EDCD:"Apple",A0EF84:"Seine Image Int'l Co. Ltd",A0F217:"GE Medical System(China) Co. Ltd",A0F3C1:"TP-Link Technologies Co. Ltd",A0F3E4:"Alcatel-Lucent IPD",A0F419:"Nokia Corporation",A0F450:"HTC Corporation",A0F459:"FN-Link Technology Limited",A0F479:"Huawei Technologies Co. Ltd",A0F6FD:"Texas Instruments",A0F849:"Cisco Systems Inc.",A0F895:"Shenzhen TINNO Mobile Technology Corp.",A0F9E0:"Vivatel Company Limited",A0FC6E:"Telegrafia a.s.",A0FE61:"Vivint Wireless Inc.",A0FE91:"AVAT Automation GmbH",A40130:"ABIsystems Co. Ltd",A402B9:"Intel Corporation",A40450:"nFore Technology Inc.",A4059E:"STA Infinity LLP",A407B6:"Samsung Electronics Co. Ltd",A408EA:"Murata Manufacturing Co. Ltd",A408F5:"Sagemcom Broadband SAS",A409CB:"Alfred Kaercher GmbH & Co KG",A40BED:"Carry Technology Co. Ltd",A40CC3:"Cisco Systems Inc.",A40DBC:"Xiamen Intretech Inc.",A40E2B:"Facebook Inc",A41115:"Robert Bosch Engineering and Business Solutions pvt. Ltd",A41163:"IEEE Registration Authority",A41242:"NEC Platforms Ltd",A4134E:"Luxul",A41437:"Hangzhou Hikvision Digital Technology Co. Ltd",A41566:"Weifang GoerTek Technology Co. Ltd",A41588:"ARRIS Group, Inc.",A41731:"Hon Hai Precision Ind. Co. Ltd",A41875:"Cisco Systems Inc.",A41BC0:"Fastec Imaging Corporation",A41F72:"Dell Inc.",A4218A:"Nortel Networks",A42305:"Open Networking Laboratory",A424B3:"FlatFrog Laboratories AB",A424DD:"Cambrionix Ltd",A4251B:"Avaya Inc",A42940:"Shenzhen YOUHUA Technology Co. Ltd",A42983:"Boeing Defence Australia",A429B7:"bluesky",A42B8C:"Netgear",A42BB0:"TP-Link Technologies Co. Ltd",A42C08:"Masterwork Automodules",A43111:"ZIV",A43135:"Apple",A433D1:"Fibrlink Communications Co. Ltd",A433D7:"MitraStar Technology Corp.",A43412:"Thales Alenia Space",A434D9:"Intel Corporation",A434F1:"Texas Instruments",A43831:"RF elements s.r.o.",A438CC:"Nintendo Co. Ltd",A438FC:"Plastic Logic",A43A69:"Vers Inc",A43BFA:"IEEE Registration Authority",A43D78:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",A43E51:"Anov France",A44027:"zte Corporation",A444D1:"Wingtech Group (HongKong)Limited",A4466B:"EOC Technology",A446FA:"AmTRAN Video Corporation",A44AD3:"ST Electronics(Shanghai) Co. Ltd",A44B15:"Sun Cupid Technology (HK) Ltd",A44C11:"Cisco Systems Inc.",A44CC8:"Dell Inc.",A44E2D:"Adaptive Wireless Solutions, LLC",A44E31:"Intel Corporation",A44F29:"IEEE Registration Authority",A45055:"Busware.DE",A4516F:"Microsoft Mobile Oy",A4526F:"ADB Broadband Italia",A45385:"Weifang GoerTek Technology Co. Ltd",A45602:"fenglian Technology Co. Ltd",A4561B:"MCOT Corporation",A45630:"Cisco Systems Inc.",A4580F:"IEEE Registration Authority",A45A1C:"smart-electronic GmbH",A45C27:"Nintendo Co. Ltd",A45D36:"Hewlett-Packard Company",A45DA1:"ADB Broadband Italia",A45E60:"Apple",A46011:"Verifone",A46032:"MRV Communications (Networks) Ltd",A462DF:"DS Global. Co. Ltd",A46706:"Apple",A468BC:"Private",A46C2A:"Cisco Systems Inc.",A46CC1:"LTi REEnergy GmbH",A46CF1:"Samsung Electronics Co. Ltd",A46E79:"DFT System Co.Ltd",A470D6:"Motorola Mobility LLC, a Lenovo Company",A47174:"Huawei Technologies Co. Ltd",A47733:"Google, Inc.",A47758:"Ningbo Freewings Technologies Co. Ltd",A47760:"Nokia Corporation",A47886:"Avaya Inc",A479E4:"KLINFO Corp",A47AA4:"ARRIS Group, Inc.",A47ACF:"Vibicom Communications Inc.",A47B2C:"Nokia",A47B85:"ULTIMEDIA Co Ltd,",A47B9D:"Espressif Inc.",A47C14:"ChargeStorm AB",A47C1F:"Cobham plc",A47E39:"zte Corporation",A481EE:"Nokia Corporation",A48269:"Datrium, Inc.",A48431:"Samsung Electronics Co. Ltd",A4856B:"Q Electronics Ltd",A486AE:"Quectel Wireless Solutions",A4895B:"ARK Infosolutions PVT Ltd",A48CDB:"Lenovo",A48D3B:"Vizio, Inc",A48E0A:"DeLaval International AB",A49005:"China Greatwall Computer Shenzhen Co. Ltd",A491B1:"Technicolor",A4933F:"Huawei Technologies Co. Ltd",A4934C:"Cisco Systems Inc.",A497BB:"Hitachi Industrial Equipment Systems Co. Ltd",A49947:"Huawei Technologies Co. Ltd",A49981:"FuJian Elite Power Tech Co. Ltd",A49A58:"Samsung Electronics Co. Ltd",A49B13:"Digital Check",A49BF5:"Hybridserver Tec GmbH",A49D49:"Ketra, Inc.",A49EDB:"AutoCrib, Inc.",A49F85:"Lyve Minds, Inc",A49F89:"Shanghai Rui Rui Communication Technology Co.Ltd",A4A1C2:"Ericsson AB",A4A1E4:"Innotube, Inc.",A4A24A:"Cisco SPVTG",A4A4D3:"Bluebank Communication Technology Co.Ltd",A4A6A9:"Private",A4A80F:"Shenzhen Coship Electronics Co. Ltd",A4AD00:"Ragsdale Technology",A4ADB8:"Vitec Group, Camera Dynamics Ltd",A4AE9A:"Maestro Wireless Solutions Ltd",A4B121:"Arantia 2010 S.L.",A4B197:"Apple",A4B1E9:"Technicolor",A4B1EE:"H. ZANDER GmbH & Co. KG",A4B2A7:"Adaxys Solutions AG",A4B36A:"JSC SDO Chromatec",A4B52E:"Integrated Device Technology (Malaysia) Sdn. Bhd.",A4B805:"Apple",A4B818:"PENTA Gesellschaft f?r elektronische Industriedatenverarbeitung mbH",A4B980:"Parking BOXX Inc.",A4BA76:"Huawei Technologies Co. Ltd",A4BADB:"Dell Inc.",A4BBAF:"Lime Instruments",A4BE61:"EutroVision System, Inc.",A4BF01:"Intel Corporation",A4C0C7:"ShenZhen Hitom Communication Technology Co..Ltd",A4C0E1:"Nintendo Co. Ltd",A4C138:"Telink Semiconductor (Taipei) Co. Ltd",A4C2AB:"Hangzhou LEAD-IT Information & Technology Co. Ltd",A4C361:"Apple",A4C494:"Intel Corporation",A4C64F:"Huawei Technologies Co. Ltd",A4C7DE:"Cambridge Industries(Group) Co. Ltd",A4CAA0:"Huawei Technologies Co. Ltd",A4CC32:"Inficomm Co. Ltd",A4D094:"Erwin Peters Systemtechnik GmbH",A4D18C:"Apple",A4D18F:"Shenzhen Skyee Optical Fiber Communication Technology Ltd",A4D1D1:"ECOtality North America",A4D1D2:"Apple",A4D3B5:"GLITEL Stropkov, s.r.o.",A4D4B2:"Shenzhen MeiG Smart Technology Co. Ltd",A4D578:"Texas Instruments",A4D856:"Gimbal, Inc",A4D8CA:"Hong Kong Water World Technology Co. Limited",A4D9A4:"neXus ID Solutions AB",A4DA22:"IEEE Registration Authority",A4DA3F:"Bionics Corp.",A4DB2E:"Kingspan Environmental Ltd",A4DB30:"Liteon Technology Corporation",A4DCBE:"Huawei Technologies Co. Ltd",A4DE50:"Total Walther GmbH",A4DEC9:"QLove Mobile Intelligence Information Technology (W.H.) Co. Ltd",A4E0E6:"Filizola S.A. Pesagem E Automacao",A4E32E:"Silicon & Software Systems Ltd",A4E391:"Deny Fontaine",A4E4B8:"BlackBerry RTS",A4E597:"Gessler GmbH",A4E6B1:"Shanghai Joindata Technology Co. Ltd",A4E731:"Nokia Corporation",A4E7E4:"Connex GmbH",A4E975:"Apple",A4E991:"Sistemas Audiovisuales Itelsis S.L.",A4E9A3:"Honest Technology Co. Ltd",A4EBD3:"Samsung Electronics Co. Ltd",A4ED4E:"ARRIS Group, Inc.",A4EE57:"Seiko Epson Corporation",A4EF52:"Telewave Co. Ltd",A4F1E8:"Apple",A4F3C1:"Open Source Robotics Foundation, Inc.",A4F3E7:"Integrated Device Technology (Malaysia) Sdn. Bhd.",A4F4C2:"Vnpt Technology",A4F522:"Chofu Seisakusho Co. Ltd",A4F7D0:"LAN Accessories Co. Ltd",A4FB8D:"Hangzhou Dunchong Technology Co.Ltd",A4FCCE:"Security Expert Ltd",A80180:"IMAGO Technologies GmbH",A80600:"Samsung Electronics Co. Ltd",A80C0D:"Cisco Systems Inc.",A80C63:"Huawei Technologies Co. Ltd",A80CCA:"Shenzhen Sundray Technologies Company Limited",A811FC:"ARRIS Group, Inc.",A81374:"Panasonic Corporation AVC Networks Company",A8154D:"TP-Link Technologies Co. Ltd",A81559:"Breathometer, Inc.",A815D6:"Shenzhen Meione Technology Co. Ltd",A816B2:"LG Electronics (Mobile Communications)",A816D0:"Samsung Electronics Co. Ltd",A81758:"Elektronik System i Ume? AB",A81B18:"XTS Corp",A81B5A:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",A81B5D:"Foxtel Management Pty Ltd",A81B6A:"Texas Instruments",A81D16:"Azurewave Technologies Inc.",A81E84:"Quanta Computer Inc.",A81FAF:"Krypton Polska",A82066:"Apple",A824EB:"ZAO NPO Introtest",A825EB:"Cambridge Industries(Group) Co. Ltd",A826D9:"HTC Corporation",A8294C:"Precision Optical Transceivers, Inc.",A82BB5:"Edgecore Networks Corporation",A82BD6:"Shina System Co. Ltd",A830AD:"Weifang GoerTek Technology Co. Ltd",A8329A:"Digicom Futuristic Technologies Ltd",A8367A:"frogblue TECHNOLOGY GmbH",A83944:"Actiontec Electronics, Inc",A84041:"Dragino Technology Co., Limited",A84481:"Nokia Corporation",A845CD:"Siselectron Technology Ltd",A845E9:"Firich Enterprises Co. Ltd",A8474A:"Hon Hai Precision Ind. Co. Ltd",A849A5:"Lisantech Co. Ltd",A84E3F:"Hitron Technologies. Inc",A8515B:"Samsung Electronics Co. Ltd",A854B2:"Wistron Neweb Corporation",A8556A:"Pocketnet Technology Inc.",A8574E:"TP-Link Technologies Co. Ltd",A85840:"Cambridge Industries(Group) Co. Ltd",A85B78:"Apple",A85BB0:"Shenzhen Dehoo Technology Co. Ltd",A85BF3:"Audivo GmbH",A85C2C:"Apple",A85EE4:"12Sided Technology, LLC",A860B6:"Apple",A8610A:"Arduino AG",A861AA:"Cloudview Limited",A862A2:"Jiwumedia Co. Ltd",A863DF:"Displaire Corporation",A863F2:"Texas Instruments",A86405:"nimbus 9, Inc",A865B2:"Dongguan Yishang Electronic Technology Co., Limited",A8667F:"Apple",A86A6F:"RIM",A86AC1:"HanbitEDS Co. Ltd",A86B7C:"Shenzhen Fenglian Technology Co. Ltd",A86BAD:"Hon Hai Precision Ind. Co. Ltd",A870A5:"UniComm Inc.",A87285:"IDT, Inc.",A8741D:"PHOENIX CoNTACT Electronics GmbH",A875D6:"FreeTek International Co. Ltd",A875E2:"Aventura Technologies, Inc.",A8776F:"Zonoff",A87B39:"Nokia Corporation",A87C01:"Samsung Electronics Co. Ltd",A87E33:"Nokia Danmark A/S",A88038:"ShenZhen MovingComm Technology Co., Limited",A88195:"Samsung Electronics Co. Ltd",A881F1:"Bmeye B.V.",A88200:"Hisense Electric Co. Ltd",A8827F:"CIBN Oriental Network(Beijing) Co. Ltd",A886DD:"Apple",A88792:"Broadband Antenna Tracking Systems",A887ED:"ARC Wireless LLC",A88808:"Apple",A88CEE:"MicroMade Galka i Drozdz sp.j.",A88D7B:"SunDroid Global limited.",A88E24:"Apple",A89008:"Beijing Yuecheng Technology Co. Ltd",A8922C:"LG Electronics (Mobile Communications)",A89352:"Shanghai Zhongmi Communication Technology Co. Ltd",A893E6:"Jiangxi Jinggangshan Cking Communication Technology Co. Ltd",A895B0:"Aker Subsea Ltd",A89675:"Motorola Mobility LLC, a Lenovo Company",A8968A:"Apple",A897DC:"IBM",A898C6:"Shinbo Co. Ltd",A8995C:"aizo ag",A89B10:"inMotion Ltd",A89D21:"Cisco Systems Inc.",A89DD2:"Shanghai DareGlobal Technologies Co. Ltd",A89FBA:"Samsung Electronics Co. Ltd",A89FEC:"ARRIS Group, Inc.",A8A089:"Tactical Communications",A8A198:"TCT mobile Ltd",A8A5E2:"MSF-Vathauer Antriebstechnik GmbH & Co KG",A8A648:"Qingdao Hisense Communications Co. Ltd",A8A668:"zte Corporation",A8A795:"Hon Hai Precision Ind. Co. Ltd",A8AD3D:"Alcatel-Lucent Shanghai Bell Co. Ltd",A8B0AE:"Leoni",A8B1D4:"Cisco Systems Inc.",A8B2DA:"Fujitsu Limited",A8B86E:"LG Electronics (Mobile Communications)",A8B9B3:"Essys",A8BB50:"WiZ IoT Company Limited",A8BBCF:"Apple",A8BD1A:"Honey Bee (Hong Kong) Limited",A8BD27:"Hewlett Packard Enterprise",A8BD3A:"Unionman Technology Co. Ltd",A8BE27:"Apple",A8C222:"TM-Research Inc.",A8C83A:"Huawei Technologies Co. Ltd",A8C87F:"Roqos, Inc.",A8CA7B:"Huawei Technologies Co. Ltd",A8CB95:"East Best Co. Ltd",A8CCC5:"Saab AB (Publ)",A8CE90:"CVC",A8D0E3:"Systech Electronics Ltd",A8D0E5:"Juniper Networks",A8D236:"Lightware Visual Engineering",A8D3C8:"Topcon Electronics GmbH & Co. KG",A8D3F7:"Arcadyan Technology Corporation",A8D409:"USA 111 Inc",A8D579:"Beijing Chushang Science and Technology Co. Ltd",A8D828:"Ascensia Diabetes Care",A8D88A:"Wyconn",A8DA01:"Shenzhen NUOLIJIA Digital Technology Co. Ltd",A8E018:"Nokia Corporation",A8E3EE:"Sony Interactive Entertainment Inc.",A8E539:"Moimstone Co. Ltd",A8E705:"Fiberhome Telecommunication Technologies Co. Ltd",A8E824:"Inim Electronics S.R.L.",A8EEC6:"Muuselabs NV/SA",A8EF26:"Tritonwave",A8F038:"Shen Zhen SHI JIN HUA TAI Electronics Co. Ltd",A8F274:"Samsung Electronics Co. Ltd",A8F470:"Fujian Newland Communication Science Technologies Co. Ltd",A8F5AC:"Huawei Technologies Co. Ltd",A8F7E0:"PLANET Technology Corporation",A8F94B:"Eltex Enterprise Ltd",A8FAD8:"Apple",A8FB70:"WiseSec L.t.d",A8FCB7:"Consolidated Resource Imaging",AA0000:"Digital Equipment Corporation",AA0001:"Digital Equipment Corporation",AA0002:"Digital Equipment Corporation",AA0003:"Digital Equipment Corporation",AA0004:"Digital Equipment Corporation",AC0142:"Uriel Technologies SIA",AC02CA:"HI Solutions, Inc.",AC02CF:"RW Tecnologia Industria e Comercio Ltda",AC02EF:"Comsis",AC040B:"Peloton Interactive, Inc",AC0481:"Jiangsu Huaxing Electronics Co. Ltd",AC0613:"Senselogix Ltd",AC06C7:"ServerNet S.r.l.",AC075F:"Huawei Technologies Co. Ltd",AC0A61:"Labor S.r.L.",AC0D1B:"LG Electronics (Mobile Communications)",AC0DFE:"Ekon GmbH - myGEKKO",AC11D3:"Suzhou HOTEK Video Technology Co. Ltd",AC1461:"ATAW Co. Ltd",AC14D2:"wi-daq, Inc.",AC162D:"Hewlett-Packard Company",AC1702:"Fibar Group sp. z o.o.",AC17C8:"Cisco Meraki",AC1826:"Seiko Epson Corporation",AC199F:"Sungrow Power Supply Co. Ltd",AC1DDF:"IEEE Registration Authority",AC1F6B:"Super Micro Computer, Inc.",AC1F74:"Apple",AC1FD7:"Real Vision Technology Co. Ltd",AC202E:"Hitron Technologies. Inc",AC203E:"Wuhan Tianyu Information Industry Co. Ltd",AC20AA:"DMATEK Co. Ltd",AC2205:"Compal Broadband Networks, Inc.",AC220B:"ASUSTek Computer Inc.",AC233F:"Shenzhen Minew Technologies Co. Ltd",AC293A:"Apple",AC2A0C:"CSR Zhuzhou Institute Co. Ltd",AC2B6E:"Intel Corporation",AC2DA3:"TXTR GmbH",AC2FA8:"Humannix Co. Ltd",AC319D:"Shenzhen TG-NET Botone Technology Co. Ltd",AC34CB:"Shanhai GBCOM Communication Technology Co. Ltd",AC35EE:"FN-Link Technology Limited",AC3613:"Samsung Electronics Co. Ltd",AC3743:"HTC Corporation",AC3870:"Lenovo Mobile Communication Technology Ltd",AC3A7A:"Roku, Inc.",AC3C0B:"Apple",AC3CB4:"Nilan A/S",AC3D05:"Instorescreen Aisa",AC3D75:"Hangzhou Zhiway Technologies Co. Ltd",AC3FA4:"Taiyo Yuden Co. Ltd",AC40EA:"C&T Solution Inc.",AC4122:"Eclipse Electronic Systems Inc.",AC44F2:"Yamaha Corporation",AC4723:"Genelec",AC482D:"Ralinwi Nanjing Electronic Technology Co. Ltd",AC4AFE:"Hisense Broadband Multimedia Technology Co. Ltd",AC4BC8:"Juniper Networks",AC4E2E:"Shenzhen JingHanDa Electronics Co.Ltd",AC4E91:"Huawei Technologies Co. Ltd",AC4FFC:"SVS-VISTEK GmbH",AC5036:"Pi-Coral Inc",AC512C:"Infinix mobility limited",AC5135:"MPI Tech",AC51EE:"Cambridge Communication Systems Ltd",AC54EC:"IEEE P1823 Standards Working Group",AC562C:"Lava International(H.K) Limited",AC583B:"Human Assembler, Inc.",AC587B:"JCT Healthcare",AC5A14:"Samsung Electronics Co. Ltd",AC5D10:"Pace Americas",AC5E8C:"Utillink",AC5F3E:"Samsung Electro-Mechanics(Thailand)",AC60B6:"Ericsson AB",AC6123:"Drivven, Inc.",AC6175:"Huawei Technologies Co. Ltd",AC61EA:"Apple",AC620D:"Jabil Circuit(Wuxi) Co. Ltd",AC63BE:"Amazon Technologies Inc.",AC6417:"Siemens AG - Industrial Automation - EWA",AC6462:"zte Corporation",AC64DD:"IEEE Registration Authority",AC6706:"Ruckus Wireless",AC676F:"Electrocompaniet A.S.",AC6B0F:"Cadence Design Systems Inc",AC6BAC:"Jenny Science AG",AC6E1A:"Shenzhen Gongjin Electronics Co.,LT",AC6F4F:"Enspert Inc",AC6FBB:"TATUNG Technology Inc.",AC6FD9:"Valueplus Inc.",AC7236:"Lexking Technology Co. Ltd",AC7289:"Intel Corporation",AC7409:"Hangzhou H3C Technologies Co., Limited",AC7A42:"iConnectivity",AC7A4D:"Alps Electric Co. Ltd",AC7BA1:"Intel Corporation",AC7E8A:"Cisco Systems Inc.",AC7F3E:"Apple",AC80D6:"Hexatronic AB",AC8112:"Gemtek Technology Co. Ltd",AC81F3:"Nokia Corporation",AC8317:"Shenzhen Furtunetel Communication Co. Ltd",AC83F0:"ImmediaTV Corporation",AC83F3:"AMPAK Technology, Inc.",AC84C6:"TP-Link Technologies Co. Ltd",AC84C9:"Sagemcom Broadband SAS",AC853D:"Huawei Technologies Co. Ltd",AC8674:"Open Mesh, Inc.",AC867E:"Create New Technology (HK) Limited Company",AC87A3:"Apple",AC8995:"Azurewave Technologies Inc.",AC8ACD:"ROGER D.Wensker, G.Wensker sp.j.",AC8D14:"Smartrove Inc",AC932F:"Nokia Corporation",AC9403:"Envision Peripherals Inc",AC9A22:"NXP Semiconductors",AC9A96:"Lantiq Deutschland GmbH",AC9B0A:"Sony Corporation",AC9B84:"Smak Tecnologia e Automacao",AC9CE4:"Alcatel-Lucent Shanghai Bell Co. Ltd",AC9E17:"ASUSTek Computer Inc.",ACA016:"Cisco Systems Inc.",ACA213:"Shenzhen Bilian electronic Co. Ltd",ACA22C:"Baycity Technologies Ltd",ACA31E:"Aruba Networks",ACA430:"Peerless AV",ACA667:"Electronic Systems Protection, Inc.",ACA919:"TrekStor GmbH",ACA9A0:"Audioengine Ltd",ACAB2E:"Beijing LasNubes Technology Co. Ltd",ACAB8D:"Lyngso Marine A/S",ACABBF:"AthenTek Inc.",ACAFB9:"Samsung Electronics Co. Ltd",ACB313:"ARRIS Group, Inc.",ACB57D:"Liteon Technology Corporation",ACB74F:"METEL s.r.o.",ACB859:"Uniband Electronic Corp,",ACBC32:"Apple",ACBD0B:"Imac Co. Ltd",ACBE75:"Ufine Technologies Co. Ltd",ACBEB6:"Visualedge Technology Co. Ltd",ACC1EE:"Xiaomi Communications Co Ltd",ACC2EC:"CLT Int'l Ind. Corp.",ACC33A:"Samsung Electronics Co. Ltd",ACC51B:"Zhuhai Pantum Electronics Co. Ltd",ACC595:"Graphite Systems",ACC662:"MitraStar Technology Corp.",ACC698:"Kohzu Precision Co. Ltd",ACC73F:"Vitsmo Co. Ltd",ACC935:"Ness Corporation",ACCA54:"Telldus Technologies AB",ACCA8E:"ODA Technologies",ACCAAB:"Virtual Electric Inc",ACCABA:"Midokura Co. Ltd",ACCB09:"Hefcom Metering (Pty) Ltd",ACCC8E:"Axis Communications AB",ACCE8F:"HWA YAO Technologies Co. Ltd",ACCF23:"Hi-flying electronics technology Co. Ltd",ACCF5C:"Apple",ACCF85:"Huawei Technologies Co. Ltd",ACD074:"Espressif Inc.",ACD180:"Crexendo Business Solutions, Inc.",ACD1B8:"Hon Hai Precision Ind. Co. Ltd",ACD364:"ABB SPA, ABB Sace Div.",ACD657:"Shaanxi GuoLian Digital TV Technology Co. Ltd",ACD9D6:"tci GmbH",ACDBDA:"Shenzhen Geniatech Inc Ltd",ACDCE5:"Procter & Gamble Company",ACDE48:"Private",ACE010:"Liteon Technology Corporation",ACE069:"ISAAC Instruments",ACE215:"Huawei Technologies Co. Ltd",ACE2D3:"Hewlett-Packard Company",ACE348:"MadgeTech, Inc",ACE42E:"SK hynix",ACE4B5:"Apple",ACE5F0:"Doppler Labs",ACE64B:"Shenzhen Baojia Battery Technology Co. Ltd",ACE77B:"Sichuan Tianyi Comheart Telecomco. Ltd",ACE87B:"Huawei Technologies Co. Ltd",ACE87E:"Bytemark Computer Consulting Ltd",ACE97F:"IoT Tech Limited",ACE9AA:"Hay Systems Ltd",ACEA6A:"Genix Infocomm Co. Ltd",ACEC80:"ARRIS Group, Inc.",ACED5C:"Intel Corporation",ACEE3B:"6harmonics Inc",ACEE9E:"Samsung Electronics Co. Ltd",ACF0B2:"Becker Electronics Taiwan Ltd",ACF1DF:"D-Link International",ACF2C5:"Cisco Systems Inc.",ACF7F3:"Xiaomi Communications Co Ltd",ACF85C:"Private",ACF970:"Huawei Technologies Co. Ltd",ACF97E:"Elesys Inc.",ACFD93:"Weifang GoerTek Technology Co. Ltd",ACFDCE:"Intel Corporation",ACFDEC:"Apple",B000B4:"Cisco Systems Inc.",B00594:"Liteon Technology Corporation",B008BF:"Vital Connect, Inc.",B009D3:"Avizia",B009DA:"Ring Solutions",B01041:"Hon Hai Precision Ind. Co. Ltd",B01203:"Dynamics Hong Kong Limited",B01266:"Futaba-Kikaku",B01408:"Lightspeed International Co.",B01743:"Edison Global Circuits LLC",B019C6:"Apple",B01B7C:"Ontrol A.S.",B01BD2:"Le Shi Zhi Xin Electronic Technology (Tianjin) Limited",B01C91:"Elim Co",B01F29:"Helvetia Inc.",B01F81:"IEEE Registration Authority",B024F3:"Progeny Systems",B025AA:"Private",B02628:"Broadcom Limited",B02680:"Cisco Systems Inc.",B03495:"Apple",B0350B:"Mobiwire Mobiles (Ningbo) Co. Ltd",B0358D:"Nokia Corporation",B0359F:"Intel Corporation",B03829:"Siliconware Precision Industries Co. Ltd",B03850:"Nanjing CAS-ZDC IOT SysTEM Co. Ltd",B03956:"Netgear",B03D96:"Vision Valley FZ LLC",B03EB0:"MICRODIA Ltd",B04089:"Senient Systems Ltd",B0411D:"ITTIM Technologies",B0416F:"Shenzhen Maxtang Computer Co. Ltd",B0435D:"NuLEDs, Inc.",B04515:"mira fitness,LLC.",B04519:"TCT mobile Ltd",B04545:"YACOUB Automation GmbH",B046FC:"MitraStar Technology Corp.",B047BF:"Samsung Electronics Co. Ltd",B0481A:"Apple",B0487A:"TP-Link Technologies Co. Ltd",B0495F:"OMRON HEALTHCARE Co. Ltd",B04BBF:"PT HAN Sung Electoronics Indonesia",B04C05:"Fresenius Medical Care Deutschland GmbH",B04E26:"TP-Link Technologies Co. Ltd",B050BC:"Shenzhen Basicom Electronic Co. Ltd",B0518E:"Holl technology Co.Ltd",B05216:"Hon Hai Precision Ind. Co. Ltd",B05508:"Huawei Technologies Co. Ltd",B05706:"Vallox Oy",B058C4:"Broadcast Microwave Services, Inc",B05947:"Shenzhen Qihu Intelligent Technology Company Limited",B05ADA:"Hewlett-Packard Company",B05B1F:"Thermo Fisher Scientific S.P.A.",B05B67:"Huawei Technologies Co. Ltd",B05CE5:"Nokia Corporation",B061C7:"Ericsson-LG Enterprise",B06563:"Shanghai Railway Communication Factory",B065BD:"Apple",B0672F:"Bowers & Wilkins",B068B6:"Hangzhou OyE Technology Co. Ltd",B06971:"DEI Sales, Inc.",B06CBF:"3ality Digital Systems GmbH",B06EBF:"ASUSTek Computer Inc.",B0702D:"Apple",B072BF:"Murata Manufacturing Co. Ltd",B0750C:"QA Cafe",B0754D:"Nokia",B075D5:"zte Corporation",B077AC:"ARRIS Group, Inc.",B07870:"Wi-NEXT, Inc.",B078F0:"Beijing HuaqinWorld Technology Co. Ltd",B07908:"Cummings Engineering",B0793C:"Revolv Inc",B07994:"Motorola Mobility LLC, a Lenovo Company",B07D47:"Cisco Systems Inc.",B07D62:"Dipl.-Ing. H. Horstmann GmbH",B07E70:"Zadara Storage Ltd",B07FB9:"Netgear",B0808C:"Laser Light Engines",B081D8:"I-Sys Corp",B083D6:"ARRIS Group, Inc.",B083FE:"Dell Inc.",B0869E:"Chloride S.r.L",B08807:"Strata Worldwide",B08900:"Huawei Technologies Co. Ltd",B08991:"LGE",B089C2:"Zyptonite",B08E1A:"URadio Systems Co. Ltd",B09074:"Fulan Electronics Limited",B090D4:"Shenzhen Hoin Internet Technology Co. Ltd",B09122:"Texas Instruments",B09134:"Taleo",B09137:"ISis ImageStream Internet Solutions, Inc",B0935B:"ARRIS Group, Inc.",B0958E:"TP-Link Technologies Co. Ltd",B0966C:"Lanbowan Technology Ltd",B0973A:"E-Fuel Corporation",B0982B:"Sagemcom Broadband SAS",B0989F:"LG CNS",B09928:"Fujitsu Limited",B09AE2:"STEMMER IMAGING GmbH",B09BD4:"GNH Software India Private Limited",B09FBA:"Apple",B0A10A:"Pivotal Systems Corporation",B0A2E7:"Shenzhen TINNO Mobile Technology Corp.",B0A37E:"Qing DAO Haier Telecom Co. Ltd",B0A72A:"Ensemble Designs, Inc.",B0A737:"Roku, Inc.",B0A86E:"Juniper Networks",B0AA36:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",B0AA77:"Cisco Systems Inc.",B0ACD2:"zte Corporation",B0ACFA:"Fujitsu Limited",B0ADAA:"Avaya Inc",B0B28F:"Sagemcom Broadband SAS",B0B2DC:"ZyXEL Communications Corp",B0B32B:"Slican Sp. z o.o.",B0B3AD:"HUMAX Co. Ltd",B0B448:"Texas Instruments",B0B8D5:"Nanjing Nengrui Auto Equipment Co. Ltd",B0B98A:"Netgear",B0BD6D:"Echostreams Innovative Solutions",B0BDA1:"Zaklad Elektroniczny Sims",B0BF99:"Wizitdongdo",B0C090:"Chicony Electronics Co. Ltd",B0C128:"Adler ELREHA GmbH",B0C19E:"zte Corporation",B0C205:"Bionime",B0C287:"Technicolor CH USA Inc.",B0C46C:"Senseit",B0C4E7:"Samsung Electronics Co. Ltd",B0C554:"D-Link International",B0C559:"Samsung Electronics Co. Ltd",B0C5CA:"IEEE Registration Authority",B0C69A:"Juniper Networks",B0C745:"Buffalo.Inc",B0C83F:"Jiangsu Cynray IOT Co. Ltd",B0C8AD:"People Power Company",B0C95B:"Beijing Symtech Co. Ltd",B0CA68:"Apple",B0CE18:"Zhejiang shenghui lighting Co. Ltd",B0CF4D:"MI-Zone Technology Ireland",B0D09C:"Samsung Electronics Co. Ltd",B0D2F5:"Vello Systems, Inc.",B0D59D:"Shenzhen Zowee Technology Co. Ltd",B0D5CC:"Texas Instruments",B0D7C5:"Logipix Ltd",B0D7CC:"Tridonic GmbH & Co KG",B0DA00:"Cera Electronique",B0DAF9:"ARRIS Group, Inc.",B0DF3A:"Samsung Electronics Co. Ltd",B0DFC1:"Tenda Technology Co. LtdDongguan branch",B0E03C:"TCT mobile Ltd",B0E17E:"Huawei Technologies Co. Ltd",B0E235:"Xiaomi Communications Co Ltd",B0E2E5:"Fiberhome Telecommunication Technologies Co. Ltd",B0E39D:"CAT System Co. Ltd",B0E50E:"NRG Systems Inc",B0E5ED:"Huawei Technologies Co. Ltd",B0E754:"2Wire Inc.",B0E892:"Seiko Epson Corporation",B0E97E:"Advanced Micro Peripherals",B0EABC:"Askey Computer Corp",B0EC71:"Samsung Electronics Co. Ltd",B0EC8F:"GMX SAS",B0ECE1:"Private",B0EE45:"Azurewave Technologies Inc.",B0EE7B:"Roku, Inc",B0F1A3:"Fengfan (BeiJing) Technology Co. Ltd",B0F1BC:"Dhemax Ingenieros Ltda",B0F1EC:"AMPAK Technology, Inc.",B0F893:"Shanghai MXCHIP Information Technology Co. Ltd",B0F963:"Hangzhou H3C Technologies Co., Limited",B0FAEB:"Cisco Systems Inc.",B0FC36:"CyberTAN Technology Inc.",B0FEBD:"Private",B40016:"Ingenico Terminals SAS",B4009C:"CableWorld Ltd",B40142:"GCI Science & Technology Co. Ltd",B40418:"Smartchip Integrated Inc.",B40566:"SP Best Corporation Co. Ltd",B407F9:"Samsung Electro Mechanics Co. Ltd",B40832:"TC Communications",B40AC6:"DEXON Systems Ltd",B40B44:"Smartisan Technology Co. Ltd",B40B7A:"Brusa Elektronik AG",B40C25:"Palo Alto Networks",B40E96:"Heran",B40EDC:"LG-Ericsson Co. Ltd",B40F3B:"Tenda Technology Co. LtdDongguan branch",B41489:"Cisco Systems Inc.",B41513:"Huawei Technologies Co. Ltd",B41780:"DTI Group Ltd",B418D1:"Apple",B41C30:"zte Corporation",B41DEF:"Internet Laboratories, Inc.",B4211D:"Beijing GuangXin Technology Co. Ltd",B4218A:"Dog Hunter LLC",B424E7:"Codetek Technology Co. Ltd",B428F1:"E-Prime Co. Ltd",B4293D:"Shenzhen Urovo Technology Co. Ltd",B42A0E:"Technicolor CH USA Inc.",B42A39:"ORBIT MERRET, spol. s r. o.",B42C92:"Zhejiang Weirong Electronic Co. Ltd",B42CBE:"Direct Payment Solutions Limited",B42D56:"Extreme Networks, Inc.",B42EF8:"Eline Technology Co.Ltd",B43052:"Huawei Technologies Co. Ltd",B430C0:"York Instruments Ltd",B431B8:"Aviwest",B4346C:"Matsunichi Digital Technology (Hong Kong) Limited",B43564:"Fujian Tian Cheng Electron Science & Technical Development Co. Ltd",B435F7:"Zhejiang Pearmain Electronics Co.Ltd",B436A9:"Fibocom Wireless Inc.",B436E3:"Kbvision Group",B43741:"Consert, Inc.",B437D1:"IEEE Registration Authority",B43934:"Pen Generations, Inc.",B439D6:"ProCurve Networking by HP",B43A28:"Samsung Electronics Co. Ltd",B43DB2:"Degreane Horizon",B43E3B:"Viableware, Inc",B4417A:"Shenzhen Gongjin Electronics Co.,LT",B4430D:"Broadlink Pty Ltd",B4475E:"Avaya Inc",B44BD2:"Apple",B44CC2:"NR Electric Co. Ltd",B44F96:"Zhejiang Xinzailing Technology Co. Ltd",B451F9:"NB Software",B45253:"Seagate Technology",B4527D:"Sony Mobile Communications AB",B4527E:"Sony Mobile Communications AB",B45570:"Borea",B456B9:"Teraspek Technologies Co. Ltd",B45861:"CRemote, LLC",B45CA4:"Thing-talk Wireless Communication Technologies Corporation Limited",B45D50:"Aruba Networks",B461FF:"Lumigon A/S",B46238:"Exablox",B46293:"Samsung Electronics Co. Ltd",B462AD:"Elysia Germany GmbH",B46698:"Zealabs srl",B467E9:"Qingdao GoerTek Technology Co. Ltd",B46D35:"Dalian Seasky Automation Co;Ltd",B46D83:"Intel Corporation",B47356:"Hangzhou Treebear Networking Co. Ltd",B47443:"Samsung Electronics Co. Ltd",B47447:"CoreOS",B4749F:"Askey Computer Corp",B4750E:"Belkin International Inc.",B479A7:"Samsung Electro-Mechanics(Thailand)",B47C29:"Shenzhen Guzidi Technology Co. Ltd",B47C9C:"Amazon Technologies Inc.",B47F5E:"Foresight Manufacture (S) Pte Ltd",B481BF:"Meta-Networks, LLC",B48255:"Research Products Corporation",B4827B:"AKG Acoustics GmbH",B482C5:"Relay2, Inc.",B482FE:"Askey Computer Corp",B48547:"Amptown System Company GmbH",B48910:"Coster T.E. S.P.A.",B48B19:"Apple",B4944E:"WeTelecom Co. Ltd",B49691:"Intel Corporation",B49842:"zte Corporation",B4994C:"Texas Instruments",B499BA:"Hewlett-Packard Company",B49CDF:"Apple",B49D0B:"BQ",B49DB4:"Axion Technologies Inc.",B49EAC:"Imagik Int'l Corp",B49EE6:"Shenzhen Technology Co Ltd",B4A382:"Hangzhou Hikvision Digital Technology Co. Ltd",B4A4B5:"Zen Eye Co. Ltd",B4A4E3:"Cisco Systems Inc.",B4A5A9:"MODI GmbH",B4A5EF:"Sercomm Corporation.",B4A828:"Shenzhen Concox Information Technology Co. Ltd",B4A82B:"Histar Digital Electronics Co. Ltd",B4A8B9:"Cisco Systems Inc.",B4A95A:"Avaya Inc",B4A984:"Symantec Corporation",B4A9FE:"GHIA Technology (Shenzhen) Ltd",B4AA4D:"Ensequence, Inc.",B4AB2C:"MtM Technology Corporation",B4AE2B:"Microsoft Corporation",B4AE6F:"Circle Reliance, Inc DBA Cranberry Networks",B4B017:"Avaya Inc",B4B15A:"Siemens AG Energy Management Division",B4B265:"Daeho I&T",B4B362:"zte Corporation",B4B384:"ShenZhen Figigantic Electronic Co. Ltd",B4B52F:"Hewlett-Packard Company",B4B542:"Hubbell Power Systems, Inc.",B4B5AF:"Minsung Electronics",B4B676:"Intel Corporation",B4B859:"Texa Spa",B4B88D:"Thuh Company",B4BFF6:"Samsung Electronics Co. Ltd",B4C0F5:"Shenzhen TINNO Mobile Technology Corp.",B4C170:"Yi chip Microelectronics (Hangzhou) Co. Ltd",B4C44E:"VXL eTech Pvt Ltd",B4C6F8:"Axilspot Communication",B4C799:"Extreme Networks, Inc.",B4C810:"UMPI Elettronica",B4CCE9:"Prosyst",B4CD27:"Huawei Technologies Co. Ltd",B4CEF6:"HTC Corporation",B4CFDB:"Shenzhen Jiuzhou Electric Co. Ltd",B4D135:"Cloudistics",B4D5BD:"Intel Corporation",B4D64E:"Caldero Limited",B4D8A9:"BetterBots",B4D8DE:"iota Computing, Inc.",B4DD15:"ControlThings Oy Ab",B4DE31:"Cisco Systems Inc.",B4DEDF:"zte Corporation",B4DF3B:"Chromlech",B4DFFA:"Litemax Electronics Inc.",B4E01D:"Conception Electronique",B4E0CD:"Fusion-io, Inc",B4E10F:"Dell Inc.",B4E1C4:"Microsoft Mobile Oy",B4E1EB:"Private",B4E62A:"LG Innotek",B4E62D:"Espressif Inc.",B4E782:"Vivalnk",B4E9A3:"port GmbH",B4E9B0:"Cisco Systems Inc.",B4ED19:"Pie Digital, Inc.",B4ED54:"Wohler Technologies",B4EEB4:"Askey Computer Corp",B4EED4:"Texas Instruments",B4EF04:"DAIHAN Scientific Co. Ltd",B4EF39:"Samsung Electronics Co. Ltd",B4EFFA:"Lemobile Information Technology (Beijing) Co. Ltd",B4F0AB:"Apple",B4F1DA:"LG Electronics (Mobile Communications)",B4F2E8:"ARRIS Group, Inc.",B4F323:"Petatel Inc.",B4F61C:"Apple",B4F7A1:"LG Electronics (Mobile Communications)",B4F81E:"Kinova",B4FBE4:"Ubiquiti Networks Inc.",B4FBF9:"Huawei Technologies Co. Ltd",B4FC75:"SEMA Electronics(HK) Co. Ltd",B4FE8C:"Centro Sicurezza Italia SpA",B80018:"Htel",B80305:"Intel Corporation",B80415:"Bayan Audio",B805AB:"zte Corporation",B80716:"vivo Mobile Communication Co. Ltd",B808CF:"Intel Corporation",B808D7:"Huawei Technologies Co. Ltd",B8098A:"Apple",B80B9D:"ROPEX Industrie-Elektronik GmbH",B813E9:"Trace Live Network",B81413:"Keen High Holding(HK) Ltd",B81619:"ARRIS Group, Inc.",B816DB:"Chant Sincere Co. Ltd",B817C2:"Apple",B8186F:"Oriental Motor Co. Ltd",B81999:"Nesys",B81DAA:"LG Electronics (Mobile Communications)",B820E7:"Guangzhou Horizontal Information & Network Integration Co. Ltd",B8224F:"Sichuan Tianyi Comheart Telecomco. Ltd",B82410:"Magneti Marelli Slovakia s.r.o.",B8241A:"Sweda Informatica Ltda",B824F0:"SOYO Technology Development Co. Ltd",B8266C:"ANOV France",B826D4:"Furukawa Industrial S.A. Produtos El?tricos",B827EB:"Raspberry Pi Foundation",B8288B:"Parker Hannifin Manufacturing (UK) Ltd",B829F7:"Blaster Tech",B82A72:"Dell Inc.",B82ADC:"EFR Europ?ische Funk-Rundsteuerung GmbH",B82CA0:"Honeywell HomMed",B830A8:"Road-Track Telematics Development",B83241:"Wuhan Tianyu Information Industry Co. Ltd",B836D8:"Videoswitch",B83765:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",B83861:"Cisco Systems Inc.",B838CA:"Kyokko Tsushin System Co. Ltd",B83A08:"Tenda Technology Co. LtdDongguan branch",B83A7B:"Worldplay (Canada) Inc.",B83A9D:"Alarm.com",B83D4E:"Shenzhen Cultraview Digital Technology Co. Ltd Shanghai Branch",B83E59:"Roku, Inc.",B8415F:"ASP AG",B841A4:"Apple",B843E4:"Vlatacom",B844D9:"Apple",B847C6:"SanJet Technology Corp.",B84FD5:"Microsoft Corporation",B85001:"Extreme Networks, Inc.",B853AC:"Apple",B85510:"Zioncom Electronics (Shenzhen) Ltd",B856BD:"ITT LLC",B857D8:"Samsung Electronics Co. Ltd",B85810:"Numera, Inc.",B85A73:"Samsung Electronics Co. Ltd",B85AF7:"Ouya, Inc",B85AFE:"Handaer Communication Technology (Beijing) Co. Ltd",B85E7B:"Samsung Electronics Co. Ltd",B86091:"Onnet Technologies and Innovations LLC",B8616F:"Accton Technology Corp",B8621F:"Cisco Systems Inc.",B8634D:"Apple",B863BC:"ROBOTIS, Co Ltd",B86491:"CK Telecom Ltd",B8653B:"Bolymin, Inc.",B869C2:"Sunitec Enterprise Co. Ltd",B86B23:"Toshiba",B86CE8:"Samsung Electronics Co. Ltd",B870F4:"Compal Information (Kunshan) Co. Ltd",B87424:"Viessmann Elektronik GmbH",B87447:"Convergence Technologies",B875C0:"PayPal, Inc.",B8763F:"Hon Hai Precision Ind. Co. Ltd",B877C3:"METER Group",B8782E:"Apple",B87879:"Roche Diagnostics GmbH",B8797E:"Secure Meters (UK) Limited",B87AC9:"Siemens Ltd",B87CF2:"Aerohive Networks Inc.",B88198:"Intel Corporation",B88687:"Liteon Technology Corporation",B8871E:"Good Mind Industries Co. Ltd",B887A8:"Step Ahead Innovations Inc.",B888E3:"Compal Information (Kunshan) Co. Ltd",B88981:"Chengdu InnoThings Technology Co. Ltd",B889CA:"ILJIN ELECTRIC Co. Ltd",B88A60:"Intel Corporation",B88D12:"Apple",B88E3A:"Infinite Technologies JLT",B88EC6:"Stateless Networks",B88EDF:"Zencheer Communication Technology Co. Ltd",B88F14:"Analytica GmbH",B8921D:"BG T&A",B89436:"Huawei Technologies Co. Ltd",B894D2:"Retail Innovation HTT AB",B89674:"AllDSP GmbH & Co. KG",B8975A:"BIOSTAR Microtech Int'l Corp.",B898B0:"Atlona Inc.",B898F7:"Gionee Communication Equipment Co LtdShenZhen",B89919:"7signal Solutions, Inc",B899B0:"Cohere Technologies",B89ACD:"Elite Optoelectronic(Asia)Co. Ltd",B89AED:"OceanServer Technology, Inc",B89BC9:"SMC Networks Inc",B89BE4:"ABB Power Systems Power Generation",B89F09:"Wistron Neweb Corporation",B8A175:"Roku, Inc.",B8A386:"D-Link International",B8A3E0:"BenRui Technology Co. Ltd",B8A8AF:"Logic S.p.A.",B8AC6F:"Dell Inc.",B8AD3E:"Bluecom",B8AE6E:"Nintendo Co. Ltd",B8AEED:"Elitegroup Computer Systems Co. Ltd",B8AF67:"Hewlett-Packard Company",B8B1C7:"BT&CoM Co. Ltd",B8B2EB:"Googol Technology (HK) Limited",B8B3DC:"Derek (Shaoguan) Limited",B8B42E:"Gionee Communication Equipment Co LtdShenZhen",B8B7D7:"2GIG Technologies",B8B81E:"Intel Corporation",B8B94E:"Shenzhen iBaby Labs, Inc.",B8BA68:"Xi'an Jizhong Digital Communication Co. Ltd",B8BA72:"Cynove",B8BB23:"Guangdong Nufront CSC Co. Ltd",B8BB6D:"ENERES Co. Ltd",B8BBAF:"Samsung Electronics Co. Ltd",B8BC1B:"Huawei Technologies Co. Ltd",B8BD79:"TrendPoint Systems",B8BEBF:"Cisco Systems Inc.",B8BF83:"Intel Corporation",B8C111:"Apple",B8C1A2:"Dragon Path Technologies Co., Limited",B8C3BF:"Henan Chengshi NetWork Technology Co. Ltd",B8C46F:"Primmcon Industries Inc",B8C68E:"Samsung Electronics Co. Ltd",B8C716:"Fiberhome Telecommunication Technologies Co. Ltd",B8C75D:"Apple",B8C855:"Shanghai GBCOM Communication Technology Co. Ltd",B8C8EB:"Itel Mobile Limited",B8CA04:"Holtek Semiconductor Inc.",B8CA3A:"Dell Inc.",B8CD93:"Penetek, Inc",B8CDA7:"Maxeler Technologies Ltd",B8D06F:"Guangzhou Hkust FOK Ying Tung Research Institute",B8D49D:"M Seven System Ltd",B8D50B:"Sunitec Enterprise Co. Ltd",B8D7AF:"Murata Manufacturing Co. Ltd",B8D812:"IEEE Registration Authority",B8D94D:"Sagemcom Broadband SAS",B8D9CE:"Samsung Electronics Co. Ltd",B8DAF1:"Strahlenschutz- Entwicklungs- und Ausruestungsgesellschaft mbH",B8DAF7:"Advanced Photonics, Inc.",B8DB1C:"Integrated Device Technology (Malaysia) Sdn. Bhd.",B8DC87:"IAI Corporation",B8DE5E:"Longcheer Telecommunication Limited",B8DF6B:"SpotCam Co. Ltd",B8E589:"Payter BV",B8E625:"2Wire Inc.",B8E779:"9Solutions Oy",B8E856:"Apple",B8E937:"Sonos, Inc.",B8EAAA:"ICG NETWORKS Co. Ltd",B8ECA3:"ZyXEL Communications Corp",B8EE0E:"Sagemcom Broadband SAS",B8EE65:"Liteon Technology Corporation",B8EE79:"YWire Technologies, Inc.",B8F080:"SPS, Inc.",B8F317:"iSun Smasher Communications Private Limited",B8F4D0:"Herrmann Ultraschalltechnik GmbH & Co. Kg",B8F5E7:"WayTools, LLC",B8F6B1:"Apple",B8F732:"Aryaka Networks Inc",B8F74A:"Rcntec",B8F828:"Changshu Gaoshida Optoelectronic Technology Co. Ltd",B8F883:"TP-Link Technologies Co. Ltd",B8F8BE:"Bluecom",B8F934:"Sony Mobile Communications AB",B8FC9A:"Le Shi Zhi Xin Electronic Technology (Tianjin) Limited",B8FD32:"Zhejiang ROICX Microelectronics",B8FF61:"Apple",B8FF6F:"Shanghai Typrotech Technology Co.Ltd",B8FFB3:"MitraStar Technology Corp.",B8FFFE:"Texas Instruments",BC0200:"Stewart Audio",BC024A:"HMD Global Oy",BC0543:"AVM GmbH",BC0DA5:"Texas Instruments",BC0F2B:"Fortune Techgroup Co. Ltd",BC0F64:"Intel Corporation",BC0FA7:"Ouster",BC125E:"Beijing WisVideo Inc.",BC1401:"Hitron Technologies. Inc",BC1485:"Samsung Electronics Co. Ltd",BC14EF:"ITON Technology Limited",BC15A6:"Taiwan Jantek Electronics Ltd",BC15AC:"Vodafone Italia S.p.A.",BC1665:"Cisco Systems Inc.",BC16F5:"Cisco Systems Inc.",BC1A67:"YF Technology Co. Ltd",BC1C81:"Sichuan iLink Technology Co. Ltd",BC20A4:"Samsung Electronics Co. Ltd",BC20BA:"Inspur (Shandong) Electronic Information Co. Ltd",BC25E0:"Huawei Technologies Co. Ltd",BC25F0:"3D Display Technologies Co. Ltd",BC261D:"Hong Kong Tecon Technology",BC2643:"Elprotronic Inc.",BC282C:"e-Smart Systems Pvt. Ltd",BC2846:"NextBIT Computing Pvt. Ltd",BC28D6:"Rowley Associates Limited",BC2B6B:"Beijing Haier IC Design Co. Ltd",BC2BD7:"Revogi Innovation Co. Ltd",BC2C55:"Bear Flag Design, Inc.",BC2D98:"ThinGlobal LLC",BC2E48:"ARRIS Group, Inc.",BC2F3D:"vivo Mobile Communication Co. Ltd",BC305B:"Dell Inc.",BC307D:"Wistron Neweb Corporation",BC307E:"Wistron Neweb Corporation",BC3400:"IEEE Registration Authority",BC35E5:"Hydro Systems Company",BC38D2:"Pandachip Limited",BC39A6:"CSUN System Technology Co. Ltd",BC39D9:"Z-TEC",BC3AEA:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",BC3BAF:"Apple",BC3D85:"Huawei Technologies Co. Ltd",BC3E13:"Accordance Systems Inc.",BC3F8F:"Huawei Technologies Co. Ltd",BC4100:"CoDACO ELECTRONIC s.r.o.",BC4101:"Shenzhen TINNO Mobile Technology Corp.",BC4377:"Hang Zhou Huite Technology Co. Ltd",BC4434:"Shenzhen TINNO Mobile Technology Corp.",BC4486:"Samsung Electronics Co. Ltd",BC44B0:"Elastifile",BC452E:"Knowledge Development for POF S.L.",BC4699:"TP-Link Technologies Co. Ltd",BC4760:"Samsung Electronics Co. Ltd",BC4B79:"SensingTek",BC4CC4:"Apple",BC4DFB:"Hitron Technologies. Inc",BC4E3C:"Core Staff Co. Ltd",BC4E5D:"ZhongMiao Technology Co. Ltd",BC51FE:"Swann Communications Pty Ltd",BC52B4:"Nokia",BC52B7:"Apple",BC5436:"Apple",BC5451:"Samsung Electronics Co. Ltd",BC54F9:"Drogoo Technology Co. Ltd",BC54FC:"Shenzhen Mercury Communication Technologies Co. Ltd",BC5C4C:"Elecom Co. Ltd",BC5FF4:"ASRock Incorporation",BC5FF6:"Shenzhen Mercury Communication Technologies Co. Ltd",BC6010:"Qingdao Hisense Communications Co. Ltd",BC60A7:"Sony Interactive Entertainment Inc.",BC620E:"Huawei Technologies Co. Ltd",BC629F:"Telenet Systems P. Ltd",BC644B:"ARRIS Group, Inc.",BC6641:"IEEE Registration Authority",BC66DE:"Shadow Creator Information Technology Co. Ltd",BC671C:"Cisco Systems Inc.",BC6778:"Apple",BC6784:"Environics Oy",BC6A16:"tdvine",BC6A29:"Texas Instruments",BC6A2F:"Henge Docks LLC",BC6A44:"Commend International GmbH",BC6B4D:"Nokia",BC6C21:"Apple",BC6E64:"Sony Mobile Communications AB",BC6E76:"Green Energy Options Ltd",BC71C1:"XTrillion, Inc.",BC72B1:"Samsung Electronics Co. Ltd",BC74D7:"HangZhou JuRu Technology Co. Ltd",BC7574:"Huawei Technologies Co. Ltd",BC764E:"Rackspace US, Inc.",BC765E:"Samsung Electronics Co. Ltd",BC7670:"Huawei Technologies Co. Ltd",BC7737:"Intel Corporation",BC779F:"SBM Co. Ltd",BC79AD:"Samsung Electronics Co. Ltd",BC7DD1:"Radio Data Comms",BC811F:"Ingate Systems",BC8199:"BASIC Co. Ltd",BC825D:"Mitsumi Electric Co. Ltd",BC8385:"Microsoft Corporation",BC83A7:"Shenzhen Chuangwei-RGB Electronics Co. Ltd",BC851F:"Samsung Electronics Co. Ltd",BC8556:"Hon Hai Precision Ind. Co. Ltd",BC8893:"VILLBAU Ltd",BC88C3:"Ningbo Dooya Mechanic & Electronic Technology Co. Ltd",BC8AA3:"NHN Entertainment",BC8AE8:"Qing DAO Haier Telecom Co. Ltd",BC8B55:"NPP ELIKS America Inc. DBA T&M Atlantic",BC8CCD:"Samsung Electro-Mechanics(Thailand)",BC8D0E:"Nokia",BC903A:"Robert Bosch GmbH",BC91B5:"Infinix mobility limited",BC926B:"Apple",BC9680:"Shenzhen Gongjin Electronics Co.,LT",BC9889:"Fiberhome Telecommunication Technologies Co. Ltd",BC99BC:"FonSee Technology Inc.",BC9C31:"Huawei Technologies Co. Ltd",BC9CC5:"Beijing Huafei Technology Co. Ltd",BC9DA5:"DASCOM Europe GmbH",BC9FEF:"Apple",BCA042:"Shanghai Flyco Electrical Appliance Co. Ltd",BCA4E1:"Nabto",BCA8A6:"Intel Corporation",BCA920:"Apple",BCA9D6:"Cyber-Rain, Inc.",BCAB7C:"TRnP KOREA Co Ltd",BCAD28:"Hangzhou Hikvision Digital Technology Co. Ltd",BCADAB:"Avaya Inc",BCAEC5:"ASUSTek Computer Inc.",BCB181:"Sharp Corporation",BCB1F3:"Samsung Electronics Co. Ltd",BCB308:"Hongkong Ragentek Communication Technology Co.,Limited",BCB852:"Cybera, Inc.",BCBAE1:"AREC Inc.",BCBBC9:"Kellendonk Elektronik GmbH",BCBC46:"SKS Welding Systems GmbH",BCC00F:"Fiberhome Telecommunication Technologies Co. Ltd",BCC168:"DinBox Sverige AB",BCC23A:"Thomson Video Networks",BCC31B:"Kygo Life AS",BCC342:"Panasonic Communications Co. Ltd",BCC493:"Cisco Systems Inc.",BCC61A:"Spectra Embedded Systems",BCC6DB:"Nokia Corporation",BCC810:"Cisco SPVTG",BCCAB5:"ARRIS Group, Inc.",BCCD45:"Voismart",BCCFCC:"HTC Corporation",BCD11F:"Samsung Electronics Co. Ltd",BCD165:"Cisco SPVTG",BCD177:"TP-Link Technologies Co. Ltd",BCD1D3:"Shenzhen TINNO Mobile Technology Corp.",BCD5B6:"d2d technologies",BCD713:"Owl Labs",BCD940:"ASR Co,.Ltd",BCDDC2:"Espressif Inc.",BCE09D:"Eoslink",BCE143:"Apple",BCE59F:"WATERWORLD Technology Co. Ltd",BCE63F:"Samsung Electronics Co. Ltd",BCE767:"Quanzhou TDX Electronics Co. Ltd",BCEA2B:"CityCom GmbH",BCEAFA:"Hewlett-Packard Company",BCEB5F:"Fujian Beifeng Telecom Technology Co. Ltd",BCEC23:"Shenzhen Chuangwei-RGB Electronics Co. Ltd",BCEC5D:"Apple",BCEE7B:"ASUSTek Computer Inc.",BCF1F2:"Cisco Systems Inc.",BCF292:"Plantronics, Inc.",BCF2AF:"devolo AG",BCF5AC:"LG Electronics (Mobile Communications)",BCF61C:"Geomodeling Wuxi Technology Co. Ltd",BCF685:"D-Link International",BCF811:"Xiamen DNAKE Technology Co. Ltd",BCFE8C:"Altronic, LLC",BCFFAC:"Topcon Corporation",BCFFEB:"Motorola Mobility LLC, a Lenovo Company",C0028D:"WINSTAR Display Co. Ltd",C005C2:"ARRIS Group, Inc.",C00D7E:"Additech, Inc.",C01173:"Samsung Electronics Co. Ltd",C011A6:"Fort-Telecom Ltd",C01242:"Alpha Security Products",C0143D:"Hon Hai Precision Ind. Co. Ltd",C0174D:"Samsung Electronics Co. Ltd",C01885:"Hon Hai Precision Ind. Co. Ltd",C01ADA:"Apple",C01E9B:"Pixavi AS",C0210D:"Shenzhen RF-Link Technology Co. Ltd",C02250:"Private",C02506:"AVM GmbH",C0255C:"Cisco Systems Inc.",C02567:"Nexxt Solutions",C025A2:"NEC Platforms Ltd",C025E9:"TP-Link Technologies Co. Ltd",C027B9:"Beijing National Railway Research & Design Institute Of Signal & Communication Co. Ltd",C0288D:"Logitech, Inc",C02973:"Audyssey Laboratories Inc.",C029F3:"XySystem",C02BFC:"iNES. applied Informatics GmbH",C02C7A:"Shenzhen Horn Audio Co. Ltd",C02DEE:"Cuff",C02FF1:"Volta Networks",C0335E:"Microsoft Corporation",C034B4:"Gigastone Corporation",C03580:"A&R Tech",C035BD:"Velocytech Aps",C035C5:"Prosoft Systems Ltd",C03896:"Hon Hai Precision Ind. Co. Ltd",C038F9:"Nokia Danmark A/S",C03B8F:"Minicom Digital Signage",C03D46:"Shanghai Sango Network Technology Co. Ltd",C03E0F:"BSkyB Ltd",C03F0E:"Netgear",C03F2A:"Biscotti, Inc.",C03FD5:"Elitegroup Computer Systems Co. Ltd",C041F6:"LG Electronics Inc",C042D0:"Juniper Networks",C04301:"Epec Oy",C044E3:"Shenzhen Sinkna Electronics Co. Ltd",C048E6:"Samsung Electronics Co. Ltd",C0493D:"Maitrise Technologique",C04A00:"TP-Link Technologies Co. Ltd",C04A09:"Zhejiang Everbright Communication Equip. Co,. Ltd",C04DF7:"Serelec",C05627:"Belkin International Inc.",C056E3:"Hangzhou Hikvision Digital Technology Co. Ltd",C057BC:"Avaya Inc",C058A7:"Pico Systems Co. Ltd",C05E6F:"V. Stonkaus firma Kodinis Raktas",C05E79:"Shenzhen Huaxun ARK Technologies Co. Ltd",C06118:"TP-Link Technologies Co. Ltd",C0626B:"Cisco Systems Inc.",C06394:"Apple",C064C6:"Nokia Corporation",C06599:"Samsung Electronics Co. Ltd",C067AF:"Cisco Systems Inc.",C06C0F:"Dobbs Stanford",C06C6D:"MagneMotion, Inc.",C06D1A:"Tianjin Henxinhuifeng Technology Co. Ltd",C07009:"Huawei Technologies Co. Ltd",C0742B:"Shenzhen Xunlong Software Co.,Limited",C07BBC:"Cisco Systems Inc.",C07CD1:"Pegatron Corporation",C07E40:"Shenzhen XDK Communication Equipment Co. Ltd",C08170:"Effigis GeoSolutions",C0830A:"2Wire Inc.",C0847A:"Apple",C08488:"Finis Inc",C0854C:"Ragentek Technology Group",C087EB:"Samsung Electronics Co. Ltd",C0885B:"SnD Tech Co. Ltd",C08997:"Samsung Electronics Co. Ltd",C08ADE:"Ruckus Wireless",C08B6F:"S I Sistemas Inteligentes Eletr?nicos Ltda",C08C60:"Cisco Systems Inc.",C09132:"Patriot Memory",C09134:"ProCurve Networking by HP",C09727:"Samsung Electro-Mechanics(Thailand)",C09879:"Acer Inc.",C098DA:"China Mobile IOT Company Limited",C098E5:"University Of Michigan",C09A71:"Xiamen Meitu Mobile Technology Co.Ltd",C09C04:"Shaanxi GuoLian Digital TV Technology Co. Ltd",C09C92:"Coby",C09D26:"Topicon HK Lmd.",C09F05:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",C09F42:"Apple",C0A00D:"ARRIS Group, Inc.",C0A0BB:"D-Link International",C0A0C7:"Fairfield Industries",C0A0DE:"Multi Touch Oy",C0A0E2:"Eden Innovations",C0A1A2:"MarqMetrix",C0A26D:"Abbott Point Of Care",C0A364:"3D Systems Massachusetts",C0A39E:"EarthCam, Inc.",C0A53E:"Apple",C0A5DD:"Shenzhen Mercury Communication Technologies Co. Ltd",C0A8F0:"Adamson Systems Engineering",C0AA68:"OSASI Technos Inc.",C0AC54:"Sagemcom Broadband SAS",C0B339:"Comigo Ltd",C0B357:"Yoshiki Electronics Industry Ltd",C0B658:"Apple",C0B713:"Beijing Xiaoyuer Technology Co. Ltd",C0B8B1:"BitBox Ltd",C0BAE6:"Application Solutions (Electronics and Vision) Ltd",C0BD42:"ZPA Smart Energy a.s.",C0BDD1:"Samsung Electro-Mechanics(Thailand)",C0BFC0:"Huawei Technologies Co. Ltd",C0C1C0:"Cisco-Linksys LLC",C0C3B6:"Automatic Systems",C0C520:"Ruckus Wireless",C0C522:"ARRIS Group, Inc.",C0C569:"Shanghai Lynuc CNC Technology Co. Ltd",C0C687:"Cisco SPVTG",C0C946:"Mitsuya Laboratories Inc.",C0C976:"Shenzhen TINNO Mobile Technology Corp.",C0CB38:"Hon Hai Precision Ind. Co. Ltd",C0CCF8:"Apple",C0CECD:"Apple",C0CFA3:"Creative Electronics & Software, Inc.",C0D012:"Apple",C0D044:"Sagemcom Broadband SAS",C0D391:"IEEE Registration Authority",C0D3C0:"Samsung Electronics Co. Ltd",C0D962:"Askey Computer Corp",C0D9F7:"ShanDong Domor Intelligent S&T Co. Ltd",C0DA74:"Hangzhou Sunyard Technology Co. Ltd",C0DC6A:"Qingdao Eastsoft Communication Technology Co. Ltd",C0DF77:"Conrad Electronic SE",C0E422:"Texas Instruments",C0E42D:"TP-Link Technologies Co. Ltd",C0E54E:"ARIES Embedded GmbH",C0EAE4:"Sonicwall",C0EE40:"Laird Technologies",C0EEB5:"Enice Network.",C0EEFB:"OnePlus Tech (Shenzhen) Ltd",C0F1C4:"Pacidal Corporation Ltd",C0F2FB:"Apple",C0F636:"Hangzhou Kuaiyue Technologies Ltd",C0F79D:"Powercode",C0F8DA:"Hon Hai Precision Ind. Co. Ltd",C0F945:"Toshiba Toko Meter Systems Co. Ltd",C0F991:"GME Standard Communications P/L",C0FFD4:"Netgear",C40006:"Lipi Data Systems Ltd",C40049:"Kamama",C400AD:"Advantech Technology (CHINA) Co. Ltd",C40142:"MaxMedia Technology Limited",C4017C:"Ruckus Wireless",C401B1:"SeekTech Inc",C401CE:"Presition (2000) Co. Ltd",C40415:"Netgear",C4047B:"Shenzhen YOUHUA Technology Co. Ltd",C40528:"Huawei Technologies Co. Ltd",C4072F:"Huawei Technologies Co. Ltd",C4084A:"Nokia",C40880:"Shenzhen UTEPO Tech Co. Ltd",C40938:"Fujian Star-NET Communication Co. Ltd",C40ACB:"Cisco Systems Inc.",C40BCB:"Xiaomi Communications Co Ltd",C40E45:"ACK Networks,Inc.",C40F09:"Hermes electronic GmbH",C4108A:"Ruckus Wireless",C411E0:"Bull Group Co. Ltd",C412F5:"D-Link International",C413E2:"Aerohive Networks Inc.",C4143C:"Cisco Systems Inc.",C416FA:"Prysm Inc",C417FE:"Hon Hai Precision Ind. Co. Ltd",C4198B:"Dominion Voting Systems Corporation",C419EC:"Qualisys AB",C41CFF:"Vizio, Inc",C41ECE:"HMI Sources Ltd",C421C8:"Kyocera Corporation",C4237A:"WhizNets Inc.",C4242E:"Galvanic Applied Sciences Inc",C42628:"Airo Wireless",C42795:"Technicolor CH USA Inc.",C4282D:"Embedded Intellect Pty Ltd",C4291D:"Klemsan Elektrik Elektronik SAN.VE TIC.AS.",C42C03:"Apple",C42C4F:"Qingdao Hisense Mobile Communication Technology Co Ltd",C42F90:"Hangzhou Hikvision Digital Technology Co. Ltd",C43018:"MCS Logic Inc.",C43306:"China Mobile Group Device Co. Ltd",C4346B:"Hewlett-Packard Company",C43655:"Shenzhen Fenglian Technology Co. Ltd",C4366C:"LG Innotek",C436DA:"Rusteletech Ltd",C438D3:"Tagatec Co. Ltd",C4393A:"SMC Networks Inc",C43A9F:"Siconix Inc.",C43ABE:"Sony Mobile Communications AB",C43C3C:"Cybelec SA",C43DC7:"Netgear",C44044:"RackTop Systems Inc.",C44202:"Samsung Electronics Co. Ltd",C4438F:"LG Electronics (Mobile Communications)",C444A0:"Cisco Systems Inc.",C44567:"SAMBON PRECISON and ELECTRONICS",C445EC:"Shanghai Yali Electron Co. Ltd",C44619:"Hon Hai Precision Ind. Co. Ltd",C4473F:"Huawei Technologies Co. Ltd",C44838:"Satcom Direct, Inc.",C449BB:"Mitsumi Electric Co. Ltd",C44AD0:"Fireflies Systems",C44B44:"Omniprint Inc.",C44BD1:"Wallys Communications Teachnologies Co. Ltd",C44E1F:"BlueN",C44EAC:"Shenzhen Shiningworth Technology Co. Ltd",C45006:"Samsung Electronics Co. Ltd",C45444:"Quanta Computer Inc.",C455A6:"Cadac Holdings Ltd",C455C2:"Bach-Simpson",C45600:"Galleon Embedded Computing",C456FE:"Lava International Ltd",C4571F:"June Life Inc",C4576E:"Samsung Electronics Co. Ltd",C458C2:"Shenzhen TATFOOK Technology Co. Ltd",C45976:"Fugoo Coorporation",C45DD8:"HDMI Forum",C46044:"Everex Electronics Limited",C4618B:"Apple",C4626B:"ZPT Vigantice",C462EA:"Samsung Electronics Co. Ltd",C46354:"U-Raku, Inc.",C46413:"Cisco Systems Inc.",C464E3:"Texas Instruments",C46699:"vivo Mobile Communication Co. Ltd",C467B5:"Libratone A/S",C468D0:"VTech Telecommunications Ltd",C4693E:"Turbulence Design Inc.",C46AB7:"Xiaomi Communications Co Ltd",C46BB4:"myIDkey",C46DF1:"DataGravity",C46E1F:"TP-Link Technologies Co. Ltd",C4700B:"Guangzhou Chip Technologies Co. Ltd",C47130:"Fon Technology S.L.",C47154:"TP-Link Technologies Co. Ltd",C471FE:"Cisco Systems Inc.",C47295:"Cisco Systems Inc.",C4731E:"Samsung Electronics Co. Ltd",C477AB:"Beijing ASU Tech Co. Ltd",C477AF:"Advanced Digital Broadcast SA",C47B2F:"Beijing JoinHope Image Technology Ltd",C47BA3:"NAVIS Inc.",C47C8D:"IEEE Registration Authority",C47D46:"Fujitsu Limited",C47D4F:"Cisco Systems Inc.",C47DCC:"Zebra Technologies Inc",C47DFE:"A.N. Solutions GmbH",C47F51:"Inventek Systems",C4823F:"Fujian Newland Auto-ID Tech. Co,.Ltd",C4824E:"Changzhou Uchip Electronics Co. Ltd",C4836F:"Ciena Corporation",C48466:"Apple",C48508:"Intel Corporation",C486E9:"Huawei Technologies Co. Ltd",C488E5:"Samsung Electronics Co. Ltd",C48E8F:"Hon Hai Precision Ind. Co. Ltd",C48F07:"Shenzhen Yihao Hulian Science and Technology Co. Ltd",C4913A:"Shenzhen Sanland Electronic Co. Ltd",C4924C:"Keisokuki Center Co. Ltd",C49300:"8Devices",C49313:"100fio networks technology llc",C49380:"Speedytel technology",C495A2:"Shenzhen Weijiu Industry AND Trade Development Co. Ltd",C49805:"Minieum Networks, Inc",C49880:"Apple",C49A02:"LG Electronics (Mobile Communications)",C49DED:"Microsoft Corporation",C49E41:"G24 Power Limited",C49F4C:"Huawei Technologies Co. Ltd",C49FF3:"Mciao Technologies, Inc.",C4A366:"zte Corporation",C4A81D:"D-Link International",C4AAA1:"SUMMIT DEVELOPMENT, spol.s r.o.",C4ABB2:"vivo Mobile Communication Co. Ltd",C4AD21:"MEDIAEDGE Corporation",C4ADF1:"GOPEACE Inc.",C4AE12:"Samsung Electronics Co. Ltd",C4B301:"Apple",C4B512:"General Electric Digital Energy",C4B9CD:"Cisco Systems Inc.",C4BA99:"I+ME Actia Informatik und Mikro-Elektronik GmbH",C4BAA3:"Beijing Winicssec Technologies Co. Ltd",C4BB4C:"Zebra Information Tech Co. Ltd",C4BBEA:"Pakedge Device and Software Inc",C4BD6A:"SKF GmbH",C4BE84:"Texas Instruments",C4BED4:"Avaya Inc",C4C0AE:"Midori Electronic Co. Ltd",C4C19F:"National Oilwell Varco Instrumentation, Monitoring, and Optimization (NOV IMO)",C4C563:"Tecno Mobile Limited",C4C755:"Beijing HuaqinWorld Technology Co. Ltd",C4C919:"Energy Imports Ltd",C4C9EC:"Gugaoo HK Limited",C4CAD9:"Hangzhou H3C Technologies Co., Limited",C4CB6B:"Airista Flow, Inc.",C4CD45:"Beijing Boomsense Technology Co. Ltd",C4CD82:"Hangzhou Lowan Information Technology Co. Ltd",C4D197:"Ventia Utility Services",C4D489:"JiangSu Joyque Information Industry Co. Ltd",C4D655:"Tercel technology Co. Ltd",C4D987:"Intel Corporation",C4DA26:"Noblex SA",C4DA7D:"Ivium Technologies B.V.",C4E032:"IEEE 1904.1 Working Group",C4E17C:"U2S Co.",C4E510:"Mechatro, Inc.",C4E7BE:"SCSpro Co. Ltd",C4E92F:"AB Sciex",C4E984:"TP-Link Technologies Co. Ltd",C4EA1D:"Technicolor",C4EBE3:"Rrcn SAS",C4EDBA:"Texas Instruments",C4EEAE:"VSS Monitoring",C4EEF5:"II-VI Incorporated",C4EF70:"Home Skinovations",C4F081:"Huawei Technologies Co. Ltd",C4F1D1:"Beijing Sogou Technology Development Co. Ltd",C4F312:"Texas Instruments",C4F464:"Spica international",C4F57C:"Brocade Communications Systems, Inc.",C4F5A5:"Kumalift Co. Ltd",C4FCE4:"DishTV NZ Ltd",C4FF1F:"Huawei Technologies Co. Ltd",C4FFBC:"IEEE Registration Authority",C80084:"Cisco Systems Inc.",C80210:"LG Innotek",C80258:"ITW GSE ApS",C8028F:"Nova Electronics (Shanghai) Co. Ltd",C802A6:"Beijing Newmine Technology",C80718:"TDSi",C808E9:"LG Electronics",C80AA9:"Quanta Computer Inc.",C80CC8:"Huawei Technologies Co. Ltd",C80E14:"AVM Audiovisuelles Marketing und Computersysteme GmbH",C80E77:"Le Shi Zhi Xin Electronic Technology (Tianjin) Limited",C80E95:"OmniLync Inc.",C81073:"Century Opticomm Co. Ltd",C81451:"Huawei Technologies Co. Ltd",C81479:"Samsung Electronics Co. Ltd",C816A5:"Masimo Corporation",C816BD:"Qingdao Hisense Communications Co. Ltd",C819F7:"Samsung Electronics Co. Ltd",C81AFE:"DLOGIC GmbH",C81B5C:"BCTech",C81B6B:"Innova Security",C81E8E:"ADV Security (S) Pte Ltd",C81EE7:"Apple",C81F66:"Dell Inc.",C81FBE:"Huawei Technologies Co. Ltd",C81FEA:"Avaya Inc",C8208E:"Storagedata",C82158:"Intel Corporation",C825E1:"Lemobile Information Technology (Beijing) Co. Ltd",C8292A:"Barun Electronics",C82A14:"Apple",C82E94:"Halfa Enterprise Co. Ltd",C83168:"eZEX Corporation",C83232:"Hunting Innova",C8334B:"Apple",C8348E:"Intel Corporation",C835B8:"Ericsson, EAB/RWI/K",C83870:"Samsung Electronics Co. Ltd",C83A35:"Tenda Technology Co. Ltd",C83A6B:"Roku, Inc",C83B45:"JRI",C83C85:"Apple",C83D97:"Nokia Corporation",C83DD4:"CyberTAN Technology Inc.",C83DFC:"Pioneer DJ Corporation",C83E99:"Texas Instruments",C83EA7:"KUNBUS GmbH",C83F26:"Microsoft Corporation",C83FB4:"ARRIS Group, Inc.",C84029:"Fiberhome Telecommunication Technologies Co. Ltd",C84529:"IMK Networks Co. Ltd",C84544:"Asia Pacific CIS (Wuxi) Co Ltd",C8458F:"Wyler AG",C8478C:"Beken Corporation",C848F5:"MEDISON Xray Co. Ltd",C84C75:"Cisco Systems Inc.",C850E9:"Raisecom Technology Co. Ltd",C85195:"Huawei Technologies Co. Ltd",C85645:"Intermas France",C85663:"Sunflex Europe GmbH",C85B76:"LCFC(HeFei) Electronics Technology Co. Ltd",C86000:"ASUSTek Computer Inc.",C863F1:"Sony Interactive Entertainment Inc.",C864C7:"zte Corporation",C8662C:"Beijing Haitai Fangyuan High Technology Co,.Ltd",C8665D:"Aerohive Networks Inc.",C8675E:"Aerohive Networks Inc.",C869CD:"Apple",C86C1E:"Display Systems Ltd",C86C87:"ZyXEL Communications Corp",C86CB6:"Optcom Co. Ltd",C86F1D:"Apple",C87248:"Aplicom Oy",C87324:"Sow Cheng Technology Co. Ltd",C8755B:"Quantify Technology Pty. Ltd",C87765:"Tiesse SpA",C8778B:"Themis Computer",C87B5B:"zte Corporation",C87CBC:"Valink Co. Ltd",C87D77:"Shenzhen Kingtech Communication Equipment Co. Ltd",C87E75:"Samsung Electronics Co. Ltd",C88439:"Sunrise Technologies",C88447:"Beautiful Enterprise Co. Ltd",C88550:"Apple",C88629:"Shenzhen Duubee Intelligent Technologies Co. Ltd",C88722:"Lumenpulse",C8873B:"Net Optics",C88A83:"Dongguan HuaHong Electronics Co. Ltd",C88B47:"Nolangroup S.P.A Con Socio Unico",C88D83:"Huawei Technologies Co. Ltd",C88ED1:"IEEE Registration Authority",C88F26:"Skyworth Digital Technology(Shenzhen) Co. Ltd",C8903E:"Pakton Technologies",C891F9:"Sagemcom Broadband SAS",C89346:"MXCHIP Company Limited",C89383:"Embedded Automation, Inc.",C894BB:"Huawei Technologies Co. Ltd",C894D2:"Jiangsu Datang Electronic Products Co. Ltd",C8979F:"Nokia Corporation",C89C1D:"Cisco Systems Inc.",C89CDC:"Elitegroup Computer Systems Co. Ltd",C89F1D:"Shenzhen Communication Technologies Co. Ltd",C89F42:"VDII Innovation AB",C8A030:"Texas Instruments",C8A1B6:"Shenzhen Longway Technologies Co. Ltd",C8A1BA:"Neul Ltd",C8A2CE:"Oasis Media Systems LLC",C8A620:"Nebula, Inc",C8A70A:"Verizon Business",C8A729:"Systronics Co. Ltd",C8A823:"Samsung Electronics Co. Ltd",C8A9FC:"Goyoo Networks Inc.",C8AA21:"ARRIS Group, Inc.",C8AA55:"Hunan Comtom Electronic Incorporated Co. Ltd",C8AACC:"Private",C8AE9C:"Shanghai TYD Elecronic Technology Co. Ltd",C8AF40:"marco Systemanalyse und Entwicklung GmbH",C8AFE3:"Hefei Radio Communication Technology Co. Ltd",C8B21E:"Chipsea Technologies (Shenzhen) Corp.",C8B373:"Cisco-Linksys LLC",C8B5AD:"Hewlett Packard Enterprise",C8B5B7:"Apple",C8BA94:"Samsung Electro-Mechanics(Thailand)",C8BBD3:"Embrane",C8BCC8:"Apple",C8BE19:"D-Link International",C8C126:"ZPM Industria e Comercio Ltda",C8C13C:"RuggedTek Hangzhou Co. Ltd",C8C2C6:"Shanghai Airm2m Communication Technology Co. Ltd",C8C50E:"Shenzhen Primestone Network Technologies.Co. Ltd",C8C791:"Zero1.tv GmbH",C8CBB8:"Hewlett-Packard Company",C8CD72:"Sagemcom Broadband SAS",C8D019:"Shanghai Tigercel Communication Technology Co. Ltd",C8D083:"Apple",C8D10B:"Nokia Corporation",C8D12A:"Comtrend Corporation",C8D15E:"Huawei Technologies Co. Ltd",C8D1D1:"AGAiT Technology Corporation",C8D2C1:"Jetlun (Shenzhen) Corporation",C8D3A3:"D-Link International",C8D3FF:"Hewlett-Packard Company",C8D429:"Muehlbauer AG",C8D590:"Flight Data Systems",C8D5FE:"Shenzhen Zowee Technology Co. Ltd",C8D719:"Cisco-Linksys LLC",C8D779:"Qing DAO Haier Telecom Co. Ltd",C8D7B0:"Samsung Electronics Co. Ltd",C8DB26:"Logitech",C8DDC9:"Lenovo Mobile Communication Technology Ltd",C8DE51:"IntegraOptics",C8DEC9:"Coriant",C8DF7C:"Nokia Corporation",C8DF84:"Texas Instruments",C8E0EB:"Apple",C8E130:"Milkyway Group Ltd",C8E1A7:"Vertu Corporation Limited",C8E42F:"Technical Research Design and Development",C8E776:"PTCOM Technology",C8E7D8:"Shenzhen Mercury Communication Technologies Co. Ltd",C8E7F0:"Juniper Networks",C8EE08:"Tangtop Technology Co. Ltd",C8EE75:"Pishion International Co. Ltd",C8EEA6:"Shenzhen SHX Technology Co. Ltd",C8EF2E:"Beijing Gefei Tech. Co. Ltd",C8F230:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",C8F36B:"Yamato Scale Co. Ltd",C8F386:"Shenzhen Xiaoniao Technology Co. Ltd",C8F406:"Avaya Inc",C8F650:"Apple",C8F68D:"S.E.Technologies Limited",C8F704:"Building Block Video",C8F733:"Intel Corporation",C8F86D:"Alcatel-Lucent Shanghai Bell Co. Ltd",C8F946:"LOCOSYS Technology Inc.",C8F981:"Seneca s.r.l.",C8F9C8:"NewSharp Technology(SuZhou)Co Ltd",C8F9F9:"Cisco Systems Inc.",C8FAE1:"ARQ Digital LLC",C8FB26:"Cisco SPVTG",C8FD19:"Texas Instruments",C8FE30:"Bejing DAYO Mobile Communication Technology Ltd",C8FF28:"Liteon Technology Corporation",C8FF77:"Dyson Limited",CC0080:"Bettini SRL",CC03D9:"Cisco Meraki",CC03FA:"Technicolor CH USA Inc.",CC047C:"G-WAY Microwave",CC04B4:"Select Comfort",CC051B:"Samsung Electronics Co. Ltd",CC0677:"Fiberhome Telecommunication Technologies Co. Ltd",CC07AB:"Samsung Electronics Co. Ltd",CC07E4:"Lenovo Mobile Communication Technology Ltd",CC088D:"Apple",CC08E0:"Apple",CC09C8:"Imaqliq Ltd",CC0CDA:"Miljovakt AS",CC0DEC:"Cisco SPVTG",CC10A3:"Beijing Nan Bao Technology Co. Ltd",CC14A6:"Yichun MyEnergy Domain, Inc",CC167E:"Cisco Systems Inc.",CC187B:"Manzanita Systems, Inc.",CC19A8:"PT Inova??o e Sistemas SA",CC1AFA:"zte Corporation",CC1BE0:"IEEE Registration Authority",CC1EFF:"Metrological Group BV",CC1FC4:"InVue",CC20E8:"Apple",CC2218:"InnoDigital Co. Ltd",CC2237:"IEEE Registration Authority",CC25EF:"Apple",CC262D:"Verifi, LLC",CC29F5:"Apple",CC2A80:"Micro-Biz Intelligence solutions Co. Ltd",CC2D21:"Tenda Technology Co. LtdDongguan branch",CC2D83:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",CC2D8C:"LG Electronics Inc",CC2DB7:"Apple",CC2DE0:"Routerboard.com",CC2F71:"Intel Corporation",CC3080:"VAIO Corporation",CC33BB:"Sagemcom Broadband SAS",CC3429:"TP-Link Technologies Co. Ltd",CC34D7:"Gewiss S.P.A.",CC3540:"Technicolor CH USA Inc.",CC37AB:"Edgecore Networks Corportation",CC398C:"Shiningtek",CC3A61:"Samsung Electro Mechanics Co. Ltd",CC3ADF:"Neptune Technology Group Inc.",CC3B3E:"Lester Electrical",CC3B58:"Curiouser Products Inc",CC3C3F:"SA.S.S. Datentechnik AG",CC3D82:"Intel Corporation",CC3E5F:"Hewlett-Packard Company",CC3F1D:"Intesis Software SL",CC40D0:"Netgear",CC43E3:"Trump s.a.",CC4463:"Apple",CC4639:"WAAV, Inc.",CC46D6:"Cisco Systems Inc.",CC4703:"Intercon Systems Co. Ltd",CC4AE1:"fourtec -Fourier Technologies",CC4B73:"AMPAK Technology, Inc.",CC4BFB:"Hellberg Safety AB",CC4D38:"Carnegie Technologies",CC4E24:"Brocade Communications Systems, Inc.",CC4EEC:"HUMAX Co. Ltd",CC500A:"Fiberhome Telecommunication Technologies Co. Ltd",CC501C:"KVH Industries, Inc.",CC5076:"Ocom Communications, Inc.",CC52AF:"Universal Global Scientific Industrial Co. Ltd",CC53B5:"Huawei Technologies Co. Ltd",CC5459:"OnTime Networks AS",CC55AD:"RIM",CC593E:"Toumaz Ltd",CC5A53:"Cisco Systems Inc.",CC5C75:"Weightech Com. Imp. Exp. Equip. Pesagem Ltda",CC5D4E:"ZyXEL Communications Corp",CC5D57:"Information System Research Institute,Inc.",CC5FBF:"Topwise 3G Communication Co. Ltd",CC60BB:"Empower RF Systems",CC61E5:"Motorola Mobility LLC, a Lenovo Company",CC65AD:"ARRIS Group, Inc.",CC66B2:"Nokia",CC69B0:"Global Traffic Technologies, LLC",CC6B98:"Minetec Wireless Technologies",CC6BF1:"Sound Masking Inc.",CC6DA0:"Roku, Inc.",CC6DEF:"TJK Tietolaite Oy",CC6EA4:"Samsung Electronics Co. Ltd",CC720F:"Viscount Systems Inc.",CC7314:"Hong Kong Wheatek Technology Limited",CC7498:"Filmetrics Inc.",CC7669:"Seetech",CC785F:"Apple",CC78AB:"Texas Instruments",CC794A:"BLU Products Inc.",CC79CF:"Shenzhen RF-Link Technology Co. Ltd",CC7A30:"CMAX Wireless Co. Ltd",CC7B35:"zte Corporation",CC7D37:"ARRIS Group, Inc.",CC7EE7:"Panasonic Corporation AVC Networks Company",CC81DA:"Phicomm (Shanghai) Co. Ltd",CC82EB:"Kyocera Corporation",CC856C:"Shenzhen MDK Digital Technology Co. Ltd",CC89FD:"Nokia Corporation",CC8CDA:"Shenzhen Wei Da Intelligent Technology Go. Ltd",CC8CE3:"Texas Instruments",CC8E71:"Cisco Systems Inc.",CC9093:"Hansong Tehnologies",CC90E8:"Shenzhen YOUHUA Technology Co. Ltd",CC912B:"TE Connectivity Touch Solutions",CC934A:"Sierra Wireless",CC944A:"Pfeiffer Vacuum GmbH",CC9470:"Kinestral Technologies, Inc.",CC95D7:"Vizio, Inc",CC9635:"LVS Co. Ltd",CC96A0:"Huawei Technologies Co. Ltd",CC9891:"Cisco Systems Inc.",CC9916:"Integrated Device Technology (Malaysia) Sdn. Bhd.",CC9E00:"Nintendo Co. Ltd",CC9F35:"Transbit Sp. z o.o.",CC9F7A:"Chiun Mai Communication Systems, Inc",CCA0E5:"DZG Metering GmbH",CCA219:"Shenzhen Along Investment Co. Ltd",CCA223:"Huawei Technologies Co. Ltd",CCA260:"Sichuan Tianyi Comheart Telecomco. Ltd",CCA374:"Guangdong Guanglian Electronic Technology Co.Ltd",CCA462:"ARRIS Group, Inc.",CCA4AF:"Shenzhen Sowell Technology Co. Ltd",CCA614:"Aifa Technology Corp.",CCAF78:"Hon Hai Precision Ind. Co. Ltd",CCB0DA:"Liteon Technology Corporation",CCB11A:"Samsung Electronics Co. Ltd",CCB255:"D-Link International",CCB3AB:"shenzhen Biocare Bio-Medical Equipment Co. Ltd",CCB3F8:"Fujitsu Isotec Limited",CCB55A:"Fraunhofer ITWM",CCB691:"NECMagnusCommunications",CCB888:"AnB Securite s.a.",CCB8A8:"AMPAK Technology, Inc.",CCB8F1:"Eagle Kingdom Technologies Limited",CCBD35:"Steinel GmbH",CCBDD3:"Ultimaker B.V.",CCBE59:"Calix Inc.",CCBE71:"OptiLogix BV",CCC079:"Murata Manufacturing Co. Ltd",CCC104:"Applied Technical Systems",CCC2E0:"Raisecom Technology Co. Ltd",CCC3EA:"Motorola Mobility LLC, a Lenovo Company",CCC50A:"Shenzhen Dajiahao Technology Co. Ltd",CCC5EF:"Co-Comm Servicios Telecomunicaciones S.L.",CCC62B:"Tri-Systems Corporation",CCC760:"Apple",CCC8D7:"CIAS Elettronica srl",CCCC4E:"Sun Fountainhead USA. Corp",CCCC81:"Huawei Technologies Co. Ltd",CCCD64:"SM-Electronic GmbH",CCCE1E:"AVM Audiovisuelles Marketing und Computersysteme GmbH",CCCE40:"Janteq Corp",CCD29B:"Shenzhen Bopengfa Elec&Technology Co. Ltd",CCD31E:"IEEE Registration Authority",CCD3E2:"Jiangsu Yinhe Electronics Co. Ltd",CCD539:"Cisco Systems Inc.",CCD811:"Aiconn Technology Corporation",CCD8C1:"Cisco Systems Inc.",CCD9E9:"SCR Engineers Ltd",CCE0C3:"Mangstor, Inc.",CCE17F:"Juniper Networks",CCE1D5:"Buffalo.Inc",CCE798:"My Social Stuff",CCE7DF:"American Magnetics, Inc.",CCE8AC:"SOYEA Technology Co. Ltd",CCEA1C:"DCONWORKS Co. Ltd",CCEED9:"VAHLE DETO GmbH",CCEF48:"Cisco Systems Inc.",CCF3A5:"Chi Mei Communication Systems, Inc",CCF407:"Eukrea Electromatique Sarl",CCF538:"3isysnetworks",CCF67A:"Ayecka Communication Systems Ltd",CCF841:"Lumewave",CCF8F0:"Xi'an HISU Multimedia Technology Co. Ltd",CCF954:"Avaya Inc",CCF957:"u-blox AG",CCF9E8:"Samsung Electronics Co. Ltd",CCFA00:"LG Electronics (Mobile Communications)",CCFB65:"Nintendo Co. Ltd",CCFC6D:"RIZ Transmitters",CCFCB1:"Wireless Technology, Inc.",CCFD17:"TCT mobile Ltd",CCFE3C:"Samsung Electronics Co. Ltd",D0034B:"Apple",D00401:"Motorola Mobility LLC, a Lenovo Company",D00492:"Fiberhome Telecommunication Technologies Co. Ltd",D0052A:"Arcadyan Corporation",D00790:"Texas Instruments",D007CA:"Juniper Networks",D00AAB:"Yokogawa Digital Computer Corporation",D00EA4:"Porsche Cars North America",D00ED9:"Taicang T&W Electronics",D00F6D:"T&W Electronics Company",D01242:"BIOS Corporation",D0131E:"Sunrex Technology Corp",D013FD:"LG Electronics (Mobile Communications)",D0154A:"zte Corporation",D0176A:"Samsung Electronics Co. Ltd",D017C2:"ASUSTek Computer Inc.",D01AA7:"UniPrint",D01CBB:"Beijing Ctimes Digital Technology Co. Ltd",D02212:"IEEE Registration Authority",D022BE:"Samsung Electro-Mechanics(Thailand)",D023DB:"Apple",D02516:"Shenzhen Mercury Communication Technologies Co. Ltd",D02544:"Samsung Electro-Mechanics(Thailand)",D02598:"Apple",D02788:"Hon Hai Precision Ind. Co. Ltd",D02B20:"Apple",D02C45:"littleBits Electronics, Inc.",D02DB3:"Huawei Technologies Co. Ltd",D03110:"Ingenic Semiconductor Co. Ltd",D03169:"Samsung Electronics Co. Ltd",D03311:"Apple",D03742:"Yulong Computer Telecommunication Scientific (Shenzhen) Co. Ltd",D03761:"Texas Instruments",D03972:"Texas Instruments",D039B3:"ARRIS Group, Inc.",D03DC3:"AQ Corporation",D03E5C:"Huawei Technologies Co. Ltd",D0431E:"Dell Inc.",D046DC:"Southwest Research Institute",D048F3:"DATTUS Inc",D0498B:"Zoom Server",D04CC1:"SINTRONES Technology Corp.",D04D2C:"Roku, Inc.",D04F7E:"Apple",D05099:"ASRock Incorporation",D05162:"Sony Mobile Communications AB",D052A8:"Physical Graph Corporation",D05349:"Liteon Technology Corporation",D0542D:"Cambridge Industries(Group) Co. Ltd",D055B2:"Integrated Device Technology (Malaysia) Sdn. Bhd.",D0574C:"Cisco Systems Inc.",D0577B:"Intel Corporation",D05785:"Pantech Co. Ltd",D057A1:"Werma Signaltechnik GmbH & Co. KG",D05875:"Active Control Technology Inc.",D058A8:"zte Corporation",D05995:"Fiberhome Telecommunication Technologies Co. Ltd",D059C3:"CeraMicro Technology Corporation",D059E4:"Samsung Electronics Co. Ltd",D05A00:"Technicolor CH USA Inc.",D05A0F:"I-BT Digital Co. Ltd",D05AF1:"Shenzhen Pulier Tech Co. Ltd",D05BA8:"zte Corporation",D05C7A:"Sartura d.o.o.",D05FB8:"Texas Instruments",D05FCE:"Hitachi Data Systems",D0608C:"zte Corporation",D062A0:"China Essence Technology (Zhumadian) Co. Ltd",D0634D:"Meiko Maschinenbau GmbH & Co. KG",D063B4:"SolidRun Ltd",D065CA:"Huawei Technologies Co. Ltd",D0666D:"Shenzhen Bus-Lan Technology Co. Ltd",D0667B:"Samsung Electronics Co. Ltd",D06726:"Hewlett Packard Enterprise",D067E5:"Dell Inc.",D0699E:"LUMINEX Lighting Control Equipment",D069D0:"Verto Medical Solutions, LLC",D06A1F:"BSE Co. Ltd",D06F4A:"Topwell International Holdings Limited",D06F82:"Huawei Technologies Co. Ltd",D071C4:"zte Corporation",D072DC:"Cisco Systems Inc.",D0737F:"Mini-Circuits",D0738E:"Dong OH Precision Co. Ltd",D073D5:"Lifi Labs Management Pty Ltd",D075BE:"Reno A&E",D07650:"IEEE Registration Authority",D076E7:"TP-Link Technologies Co. Ltd",D07714:"Motorola Mobility LLC, a Lenovo Company",D07AB5:"Huawei Technologies Co. Ltd",D07C2D:"Leie IOT technology Co. Ltd",D07DE5:"Forward Pay Systems, Inc.",D07E28:"Hewlett-Packard Company",D07E35:"Intel Corporation",D07FC4:"Ou Wei Technology Co. Ltd Of Shenzhen City",D0817A:"Apple",D083D4:"Xtel Wireless ApS",D084B0:"Sagemcom Broadband SAS",D087E2:"Samsung Electronics Co. Ltd",D08999:"APCON, Inc.",D08A55:"Skullcandy",D08B7E:"Passif Semiconductor",D08CB5:"Texas Instruments",D08CFF:"Upwis AB",D0929E:"Microsoft Corporation",D09380:"Ducere Technologies Pvt. Ltd",D093F8:"Stonestreet One LLC",D09466:"Dell Inc.",D095C7:"Pantech Co. Ltd",D096FB:"DASAN Network Solutions",D099D5:"Alcatel-Lucent",D09B05:"Emtronix",D09C30:"Foster Electric Company, Limited",D09D0A:"Linkcom",D09DAB:"TCT mobile Ltd",D0A0D6:"Chengdu TD Tech Ltd",D0A311:"Neuberger Geb?udeautomation GmbH",D0A4B1:"Sonifex Ltd",D0A5A6:"Cisco Systems Inc.",D0A637:"Apple",D0AEEC:"Alpha Networks Inc.",D0AFB6:"Linktop Technology Co. Ltd",D0B0CD:"Moen",D0B128:"Samsung Electronics Co. Ltd",D0B2C4:"Technicolor CH USA Inc.",D0B33F:"Shenzhen TINNO Mobile Technology Corp.",D0B498:"Robert Bosch LLC Automotive Electronics",D0B523:"Bestcare Cloucal Corp.",D0B53D:"Sepro Robotique",D0B5C2:"Texas Instruments",D0BAE4:"Shanghai MXCHIP Information Technology Co. Ltd",D0BB80:"SHL Telemedicine International Ltd",D0BD01:"DS International",D0BE2C:"CNSLink Co. Ltd",D0BF9C:"Hewlett-Packard Company",D0C0BF:"Actions Microelectronics Co. Ltd",D0C193:"Skybell, Inc",D0C1B1:"Samsung Electronics Co. Ltd",D0C282:"Cisco Systems Inc.",D0C42F:"Tamagawa Seiki Co. Ltd",D0C5F3:"Apple",D0C789:"Cisco Systems Inc.",D0C7C0:"TP-Link Technologies Co. Ltd",D0CDE1:"Scientech Electronics",D0CF5E:"Energy Micro AS",D0D04B:"Huawei Technologies Co. Ltd",D0D0FD:"Cisco Systems Inc.",D0D212:"K2NET Co. Ltd",D0D286:"Beckman Coulter K.K.",D0D2B0:"Apple",D0D3FC:"Mios Ltd",D0D412:"ADB Broadband Italia",D0D471:"MVTECH Co. Ltd",D0D6CC:"Wintop",D0D94F:"IEEE Registration Authority",D0DB32:"Nokia Corporation",D0DF9A:"Liteon Technology Corporation",D0DFB2:"Genie Networks Limited",D0DFC7:"Samsung Electronics Co. Ltd",D0E140:"Apple",D0E347:"Yoga",D0E40B:"Wearable Inc.",D0E44A:"Murata Manufacturing Co. Ltd",D0E54D:"ARRIS Group, Inc.",D0E782:"Azurewave Technologies Inc.",D0EB03:"Zhehua technology limited",D0EB9E:"Seowoo Inc.",D0F0DB:"Ericsson",D0F27F:"SteadyServ Technoligies, LLC",D0F73B:"Helmut Mauell GmbH Werk Weida",D0F88C:"Motorola (Wuhan) Mobility Technologies Communication Co. Ltd",D0FA1D:"Qihoo 360 Technology Co. Ltd",D0FCCC:"Samsung Electronics Co. Ltd",D0FF50:"Texas Instruments",D0FF98:"Huawei Technologies Co. Ltd",D4000D:"Phoenix Broadband Technologies, LLC.",D40057:"MC Technologies GmbH",D40129:"Broadcom",D4016D:"TP-Link Technologies Co. Ltd",D4024A:"Delphian Systems LLC",D404CD:"ARRIS Group, Inc.",D404FF:"Juniper Networks",D40598:"ARRIS Group, Inc.",D40AA9:"ARRIS Group, Inc.",D40B1A:"HTC Corporation",D40BB9:"Solid Semecs bv.",D40FB2:"Applied Micro Electronics AME bv",D41090:"InfORM Systems AG",D410CF:"Huanshun Network Science and Technology Co. Ltd",D411D6:"ShotSpotter, Inc.",D41296:"Anobit Technologies Ltd",D412BB:"Quadrant Components Inc. Ltd",D4136F:"Asia Pacific Brands",D41A3F:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",D41C1C:"RCF S.P.A.",D41D71:"Palo Alto Networks",D41E35:"TOHO Electronics Inc.",D41F0C:"JAI Oy",D4206D:"HTC Corporation",D42122:"Sercomm Corporation",D4223F:"Lenovo Mobile Communication Technology Ltd",D4224E:"Alcatel Lucent",D4258B:"Intel Corporation",D42751:"Infopia Co. Ltd",D428B2:"ioBridge, Inc.",D428D5:"TCT mobile Ltd",D429EA:"Zimory GmbH",D42C0F:"ARRIS Group, Inc.",D42C3D:"Sky Light Digital Limited",D42C44:"Cisco Systems Inc.",D42F23:"Akenori PTE Ltd",D4319D:"Sinwatec",D43266:"Fike Corporation",D43639:"Texas Instruments",D436DB:"Jiangsu Toppower Automotive Electronics Co. Ltd",D437D7:"zte Corporation",D4389C:"Sony Mobile Communications AB",D43A65:"IGRS Engineering Lab Ltd",D43AE9:"DONGGUAN ipt IndUSTRIAL Co. Ltd",D43D67:"Carma Industries Inc.",D43D7E:"Micro-Star International",D440F0:"Huawei Technologies Co. Ltd",D44165:"Sichuan Tianyi Comheart Telecomco. Ltd",D443A8:"Changzhou Haojie Electric Co. Ltd",D445E8:"Jiangxi Hongpai Technology Co. Ltd",D44B5E:"Taiyo Yuden Co. Ltd",D44C24:"Vuppalamritha Magnetic Components Ltd",D44C9C:"Shenzhen YOOBAO Technology Co.Ltd",D44CA7:"Informtekhnika & Communication, LLC",D44F80:"Kemper Digital GmbH",D4503F:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",D4507A:"CEIVA Logic, Inc",D4522A:"TangoWiFi.com",D45251:"IBT Ingenieurbureau Broennimann Thun",D45297:"nSTREAMS Technologies, Inc.",D453AF:"VIGO System S.A.",D45556:"Fiber Mountain Inc.",D455BE:"Shenzhen Fast Technologies Co. Ltd",D45AB2:"Galleon Systems",D45C70:"Wi-Fi Alliance",D45D42:"Nokia Corporation",D45DDF:"Pegatron Corporation",D45F25:"Shenzhen YOUHUA Technology Co. Ltd",D460E3:"Sercomm Corporation.",D4612E:"Huawei Technologies Co. Ltd",D46132:"Pro Concept Manufacturer Co. Ltd",D4619D:"Apple",D461DA:"Apple",D461FE:"Hangzhou H3C Technologies Co., Limited",D463C6:"Motorola Mobility LLC, a Lenovo Company",D463FE:"Arcadyan Corporation",D464F7:"Chengdu Usee Digital Technology Co. Ltd",D466A8:"Riedo Networks Ltd",D46761:"Sahab Technology",D467E7:"Fiberhome Telecommunication Technologies Co. Ltd",D4684D:"Ruckus Wireless",D46867:"Neoventus Design Group",D468BA:"Shenzhen Sundray Technologies Company Limited",D46A6A:"Hon Hai Precision Ind. Co. Ltd",D46A91:"Snap AV",D46AA8:"Huawei Technologies Co. Ltd",D46CBF:"Goodrich ISR",D46CDA:"CSM GmbH",D46D50:"Cisco Systems Inc.",D46D6D:"Intel Corporation",D46E0E:"TP-Link Technologies Co. Ltd",D46E5C:"Huawei Technologies Co. Ltd",D46F42:"WAXESS USA Inc",D47208:"Bragi GmbH",D47226:"zte Corporation",D476EA:"zte Corporation",D47856:"Avaya Inc",D479C3:"Cameronet GmbH & Co. KG",D47AE2:"Samsung Electronics Co. Ltd",D47B35:"NEO Monitors AS",D47B75:"HARTING Electronics GmbH",D47BB0:"Askey Computer Corp",D47DFC:"Tecno Mobile Limited",D481CA:"iDevices, LLC",D481D7:"Dell Inc.",D4823E:"Argosy Technologies Ltd",D48304:"Shenzhen Fast Technologies Co. Ltd",D48564:"Hewlett-Packard Company",D487D8:"Samsung Electronics Co. Ltd",D4883F:"Hdpro Co. Ltd",D48890:"Samsung Electronics Co. Ltd",D48CB5:"Cisco Systems Inc.",D48DD9:"Meld Technology, Inc",D48F33:"Microsoft Corporation",D48FAA:"Sogecam Industrial, S.A.",D4909C:"Apple",D490E0:"Topcon Electronics GmbH & Co. KG",D491AF:"Electroacustica General Iberica, S.A.",D49398:"Nokia Corporation",D493A0:"Fidelix Oy",D4945A:"Cosmo Co. Ltd",D494A1:"Texas Instruments",D494E8:"Huawei Technologies Co. Ltd",D49524:"Clover Network, Inc.",D496DF:"Sungjin C&T Co. Ltd",D4970B:"Xiaomi Communications Co Ltd",D49A20:"Apple",D49B5C:"Chongqing Miedu Technology Co. Ltd",D49C28:"JayBird LLC",D49C8E:"University Of FUKUI",D49CF4:"Palo Alto Networks",D49E6D:"Wuhan Zhongyuan Huadian Science & Technology Co.,",D4A02A:"Cisco Systems Inc.",D4A148:"Huawei Technologies Co. Ltd",D4A33D:"Apple",D4A425:"SMAX Technology Co. Ltd",D4A499:"InView Technology Corporation",D4A928:"GreenWave Reality Inc",D4AAFF:"Micro World",D4AC4E:"BODi rS, LLC",D4AD2D:"Fiberhome Telecommunication Technologies Co. Ltd",D4AE05:"Samsung Electronics Co. Ltd",D4AE52:"Dell Inc.",D4B110:"Huawei Technologies Co. Ltd",D4B169:"Le Shi Zhi Xin Electronic Technology (Tianjin) Limited",D4B27A:"ARRIS Group, Inc.",D4B43E:"Messcomp Datentechnik GmbH",D4B8FF:"Home Control Singapore Pte Ltd",D4BED9:"Dell Inc.",D4BF2D:"SE Controls Asia Pacific Ltd",D4BF7F:"Upvel",D4C19E:"Ruckus Wireless",D4C1C8:"zte Corporation",D4C1FC:"Nokia Corporation",D4C766:"Acentic GmbH",D4C8B0:"Prime Electronics & Satellitics Inc.",D4C9B2:"Quanergy Systems Inc",D4C9EF:"Hewlett-Packard Company",D4CA6D:"Routerboard.com",D4CA6E:"u-blox AG",D4CBAF:"Nokia Corporation",D4CEB8:"Enatel Ltd",D4CF37:"Symbolic IO",D4CFF9:"Shenzhen Sen5 Technology Co. Ltd",D4D184:"ADB Broadband Italia",D4D249:"Power Ethernet",D4D2E5:"BKAV Corporation",D4D50D:"Southwest Microwave, Inc",D4D748:"Cisco Systems Inc.",D4D7A9:"Shanghai Kaixiang Info Tech Ltd",D4D898:"Korea CNO Tech Co. Ltd",D4D919:"GoPro",D4DCCD:"Apple",D4DF57:"Alpinion Medical Systems",D4E08E:"ValueHD Corporation",D4E32C:"S. Siedle & Sohne",D4E33F:"Nokia",D4E6B7:"Samsung Electronics Co. Ltd",D4E8B2:"Samsung Electronics Co. Ltd",D4E90B:"CVT Co. Ltd",D4EA0E:"Avaya Inc",D4EC0C:"Harley-Davidson Motor Company",D4EC86:"LinkedHope Intelligent Technologies Co. Ltd",D4EE07:"HIWIFI Co. Ltd",D4F027:"Navetas Energy Management",D4F0B4:"Napco Security Technologies",D4F143:"IPROAD.,Inc",D4F207:"DIAODIAO(Beijing)Technology Co. Ltd",D4F46F:"Apple",D4F4BE:"Palo Alto Networks",D4F513:"Texas Instruments",D4F63F:"IEA S.R.L.",D4F786:"Fiberhome Telecommunication Technologies Co. Ltd",D4F9A1:"Huawei Technologies Co. Ltd",D8004D:"Apple",D8052E:"Skyviia Corporation",D806D1:"Honeywell Fire System (Shanghai) Co,. Ltd",D80831:"Samsung Electronics Co. Ltd",D808F5:"Arcadia Networks Co. Ltd",D809C3:"Cercacor Labs",D80CCF:"C.G.V. S.A.S.",D80DE3:"FXI Technologies AS",D80F99:"Hon Hai Precision Ind. Co. Ltd",D814D6:"SURE SysTEM Co Ltd",D8150D:"TP-Link Technologies Co. Ltd",D8160A:"Nippon Electro-Sensory Devices",D816C1:"Dewav (HK) Electronics Limited",D8182B:"Conti Temic Microelectronic GmbH",D818D3:"Juniper Networks",D8197A:"Nuheara Ltd",D819CE:"Telesquare",D81BFE:"Twinlinx Corporation",D81C14:"Compacta International Ltd",D81D72:"Apple",D81EDE:"B&W Group Ltd",D81FCC:"Brocade Communications Systems, Inc.",D8209F:"Cubro Acronet GesmbH",D822F4:"Avnet Silica",D824BD:"Cisco Systems Inc.",D82522:"ARRIS Group, Inc.",D825B0:"Rockeetech Systems Co. Ltd",D826B9:"Guangdong Coagent Electronics S&T Co. Ltd",D8270C:"MaxTronic International Co. Ltd",D828C9:"General Electric Consumer and Industrial",D82916:"Ascent Communication Technology",D82986:"Best Wish Technology Ltd",D82A15:"Leitner SpA",D82A7E:"Nokia Corporation",D82D9B:"Shenzhen G.Credit Communication Technology Co. Ltd",D82DE1:"Tricascade Inc.",D83062:"Apple",D831CF:"Samsung Electronics Co. Ltd",D83214:"Tenda Technology Co. LtdDongguan branch",D8325A:"Shenzhen YOUHUA Technology Co. Ltd",D8337F:"Office FA.com Co. Ltd",D837BE:"Shenzhen Gongjin Electronics Co.,LT",D8380D:"SHENZHEN IP-CoM Network Co. Ltd",D838FC:"Ruckus Wireless",D83C69:"Shenzhen TINNO Mobile Technology Corp.",D842AC:"Shanghai Feixun Communication Co. Ltd",D842E2:"Canary Connect, Inc.",D843ED:"Suzuken",D8445C:"DEV Tecnologia Ind Com Man Eq LtdA",D8452B:"Integrated Device Technology (Malaysia) Sdn. Bhd.",D84606:"Silicon Valley Global Marketing",D84710:"Sichuan Changhong Electric Ltd",D848EE:"Hangzhou Xueji Technology Co. Ltd",D8490B:"Huawei Technologies Co. Ltd",D8492F:"Canon Inc.",D84A87:"OI Electric Co. Ltd",D84B2A:"Cognitas Technologies, Inc.",D84FB8:"LG Electronics",D850E6:"ASUSTek Computer Inc.",D8543A:"Texas Instruments",D854A2:"Aerohive Networks Inc.",D855A3:"zte Corporation",D857EF:"Samsung Electronics Co. Ltd",D858D7:"CZ.NIC, z.s.p.o.",D85B2A:"Samsung Electronics Co. Ltd",D85D4C:"TP-Link Technologies Co. Ltd",D85D84:"CAx soft GmbH",D85DE2:"Hon Hai Precision Ind. Co. Ltd",D85DEF:"Busch-Jaeger Elektro GmbH",D85DFB:"Private",D860B0:"bioM?rieux Italia S.p.A.",D860B3:"Guangdong Global Electronic Technology Co. Ltd",D86162:"Wistron Neweb Corporation",D86194:"Objetivos y Sevicios de Valor An?adido",D862DB:"Eno Inc.",D86375:"Xiaomi Communications Co Ltd",D86595:"Toy's Myth Inc.",D866C6:"Shenzhen Daystar Technology Co. Ltd",D866EE:"Boxin Communication Co. Ltd",D867D9:"Cisco Systems Inc.",D86960:"Steinsvik",D86BF7:"Nintendo Co. Ltd",D86C02:"Huaqin Telecom Technology Co. Ltd",D86C63:"Google, Inc.",D86CE9:"Sagemcom Broadband SAS",D87157:"Lenovo Mobile Communication Technology Ltd",D87495:"zte Corporation",D87533:"Nokia Corporation",D8760A:"Escort, Inc.",D878E5:"Kuhn SA",D87988:"Hon Hai Precision Ind. Co. Ltd",D87CDD:"Sanix Incorporated",D87EB1:"x.o.ware, Inc.",D88039:"Microchip Technology Inc.",D8803C:"Anhui Huami Information Technology Company Limited",D881CE:"AHN Inc.",D88466:"Extreme Networks, Inc.",D887D5:"Leadcore Technology Co. Ltd",D888CE:"RF Technology Pty Ltd",D88A3B:"Unit-EM",D88B4C:"KingTing Tech.",D88D5C:"Elentec",D88F76:"Apple",D890E8:"Samsung Electronics Co. Ltd",D89341:"General Electric Global Research",D89403:"Hewlett Packard Enterprise",D8952F:"Texas Instruments",D89685:"GoPro",D89695:"Apple",D896E0:"Alibaba Cloud Computing Ltd",D8973B:"Artesyn Embedded Technologies",D89760:"C2 Development, Inc.",D8977C:"Grey Innovation",D897BA:"Pegatron Corporation",D89A34:"Beijing SHENQI Technology Co. Ltd",D89C67:"Hon Hai Precision Ind. Co. Ltd",D89D67:"Hewlett-Packard Company",D89DB9:"eMegatech International Corp.",D89E3F:"Apple",D89EF3:"Dell Inc.",D8A01D:"Espressif Inc.",D8A105:"Syslane, Co. Ltd",D8A25E:"Apple",D8A534:"Spectronix Corporation",D8ADDD:"Sonavation, Inc.",D8AE90:"Itibia Technologies",D8AF3B:"Hangzhou Bigbright Integrated Communications System Co. Ltd",D8AFF1:"Panasonic Appliances Company",D8B02E:"Guangzhou Zonerich Business Machine Co. Ltd",D8B04C:"Jinan USR IOT Technology Co. Ltd",D8B122:"Juniper Networks",D8B12A:"Panasonic Mobile Communications Co. Ltd",D8B190:"Cisco Systems Inc.",D8B377:"HTC Corporation",D8B6B7:"Comtrend Corporation",D8B6C1:"NetworkAccountant, Inc.",D8B6D6:"Blu Tether Limited",D8B8F6:"Nantworks",D8B90E:"Triple Domain Vision Co. Ltd",D8BB2C:"Apple",D8BF4C:"Victory Concept Electronics Limited",D8C068:"Netgenetech.Co. Ltd",D8C06A:"Hunantv.com Interactive Entertainment Media Co. Ltd",D8C3FB:"Detracom",D8C46A:"Murata Manufacturing Co. Ltd",D8C497:"Quanta Computer Inc.",D8C4E9:"Samsung Electronics Co. Ltd",D8C691:"Hichan Technology Corp.",D8C771:"Huawei Technologies Co. Ltd",D8C7C8:"Aruba Networks",D8C8E9:"Phicomm (Shanghai) Co. Ltd",D8C99D:"EA Display Limited",D8CB8A:"Micro-Star INTL Co. Ltd",D8CF9C:"Apple",D8D1CB:"Apple",D8D27C:"Jema Energy, SA",D8D385:"Hewlett-Packard Company",D8D43C:"Sony Corporation",D8D5B9:"Rainforest Automation, Inc.",D8D67E:"GSK CNC Equipment Co. Ltd",D8D723:"IDS, Inc",D8D775:"Sagemcom Broadband SAS",D8D866:"Shenzhen Tozed Technologies Co. Ltd",D8DA52:"Apator S.A.",D8DCE9:"Kunshan Erlab ductless filtration System Co. Ltd",D8DD5F:"BALMUDA Inc.",D8DDFD:"Texas Instruments",D8DECE:"Isung Co. Ltd",D8DF0D:"beroNet GmbH",D8DF7A:"Quest Software, Inc.",D8E004:"Vodia Networks Inc",D8E0B8:"Bulat LLC",D8E0E1:"Samsung Electronics Co. Ltd",D8E3AE:"Cirtec Medical Systems",D8E56D:"TCT mobile Ltd",D8E72B:"NetScout Systems, Inc.",D8E743:"Wush, Inc",D8E952:"Keopsys",D8EB97:"TRENDnet, Inc.",D8ED1C:"Magna Technology SL",D8EE78:"Moog Protokraft",D8EFCD:"Nokia",D8F0F2:"Zeebo Inc",D8F1F0:"Pepxim International Limited",D8F710:"Libre Wireless Technologies Inc.",D8FB11:"Axacore",D8FB5E:"Askey Computer Corp",D8FB68:"Cloud Corner Ltd",D8FC38:"Giantec Semiconductor Inc",D8FC93:"Intel Corporation",D8FE8F:"IDFone Co. Ltd",D8FEE3:"D-Link International",DC0077:"TP-Link Technologies Co. Ltd",DC0265:"Meditech Kft",DC028E:"zte Corporation",DC052F:"National Products Inc.",DC0575:"Siemens Energy Automation",DC05ED:"Nabtesco Corporation",DC07C1:"HangZhou QiYang Technology Co. Ltd",DC0856:"Alcatel-Lucent Enterprise",DC0914:"Talk-A-Phone Co.",DC094C:"Huawei Technologies Co. Ltd",DC0B1A:"ADB Broadband Italia",DC0B34:"LG Electronics (Mobile Communications)",DC0C2D:"Weifang Goertek Electronics Co. Ltd",DC0C5C:"Apple",DC0D30:"Shenzhen Feasycom Technology Co. Ltd",DC0EA1:"Compal Information (Kunshan) Co. Ltd",DC15DB:"Ge Ruili Intelligent Technology ( Beijing ) Co. Ltd",DC16A2:"Medtronic Diabetes",DC175A:"Hitachi High-Technologies Corporation",DC1792:"Captivate Network",DC1A01:"Ecoliv Technology ( Shenzhen ) Ltd",DC1AC5:"vivo Mobile Communication Co. Ltd",DC1D9F:"U & B tech",DC1DD4:"Microstep-MIS spol. s r.o.",DC1EA3:"Accensus LLC",DC2008:"ASD Electronics Ltd",DC2834:"HAKKO Corporation",DC2919:"AltoBeam (Xiamen) Technology Ltd, Co.",DC293A:"Shenzhen Nuoshi Technology Co. Ltd",DC2A14:"Shanghai Longjing Technology Co.",DC2B2A:"Apple",DC2B61:"Apple",DC2B66:"InfoBLOCK S.A. de C.V.",DC2BCA:"Zera GmbH",DC2C26:"Iton Technology Limited",DC2DCB:"Beijing Unis HengYue Technology Co. Ltd",DC2E6A:"HCT. Co. Ltd",DC2F03:"Step forward Group Co. Ltd",DC309C:"Heyrex Limited",DC330D:"Qing DAO Haier Telecom Co. Ltd",DC3350:"TechSAT GmbH",DC35F1:"Positivo Inform?tica SA.",DC3714:"Apple",DC3752:"GE",DC37D2:"Hunan HKT Electronic Technology Co. Ltd",DC38E1:"Juniper Networks",DC3979:"Skyport Systems",DC3A5E:"Roku, Inc.",DC3C2E:"Manufacturing System Insights, Inc.",DC3C84:"Ticom Geomatics, Inc.",DC3CF6:"Atomic Rules LLC",DC3E51:"Solberg & Andersen AS",DC3EF8:"Nokia Corporation",DC415F:"Apple",DC4427:"IEEE Registration Authority",DC446D:"Allwinner Technology Co. Ltd",DC44B6:"Samsung Electronics Co. Ltd",DC4517:"ARRIS Group, Inc.",DC48B2:"Baraja Pty. Ltd",DC49C9:"Casco Signal Ltd",DC4A3E:"Hewlett-Packard Company",DC4D23:"MRV Comunications",DC4EDE:"Shinyei Technology Co. Ltd",DC4EF4:"Shenzhen MTN Electronics Co. Ltd",DC4F22:"Espressif Inc.",DC5360:"Intel Corporation",DC537C:"Compal Broadband Networks, Inc.",DC5583:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",DC56E6:"Shenzhen Bococom Technology Co. Ltd",DC56E7:"Apple",DC5726:"Power-One",DC5E36:"Paterson Technology",DC60A1:"Teledyne DALSA Professional Imaging",DC647C:"C.R.S. iiMotion GmbH",DC64B8:"Shenzhen JingHanDa Electronics Co.Ltd",DC663A:"Apacer Technology Inc.",DC6672:"Samsung Electronics Co. Ltd",DC68EB:"Nintendo Co. Ltd",DC6AEA:"Infinix mobility limited",DC6DCD:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",DC6F00:"Livescribe, Inc.",DC6F08:"Bay Storage Technology",DC7014:"Private",DC7144:"Samsung Electro Mechanics Co. Ltd",DC729B:"Huawei Technologies Co. Ltd",DC74A8:"Samsung Electronics Co. Ltd",DC7834:"Logicom SA",DC7B94:"Cisco Systems Inc.",DC7FA4:"2Wire Inc.",DC825B:"JANUS, spol. s r.o.",DC82F6:"iPort",DC85DE:"Azurewave Technologies Inc.",DC86D8:"Apple",DC9A8E:"Nanjing Cocomm electronics Co. Ltd",DC9B1E:"Intercom, Inc.",DC9B9C:"Apple",DC9C52:"Sapphire Technology Limited.",DC9C9F:"Shenzhen YOUHUA Technology Co. Ltd",DC9FA4:"Nokia Corporation",DC9FDB:"Ubiquiti Networks Inc.",DCA266:"Hon Hai Precision Ind. Co. Ltd",DCA333:"Shenzhen YOUHUA Technology Co. Ltd",DCA3AC:"RBcloudtech",DCA4CA:"Apple",DCA5F4:"Cisco Systems Inc.",DCA6BD:"Beijing Lanbo Technology Co. Ltd",DCA7D9:"Compressor Controls Corp",DCA8CF:"New Spin Golf, LLC.",DCA904:"Apple",DCA971:"Intel Corporation",DCA989:"Macandc",DCAD9E:"GreenPriz",DCAE04:"CELOXICA Ltd",DCB058:"B?rkert Werke GmbH",DCB3B4:"Honeywell Environmental & Combustion Controls (Tianjin) Co. Ltd",DCB4C4:"Microsoft XCG",DCBE7A:"Zhejiang Nurotron Biotechnology Co.",DCBF90:"Huizhou Qiaoxing Telecommunication Industry Co. Ltd",DCBFE9:"Motorola Mobility LLC, a Lenovo Company",DCC0DB:"Shenzhen Kaiboer Technology Co. Ltd",DCC0EB:"Assa Abloy C?TE Picarde",DCC101:"SOLiD Technologies, Inc.",DCC422:"Systembase Limited",DCC622:"Buheung System",DCC64B:"Huawei Technologies Co. Ltd",DCC793:"Nokia Corporation",DCC8F5:"Shanghai UMEinfo Co. Ltd",DCCBA8:"Explora Technologies Inc",DCCE41:"FE Global Hong Kong Limited",DCCEBC:"Shenzhen JSR Technology Co. Ltd",DCCEC1:"Cisco Systems Inc.",DCCF94:"Beijing Rongcheng Hutong Technology Co. Ltd",DCCF96:"Samsung Electronics Co. Ltd",DCD0F7:"Bentek Systems Ltd",DCD255:"Kinpo Electronics, Inc.",DCD2FC:"Huawei Technologies Co. Ltd",DCD321:"HUMAX Co. Ltd",DCD3A2:"Apple",DCD52A:"Sunny Heart Limited",DCD87C:"Beijing Jingdong Century Trading Co. Ltd",DCD87F:"Shenzhen JoinCyber Telecom Equipment Ltd",DCD916:"Huawei Technologies Co. Ltd",DCDA4F:"Getck Technology, Inc",DCDB70:"Tonfunk Systementwicklung und Service GmbH",DCDC07:"TRP Systems BV",DCDD24:"Energica Motor Company SpA",DCDE4F:"Gionee Communication Equipment Co Ltd",DCDECA:"Akyllor",DCE026:"Patrol Tag, Inc",DCE1AD:"Shenzhen Wintop Photoelectric Technology Co. Ltd",DCE2AC:"Lumens Digital Optics Inc.",DCE533:"IEEE Registration Authority",DCE578:"Experimental Factory Of Scientific Engineering and Special Design Department",DCE71C:"AUG Elektronik GmbH",DCE838:"CK Telecom (Shenzhen) Limited",DCEB53:"Wuhan QianXiao Elecronic Technology Co. Ltd",DCEB94:"Cisco Systems Inc.",DCEC06:"Heimi Network Technology Co. Ltd",DCEE06:"Huawei Technologies Co. Ltd",DCEF09:"Netgear",DCEFCA:"Murata Manufacturing Co. Ltd",DCF05D:"Letta Teknoloji",DCF090:"Nubia Technology Co. Ltd",DCF110:"Nokia Corporation",DCF755:"Sitronik",DCF858:"Lorent Networks, Inc.",DCFAD5:"STRONG Ges.m.b.H.",DCFB02:"Buffalo.Inc",DCFE07:"Pegatron Corporation",DCFE18:"TP-Link Technologies Co. Ltd",E00370:"ShenZhen Continental Wireless Technology Co. Ltd",E005C5:"TP-Link Technologies Co. Ltd",E006E6:"Hon Hai Precision Ind. Co. Ltd",E0071B:"Hewlett Packard Enterprise",E00B28:"Inovonics",E00C7F:"Nintendo Co. Ltd",E00DB9:"Cree, Inc.",E00EDA:"Cisco Systems Inc.",E0107F:"Ruckus Wireless",E0143E:"Modoosis Inc.",E01877:"Fujitsu Limited",E0191D:"Huawei Technologies Co. Ltd",E019D8:"BH Technologies",E01AEA:"Allied Telesis, Inc.",E01C41:"Aerohive Networks Inc.",E01CEE:"Bravo Tech, Inc.",E01D38:"Beijing HuaqinWorld Technology Co. Ltd",E01D3B:"Cambridge Industries(Group) Co. Ltd",E01E07:"Anite Telecoms US. Inc",E01F0A:"Xslent Energy Technologies. LLC",E02202:"ARRIS Group, Inc.",E0247F:"Huawei Technologies Co. Ltd",E02538:"Titan Pet Products",E02630:"Intrigue Technologies, Inc.",E02636:"Nortel Networks",E0271A:"TTC Next-generation Home Network System WG",E02861:"Huawei Technologies Co. Ltd",E0286D:"AVM Audiovisuelles Marketing und Computersysteme GmbH",E02A82:"Universal Global Scientific Industrial Co. Ltd",E02CB2:"Lenovo Mobile Communication (Wuhan) Company Limited",E02CF3:"MRS Electronic GmbH",E02F6D:"Cisco Systems Inc.",E03005:"Alcatel-Lucent Shanghai Bell Co. Ltd",E0319E:"Valve Corporation",E031D0:"SZ Telstar Co. Ltd",E0338E:"Apple",E034E4:"Feit Electric Company, Inc.",E03560:"Challenger Supply Holdings, LLC",E03676:"Huawei Technologies Co. Ltd",E036E3:"Stage One International Co. Ltd",E037BF:"Wistron Neweb Corporation",E0383F:"zte Corporation",E039D7:"Plexxi, Inc.",E03C5B:"Shenzhen Jiaxinjie Electron Co. Ltd",E03E44:"Broadcom",E03E4A:"Cavanagh Group International",E03E7D:"data-Complex GmbH",E03F49:"ASUSTek Computer Inc.",E04136:"MitraStar Technology Corp.",E043DB:"Shenzhen ViewAt Technology Co. Ltd",E0469A:"Netgear",E048AF:"Premietech Limited",E048D3:"Mobiwire Mobiles (Ningbo) Co. Ltd",E04B45:"Hi-P Electronics Pte Ltd",E04F43:"Universal Global Scientific Industrial Co. Ltd",E04FBD:"Sichuan Tianyi Comheart Telecomco. Ltd",E0508B:"Zhejiang Dahua Technology Co. Ltd",E05124:"NXP Semiconductors",E05163:"Arcadyan Corporation",E0553D:"Cisco Meraki",E05597:"Emergent Vision Technologies Inc.",E056F4:"AxesNetwork Solutions Inc.",E0589E:"Laerdal Medical",E05B70:"Innovid, Co. Ltd",E05DA6:"Detlef Fink Elektronik & Softwareentwicklung",E05F45:"Apple",E05FB9:"Cisco Systems Inc.",E06066:"Sercomm Corporation",E06089:"Cloudleaf, Inc.",E061B2:"Hangzhou Zenointel Technology Co. Ltd",E06290:"Jinan Jovision Science & Technology Co. Ltd",E063E5:"Sony Mobile Communications AB",E064BB:"DigiView S.r.l.",E06678:"Apple",E067B3:"C-Data Technology Co. Ltd",E0686D:"Raybased AB",E06995:"Pegatron Corporation",E0750A:"Alps Electric Co. Ltd",E0757D:"Motorola Mobility LLC, a Lenovo Company",E076D0:"AMPAK Technology, Inc.",E078A3:"Shanghai Winner Information Technology Co.,Inc",E07C13:"zte Corporation",E07C62:"Whistle Labs, Inc.",E07DEA:"Texas Instruments",E07F53:"Techboard SRL",E07F88:"EVIDENCE Network SIA",E08177:"GreenBytes, Inc.",E084F3:"High Grade Controls Corporation",E087B1:"Nata-Info Ltd",E0885D:"Technicolor CH USA Inc.",E0899D:"Cisco Systems Inc.",E08A7E:"Exponent",E08E3C:"Aztech Electronics Pte Ltd",E08FEC:"Repotec Co. Ltd",E09153:"XAVi Technologies Corp.",E091F5:"Netgear",E09467:"Intel Corporation",E09579:"ORTHOsoft Inc, d/b/a Zimmer CAS",E09796:"Huawei Technologies Co. Ltd",E097F2:"Atomax Inc.",E09861:"Motorola Mobility LLC, a Lenovo Company",E09971:"Samsung Electronics Co. Ltd",E09D31:"Intel Corporation",E09DB8:"Planex Communications Inc.",E09DFA:"Wanan Hongsheng Electronic Co.Ltd",E0A198:"NOJA Power Switchgear Pty Ltd",E0A1D7:"SFR",E0A30F:"Pevco",E0A3AC:"Huawei Technologies Co. Ltd",E0A670:"Nokia Corporation",E0A700:"Verkada Inc",E0A8B8:"Le Shi Zhi Xin Electronic Technology (Tianjin) Limited",E0AA96:"Samsung Electronics Co. Ltd",E0AAB0:"General Vision Electronics Co. Ltd",E0AADB:"Nanjing PANENG Technology Development Co. Ltd",E0ABFE:"Orb Networks, Inc.",E0ACCB:"Apple",E0ACF1:"Cisco Systems Inc.",E0AE5E:"Alps Electric Co. Ltd",E0AEB2:"Bender GmbH & Co.KG",E0AEED:"Loenk",E0AF4B:"Pluribus Networks, Inc.",E0B2F1:"FN-Link Technology Limited",E0B52D:"Apple",E0B6F5:"IEEE Registration Authority",E0B70A:"ARRIS Group, Inc.",E0B7B1:"ARRIS Group, Inc.",E0B94D:"Shenzhen Bilian Electronic Co. Ltd",E0B9A5:"Azurewave Technologies Inc.",E0B9BA:"Apple",E0B9E5:"Technicolor",E0BC43:"C2 Microsystems, Inc.",E0C0D1:"CK Telecom (Shenzhen) Limited",E0C286:"Aisai Communication Technology Co. Ltd",E0C2B7:"Masimo Corporation",E0C3F3:"zte Corporation",E0C6B3:"MilDef AB",E0C767:"Apple",E0C79D:"Texas Instruments",E0C86A:"SHENZHEN TW-SCIE Co. Ltd",E0C922:"Jireh Energy Tech. Ltd",E0C97A:"Apple",E0CA4D:"Shenzhen Unistar Communication Co. Ltd",E0CA94:"Askey Computer Corp",E0CB1D:"Private",E0CB4E:"ASUSTek Computer Inc.",E0CBBC:"Cisco Meraki",E0CBEE:"Samsung Electronics Co. Ltd",E0CDFD:"Beijing E3Control Technology Co Ltd",E0CEC3:"Askey Computer Corp",E0CF2D:"Gemintek Corporation",E0D10A:"Katoudenkikougyousyo Co Ltd",E0D173:"Cisco Systems Inc.",E0D1E6:"Aliph dba Jawbone",E0D31A:"EQUES Technology Co., Limited",E0D55E:"Giga-Byte Technology Co. Ltd",E0D7BA:"Texas Instruments",E0D848:"Dell Inc.",E0D9A2:"Hippih aps",E0D9E3:"Eltex Enterprise Ltd",E0DADC:"JVC KENWOOD Corporation",E0DB10:"Samsung Electronics Co. Ltd",E0DB55:"Dell Inc.",E0DB88:"Open Standard Digital-IF Interface for SATCOM Systems",E0DCA0:"Siemens Industrial Automation Products Ltd Chengdu",E0DDC0:"vivo Mobile Communication Co. Ltd",E0E5CF:"Texas Instruments",E0E62E:"TCT mobile Ltd",E0E631:"SNB Technologies Limited",E0E751:"Nintendo Co. Ltd",E0E7BB:"Nureva, Inc.",E0E8E8:"Olive Telecommunication Pvt. Ltd",E0ED1A:"vastriver Technology Co. Ltd",E0EDC7:"Shenzhen Friendcom Technology Development Co. Ltd",E0EE1B:"Panasonic Automotive Systems Company Of America",E0EF25:"Lintes Technology Co. Ltd",E0F211:"Digitalwatt",E0F379:"Vaddio",E0F5C6:"Apple",E0F5CA:"Cheng UEI Precision Industry Co. Ltd",E0F847:"Apple",E0F9BE:"Cloudena Corp.",E0FAEC:"Platan sp. z o.o. sp. k.",E0FFF7:"Softiron Inc.",E4029B:"Intel Corporation",E40439:"TomTom Software Ltd",E40EEE:"Huawei Technologies Co. Ltd",E4115B:"Hewlett-Packard Company",E41218:"ShenZhen Rapoo Technology Co. Ltd",E4121D:"Samsung Electronics Co. Ltd",E41289:"topsystem Systemhaus GmbH",E417D8:"8BITDO Technology HK Limited",E4186B:"ZyXEL Communications Corp",E41A2C:"ZPE Systems, Inc.",E41C4B:"V2 Technology, Inc.",E41D2D:"Mellanox Technologies, Inc.",E41F13:"IBM Corp",E422A5:"Plantronics, Inc.",E42354:"Shenzhen Fuzhi Software Technology Co. Ltd",E425E7:"Apple",E425E9:"Color-Chip",E42771:"Smartlabs",E42AD3:"Magneti Marelli S.p.A. Powertrain",E42B34:"Apple",E42C56:"Lilee Systems Ltd",E42D02:"TCT mobile Ltd",E42D7B:"China Mobile IOT Company Limited",E42F26:"Fiberhome Telecommunication Technologies Co. Ltd",E42F56:"OptoMET GmbH",E42FF6:"Unicore Communication Inc.",E43022:"Hanwha Techwin Security Vietnam",E432CB:"Samsung Electronics Co. Ltd",E43593:"Hangzhou GoTo technology Co.Ltd",E435C8:"Huawei Technologies Co. Ltd",E435FB:"Sabre Technology (Hull) Ltd",E437D7:"Henri Depaepe S.A.S.",E438F2:"Advantage Controls",E43A6E:"Shenzhen Zeroone Technology Co. Ltd",E43ED7:"Arcadyan Corporation",E43FA2:"Wuxi DSP Technologies Inc.",E440E2:"Samsung Electronics Co. Ltd",E441E6:"Ottec Technology GmbH",E442A6:"Intel Corporation",E4434B:"Dell Inc.",E446BD:"C&C Technic Taiwan Co. Ltd",E446DA:"Xiaomi Communications Co Ltd",E44790:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",E448C7:"Cisco SPVTG",E44C6C:"Shenzhen Guo Wei Electronic Co,. Ltd",E44E18:"Gardasoft VisionLimited",E44E76:"Championtech Enterprise (Shenzhen) Inc",E44F29:"MA Lighting Technology GmbH",E44F5F:"EDS Elektronik Destek San.Tic.LtdSti",E4509A:"HW Communications Ltd",E455EA:"Dedicated Computing",E45614:"Suttle Apparatus",E45740:"ARRIS Group, Inc.",E457A8:"Stuart Manufacturing, Inc.",E458B8:"Samsung Electronics Co. Ltd",E458E7:"Samsung Electronics Co. Ltd",E45AA2:"vivo Mobile Communication Co. Ltd",E45D51:"SFR",E45D52:"Avaya Inc",E45D75:"Samsung Electronics Co. Ltd",E46059:"Pingtek Co. Ltd",E46251:"HAO Cheng Group Limited",E46449:"ARRIS Group, Inc.",E467BA:"Danish Interpretation Systems A/S",E468A3:"Huawei Technologies Co. Ltd",E4695A:"Dictum Health, Inc.",E46C21:"messMa GmbH",E46F13:"D-Link International",E470B8:"Intel Corporation",E47185:"Securifi Ltd",E472E2:"Huawei Technologies Co. Ltd",E4751E:"Getinge Sterilization AB",E47723:"zte Corporation",E4776B:"Aartesys AG",E477D4:"Minrray Industry Co. Ltd",E47B3F:"Beijing Co-Cloud Technology Ltd",E47CF9:"Samsung Electronics Co. Ltd",E47D5A:"Beijing Hanbang Technology Corp.",E47DBD:"Samsung Electronics Co. Ltd",E47DEB:"Shanghai Notion Information Technology Co. Ltd",E47E66:"Huawei Technologies Co. Ltd",E47FB2:"Fujitsu Limited",E48184:"Nokia",E481B3:"Shenzhen ACT Industrial Co. Ltd",E482CC:"Jumptronic GmbH",E48399:"ARRIS Group, Inc.",E48501:"Geberit International AG",E48AD5:"RF Window Co. Ltd",E48B7F:"Apple",E48C0F:"Discovery Insure",E48D8C:"Routerboard.com",E48F34:"Vodafone Italia S.p.A.",E49069:"Rockwell Automation",E4907E:"Motorola Mobility LLC, a Lenovo Company",E492E7:"Gridlink Tech. Co. Ltd",E492FB:"Samsung Electronics Co. Ltd",E4956E:"IEEE Registration Authority",E496AE:"ALTOGRAPHICS Inc.",E497F0:"Shanghai VLC Technologies Ltd Co.",E498D1:"Microsoft Mobile Oy",E498D6:"Apple",E49A79:"Apple",E49ADC:"Apple",E49E12:"Freebox SAS",E4A1E6:"Alcatel-Lucent Shanghai Bell Co. Ltd",E4A32F:"Shanghai Artimen Technology Co. Ltd",E4A387:"Control Solutions LLC",E4A471:"Intel Corporation",E4A5EF:"Tron Link Electronics Co. Ltd",E4A749:"Palo Alto Networks",E4A7A0:"Intel Corporation",E4A7C5:"Huawei Technologies Co. Ltd",E4A7FD:"Cellco Partnership",E4A8B6:"Huawei Technologies Co. Ltd",E4AA5D:"Cisco Systems Inc.",E4AB46:"UAB Selteka",E4AD7D:"SCL Elements",E4AFA1:"HES-SO",E4B005:"Beijing IQIYI Science & Technology Co. Ltd",E4B021:"Samsung Electronics Co. Ltd",E4B318:"Intel Corporation",E4BAD9:"360 Fly Inc.",E4BD4B:"zte Corporation",E4BEED:"Netcore Technology Inc.",E4C146:"Objetivos y Servicios de Valor A",E4C1F1:"SHENZHEN SPOTMAU InfORMATION TECHNOLIGY Co. Ltd",E4C2D1:"Huawei Technologies Co. Ltd",E4C483:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",E4C62B:"Airware",E4C63D:"Apple",E4C6E6:"Mophie, LLC",E4C722:"Cisco Systems Inc.",E4C801:"BLU Products Inc",E4C806:"Ceiec Electric Technology Inc.",E4CB59:"Beijing Loveair Science and Technology Co. Ltd",E4CE02:"WyreStorm Technologies Ltd",E4CE70:"Health & Life Co. Ltd",E4CE8F:"Apple",E4D332:"TP-Link Technologies Co. Ltd",E4D3F1:"Cisco Systems Inc.",E4D53D:"Hon Hai Precision Ind. Co. Ltd",E4D71D:"Oraya Therapeutics",E4DD79:"En-Vision America, Inc.",E4E0A6:"Apple",E4E0C5:"Samsung Electronics Co. Ltd",E4E409:"Leifheit AG",E4E4AB:"Apple",E4EC10:"Nokia Corporation",E4EEFD:"MR&D Manufacturing",E4F004:"Dell Inc.",E4F042:"Google, Inc.",E4F14C:"Private",E4F365:"Time-O-Matic, Inc.",E4F3E3:"Shanghai iComhome Co. Ltd",E4F3F5:"Shenzhen Mercury Communication Technologies Co. Ltd",E4F4C6:"Netgear",E4F7A1:"Datafox GmbH",E4F89C:"Intel Corporation",E4F8EF:"Samsung Electronics Co. Ltd",E4F939:"Minxon Hotel Technology Inc.",E4FA1D:"PAD Peripheral Advanced Design Inc.",E4FAED:"Samsung Electronics Co. Ltd",E4FAFD:"Intel Corporation",E4FB5D:"Huawei Technologies Co. Ltd",E4FB8F:"Mobiwire Mobiles (Ningbo) Co. Ltd",E4FED9:"EDMI Europe Ltd",E4FFDD:"Electron India",E80036:"Befs Co,. Ltd",E8039A:"Samsung Electronics Co. Ltd",E8040B:"Apple",E80410:"Private",E80462:"Cisco Systems Inc.",E804F3:"Throughtek Co. Ltd",E8056D:"Nortel Networks",E80688:"Apple",E80734:"Champion Optical Network Engineering, LLC",E807BF:"Shenzhen Boomtech Industry Co. Ltd",E8088B:"Huawei Technologies Co. Ltd",E80945:"Integrated Device Technology (Malaysia) Sdn. Bhd.",E80959:"Guoguang Electric Co. Ltd",E80B13:"Akib Systems Taiwan, Inc",E80C38:"Daeyoung Information System Co. Ltd",E80C75:"Syncbak, Inc.",E8102E:"Really Simple Software, Inc",E81132:"Samsung Electronics Co. Ltd",E811CA:"Shandong Kaer Electric.Co. Ltd",E81324:"GuangZhou Bonsoninfo System Co. Ltd",E81363:"Comstock RD, Inc.",E81367:"AIRSOUND Inc.",E8150E:"Nokia Corporation",E8162B:"IDEO Security Co. Ltd",E817FC:"Fujitsu Cloud Technologies Limited",E81863:"IEEE Registration Authority",E81AAC:"ORFEO SOUNDWORKS Inc.",E81DA8:"Ruckus Wireless",E820E2:"HUMAX Co. Ltd",E82877:"TMY Co. Ltd",E828D5:"Cots Technology",E82A44:"Liteon Technology Corporation",E82AEA:"Intel Corporation",E82E24:"Out Of the Fog Research LLC",E8330D:"Xaptec GmbH",E83381:"ARRIS Group, Inc.",E8343E:"Beijing Infosec Technologies Co. Ltd",E8361D:"Sense Labs, Inc.",E8377A:"ZyXEL Communications Corp",E83935:"Hewlett-Packard Company",E839DF:"Askey Computer Corp",E83A12:"Samsung Electronics Co. Ltd",E83A97:"Toshiba Corporation",E83EB6:"RIM",E83EFB:"Geodesic Ltd",E83EFC:"ARRIS Group, Inc.",E84040:"Cisco Systems Inc.",E840F2:"Pegatron Corporation",E843B6:"QNAP Systems, Inc.",E8447E:"Bitdefender SRL",E8481F:"Advanced Automotive Antennas",E84DD0:"Huawei Technologies Co. Ltd",E84E06:"Edup International (HK) Co. Ltd",E84E84:"Samsung Electronics Co. Ltd",E84ECE:"Nintendo Co. Ltd",E8508B:"Samsung Electro-Mechanics(Thailand)",E8516E:"TSMART Inc.",E8519D:"Yeonhab Precision Co. Ltd",E85484:"NEO Information Systems Co. Ltd",E855B4:"SAI Technology Inc.",E85659:"Advanced-Connectek Inc.",E856D6:"NCTech Ltd",E85AA7:"LLC Emzior",E85B5B:"LG Electronics Inc",E85BF0:"Imaging Diagnostics",E85D6B:"Luminate Wireless",E85E53:"Infratec Datentechnik GmbH",E8611F:"Dawning Information Industry Co. Ltd",E8617E:"Liteon Technology Corporation",E86183:"Black Diamond Advanced Technology, LLC",E861BE:"Melec Inc.",E86549:"Cisco Systems Inc.",E865D4:"Tenda Technology Co. LtdDongguan branch",E866C4:"Diamanti",E86819:"Huawei Technologies Co. Ltd",E86CDA:"Supercomputers and Neurocomputers Research Center",E86D52:"ARRIS Group, Inc.",E86D54:"Digit Mobile Inc",E86D65:"AUDIO MOBIL Elektronik GmbH",E86D6E:"voestalpine SIGNALING Fareham Ltd",E86FF2:"Actiontec Electronics, Inc",E8718D:"Elsys Equipamentos Eletronicos Ltda",E874E6:"ADB Broadband Italia",E8757F:"FIRS Technologies(Shenzhen) Co. Ltd",E878A1:"Beoview Intercom DOO",E87AF3:"S5 Tech S.r.l.",E8802E:"Apple",E880D8:"GNTEK Electronics Co. Ltd",E8825B:"ARRIS Group, Inc.",E887A3:"Loxley Public Company Limited",E8886C:"Shenzhen SC Technologies Co. Ltd",E8892C:"ARRIS Group, Inc.",E88D28:"Apple",E88DF5:"ZNYX Networks, Inc.",E88E60:"NSD Corporation",E89120:"Motorola Mobility LLC, a Lenovo Company",E89218:"Arcontia International AB",E892A4:"LG Electronics (Mobile Communications)",E89309:"Samsung Electronics Co. Ltd",E8944C:"Cogent Healthcare Systems Ltd",E894F6:"TP-Link Technologies Co. Ltd",E89606:"testo Instruments (Shenzhen) Co. Ltd",E8986D:"Palo Alto Networks",E8995A:"PiiGAB, Processinformation i Goteborg AB",E899C4:"HTC Corporation",E89A8F:"Quanta Computer Inc.",E89AFF:"Fujian LANDI Commercial Equipment Co. Ltd",E89D87:"Toshiba",E89E0C:"Private",E89EB4:"Hon Hai Precision Ind. Co. Ltd",E89FEC:"Chengdu KT Electronic HI-Tech Co. Ltd",E8A364:"Signal Path International / Peachtree Audio",E8A4C1:"Deep Sea Electronics PLC",E8A7F2:"sTraffic",E8ABF3:"Huawei Technologies Co. Ltd",E8ABFA:"Shenzhen Reecam Tech.Ltd",E8B1FC:"Intel Corporation",E8B2AC:"Apple",E8B4AE:"Shenzhen C&D Electronics Co. Ltd",E8B4C8:"Samsung Electronics Co. Ltd",E8B6C2:"Juniper Networks",E8B748:"Cisco Systems Inc.",E8BA70:"Cisco Systems Inc.",E8BB3D:"Sino Prime-Tech Limited",E8BBA8:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",E8BDD1:"Huawei Technologies Co. Ltd",E8BE81:"Sagemcom Broadband SAS",E8C1B8:"Nanjing Bangzhong Electronic Commerce Limited",E8C1D7:"Philips",E8C229:"H-Displays (MSC) Bhd",E8C320:"Austco Communication Systems Pty Ltd",E8C74F:"Liteon Technology Corporation",E8CBA1:"Nokia Corporation",E8CC18:"D-Link International",E8CC32:"Micronet Ltd",E8CD2D:"Huawei Technologies Co. Ltd",E8CE06:"SkyHawke Technologies, LLC.",E8D0FA:"MKS Instruments Deutschland GmbH",E8D11B:"Askey Computer Corp",E8D483:"ULTIMATE Europe Transportation Equipment GmbH",E8D4E0:"Beijing BenyWave Technology Co. Ltd",E8D819:"Azurewave Technologies Inc.",E8DA96:"Zhuhai Tianrui Electrical Power Tech. Co. Ltd",E8DAAA:"VideoHome Technology Corp.",E8DE00:"ChongQing GuanFang Technology Co. Ltd",E8DE27:"TP-Link Technologies Co. Ltd",E8DE8E:"Integrated Device Technology (Malaysia) Sdn. Bhd.",E8DED6:"Intrising Networks, Inc.",E8DEFB:"Mesotic SAS",E8DF70:"AVM Audiovisuelles Marketing und Computersysteme GmbH",E8DFF2:"PRF Co. Ltd",E8E08F:"Gravotech Marking SAS",E8E0B7:"Toshiba",E8E1E1:"Gemtek Technology Co. Ltd",E8E1E2:"Energotest",E8E5D6:"Samsung Electronics Co. Ltd",E8E732:"Alcatel-Lucent Enterprise",E8E770:"Warp9 Tech Design, Inc.",E8E776:"Shenzhen Kootion Technology Co. Ltd",E8E875:"iS5 Communications Inc.",E8EA6A:"StarTech.com",E8EADA:"Denkovi Assembly Electronics Ltd",E8EB11:"Texas Instruments",E8ED05:"ARRIS Group, Inc.",E8EDF3:"Cisco Systems Inc.",E8EF89:"OPMEX Tech.",E8F1B0:"Sagemcom Broadband SAS",E8F226:"Millson Custom Solutions Inc.",E8F2E2:"LG Innotek",E8F2E3:"Starcor Beijing Co.,Limited",E8F724:"Hewlett Packard Enterprise",E8F928:"Rftech SRL",E8FAF7:"Guangdong Uniteddata Holding Group Co. Ltd",E8FC60:"ELCOM Innovations Private Limited",E8FCAF:"Netgear",E8FD72:"Shanghai Linguo Technology Co. Ltd",E8FD90:"Turbostor",E8FDE8:"CeLa Link Corporation",EC0133:"Trinus Systems Inc.",EC01E2:"Foxconn Interconnect Technology",EC01EE:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",EC0441:"ShenZhen TIGO Semiconductor Co. Ltd",EC086B:"TP-Link Technologies Co. Ltd",EC0D9A:"Mellanox Technologies, Inc.",EC0EC4:"Hon Hai Precision Ind. Co. Ltd",EC0ED6:"Itech Instruments SAS",EC107B:"Samsung Electronics Co. Ltd",EC1120:"FloDesign Wind Turbine Corporation",EC1127:"Texas Instruments",EC13B2:"Netonix",EC13DB:"Juniper Networks",EC14F6:"BioControl AS",EC172F:"TP-Link Technologies Co. Ltd",EC1766:"Research Centre Module",EC1A59:"Belkin International Inc.",EC1D7F:"zte Corporation",EC1D8B:"Cisco Systems Inc.",EC1F72:"Samsung Electro-Mechanics(Thailand)",EC219F:"VidaBox LLC",EC21E5:"Toshiba",EC2257:"JiangSu NanJing University Electronic Information Technology Co. Ltd",EC2280:"D-Link International",EC233D:"Huawei Technologies Co. Ltd",EC2368:"IntelliVoice Co. Ltd",EC237B:"zte Corporation",EC24B8:"Texas Instruments",EC26CA:"TP-Link Technologies Co. Ltd",EC26FB:"Tecc Co. Ltd",EC2AF0:"Ypsomed AG",EC2C49:"University Of Tokyo",EC2E4E:"Hitachi-LG Data Storage Inc",EC3091:"Cisco Systems Inc.",EC3586:"Apple",EC363F:"Markov Corporation",EC388F:"Huawei Technologies Co. Ltd",EC3BF0:"NovelSat",EC3C5A:"Shen Zhen Heng Sheng HUI Digital Technology Co. Ltd",EC3C88:"MCNEX Co. Ltd",EC3DFD:"Shenzhen Bilian Electronic Co. Ltd",EC3E09:"Performance Designed Products, LLC",EC3EF7:"Juniper Networks",EC3F05:"Institute 706, The Second Academy China Aerospace Science & Industry Corp",EC42B4:"ADC Corporation",EC42F0:"ADL Embedded Solutions, Inc.",EC438B:"Yaptv",EC43E6:"AWCER Ltd",EC43F6:"ZyXEL Communications Corp",EC4476:"Cisco Systems Inc.",EC4644:"TTK SAS",EC4670:"Meinberg Funkuhren GmbH & Co. KG",EC473C:"Redwire, LLC",EC4993:"Qihan Technology Co. Ltd",EC4C4D:"ZAO NPK RoTeK",EC4D47:"Huawei Technologies Co. Ltd",EC4F82:"Calix Inc.",EC51BC:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",EC52DC:"WORLD MEDIA AND TECHNOLOGY Corp.",EC542E:"Shanghai XiMei Electronic Technology Co. Ltd",EC55F9:"Hon Hai Precision Ind. Co. Ltd",EC59E7:"Microsoft Corporation",EC5A86:"Yulong Computer Telecommunication Scientific (Shenzhen) Co. Ltd",EC5C69:"Mitsubishi Heavy Industries Mechatronics Systems Ltd",EC5F23:"Qinghai Kimascend Electronics Technology Co. Ltd",EC60E0:"AVI-ON Labs",EC6264:"Global411 Internet Services, LLC",EC63E5:"ePBoard Design LLC",EC64E7:"MOCACARE Corporation",EC65CC:"Panasonic Automotive Systems Company Of America",EC66D1:"B&W Group Ltd",EC6881:"Palo Alto Networks",EC6C9F:"Chengdu Volans Technology Co. Ltd",EC7097:"ARRIS Group, Inc.",EC71DB:"Shenzhen Baichuan Digital Technology Co. Ltd",EC74BA:"Hirschmann Automation and Control GmbH",EC7C74:"Justone Technologies Co. Ltd",EC7D11:"vivo Mobile Communication Co. Ltd",EC7D9D:"MEI",EC7FC6:"Eccel Corporation SAS",EC8009:"NovaSparks",EC8193:"Logitech, Inc",EC8350:"Microsoft Corporation",EC836C:"RM Tech Co. Ltd",EC852F:"Apple",EC888F:"TP-Link Technologies Co. Ltd",EC8892:"Motorola Mobility LLC, a Lenovo Company",EC8914:"Huawei Technologies Co. Ltd",EC89F5:"Lenovo Mobile Communication Technology Ltd",EC8A4C:"zte Corporation",EC8AC7:"Fiberhome Telecommunication Technologies Co. Ltd",EC8CA2:"Ruckus Wireless",EC8EAD:"DLX",EC8EAE:"Nagravision SA",EC8EB5:"Hewlett-Packard Company",EC9233:"Eddyfi NDT Inc",EC9327:"MEMMERT GmbH + Co. KG",EC9365:"Mapper.ai, Inc.",EC93ED:"DDoS-Guard Ltd",EC9681:"2276427 Ontario Inc",EC986C:"Lufft Mess- und Regeltechnik GmbH",EC98C1:"Beijing Risbo Network Technology Co. Ltd",EC9A74:"Hewlett-Packard Company",EC9B5B:"Nokia Corporation",EC9B8B:"Hewlett Packard Enterprise",EC9BF3:"Samsung Electro-Mechanics(Thailand)",EC9ECD:"Artesyn Embedded Technologies",EC9F0D:"IEEE Registration Authority",ECA29B:"Kemppi Oy",ECA86B:"Elitegroup Computer Systems Co. Ltd",ECA9FA:"Guangdong Genius Technology Co. Ltd",ECAAA0:"Pegatron Corporation",ECADB8:"Apple",ECB0E1:"Ciena Corporation",ECB106:"Acuro Networks, Inc",ECB1D7:"Hewlett-Packard Company",ECB541:"SHINANO E and E Co.Ltd",ECB5FA:"Philips Lighting BV",ECB870:"Beijing Heweinet Technology Co. Ltd",ECB907:"CloudGenix Inc",ECBAFE:"Giroptic",ECBBAE:"Digivoice Tecnologia em Eletronica Ltda",ECBD09:"FUSION Electronics Ltd",ECBD1D:"Cisco Systems Inc.",ECC06A:"PowerChord Group Limited",ECC38A:"Accuenergy (CANADA) Inc",ECC882:"Cisco Systems Inc.",ECCB30:"Huawei Technologies Co. Ltd",ECCD6D:"Allied Telesis, Inc.",ECD00E:"MiraeRecognition Co. Ltd",ECD040:"GEA Farm Technologies GmbH",ECD09F:"Xiaomi Communications Co Ltd",ECD19A:"Zhuhai Liming Industries Co. Ltd",ECD68A:"Shenzhen JMicron Intelligent Technology Developmen",ECD925:"Rami",ECD950:"IRT SA",ECD9D1:"Shenzhen TG-NET Botone Technology Co. Ltd",ECDE3D:"Lamprey Networks, Inc.",ECDF3A:"vivo Mobile Communication Co. Ltd",ECE09B:"Samsung Electronics Co. Ltd",ECE154:"Beijing Unisound Information Technology Co. Ltd",ECE1A9:"Cisco Systems Inc.",ECE2FD:"SKG Electric Group(Thailand) Co. Ltd",ECE512:"tado GmbH",ECE555:"Hirschmann Automation",ECE744:"Omntec mfg. Inc",ECE90B:"Sistema Solucoes Eletronicas Ltda - Easytech",ECE915:"STI Ltd",ECE9F8:"Guang Zhou TRI-SUN Electronics Technology Co. Ltd",ECEA03:"Darfon Lighting Corp",ECEBB8:"Hewlett Packard Enterprise",ECEED8:"ZTLX Network Technology Co. Ltd",ECF00E:"AboCom",ECF236:"Neomontana Electronics",ECF342:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",ECF35B:"Nokia Corporation",ECF451:"Arcadyan Corporation",ECF4BB:"Dell Inc.",ECF72B:"HD Digital Tech Co. Ltd",ECF8EB:"Sichuan Tianyi Comheart Telecomco. Ltd",ECFA03:"FCA",ECFAAA:"The IMS Company",ECFABC:"Espressif Inc.",ECFAF4:"SenRa Tech Pvt. Ltd",ECFC55:"A. Eberle GmbH & Co. KG",ECFE7E:"BlueRadios, Inc.",F0007F:"Janz - Contadores de Energia, SA",F0022B:"Chrontel",F00248:"SmarteBuilding",F0038C:"Azurewave Technologies Inc.",F00786:"Shandong Bittel Electronics Co. Ltd",F008F1:"Samsung Electronics Co. Ltd",F00D5C:"JinQianMao Technology Co. Ltd",F00E1D:"Megafone Limited",F00FEC:"Huawei Technologies Co. Ltd",F013C3:"Shenzhen Fenda Technology Co. Ltd",F015A0:"KyungDong One Co. Ltd",F015B9:"PlayFusion Limited",F0182B:"LG Chem",F01898:"Apple",F01B6C:"vivo Mobile Communication Co. Ltd",F01C13:"LG Electronics (Mobile Communications)",F01C2D:"Juniper Networks",F01DBC:"Microsoft Corporation",F01E34:"ORICO Technologies Co. Ltd",F01FAF:"Dell Inc.",F0219D:"Cal-Comp Electronics & Communications Company Ltd",F0224E:"Esan electronic Co.",F02329:"Showa Denki Co. Ltd",F023B9:"IEEE Registration Authority",F02405:"OPUS High Technology Corporation",F02408:"Talaris (Sweden) AB",F02475:"Apple",F02572:"Cisco Systems Inc.",F025B7:"Samsung Electro-Mechanics(Thailand)",F02624:"Wafa Technologies Co. Ltd",F0264C:"Dr. Sigrist AG",F0272D:"Amazon Technologies Inc.",F02745:"F-Secure Corporation",F02765:"Murata Manufacturing Co. Ltd",F02929:"Cisco Systems Inc.",F02A23:"Creative Next Design",F02A61:"Waldo Networks, Inc.",F02FA7:"Huawei Technologies Co. Ltd",F02FD8:"Bi2-Vision",F0321A:"Mita-Teknik A/S",F03404:"TCT mobile Ltd",F037A1:"Huike Electronics (SHENZHEN) Co. Ltd",F03A4B:"Bloombase, Inc.",F03A55:"Omega Elektronik AS",F03D03:"Tecno Mobile Limited",F03D29:"Actility",F03E90:"Ruckus Wireless",F03EBF:"Gogoro Taiwan Limited",F03FF8:"R L Drake",F0407B:"Fiberhome Telecommunication Technologies Co. Ltd",F041C8:"IEEE Registration Authority",F0421C:"Intel Corporation",F04335:"DVN(Shanghai)Ltd",F04347:"Huawei Technologies Co. Ltd",F045DA:"Texas Instruments",F04A2B:"PYRAMID Computer GmbH",F04B6A:"Scientific Production Association Siberian Arsenal Ltd",F04BF2:"JTECH Communications, Inc.",F04CD5:"Maxlinear, Inc",F04DA2:"Dell Inc.",F04F7C:"Private",F05849:"CareView Communications",F05A09:"Samsung Electronics Co. Ltd",F05B7B:"Samsung Electronics Co. Ltd",F05C19:"Aruba Networks",F05D89:"Dycon Limited",F05DC8:"Duracell Powermat",F05F5A:"Getriebebau NORD GmbH and Co. KG",F06130:"Advantage Pharmacy Services, LLC",F0620D:"Shenzhen Egreat Tech Corp. Ltd",F06281:"ProCurve Networking by HP",F065C2:"Yanfeng Visteon Electronics Technology (Shanghai) Co. Ltd",F065DD:"Primax Electronics Ltd",F06853:"Integrated Corporation",F06BCA:"Samsung Electronics Co. Ltd",F06D78:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",F06E0B:"Microsoft Corporation",F06E32:"Microtel Innovation S.R.L.",F0728C:"Samsung Electronics Co. Ltd",F073AE:"PEAK-System Technik",F07485:"NGD Systems, Inc.",F074E4:"Thundercomm Technology Co. Ltd",F0761C:"Compal Information (Kunshan) Co. Ltd",F0766F:"Apple",F07765:"Sourcefire, Inc",F077D0:"Xcellen",F07816:"Cisco Systems Inc.",F07959:"ASUSTek Computer Inc.",F07960:"Apple",F079E8:"Guangdong Oppo Mobile Telecommunications Corp. Ltd",F07BCB:"Hon Hai Precision Ind. Co. Ltd",F07D68:"D-Link Corporation",F07F06:"Cisco Systems Inc.",F07F0C:"Leopold Kostal GmbH &Co. KG",F08173:"Amazon Technologies Inc.",F081AF:"IRZ Automation Technologies Ltd",F08261:"Sagemcom Broadband SAS",F0842F:"ADB Broadband Italia",F084C9:"zte Corporation",F085C1:"Shenzhen RF-Link Technology Co. Ltd",F08A28:"JIANGSU HENGSION ELECTRONIC S and T Co. Ltd",F08BFE:"Costel.,Co.Ltd",F08CFB:"Fiberhome Telecommunication Technologies Co. Ltd",F08EDB:"VeloCloud Networks",F0921C:"Hewlett-Packard Company",F092B4:"Sichuan Tianyi Comheart Telecomco. Ltd",F0933A:"NxtConect",F093C5:"Garland Technology",F097E5:"Tamio, Inc",F09838:"Huawei Technologies Co. Ltd",F0989D:"Apple",F099B6:"Apple",F099BF:"Apple",F09A51:"Shanghai Viroyal Electronic Technology Company Limited",F09CBB:"RaonThink Inc.",F09CD7:"Guangzhou Blue Cheetah Intelligent Technology Co. Ltd",F09CE9:"Aerohive Networks Inc.",F09E63:"Cisco Systems Inc.",F09FC2:"Ubiquiti Networks Inc.",F0A225:"Private",F0A764:"GST Co. Ltd",F0AB54:"Mitsumi Electric Co. Ltd",F0ACA4:"HBC-radiomatic",F0ACD7:"IEEE Registration Authority",F0AD4E:"Globalscale Technologies, Inc.",F0AE51:"Xi3 Corp",F0AF50:"Phantom Intelligence",F0B052:"Ruckus Wireless",F0B0E7:"Apple",F0B2E5:"Cisco Systems Inc.",F0B429:"Xiaomi Communications Co Ltd",F0B479:"Apple",F0B5B7:"Disruptive Technologies Research AS",F0B5D1:"Texas Instruments",F0B6EB:"Poslab Technology Co. Ltd",F0BCC8:"MaxID (Pty) Ltd",F0BD2E:"H+S Polatis Ltd",F0BDF1:"Sipod Inc.",F0BF97:"Sony Corporation",F0C1F1:"Apple",F0C24C:"Zhejiang FeiYue Digital Technology Co. Ltd",F0C27C:"Mianyang Netop Telecom Equipment Co. Ltd",F0C77F:"Texas Instruments",F0C850:"Huawei Technologies Co. Ltd",F0C88C:"LeddarTech Inc.",F0C9D1:"GD Midea Air-Conditioning Equipment Co. Ltd",F0CBA1:"Apple",F0D14F:"Linear LLC",F0D1A9:"Apple",F0D1B8:"Ledvance",F0D2F1:"Amazon Technologies Inc.",F0D3A7:"CobaltRay Co. Ltd",F0D3E7:"Sensometrix SA",F0D4F6:"Lars Thrane A/S",F0D5BF:"Intel Corporation",F0D657:"Echosens",F0D767:"Axema Passagekontroll AB",F0D7AA:"Motorola Mobility LLC, a Lenovo Company",F0D9B2:"EXO S.A.",F0DA7C:"RLH Industries,Inc.",F0DB30:"Yottabyte",F0DBE2:"Apple",F0DBF8:"Apple",F0DCE2:"Apple",F0DE71:"Shanghai EDO Technologies Co. Ltd",F0DEB9:"ShangHai Y&Y Electronics Co. Ltd",F0DEF1:"Wistron Infocomm (Zhongshan) Corporation",F0E3DC:"Tecon MT, LLC",F0E5C3:"Dr?gerwerk AG & Co. KG aA",F0E77E:"Samsung Electronics Co. Ltd",F0EBD0:"Shanghai Feixun Communication Co. Ltd",F0EC39:"Essec",F0ED1E:"Bilkon Bilgisayar Kontrollu Cih. Im.Ltd",F0EE10:"Samsung Electronics Co. Ltd",F0EE58:"PACE Telematics GmbH",F0EEBB:"VIPAR GmbH",F0EFD2:"TF Payment Service Co. Ltd",F0F002:"Hon Hai Precision Ind. Co. Ltd",F0F249:"Hitron Technologies. Inc",F0F260:"Mobitec AB",F0F336:"TP-Link Technologies Co. Ltd",F0F5AE:"Adaptrum Inc.",F0F61C:"Apple",F0F644:"Whitesky Science & Technology Co. Ltd",F0F669:"Motion Analysis Corporation",F0F755:"Cisco Systems Inc.",F0F7B3:"Phorm",F0F842:"KEEBOX, Inc.",F0F8F2:"Texas Instruments",F0F9F7:"IES GmbH & Co. KG",F0FCC8:"ARRIS Group, Inc.",F0FDA0:"Acurix Networks Pty Ltd",F0FE6B:"Shanghai High-Flying Electronics Technology Co. Ltd",F40304:"Google, Inc.",F40321:"BeNeXt B.V.",F4032F:"Reduxio Systems",F40343:"Hewlett Packard Enterprise",F4044C:"ValenceTech Limited",F40669:"Intel Corporation",F4068D:"devolo AG",F406A5:"Hangzhou Bianfeng Networking Technology Co. Ltd",F409D8:"Samsung Electro-Mechanics(Thailand)",F40A4A:"IndUSNET Communication Technology Co. Ltd",F40B93:"BlackBerry RTS",F40E11:"IEEE Registration Authority",F40E22:"Samsung Electronics Co. Ltd",F40E83:"ARRIS Group, Inc.",F40F1B:"Cisco Systems Inc.",F40F24:"Apple",F40F9B:"Wavelink",F41535:"SPON Communication Technology Co. Ltd",F41563:"F5 Networks, Inc.",F415FD:"Shanghai Pateo Electronic Equipment Manufacturing Co. Ltd",F417B8:"AirTies Wireless Networks",F41BA1:"Apple",F41E26:"Simon-Kaloi Engineering",F41E5E:"RtBrick Inc.",F41F0B:"YAMABISHI Corporation",F41F88:"zte Corporation",F41FC2:"Cisco Systems Inc.",F42012:"Cuciniale GmbH",F42833:"MMPC Inc.",F42853:"Zioncom Electronics (Shenzhen) Ltd",F42896:"Specto Paineis Eletronicos Ltda",F42981:"vivo Mobile Communication Co. Ltd",F42B48:"Ubiqam",F42C56:"Senor Tech Co Ltd",F430B9:"Hewlett-Packard Company",F431C3:"Apple",F436E1:"Abilis Systems SARL",F437B7:"Apple",F43814:"Shanghai Howell Electronic Co. Ltd",F43D80:"FAG Industrial Services GmbH",F43E61:"Shenzhen Gongjin Electronics Co.,LT",F43E9D:"Benu Networks, Inc.",F44156:"Arrikto Inc.",F44227:"S & S Research Inc.",F4428F:"Samsung Electronics Co. Ltd",F44450:"BND Co. Ltd",F445ED:"Portable Innovation Technology Ltd",F44713:"Leading Public Performance Co. Ltd",F4472A:"Nanjing Rousing Sci. and Tech. Industrial Co. Ltd",F44848:"Amscreen Group Ltd",F449EF:"Emstone",F44B2A:"Cisco SPVTG",F44C70:"Skyworth Digital Technology(Shenzhen) Co. Ltd",F44C7F:"Huawei Technologies Co. Ltd",F44D17:"Goldcard High-Tech Co. Ltd",F44D30:"Elitegroup Computer Systems Co. Ltd",F44E05:"Cisco Systems Inc.",F44EFD:"Actions Semiconductor Co. Ltd(Cayman Islands)",F450EB:"Telechips Inc",F45214:"Mellanox Technologies, Inc.",F45433:"Rockwell Automation",F45595:"HENGBAO Corporation Ltd",F4559C:"Huawei Technologies Co. Ltd",F455E0:"Niceway CNC Technology Co. LtdHunan Province",F4573E:"Fiberhome Telecommunication Technologies Co. Ltd",F45842:"Boxx TV Ltd",F45B73:"Wanjiaan Interconnected Technology Co. Ltd",F45C89:"Apple",F45EAB:"Texas Instruments",F45F69:"Matsufu Electronics distribution Company",F45FD4:"Cisco SPVTG",F45FF7:"DQ Technology Inc.",F4600D:"Panoptic Technology, Inc",F462D0:"Not for Radio, LLC",F46349:"Diffon Corporation",F4645D:"Toshiba",F4672D:"ShenZhen Topstar Technology Company",F46A92:"Shenzhen Fast Technologies Co. Ltd",F46ABC:"Adonit Corp. Ltd",F46BEF:"Sagemcom Broadband SAS",F46D04:"ASUSTek Computer Inc.",F46DE2:"zte Corporation",F46E24:"NEC Personal Computers Ltd",F470AB:"vivo Mobile Communication Co. Ltd",F47190:"Samsung Electronics Co. Ltd",F473CA:"Conversion Sound Inc.",F47626:"Viltechmeda UAB",F47A4E:"Woojeon&Handan",F47ACC:"SolidFire, Inc.",F47B5E:"Samsung Electronics Co. Ltd",F47F35:"Cisco Systems Inc.",F48139:"Canon Inc.",F483CD:"TP-Link Technologies Co. Ltd",F483E1:"Shanghai Clouder Semiconductor Co. Ltd",F4844C:"Texas Instruments",F485C6:"FDT Technologies",F48771:"Infoblox",F48B32:"Xiaomi Communications Co Ltd",F48C50:"Intel Corporation",F48E09:"Nokia Corporation",F48E38:"Dell Inc.",F48E92:"Huawei Technologies Co. Ltd",F490CA:"Tensorcom",F490EA:"Deciso B.V.",F4911E:"Zhuhai Ewpe Information Technology Inc",F4939F:"Hon Hai Precision Ind. Co. Ltd",F49461:"NexGen Storage",F49466:"CountMax, Ltd",F49634:"Intel Corporation",F49651:"NAKAYO Inc",F499AC:"WEBER Schraubautomaten GmbH",F49EEF:"Taicang T&W Electronics",F49F54:"Samsung Electronics Co. Ltd",F49FF3:"Huawei Technologies Co. Ltd",F4A294:"Eagle World Development Co., Limited",F4A52A:"Hawa Technologies Inc",F4A739:"Juniper Networks",F4A997:"Canon Inc.",F4ACC1:"Cisco Systems Inc.",F4B164:"Lightning Telecommunications Technology Co. Ltd",F4B381:"WindowMaster A/S",F4B520:"Biostar Microtech international Corp.",F4B52F:"Juniper Networks",F4B549:"Xiamen Yeastar Information Technology Co. Ltd",F4B6E5:"TerraSem Co. Ltd",F4B72A:"Time Interconnect Ltd",F4B7B3:"vivo Mobile Communication Co. Ltd",F4B7E2:"Hon Hai Precision Ind. Co. Ltd",F4B85E:"Texas Instruments",F4B8A7:"zte Corporation",F4BC97:"Shenzhen Crave Communication Co. Ltd",F4BD7C:"Chengdu jinshi Communication Co. Ltd",F4C248:"Samsung Electronics Co. Ltd",F4C447:"Coagent International Enterprise Limited",F4C4D6:"Shenzhen Xinfa Electronic Co. Ltd",F4C613:"Alcatel-Lucent Shanghai Bell Co. Ltd",F4C6D7:"blackned GmbH",F4C714:"Huawei Technologies Co. Ltd",F4C795:"WEY Elektronik AG",F4CA24:"FreeBit Co. Ltd",F4CAE5:"Freebox SAS",F4CB52:"Huawei Technologies Co. Ltd",F4CC55:"Juniper Networks",F4CD90:"Vispiron Rotec GmbH",F4CE46:"Hewlett-Packard Company",F4CFE2:"Cisco Systems Inc.",F4D032:"Yunnan Ideal Information&Technology. Ltd",F4D261:"SEMOCON Co. Ltd",F4D7B2:"LGS Innovations, LLC",F4D9FB:"Samsung Electronics Co. Ltd",F4DC41:"Youngzone Culture (Shanghai) Corp",F4DC4D:"Beijing CCD Digital Technology Co. Ltd",F4DCA5:"Dawon DNS",F4DCDA:"Zhuhai Jiahe Communication Technology Co., limited",F4DCF9:"Huawei Technologies Co. Ltd",F4DD9E:"GoPro",F4DE0C:"ESPOD Ltd",F4E11E:"Texas Instruments",F4E142:"Delta Elektronika BV",F4E204:"Traqueur",F4E3FB:"Huawei Technologies Co. Ltd",F4E4AD:"zte Corporation",F4E6D7:"Solar Power Technologies, Inc.",F4E926:"Tianjin Zanpu Technology Inc.",F4E9D4:"QLogic Corporation",F4EA67:"Cisco Systems Inc.",F4EAB5:"Aerohive Networks Inc.",F4EB38:"Sagemcom Broadband SAS",F4EC38:"TP-Link Technologies Co. Ltd",F4ED5F:"Shenzhen KTC Technology Group",F4EE14:"Shenzhen Mercury Communication Technologies Co. Ltd",F4EF9E:"Sgsg Science & Technology Co. Ltd",F4F15A:"Apple",F4F1E1:"Motorola Mobility LLC, a Lenovo Company",F4F26D:"TP-Link Technologies Co. Ltd",F4F3AA:"JBL GmbH & Co. KG",F4F524:"Motorola Mobility LLC, a Lenovo Company",F4F5A5:"Nokia Corporation",F4F5D8:"Google, Inc.",F4F5DB:"Xiaomi Communications Co Ltd",F4F5E8:"Google, Inc.",F4F646:"Dediprog Technology Co. Ltd",F4F951:"Apple",F4FC32:"Texas Instruments",F4FCB1:"JJ Corp",F4FD2B:"ZOYI Company",F80113:"Huawei Technologies Co. Ltd",F80278:"IEEE Registration Authority",F80332:"Khomp",F80377:"Apple",F8042E:"Samsung Electro-Mechanics(Thailand)",F8051C:"DRS Imaging and Targeting Solutions",F80BBE:"ARRIS Group, Inc.",F80BCB:"Cisco Systems Inc.",F80BD0:"Datang Telecom Communication terminal (Tianjin) Co. Ltd",F80CF3:"LG Electronics (Mobile Communications)",F80D43:"Hon Hai Precision Ind. Co. Ltd",F80D60:"Canon Inc.",F80DEA:"ZyCast Technology Inc.",F80F41:"Wistron Infocomm (Zhongshan) Corporation",F80F84:"Natural Security SAS",F81037:"Atopia Systems, LP",F81547:"Avaya Inc",F81654:"Intel Corporation",F81897:"2Wire Inc.",F81A67:"TP-Link Technologies Co. Ltd",F81CE5:"Telefonbau Behnke GmbH",F81D0F:"Hitron Technologies. Inc",F81D78:"IEEE Registration Authority",F81D90:"Solidwintech",F81D93:"Longdhua(Beijing) Controls Technology Co. Ltd",F81EDF:"Apple",F82055:"Green Information System",F82285:"Cypress Technology Co. Ltd",F823B2:"Huawei Technologies Co. Ltd",F82441:"Yeelink",F82793:"Apple",F82819:"Liteon Technology Corporation",F82BC8:"Jiangsu Switter Co. Ltd",F82C18:"2Wire Inc.",F82EDB:"RTW GmbH & Co. KG",F82F08:"Molex",F82F5B:"eGauge Systems LLC",F82FA8:"Hon Hai Precision Ind. Co. Ltd",F83094:"Alcatel-Lucent Telecom Limited",F8313E:"endeavour GmbH",F832E4:"ASUSTek Computer Inc.",F83376:"Good Mind Innovation Co. Ltd",F83441:"Intel Corporation",F83553:"Magenta Research Ltd",F835DD:"Gemtek Technology Co. Ltd",F83D4E:"Softlink Automation System Co. Ltd",F83DFF:"Huawei Technologies Co. Ltd",F83F51:"Samsung Electronics Co. Ltd",F842FB:"Yasuda Joho Co. Ltd",F844E3:"Taicang T&W Electronics",F845AD:"Konka Group Co. Ltd",F8461C:"Sony Interactive Entertainment Inc.",F8462D:"SYNTEC Incorporation",F8472D:"X2gen Digital Corp. Ltd",F84897:"Hitachi Ltd",F84A73:"Eumtech Co. Ltd",F84A7F:"Innometriks Inc",F84ABF:"Huawei Technologies Co. Ltd",F84F57:"Cisco Systems Inc.",F85063:"Verathon",F8516D:"Denwa Technology Corp.",F852DF:"VNL Europe AB",F854AF:"ECI Telecom Ltd",F8572E:"Core Brands, LLC",F85971:"Intel Corporation",F85A00:"Sanford LP",F85B9C:"SB SysTEMS Co. Ltd",F85BC9:"M-Cube Spa",F85C45:"IC Nexus Co. Ltd",F85C4D:"Nokia",F85F2A:"Nokia Corporation",F86214:"Apple",F862AA:"xn Systems",F8633F:"Intel Corporation",F86465:"Anova Applied Electronics, Inc.",F86601:"Suzhou Chi-tek Information technology Co. Ltd",F866D1:"Hon Hai Precision Ind. Co. Ltd",F866F2:"Cisco Systems Inc.",F86971:"Seibu Electric Co.,",F86CE1:"Taicang T&W Electronics",F86ECF:"Arcx Inc",F86EEE:"Huawei Technologies Co. Ltd",F86FC1:"Apple",F871FE:"The Goldman Sachs Group, Inc.",F872EA:"Cisco Systems Inc.",F87394:"Netgear",F873A2:"Avaya Inc",F87588:"Huawei Technologies Co. Ltd",F8769B:"Neopis Co. Ltd",F877B8:"Samsung Electronics Co. Ltd",F87AEF:"Rosonix Technology, Inc.",F87B20:"Cisco Systems Inc.",F87B62:"FASTWEL INTERNATIONAL Co. Ltd Taiwan Branch",F87B7A:"ARRIS Group, Inc.",F87B8C:"Amped Wireless",F88096:"Elsys Equipamentos Eletr?nicos Ltda",F8811A:"Overkiz",F88479:"Yaojin Technology(Shenzhen)Co. Ltd",F884F2:"Samsung Electronics Co. Ltd",F88A3C:"IEEE Registration Authority",F88B37:"ARRIS Group, Inc.",F88C1C:"Kaishun Electronic Technology Co. Ltd Beijing",F88DEF:"Tenebraex",F88E85:"Comtrend Corporation",F88FCA:"Google, Inc.",F89066:"Nain Inc.",F8912A:"GLP German Light Products GmbH",F893F3:"Volans",F894C2:"Intel Corporation",F89550:"Proton Products Chengdu Ltd",F895C7:"LG Electronics (Mobile Communications)",F895EA:"Apple",F897CF:"Daeshin-Information Technology Co. Ltd",F8983A:"Leeman International (HongKong) Limited",F898B9:"Huawei Technologies Co. Ltd",F898EF:"Huawei Technologies Co. Ltd",F89955:"Fortress Technology Inc",F89D0D:"Control Technology Inc.",F89DBB:"Tintri",F89FB8:"YAZAKI Energy System Corporation",F8A03D:"Dinstar Technologies Co. Ltd",F8A097:"ARRIS Group, Inc.",F8A188:"LED Roadway Lighting",F8A2B4:"RHEWA-WAAGENFABRIK August Freudewald GmbH &Co. KG",F8A34F:"zte Corporation",F8A45F:"Xiaomi Communications Co Ltd",F8A5C5:"Cisco Systems Inc.",F8A963:"Compal Information (Kunshan) Co. Ltd",F8A9D0:"LG Electronics (Mobile Communications)",F8A9DE:"Puissance Plus",F8AA8A:"Axview Technology (Shenzhen) Co. Ltd",F8AB05:"Sagemcom Broadband SAS",F8AC6D:"Deltenna Ltd",F8B156:"Dell Inc.",F8B2F3:"Guangzhou Bosma Technology Co. Ltd",F8B568:"IEEE Registration Authority",F8B599:"Guangzhou CHNAVS Digital Technology Co. Ltd",F8B7E2:"Cisco Systems Inc.",F8BBBF:"eero Inc.",F8BC12:"Dell Inc.",F8BC41:"Rosslare Enterprises Limited",F8BE0D:"A2UICT Co. Ltd",F8BF09:"Huawei Technologies Co. Ltd",F8C001:"Juniper Networks",F8C091:"Highgates Technology",F8C120:"Xi'an Link-Science Technology Co. Ltd",F8C288:"Cisco Systems Inc.",F8C372:"Tsuzuki Denki",F8C397:"NZXT Corp. Ltd",F8C678:"Carefusion",F8C96C:"Fiberhome Telecommunication Technologies Co. Ltd",F8CAB8:"Dell Inc.",F8CFC5:"Motorola Mobility LLC, a Lenovo Company",F8D027:"Seiko Epson Corporation",F8D0AC:"Sony Interactive Entertainment Inc.",F8D0BD:"Samsung Electronics Co. Ltd",F8D111:"TP-Link Technologies Co. Ltd",F8D3A9:"AXAN Networks",F8D462:"Pumatronix Equipamentos Eletronicos Ltda.",F8D756:"Simm Tronic Limited",F8D7BF:"REV Ritter GmbH",F8DA0C:"Hon Hai Precision Ind. Co. Ltd",F8DADF:"EcoTech, Inc.",F8DAE2:"Beta LaserMike",F8DAF4:"Taishan Online Technology Co. Ltd",F8DB4C:"PNY Technologies, Inc.",F8DB7F:"HTC Corporation",F8DB88:"Dell Inc.",F8DC7A:"Variscite Ltd",F8DF15:"Sunitec Enterprise Co. Ltd",F8DFA8:"zte Corporation",F8E079:"Motorola Mobility LLC, a Lenovo Company",F8E44E:"Mcot Inc.",F8E4FB:"Actiontec Electronics, Inc",F8E61A:"Samsung Electronics Co. Ltd",F8E71E:"Ruckus Wireless",F8E7B5:"uTech Tecnologia LtdA",F8E811:"Huawei Technologies Co. Ltd",F8E903:"D-Link International",F8E968:"Egker Kft.",F8EA0A:"Dipl.-Math. Michael Rauch",F8EDA5:"ARRIS Group, Inc.",F8F005:"Newport Media Inc.",F8F014:"RackWare Inc.",F8F082:"NAG LLC",F8F1B6:"Motorola Mobility LLC, a Lenovo Company",F8F21E:"Intel Corporation",F8F25A:"G-Lab GmbH",F8F464:"Rawe Electonic GmbH",F8F532:"ARRIS Group, Inc.",F8F7D3:"International Communications Corporation",F8F7FF:"SYN-Tech Systems Inc",F8FB2F:"Santur Corporation",F8FE5C:"Reciprocal Labs Corp",F8FEA8:"Technico Japan Corporation",F8FF0B:"Electronic Technology Inc.",F8FF5F:"Shenzhen Communication Technology Co. Ltd",FC0012:"Toshiba Samsung Storage Technolgoy Korea Corporation",FC017C:"Hon Hai Precision Ind. Co. Ltd",FC019E:"Vievu",FC01CD:"Fundacion Tekniker",FC0647:"Cortland Research, LLC",FC06ED:"M2Motive Technology Inc.",FC07A0:"LRE Medical GmbH",FC084A:"Fujitsu Limited",FC0877:"Prentke Romich Company",FC09D8:"ACTEON Group",FC09F6:"Guangdong Tonze Electric Co. Ltd",FC0A81:"Extreme Networks, Inc.",FC0F4B:"Texas Instruments",FC0FE6:"Sony Interactive Entertainment Inc.",FC10BD:"Control Sistematizado S.A.",FC10C6:"Taicang T&W Electronics",FC1186:"Logic3 plc",FC1349:"Global Apps Corp.",FC15B4:"Hewlett-Packard Company",FC1607:"Taian Technology(Wuxi) Co. Ltd",FC1794:"InterCreative Co. Ltd",FC1910:"Samsung Electronics Co. Ltd",FC19D0:"Cloud Vision Networks Technology Co. Ltd",FC1A11:"vivo Mobile Communication Co. Ltd",FC1BFF:"V-ZUG AG",FC1D59:"I Smart Cities HK Ltd",FC1D84:"Autobase",FC1E16:"IPEVO Corp",FC1F19:"Samsung Electro Mechanics Co. Ltd",FC1FC0:"Eurecam",FC229C:"Han Kyung I Net Co. Ltd",FC2325:"EosTek (Shenzhen) Co. Ltd",FC253F:"Apple",FC27A2:"Trans Electric Co. Ltd",FC2A54:"Connected Data, Inc.",FC2A9C:"Apple",FC2D5E:"zte Corporation",FC2E2D:"Lorom Industrial Co.Ltd",FC2F40:"Calxeda, Inc.",FC2F6B:"Everspin Technologies, Inc.",FC2FAA:"Nokia",FC2FEF:"UTT Technologies Co. Ltd",FC3288:"CELOT Wireless Co. Ltd",FC335F:"Polyera",FC3598:"Favite Inc.",FC35E6:"Visteon Corp",FC372B:"Sichuan Tianyi Comheart Telecomco. Ltd",FC3CE9:"Tsingtong Technologies Co Ltd",FC3D93:"Longcheer Telecommunication Limited",FC3F7C:"Huawei Technologies Co. Ltd",FC3FAB:"Henan Lanxin Technology Co. Ltd",FC3FDB:"Hewlett-Packard Company",FC4203:"Samsung Electronics Co. Ltd",FC4463:"Universal Audio, Inc",FC4499:"Swarco LEA d.o.o.",FC455F:"Jiangxi Shanshui Optoelectronic Technology Co. Ltd",FC4596:"Compal Information (Kunshan) Co. Ltd",FC48EF:"Huawei Technologies Co. Ltd",FC4AE9:"Castlenet Technology Inc.",FC4B1C:"Intersensor S.R.L.",FC4BBC:"Sunplus Technology Co. Ltd",FC4D8C:"Shenzhen Pante Electronics Technology Co. Ltd",FC4DD4:"Universal Global Scientific Industrial Co. Ltd",FC5090:"SIMEX Sp. z o.o.",FC51A4:"ARRIS Group, Inc.",FC528D:"Technicolor CH USA Inc.",FC52CE:"Control iD",FC539E:"Shanghai Wind Technologies Co. Ltd",FC55DC:"Baltic Latvian Universal Electronics LLC",FC58FA:"Shen Zhen Shi Xin Zhong Xin Technology Co. Ltd",FC5A1D:"Hitron Technologies. Inc",FC5B24:"Weibel Scientific A/S",FC5B26:"MikroBits",FC5B39:"Cisco Systems Inc.",FC6018:"Zhejiang Kangtai Electric Co. Ltd",FC6198:"NEC Personal Products Ltd",FC626E:"Beijing MDC Telecom",FC62B9:"Alps Electric Co. Ltd",FC643A:"Samsung Electronics Co. Ltd",FC64BA:"Xiaomi Communications Co Ltd",FC65DE:"Amazon Technologies Inc.",FC683E:"Directed Perception, Inc",FC6947:"Texas Instruments",FC6C31:"LXinstruments GmbH",FC6DC0:"BME Corporation",FC6FB7:"ARRIS Group, Inc.",FC7516:"D-Link International",FC75E6:"Handreamnet",FC790B:"Hitachi High Technologies America, Inc.",FC7C02:"Phicomm (Shanghai) Co. Ltd",FC7CE7:"FCI USA LLC",FC7F56:"CoSyst Control Systems GmbH",FC8329:"Trei technics",FC8399:"Avaya Inc",FC83C6:"N-Radio Technologies Co. Ltd",FC8B97:"Shenzhen Gongjin Electronics Co.,LT",FC8E7E:"ARRIS Group, Inc.",FC8F90:"Samsung Electronics Co. Ltd",FC8FC4:"Intelligent Technology Inc.",FC9114:"Technicolor CH USA Inc.",FC923B:"Nokia Corporation",FC946C:"Ubivelox",FC94E3:"Technicolor CH USA Inc.",FC9947:"Cisco Systems Inc.",FC9AFA:"Motus Global Inc.",FC9BC6:"Sumavision Technologies Co. Ltd",FC9DD8:"Beijing TongTongYiLian Science and Technology Ltd",FC9FAE:"Fidus Systems Inc",FC9FE1:"CoNWIN.Tech. Ltd",FCA13E:"Samsung Electronics Co. Ltd",FCA183:"Amazon Technologies Inc.",FCA22A:"PT. Callysta Multi Engineering",FCA386:"Shenzhen Chuangwei-RGB Electronics Co. Ltd",FCA667:"Amazon Technologies Inc.",FCA6CD:"Fiberhome Telecommunication Technologies Co. Ltd",FCA841:"Avaya Inc",FCA89A:"Sunitec Enterprise Co. Ltd",FCA9B0:"Miartech (Shanghai),Inc.",FCAA14:"Giga-Byte Technology Co. Ltd",FCAD0F:"QTS Networks",FCAF6A:"Qulsar Inc",FCAFAC:"Socionext Inc.",FCB0C4:"Shanghai DareGlobal Technologies Co. Ltd",FCB4E6:"Askey Computer Corp",FCB58A:"Wapice Ltd",FCB698:"Cambridge Industries(Group) Co. Ltd",FCB7F0:"Idaho National Laboratory",FCBBA1:"Shenzhen Minicreate Technology Co. Ltd",FCBC9C:"Vimar Spa",FCC233:"Private",FCC23D:"Atmel Corporation",FCC2DE:"Murata Manufacturing Co. Ltd",FCC734:"Samsung Electronics Co. Ltd",FCC897:"zte Corporation",FCCAC4:"LifeHealth, LLC",FCCCE4:"Ascon Ltd",FCCF43:"Huizhou City Huiyang District Meisiqi Industry Development Co,.Ltd",FCCF62:"IBM Corp",FCD4F2:"The Coca Cola Company",FCD4F6:"Messana Air.Ray Conditioning s.r.l.",FCD5D9:"Shenzhen SDMC Technology Co. Ltd",FCD6BD:"Robert Bosch GmbH",FCD733:"TP-Link Technologies Co. Ltd",FCD817:"Beijing Hesun Technologies Co.Ltd",FCD848:"Apple",FCDB96:"Enervalley Co. Ltd",FCDBB3:"Murata Manufacturing Co. Ltd",FCDC4A:"G-Wearables Corp.",FCDD55:"Shenzhen WeWins wireless Co. Ltd",FCE186:"A3M Co. Ltd",FCE192:"Sichuan Jinwangtong Electronic Science&Technology Co,.Ltd",FCE1D9:"Stable Imaging Solutions LLC",FCE1FB:"Array Networks",FCE23F:"Clay Paky SPA",FCE33C:"Huawei Technologies Co. Ltd",FCE557:"Nokia Corporation",FCE66A:"Industrial Software Co",FCE892:"Hangzhou Lancable Technology Co. Ltd",FCE998:"Apple",FCECDA:"Ubiquiti Networks Inc.",FCEDB9:"Arrayent",FCEEE6:"Formike Electronic Co. Ltd",FCF136:"Samsung Electronics Co. Ltd",FCF152:"Sony Corporation",FCF1CD:"Optex-FA Co. Ltd",FCF528:"ZyXEL Communications Corp",FCF647:"Fiberhome Telecommunication Technologies Co. Ltd",FCF8AE:"Intel Corporation",FCF8B7:"TRONTEQ Electronic",FCFAF7:"Shanghai Baud Data Communication Co. Ltd",FCFBFB:"Cisco Systems Inc.",FCFC48:"Apple",FCFE77:"Hitachi Reftechno, Inc.",FCFEC2:"Invensys Controls UK Limited",FCFFAA:"IEEE Registration Authority"},e=[/^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/i,/^([0-9A-F]{2}[:-]){2}([0-9A-F]{2})$/i,/^([0-9A-F]{4}[.]){2}([0-9A-F]{4})$/i,/^[0-9A-F]{6}$/i,/^[0-9A-F]{12}$/i];return function(n,t){if("string"!=typeof n)throw new Error("Input not a string");if(t=Object.assign({},t),n=n.toUpperCase(),t.strict){if(!e.some(function(o){if(o.test(n))return!0}))throw new Error("Input not in strict format");n=n.replace(/[.:-]/g,"").substring(0,6)}else n=(i=n,/^[0-9A-F:]+$/.test(i)?i.split(":").map(function(o){return 1===o.length?"0"+o:o}).join(":"):i).replace(/[^0-9a-fA-F]/g,"").substring(0,6);var i;return n.length<6?null:o[n]||null}});
+0
-6
faraday/server/www/script/papaparse.min.js less more
0 /*!
1 Papa Parse
2 v4.1.2
3 https://github.com/mholt/PapaParse
4 */
5 !function(e){"use strict";function t(t,r){if(r=r||{},r.worker&&S.WORKERS_SUPPORTED){var n=f();return n.userStep=r.step,n.userChunk=r.chunk,n.userComplete=r.complete,n.userError=r.error,r.step=m(r.step),r.chunk=m(r.chunk),r.complete=m(r.complete),r.error=m(r.error),delete r.worker,void n.postMessage({input:t,config:r,workerId:n.id})}var o=null;return"string"==typeof t?o=r.download?new i(r):new a(r):(e.File&&t instanceof File||t instanceof Object)&&(o=new s(r)),o.stream(t)}function r(e,t){function r(){"object"==typeof t&&("string"==typeof t.delimiter&&1==t.delimiter.length&&-1==S.BAD_DELIMITERS.indexOf(t.delimiter)&&(u=t.delimiter),("boolean"==typeof t.quotes||t.quotes instanceof Array)&&(o=t.quotes),"string"==typeof t.newline&&(h=t.newline))}function n(e){if("object"!=typeof e)return[];var t=[];for(var r in e)t.push(r);return t}function i(e,t){var r="";"string"==typeof e&&(e=JSON.parse(e)),"string"==typeof t&&(t=JSON.parse(t));var n=e instanceof Array&&e.length>0,i=!(t[0]instanceof Array);if(n){for(var a=0;a<e.length;a++)a>0&&(r+=u),r+=s(e[a],a);t.length>0&&(r+=h)}for(var o=0;o<t.length;o++){for(var f=n?e.length:t[o].length,c=0;f>c;c++){c>0&&(r+=u);var d=n&&i?e[c]:c;r+=s(t[o][d],c)}o<t.length-1&&(r+=h)}return r}function s(e,t){if("undefined"==typeof e||null===e)return"";e=e.toString().replace(/"/g,'""');var r="boolean"==typeof o&&o||o instanceof Array&&o[t]||a(e,S.BAD_DELIMITERS)||e.indexOf(u)>-1||" "==e.charAt(0)||" "==e.charAt(e.length-1);return r?'"'+e+'"':e}function a(e,t){for(var r=0;r<t.length;r++)if(e.indexOf(t[r])>-1)return!0;return!1}var o=!1,u=",",h="\r\n";if(r(),"string"==typeof e&&(e=JSON.parse(e)),e instanceof Array){if(!e.length||e[0]instanceof Array)return i(null,e);if("object"==typeof e[0])return i(n(e[0]),e)}else if("object"==typeof e)return"string"==typeof e.data&&(e.data=JSON.parse(e.data)),e.data instanceof Array&&(e.fields||(e.fields=e.data[0]instanceof Array?e.fields:n(e.data[0])),e.data[0]instanceof Array||"object"==typeof e.data[0]||(e.data=[e.data])),i(e.fields||[],e.data||[]);throw"exception: Unable to serialize unrecognized input"}function n(t){function r(e){var t=_(e);t.chunkSize=parseInt(t.chunkSize),e.step||e.chunk||(t.chunkSize=null),this._handle=new o(t),this._handle.streamer=this,this._config=t}this._handle=null,this._paused=!1,this._finished=!1,this._input=null,this._baseIndex=0,this._partialLine="",this._rowCount=0,this._start=0,this._nextChunk=null,this.isFirstChunk=!0,this._completeResults={data:[],errors:[],meta:{}},r.call(this,t),this.parseChunk=function(t){if(this.isFirstChunk&&m(this._config.beforeFirstChunk)){var r=this._config.beforeFirstChunk(t);void 0!==r&&(t=r)}this.isFirstChunk=!1;var n=this._partialLine+t;this._partialLine="";var i=this._handle.parse(n,this._baseIndex,!this._finished);if(!this._handle.paused()&&!this._handle.aborted()){var s=i.meta.cursor;this._finished||(this._partialLine=n.substring(s-this._baseIndex),this._baseIndex=s),i&&i.data&&(this._rowCount+=i.data.length);var a=this._finished||this._config.preview&&this._rowCount>=this._config.preview;if(y)e.postMessage({results:i,workerId:S.WORKER_ID,finished:a});else if(m(this._config.chunk)){if(this._config.chunk(i,this._handle),this._paused)return;i=void 0,this._completeResults=void 0}return this._config.step||this._config.chunk||(this._completeResults.data=this._completeResults.data.concat(i.data),this._completeResults.errors=this._completeResults.errors.concat(i.errors),this._completeResults.meta=i.meta),!a||!m(this._config.complete)||i&&i.meta.aborted||this._config.complete(this._completeResults),a||i&&i.meta.paused||this._nextChunk(),i}},this._sendError=function(t){m(this._config.error)?this._config.error(t):y&&this._config.error&&e.postMessage({workerId:S.WORKER_ID,error:t,finished:!1})}}function i(e){function t(e){var t=e.getResponseHeader("Content-Range");return parseInt(t.substr(t.lastIndexOf("/")+1))}e=e||{},e.chunkSize||(e.chunkSize=S.RemoteChunkSize),n.call(this,e);var r;this._nextChunk=k?function(){this._readChunk(),this._chunkLoaded()}:function(){this._readChunk()},this.stream=function(e){this._input=e,this._nextChunk()},this._readChunk=function(){if(this._finished)return void this._chunkLoaded();if(r=new XMLHttpRequest,k||(r.onload=g(this._chunkLoaded,this),r.onerror=g(this._chunkError,this)),r.open("GET",this._input,!k),this._config.chunkSize){var e=this._start+this._config.chunkSize-1;r.setRequestHeader("Range","bytes="+this._start+"-"+e),r.setRequestHeader("If-None-Match","webkit-no-cache")}try{r.send()}catch(t){this._chunkError(t.message)}k&&0==r.status?this._chunkError():this._start+=this._config.chunkSize},this._chunkLoaded=function(){if(4==r.readyState){if(r.status<200||r.status>=400)return void this._chunkError();this._finished=!this._config.chunkSize||this._start>t(r),this.parseChunk(r.responseText)}},this._chunkError=function(e){var t=r.statusText||e;this._sendError(t)}}function s(e){e=e||{},e.chunkSize||(e.chunkSize=S.LocalChunkSize),n.call(this,e);var t,r,i="undefined"!=typeof FileReader;this.stream=function(e){this._input=e,r=e.slice||e.webkitSlice||e.mozSlice,i?(t=new FileReader,t.onload=g(this._chunkLoaded,this),t.onerror=g(this._chunkError,this)):t=new FileReaderSync,this._nextChunk()},this._nextChunk=function(){this._finished||this._config.preview&&!(this._rowCount<this._config.preview)||this._readChunk()},this._readChunk=function(){var e=this._input;if(this._config.chunkSize){var n=Math.min(this._start+this._config.chunkSize,this._input.size);e=r.call(e,this._start,n)}var s=t.readAsText(e,this._config.encoding);i||this._chunkLoaded({target:{result:s}})},this._chunkLoaded=function(e){this._start+=this._config.chunkSize,this._finished=!this._config.chunkSize||this._start>=this._input.size,this.parseChunk(e.target.result)},this._chunkError=function(){this._sendError(t.error)}}function a(e){e=e||{},n.call(this,e);var t,r;this.stream=function(e){return t=e,r=e,this._nextChunk()},this._nextChunk=function(){if(!this._finished){var e=this._config.chunkSize,t=e?r.substr(0,e):r;return r=e?r.substr(e):"",this._finished=!r,this.parseChunk(t)}}}function o(e){function t(){if(b&&d&&(h("Delimiter","UndetectableDelimiter","Unable to auto-detect delimiting character; defaulted to '"+S.DefaultDelimiter+"'"),d=!1),e.skipEmptyLines)for(var t=0;t<b.data.length;t++)1==b.data[t].length&&""==b.data[t][0]&&b.data.splice(t--,1);return r()&&n(),i()}function r(){return e.header&&0==y.length}function n(){if(b){for(var e=0;r()&&e<b.data.length;e++)for(var t=0;t<b.data[e].length;t++)y.push(b.data[e][t]);b.data.splice(0,1)}}function i(){if(!b||!e.header&&!e.dynamicTyping)return b;for(var t=0;t<b.data.length;t++){for(var r={},n=0;n<b.data[t].length;n++){if(e.dynamicTyping){var i=b.data[t][n];b.data[t][n]="true"==i||"TRUE"==i?!0:"false"==i||"FALSE"==i?!1:o(i)}e.header&&(n>=y.length?(r.__parsed_extra||(r.__parsed_extra=[]),r.__parsed_extra.push(b.data[t][n])):r[y[n]]=b.data[t][n])}e.header&&(b.data[t]=r,n>y.length?h("FieldMismatch","TooManyFields","Too many fields: expected "+y.length+" fields but parsed "+n,t):n<y.length&&h("FieldMismatch","TooFewFields","Too few fields: expected "+y.length+" fields but parsed "+n,t))}return e.header&&b.meta&&(b.meta.fields=y),b}function s(t){for(var r,n,i,s=[","," ","|",";",S.RECORD_SEP,S.UNIT_SEP],a=0;a<s.length;a++){var o=s[a],h=0,f=0;i=void 0;for(var c=new u({delimiter:o,preview:10}).parse(t),d=0;d<c.data.length;d++){var l=c.data[d].length;f+=l,"undefined"!=typeof i?l>1&&(h+=Math.abs(l-i),i=l):i=l}c.data.length>0&&(f/=c.data.length),("undefined"==typeof n||n>h)&&f>1.99&&(n=h,r=o)}return e.delimiter=r,{successful:!!r,bestDelimiter:r}}function a(e){e=e.substr(0,1048576);var t=e.split("\r");if(1==t.length)return"\n";for(var r=0,n=0;n<t.length;n++)"\n"==t[n][0]&&r++;return r>=t.length/2?"\r\n":"\r"}function o(e){var t=l.test(e);return t?parseFloat(e):e}function h(e,t,r,n){b.errors.push({type:e,code:t,message:r,row:n})}var f,c,d,l=/^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i,p=this,g=0,v=!1,k=!1,y=[],b={data:[],errors:[],meta:{}};if(m(e.step)){var R=e.step;e.step=function(n){if(b=n,r())t();else{if(t(),0==b.data.length)return;g+=n.data.length,e.preview&&g>e.preview?c.abort():R(b,p)}}}this.parse=function(r,n,i){if(e.newline||(e.newline=a(r)),d=!1,!e.delimiter){var o=s(r);o.successful?e.delimiter=o.bestDelimiter:(d=!0,e.delimiter=S.DefaultDelimiter),b.meta.delimiter=e.delimiter}var h=_(e);return e.preview&&e.header&&h.preview++,f=r,c=new u(h),b=c.parse(f,n,i),t(),v?{meta:{paused:!0}}:b||{meta:{paused:!1}}},this.paused=function(){return v},this.pause=function(){v=!0,c.abort(),f=f.substr(c.getCharIndex())},this.resume=function(){v=!1,p.streamer.parseChunk(f)},this.aborted=function(){return k},this.abort=function(){k=!0,c.abort(),b.meta.aborted=!0,m(e.complete)&&e.complete(b),f=""}}function u(e){e=e||{};var t=e.delimiter,r=e.newline,n=e.comments,i=e.step,s=e.preview,a=e.fastMode;if(("string"!=typeof t||S.BAD_DELIMITERS.indexOf(t)>-1)&&(t=","),n===t)throw"Comment character same as delimiter";n===!0?n="#":("string"!=typeof n||S.BAD_DELIMITERS.indexOf(n)>-1)&&(n=!1),"\n"!=r&&"\r"!=r&&"\r\n"!=r&&(r="\n");var o=0,u=!1;this.parse=function(e,h,f){function c(e){b.push(e),S=o}function d(t){return f?p():("undefined"==typeof t&&(t=e.substr(o)),w.push(t),o=g,c(w),y&&_(),p())}function l(t){o=t,c(w),w=[],O=e.indexOf(r,o)}function p(e){return{data:b,errors:R,meta:{delimiter:t,linebreak:r,aborted:u,truncated:!!e,cursor:S+(h||0)}}}function _(){i(p()),b=[],R=[]}if("string"!=typeof e)throw"Input must be a string";var g=e.length,m=t.length,v=r.length,k=n.length,y="function"==typeof i;o=0;var b=[],R=[],w=[],S=0;if(!e)return p();if(a||a!==!1&&-1===e.indexOf('"')){for(var C=e.split(r),E=0;E<C.length;E++){var w=C[E];if(o+=w.length,E!==C.length-1)o+=r.length;else if(f)return p();if(!n||w.substr(0,k)!=n){if(y){if(b=[],c(w.split(t)),_(),u)return p()}else c(w.split(t));if(s&&E>=s)return b=b.slice(0,s),p(!0)}}return p()}for(var x=e.indexOf(t,o),O=e.indexOf(r,o);;)if('"'!=e[o])if(n&&0===w.length&&e.substr(o,k)===n){if(-1==O)return p();o=O+v,O=e.indexOf(r,o),x=e.indexOf(t,o)}else if(-1!==x&&(O>x||-1===O))w.push(e.substring(o,x)),o=x+m,x=e.indexOf(t,o);else{if(-1===O)break;if(w.push(e.substring(o,O)),l(O+v),y&&(_(),u))return p();if(s&&b.length>=s)return p(!0)}else{var I=o;for(o++;;){var I=e.indexOf('"',I+1);if(-1===I)return f||R.push({type:"Quotes",code:"MissingQuotes",message:"Quoted field unterminated",row:b.length,index:o}),d();if(I===g-1){var D=e.substring(o,I).replace(/""/g,'"');return d(D)}if('"'!=e[I+1]){if(e[I+1]==t){w.push(e.substring(o,I).replace(/""/g,'"')),o=I+1+m,x=e.indexOf(t,o),O=e.indexOf(r,o);break}if(e.substr(I+1,v)===r){if(w.push(e.substring(o,I).replace(/""/g,'"')),l(I+1+v),x=e.indexOf(t,o),y&&(_(),u))return p();if(s&&b.length>=s)return p(!0);break}}else I++}}return d()},this.abort=function(){u=!0},this.getCharIndex=function(){return o}}function h(){var e=document.getElementsByTagName("script");return e.length?e[e.length-1].src:""}function f(){if(!S.WORKERS_SUPPORTED)return!1;if(!b&&null===S.SCRIPT_PATH)throw new Error("Script path cannot be determined automatically when Papa Parse is loaded asynchronously. You need to set Papa.SCRIPT_PATH manually.");var t=S.SCRIPT_PATH||v;t+=(-1!==t.indexOf("?")?"&":"?")+"papaworker";var r=new e.Worker(t);return r.onmessage=c,r.id=w++,R[r.id]=r,r}function c(e){var t=e.data,r=R[t.workerId],n=!1;if(t.error)r.userError(t.error,t.file);else if(t.results&&t.results.data){var i=function(){n=!0,d(t.workerId,{data:[],errors:[],meta:{aborted:!0}})},s={abort:i,pause:l,resume:l};if(m(r.userStep)){for(var a=0;a<t.results.data.length&&(r.userStep({data:[t.results.data[a]],errors:t.results.errors,meta:t.results.meta},s),!n);a++);delete t.results}else m(r.userChunk)&&(r.userChunk(t.results,s,t.file),delete t.results)}t.finished&&!n&&d(t.workerId,t.results)}function d(e,t){var r=R[e];m(r.userComplete)&&r.userComplete(t),r.terminate(),delete R[e]}function l(){throw"Not implemented."}function p(t){var r=t.data;if("undefined"==typeof S.WORKER_ID&&r&&(S.WORKER_ID=r.workerId),"string"==typeof r.input)e.postMessage({workerId:S.WORKER_ID,results:S.parse(r.input,r.config),finished:!0});else if(e.File&&r.input instanceof File||r.input instanceof Object){var n=S.parse(r.input,r.config);n&&e.postMessage({workerId:S.WORKER_ID,results:n,finished:!0})}}function _(e){if("object"!=typeof e)return e;var t=e instanceof Array?[]:{};for(var r in e)t[r]=_(e[r]);return t}function g(e,t){return function(){e.apply(t,arguments)}}function m(e){return"function"==typeof e}var v,k=!e.document&&!!e.postMessage,y=k&&/(\?|&)papaworker(=|&|$)/.test(e.location.search),b=!1,R={},w=0,S={};if(S.parse=t,S.unparse=r,S.RECORD_SEP=String.fromCharCode(30),S.UNIT_SEP=String.fromCharCode(31),S.BYTE_ORDER_MARK="",S.BAD_DELIMITERS=["\r","\n",'"',S.BYTE_ORDER_MARK],S.WORKERS_SUPPORTED=!k&&!!e.Worker,S.SCRIPT_PATH=null,S.LocalChunkSize=10485760,S.RemoteChunkSize=5242880,S.DefaultDelimiter=",",S.Parser=u,S.ParserHandle=o,S.NetworkStreamer=i,S.FileStreamer=s,S.StringStreamer=a,"undefined"!=typeof module&&module.exports?module.exports=S:m(e.define)&&e.define.amd?define(function(){return S}):e.Papa=S,e.jQuery){var C=e.jQuery;C.fn.parse=function(t){function r(){if(0==a.length)return void(m(t.complete)&&t.complete());var e=a[0];if(m(t.before)){var r=t.before(e.file,e.inputElem);if("object"==typeof r){if("abort"==r.action)return void n("AbortError",e.file,e.inputElem,r.reason);if("skip"==r.action)return void i();"object"==typeof r.config&&(e.instanceConfig=C.extend(e.instanceConfig,r.config))}else if("skip"==r)return void i()}var s=e.instanceConfig.complete;e.instanceConfig.complete=function(t){m(s)&&s(t,e.file,e.inputElem),i()},S.parse(e.file,e.instanceConfig)}function n(e,r,n,i){m(t.error)&&t.error({name:e},r,n,i)}function i(){a.splice(0,1),r()}var s=t.config||{},a=[];return this.each(function(){var t="INPUT"==C(this).prop("tagName").toUpperCase()&&"file"==C(this).attr("type").toLowerCase()&&e.FileReader;if(!t||!this.files||0==this.files.length)return!0;for(var r=0;r<this.files.length;r++)a.push({file:this.files[r],inputElem:this,instanceConfig:C.extend({},s)})}),r(),this}}y?e.onmessage=p:S.WORKERS_SUPPORTED&&(v=h(),document.body?document.addEventListener("DOMContentLoaded",function(){b=!0},!0):b=!0),i.prototype=Object.create(n.prototype),i.prototype.constructor=i,s.prototype=Object.create(n.prototype),s.prototype.constructor=s,a.prototype=Object.create(a.prototype),a.prototype.constructor=a}("undefined"!=typeof window?window:this);
+0
-514
faraday/server/www/script/sanitize.js less more
0 'use strict';
1
2 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3 * Any commits to this file should be reviewed with security in mind. *
4 * Changes to this file can potentially create security vulnerabilities. *
5 * An approval from 2 Core members with history of modifying *
6 * this file is required. *
7 * *
8 * Does the change somehow allow for arbitrary javascript to be executed? *
9 * Or allows for someone to change the prototype of built-in objects? *
10 * Or gives undesired access to variables likes document or window? *
11 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13 var $sanitizeMinErr = angular.$$minErr('$sanitize');
14
15 /**
16 * @ngdoc module
17 * @name ngSanitize
18 * @description
19 *
20 * # ngSanitize
21 *
22 * The `ngSanitize` module provides functionality to sanitize HTML.
23 *
24 *
25 * <div doc-module-components="ngSanitize"></div>
26 *
27 * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
28 */
29
30 /**
31 * @ngdoc service
32 * @name $sanitize
33 * @kind function
34 *
35 * @description
36 * Sanitizes an html string by stripping all potentially dangerous tokens.
37 *
38 * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
39 * then serialized back to properly escaped html string. This means that no unsafe input can make
40 * it into the returned string.
41 *
42 * The whitelist for URL sanitization of attribute values is configured using the functions
43 * `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider
44 * `$compileProvider`}.
45 *
46 * The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.
47 *
48 * @param {string} html HTML input.
49 * @returns {string} Sanitized HTML.
50 *
51 * @example
52 <example module="sanitizeExample" deps="angular-sanitize.js">
53 <file name="index.html">
54 <script>
55 angular.module('sanitizeExample', ['ngSanitize'])
56 .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
57 $scope.snippet =
58 '<p style="color:blue">an html\n' +
59 '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
60 'snippet</p>';
61 $scope.deliberatelyTrustDangerousSnippet = function() {
62 return $sce.trustAsHtml($scope.snippet);
63 };
64 }]);
65 </script>
66 <div ng-controller="ExampleController">
67 Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
68 <table>
69 <tr>
70 <td>Directive</td>
71 <td>How</td>
72 <td>Source</td>
73 <td>Rendered</td>
74 </tr>
75 <tr id="bind-html-with-sanitize">
76 <td>ng-bind-html</td>
77 <td>Automatically uses $sanitize</td>
78 <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
79 <td><div ng-bind-html="snippet"></div></td>
80 </tr>
81 <tr id="bind-html-with-trust">
82 <td>ng-bind-html</td>
83 <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
84 <td>
85 <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
86 &lt;/div&gt;</pre>
87 </td>
88 <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
89 </tr>
90 <tr id="bind-default">
91 <td>ng-bind</td>
92 <td>Automatically escapes</td>
93 <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
94 <td><div ng-bind="snippet"></div></td>
95 </tr>
96 </table>
97 </div>
98 </file>
99 <file name="protractor.js" type="protractor">
100 it('should sanitize the html snippet by default', function() {
101 expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
102 toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
103 });
104
105 it('should inline raw snippet if bound to a trusted value', function() {
106 expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).
107 toBe("<p style=\"color:blue\">an html\n" +
108 "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
109 "snippet</p>");
110 });
111
112 it('should escape snippet without any filter', function() {
113 expect(element(by.css('#bind-default div')).getInnerHtml()).
114 toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
115 "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
116 "snippet&lt;/p&gt;");
117 });
118
119 it('should update', function() {
120 element(by.model('snippet')).clear();
121 element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
122 expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
123 toBe('new <b>text</b>');
124 expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(
125 'new <b onclick="alert(1)">text</b>');
126 expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(
127 "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
128 });
129 </file>
130 </example>
131 */
132
133
134 /**
135 * @ngdoc provider
136 * @name $sanitizeProvider
137 *
138 * @description
139 * Creates and configures {@link $sanitize} instance.
140 */
141 function $SanitizeProvider() {
142 var svgEnabled = false;
143
144 this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
145 if (svgEnabled) {
146 angular.extend(validElements, svgElements);
147 }
148 return function(html) {
149 var buf = [];
150 htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
151 return !/^unsafe:/.test($$sanitizeUri(uri, isImage));
152 }));
153 return buf.join('');
154 };
155 }];
156
157
158 /**
159 * @ngdoc method
160 * @name $sanitizeProvider#enableSvg
161 * @kind function
162 *
163 * @description
164 * Enables a subset of svg to be supported by the sanitizer.
165 *
166 * <div class="alert alert-warning">
167 * <p>By enabling this setting without taking other precautions, you might expose your
168 * application to click-hijacking attacks. In these attacks, sanitized svg elements could be positioned
169 * outside of the containing element and be rendered over other elements on the page (e.g. a login
170 * link). Such behavior can then result in phishing incidents.</p>
171 *
172 * <p>To protect against these, explicitly setup `overflow: hidden` css rule for all potential svg
173 * tags within the sanitized content:</p>
174 *
175 * <br>
176 *
177 * <pre><code>
178 * .rootOfTheIncludedContent svg {
179 * overflow: hidden !important;
180 * }
181 * </code></pre>
182 * </div>
183 *
184 * @param {boolean=} regexp New regexp to whitelist urls with.
185 * @returns {boolean|ng.$sanitizeProvider} Returns the currently configured value if called
186 * without an argument or self for chaining otherwise.
187 */
188 this.enableSvg = function(enableSvg) {
189 if (angular.isDefined(enableSvg)) {
190 svgEnabled = enableSvg;
191 return this;
192 } else {
193 return svgEnabled;
194 }
195 };
196 }
197
198 function sanitizeText(chars) {
199 var buf = [];
200 var writer = htmlSanitizeWriter(buf, angular.noop);
201 writer.chars(chars);
202 return buf.join('');
203 }
204
205
206 // Regular Expressions for parsing tags and attributes
207 var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
208 // Match everything outside of normal chars and " (quote character)
209 NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g;
210
211
212 // Good source of info about elements and attributes
213 // http://dev.w3.org/html5/spec/Overview.html#semantics
214 // http://simon.html5.org/html-elements
215
216 // Safe Void Elements - HTML5
217 // http://dev.w3.org/html5/spec/Overview.html#void-elements
218 var voidElements = toMap("area,br,col,hr,img,wbr");
219
220 // Elements that you can, intentionally, leave open (and which close themselves)
221 // http://dev.w3.org/html5/spec/Overview.html#optional-tags
222 var optionalEndTagBlockElements = toMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
223 optionalEndTagInlineElements = toMap("rp,rt"),
224 optionalEndTagElements = angular.extend({},
225 optionalEndTagInlineElements,
226 optionalEndTagBlockElements);
227
228 // Safe Block Elements - HTML5
229 var blockElements = angular.extend({}, optionalEndTagBlockElements, toMap("address,article," +
230 "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
231 "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul"));
232
233 // Inline Elements - HTML5
234 var inlineElements = angular.extend({}, optionalEndTagInlineElements, toMap("a,abbr,acronym,b," +
235 "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
236 "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
237
238 // SVG Elements
239 // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
240 // Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
241 // They can potentially allow for arbitrary javascript to be executed. See #11290
242 var svgElements = toMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," +
243 "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," +
244 "radialGradient,rect,stop,svg,switch,text,title,tspan,use");
245
246 // Blocked Elements (will be stripped)
247 var blockedElements = toMap("script,style");
248
249 var validElements = angular.extend({},
250 voidElements,
251 blockElements,
252 inlineElements,
253 optionalEndTagElements);
254
255 //Attributes that have href and hence need to be sanitized
256 var uriAttrs = toMap("background,cite,href,longdesc,src,usemap,xlink:href");
257
258 var htmlAttrs = toMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
259 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
260 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
261 'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' +
262 'valign,value,vspace,width');
263
264 // SVG attributes (without "id" and "name" attributes)
265 // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
266 var svgAttrs = toMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
267 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +
268 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +
269 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +
270 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' +
271 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' +
272 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' +
273 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' +
274 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' +
275 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' +
276 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' +
277 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' +
278 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' +
279 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' +
280 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);
281
282 var validAttrs = angular.extend({},
283 uriAttrs,
284 svgAttrs,
285 htmlAttrs);
286
287 function toMap(str, lowercaseKeys) {
288 var obj = {}, items = str.split(','), i;
289 for (i = 0; i < items.length; i++) {
290 obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true;
291 }
292 return obj;
293 }
294
295 var inertBodyElement;
296 (function(window) {
297 var doc;
298 if (window.document && window.document.implementation) {
299 doc = window.document.implementation.createHTMLDocument("inert");
300 } else {
301 throw $sanitizeMinErr('noinert', "Can't create an inert html document");
302 }
303 var docElement = doc.documentElement || doc.getDocumentElement();
304 var bodyElements = docElement.getElementsByTagName('body');
305
306 // usually there should be only one body element in the document, but IE doesn't have any, so we need to create one
307 if (bodyElements.length === 1) {
308 inertBodyElement = bodyElements[0];
309 } else {
310 var html = doc.createElement('html');
311 inertBodyElement = doc.createElement('body');
312 html.appendChild(inertBodyElement);
313 doc.appendChild(html);
314 }
315 })(window);
316
317 /**
318 * @example
319 * htmlParser(htmlString, {
320 * start: function(tag, attrs) {},
321 * end: function(tag) {},
322 * chars: function(text) {},
323 * comment: function(text) {}
324 * });
325 *
326 * @param {string} html string
327 * @param {object} handler
328 */
329 function htmlParser(html, handler) {
330 if (html === null || html === undefined) {
331 html = '';
332 } else if (typeof html !== 'string') {
333 html = '' + html;
334 }
335 inertBodyElement.innerHTML = html;
336
337 //mXSS protection
338 var mXSSAttempts = 5;
339 do {
340 if (mXSSAttempts === 0) {
341 throw $sanitizeMinErr('uinput', "Failed to sanitize html because the input is unstable");
342 }
343 mXSSAttempts--;
344
345 // strip custom-namespaced attributes on IE<=11
346 if (document.documentMode <= 11) {
347 stripCustomNsAttrs(inertBodyElement);
348 }
349 html = inertBodyElement.innerHTML; //trigger mXSS
350 inertBodyElement.innerHTML = html;
351 } while (html !== inertBodyElement.innerHTML);
352
353 var node = inertBodyElement.firstChild;
354 while (node) {
355 switch (node.nodeType) {
356 case 1: // ELEMENT_NODE
357 handler.start(node.nodeName.toLowerCase(), attrToMap(node.attributes));
358 break;
359 case 3: // TEXT NODE
360 handler.chars(node.textContent);
361 break;
362 }
363
364 var nextNode;
365 if (!(nextNode = node.firstChild)) {
366 if (node.nodeType == 1) {
367 handler.end(node.nodeName.toLowerCase());
368 }
369 nextNode = node.nextSibling;
370 if (!nextNode) {
371 while (nextNode == null) {
372 node = node.parentNode;
373 if (node === inertBodyElement) break;
374 nextNode = node.nextSibling;
375 if (node.nodeType == 1) {
376 handler.end(node.nodeName.toLowerCase());
377 }
378 }
379 }
380 }
381 node = nextNode;
382 }
383
384 while (node = inertBodyElement.firstChild) {
385 inertBodyElement.removeChild(node);
386 }
387 }
388
389 function attrToMap(attrs) {
390 var map = {};
391 for (var i = 0, ii = attrs.length; i < ii; i++) {
392 var attr = attrs[i];
393 map[attr.name] = attr.value;
394 }
395 return map;
396 }
397
398
399 /**
400 * Escapes all potentially dangerous characters, so that the
401 * resulting string can be safely inserted into attribute or
402 * element text.
403 * @param value
404 * @returns {string} escaped text
405 */
406 function encodeEntities(value) {
407 return value.
408 replace(/&/g, '&amp;').
409 replace(SURROGATE_PAIR_REGEXP, function(value) {
410 var hi = value.charCodeAt(0);
411 var low = value.charCodeAt(1);
412 return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
413 }).
414 replace(NON_ALPHANUMERIC_REGEXP, function(value) {
415 return '&#' + value.charCodeAt(0) + ';';
416 }).
417 replace(/</g, '&lt;').
418 replace(/>/g, '&gt;');
419 }
420
421 /**
422 * create an HTML/XML writer which writes to buffer
423 * @param {Array} buf use buf.join('') to get out sanitized html string
424 * @returns {object} in the form of {
425 * start: function(tag, attrs) {},
426 * end: function(tag) {},
427 * chars: function(text) {},
428 * comment: function(text) {}
429 * }
430 */
431 function htmlSanitizeWriter(buf, uriValidator) {
432 var ignoreCurrentElement = false;
433 var out = angular.bind(buf, buf.push);
434 return {
435 start: function(tag, attrs) {
436 tag = angular.lowercase(tag);
437 if (!ignoreCurrentElement && blockedElements[tag]) {
438 ignoreCurrentElement = tag;
439 }
440 if (!ignoreCurrentElement && validElements[tag] === true) {
441 out('<');
442 out(tag);
443 angular.forEach(attrs, function(value, key) {
444 var lkey=angular.lowercase(key);
445 var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
446 if (validAttrs[lkey] === true &&
447 (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
448 out(' ');
449 out(key);
450 out('="');
451 out(encodeEntities(value));
452 out('"');
453 }
454 });
455 out('>');
456 }
457 },
458 end: function(tag) {
459 tag = angular.lowercase(tag);
460 if (!ignoreCurrentElement && validElements[tag] === true && voidElements[tag] !== true) {
461 out('</');
462 out(tag);
463 out('>');
464 }
465 if (tag == ignoreCurrentElement) {
466 ignoreCurrentElement = false;
467 }
468 },
469 chars: function(chars) {
470 if (!ignoreCurrentElement) {
471 out(encodeEntities(chars));
472 }
473 }
474 };
475 }
476
477
478 /**
479 * When IE9-11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1' attribute to declare
480 * ns1 namespace and prefixes the attribute with 'ns1' (e.g. 'ns1:xlink:foo'). This is undesirable since we don't want
481 * to allow any of these custom attributes. This method strips them all.
482 *
483 * @param node Root element to process
484 */
485 function stripCustomNsAttrs(node) {
486 if (node.nodeType === Node.ELEMENT_NODE) {
487 var attrs = node.attributes;
488 for (var i = 0, l = attrs.length; i < l; i++) {
489 var attrNode = attrs[i];
490 var attrName = attrNode.name.toLowerCase();
491 if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
492 node.removeAttributeNode(attrNode);
493 i--;
494 l--;
495 }
496 }
497 }
498
499 var nextNode = node.firstChild;
500 if (nextNode) {
501 stripCustomNsAttrs(nextNode);
502 }
503
504 nextNode = node.nextSibling;
505 if (nextNode) {
506 stripCustomNsAttrs(nextNode);
507 }
508 }
509
510
511
512 // define ngSanitize module and register $sanitize service
513 angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
+0
-112
faraday/server/www/script/showdown-table.js less more
0 /*! showdown-table 17-06-2015 */
1 /*
2 * Basic table support with re-entrant parsing, where cell content
3 * can also specify markdown.
4 *
5 * Tables
6 * ======
7 *
8 * | Col 1 | Col 2 |
9 * |======== |====================================================|
10 * |**bold** | ![Valid XHTML] (http://w3.org/Icons/valid-xhtml10) |
11 * | Plain | Value |
12 *
13 */
14
15 (function () {
16 'use strict';
17
18 var table = function (converter) {
19
20 var tables = {}, style = 'text-align:left;', filter;
21 tables.th = function (header) {
22 if (header.trim() === '') {
23 return '';
24 }
25 var id = header.trim().replace(/ /g, '_').toLowerCase();
26 return '<th id="' + id + '" style="' + style + '">' + header + '</th>';
27 };
28 tables.td = function (cell) {
29 return '<td style="' + style + '">' + converter.makeHtml(cell) + '</td>';
30 };
31 tables.ths = function () {
32 var out = '',
33 i = 0,
34 hs = [].slice.apply(arguments);
35 for (i; i < hs.length; i += 1) {
36 out += tables.th(hs[i]) + '\n';
37 }
38 return out;
39 };
40 tables.tds = function () {
41 var out = '', i = 0, ds = [].slice.apply(arguments);
42 for (i; i < ds.length; i += 1) {
43 out += tables.td(ds[i]) + '\n';
44 }
45 return out;
46 };
47 tables.thead = function () {
48 var out,
49 hs = [].slice.apply(arguments);
50 out = '<thead class="thead-dark">\n';
51 out += '<tr>\n';
52 out += tables.ths.apply(this, hs);
53 out += '</tr>\n';
54 out += '</thead>\n';
55 return out;
56 };
57 tables.tr = function () {
58 var out,
59 cs = [].slice.apply(arguments);
60 out = '<tr>\n';
61 out += tables.tds.apply(this, cs);
62 out += '</tr>\n';
63 return out;
64 };
65 filter = function (text) {
66 var i = 0, lines = text.split('\n'), line, hs, out = [];
67 for (i; i < lines.length; i += 1) {
68 line = lines[i];
69 if (line.trim().match(/^[|].*[|]$/)) {
70 line = line.trim();
71 var tbl = [];
72 tbl.push('<table class="table table-sm">');
73 hs = line.substring(1, line.length - 1).split('|');
74 tbl.push(tables.thead.apply(this, hs));
75 line = lines[++i];
76 if (!line.trim().match(/^[|][-=|: ]+[|]$/)) {
77 line = lines[--i];
78 } else {
79 line = lines[++i];
80 tbl.push('<tbody>');
81 while (line.trim().match(/^[|].*[|]$/)) {
82 line = line.trim();
83 tbl.push(tables.tr.apply(this, line.substring(1, line.length - 1).split('|')));
84 line = lines[++i];
85 }
86 tbl.push('</tbody>');
87 tbl.push('</table>');
88 out.push(tbl.join('\n'));
89 continue;
90 }
91 }
92 out.push(line);
93 }
94 return out.join('\n');
95 };
96 return [
97 {
98 type: 'lang',
99 filter: filter
100 }
101 ];
102 };
103 if (typeof window !== 'undefined' && window.showdown && window.showdown.extensions) {
104 window.showdown.extensions.table = table;
105 }
106 if (typeof module !== 'undefined') {
107 module.exports = table;
108 }
109 }());
110
111 //# sourceMappingURL=showdown-table.js.map
+0
-4
faraday/server/www/script/showdown-table.min.js less more
0 /*! showdown-table 17-06-2015 */
1
2 !function(){"use strict";var a=function(a){var b,c={},d="text-align:left;";return c.th=function(a){if(""===a.trim())return"";var b=a.trim().replace(/ /g,"_").toLowerCase();return'<th id="'+b+'" style="'+d+'">'+a+"</th>"},c.td=function(b){return'<td style="'+d+'">'+a.makeHtml(b)+"</td>"},c.ths=function(){var a="",b=0,d=[].slice.apply(arguments);for(b;b<d.length;b+=1)a+=c.th(d[b])+"\n";return a},c.tds=function(){var a="",b=0,d=[].slice.apply(arguments);for(b;b<d.length;b+=1)a+=c.td(d[b])+"\n";return a},c.thead=function(){var a,b=[].slice.apply(arguments);return a="<thead>\n",a+="<tr>\n",a+=c.ths.apply(this,b),a+="</tr>\n",a+="</thead>\n"},c.tr=function(){var a,b=[].slice.apply(arguments);return a="<tr>\n",a+=c.tds.apply(this,b),a+="</tr>\n"},b=function(a){var b,d,e=0,f=a.split("\n"),g=[];for(e;e<f.length;e+=1){if(b=f[e],b.trim().match(/^[|].*[|]$/)){b=b.trim();var h=[];if(h.push("<table>"),d=b.substring(1,b.length-1).split("|"),h.push(c.thead.apply(this,d)),b=f[++e],b.trim().match(/^[|][-=|: ]+[|]$/)){for(b=f[++e],h.push("<tbody>");b.trim().match(/^[|].*[|]$/);)b=b.trim(),h.push(c.tr.apply(this,b.substring(1,b.length-1).split("|"))),b=f[++e];h.push("</tbody>"),h.push("</table>"),g.push(h.join("\n"));continue}b=f[--e]}g.push(b)}return g.join("\n")},[{type:"lang",filter:b}]};"undefined"!=typeof window&&window.showdown&&window.showdown.extensions&&(window.showdown.extensions.table=a),"undefined"!=typeof module&&(module.exports=a)}();
3 //# sourceMappingURL=showdown-table.min.js.map
+0
-5460
faraday/server/www/script/showdown.js less more
0 ;/*! showdown v 2.0.0-alpha1 - 24-10-2018 */
1 (function(){
2 /**
3 * Created by Tivie on 13-07-2015.
4 */
5
6 function getDefaultOpts (simple) {
7 'use strict';
8
9 var defaultOptions = {
10 omitExtraWLInCodeBlocks: {
11 defaultValue: false,
12 describe: 'Omit the default extra whiteline added to code blocks',
13 type: 'boolean'
14 },
15 noHeaderId: {
16 defaultValue: false,
17 describe: 'Turn on/off generated header id',
18 type: 'boolean'
19 },
20 prefixHeaderId: {
21 defaultValue: false,
22 describe: 'Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic \'section-\' prefix',
23 type: 'string'
24 },
25 rawPrefixHeaderId: {
26 defaultValue: false,
27 describe: 'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',
28 type: 'boolean'
29 },
30 ghCompatibleHeaderId: {
31 defaultValue: false,
32 describe: 'Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)',
33 type: 'boolean'
34 },
35 rawHeaderId: {
36 defaultValue: false,
37 describe: 'Remove only spaces, \' and " from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids',
38 type: 'boolean'
39 },
40 headerLevelStart: {
41 defaultValue: false,
42 describe: 'The header blocks level start',
43 type: 'integer'
44 },
45 parseImgDimensions: {
46 defaultValue: false,
47 describe: 'Turn on/off image dimension parsing',
48 type: 'boolean'
49 },
50 simplifiedAutoLink: {
51 defaultValue: false,
52 describe: 'Turn on/off GFM autolink style',
53 type: 'boolean'
54 },
55 literalMidWordUnderscores: {
56 defaultValue: false,
57 describe: 'Parse midword underscores as literal underscores',
58 type: 'boolean'
59 },
60 literalMidWordAsterisks: {
61 defaultValue: false,
62 describe: 'Parse midword asterisks as literal asterisks',
63 type: 'boolean'
64 },
65 strikethrough: {
66 defaultValue: false,
67 describe: 'Turn on/off strikethrough support',
68 type: 'boolean'
69 },
70 tables: {
71 defaultValue: false,
72 describe: 'Turn on/off tables support',
73 type: 'boolean'
74 },
75 tablesHeaderId: {
76 defaultValue: false,
77 describe: 'Add an id to table headers',
78 type: 'boolean'
79 },
80 ghCodeBlocks: {
81 defaultValue: true,
82 describe: 'Turn on/off GFM fenced code blocks support',
83 type: 'boolean'
84 },
85 tasklists: {
86 defaultValue: false,
87 describe: 'Turn on/off GFM tasklist support',
88 type: 'boolean'
89 },
90 smoothLivePreview: {
91 defaultValue: false,
92 describe: 'Prevents weird effects in live previews due to incomplete input',
93 type: 'boolean'
94 },
95 smartIndentationFix: {
96 defaultValue: false,
97 description: 'Tries to smartly fix indentation in es6 strings',
98 type: 'boolean'
99 },
100 disableForced4SpacesIndentedSublists: {
101 defaultValue: false,
102 description: 'Disables the requirement of indenting nested sublists by 4 spaces',
103 type: 'boolean'
104 },
105 simpleLineBreaks: {
106 defaultValue: false,
107 description: 'Parses simple line breaks as <br> (GFM Style)',
108 type: 'boolean'
109 },
110 requireSpaceBeforeHeadingText: {
111 defaultValue: false,
112 description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
113 type: 'boolean'
114 },
115 ghMentions: {
116 defaultValue: false,
117 description: 'Enables github @mentions',
118 type: 'boolean'
119 },
120 ghMentionsLink: {
121 defaultValue: 'https://github.com/{u}',
122 description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
123 type: 'string'
124 },
125 encodeEmails: {
126 defaultValue: true,
127 description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
128 type: 'boolean'
129 },
130 openLinksInNewWindow: {
131 defaultValue: false,
132 description: 'Open all links in new windows',
133 type: 'boolean'
134 },
135 backslashEscapesHTMLTags: {
136 defaultValue: false,
137 description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
138 type: 'boolean'
139 },
140 emoji: {
141 defaultValue: false,
142 description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
143 type: 'boolean'
144 },
145 underline: {
146 defaultValue: false,
147 description: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `<em>` and `<strong>`',
148 type: 'boolean'
149 },
150 completeHTMLDocument: {
151 defaultValue: false,
152 description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
153 type: 'boolean'
154 },
155 metadata: {
156 defaultValue: false,
157 description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
158 type: 'boolean'
159 },
160 splitAdjacentBlockquotes: {
161 defaultValue: false,
162 description: 'Split adjacent blockquote blocks',
163 type: 'boolean'
164 }
165 };
166 if (simple === false) {
167 return JSON.parse(JSON.stringify(defaultOptions));
168 }
169 var ret = {};
170 for (var opt in defaultOptions) {
171 if (defaultOptions.hasOwnProperty(opt)) {
172 ret[opt] = defaultOptions[opt].defaultValue;
173 }
174 }
175 return ret;
176 }
177
178 function allOptionsOn () {
179 'use strict';
180 var options = getDefaultOpts(true),
181 ret = {};
182 for (var opt in options) {
183 if (options.hasOwnProperty(opt)) {
184 ret[opt] = true;
185 }
186 }
187 return ret;
188 }
189
190 /**
191 * Created by Tivie on 06-01-2015.
192 */
193 // Private properties
194 var showdown = {},
195 parsers = {},
196 extensions = {},
197 globalOptions = getDefaultOpts(true),
198 setFlavor = 'vanilla',
199 flavor = {
200 github: {
201 omitExtraWLInCodeBlocks: true,
202 simplifiedAutoLink: true,
203 literalMidWordUnderscores: true,
204 strikethrough: true,
205 tables: true,
206 tablesHeaderId: true,
207 ghCodeBlocks: true,
208 tasklists: true,
209 disableForced4SpacesIndentedSublists: true,
210 simpleLineBreaks: true,
211 requireSpaceBeforeHeadingText: true,
212 ghCompatibleHeaderId: true,
213 ghMentions: true,
214 backslashEscapesHTMLTags: true,
215 emoji: true,
216 splitAdjacentBlockquotes: true
217 },
218 original: {
219 noHeaderId: true,
220 ghCodeBlocks: false
221 },
222 ghost: {
223 omitExtraWLInCodeBlocks: true,
224 parseImgDimensions: true,
225 simplifiedAutoLink: true,
226 literalMidWordUnderscores: true,
227 strikethrough: true,
228 tables: true,
229 tablesHeaderId: true,
230 ghCodeBlocks: true,
231 tasklists: true,
232 smoothLivePreview: true,
233 simpleLineBreaks: true,
234 requireSpaceBeforeHeadingText: true,
235 ghMentions: false,
236 encodeEmails: true
237 },
238 vanilla: getDefaultOpts(true),
239 allOn: allOptionsOn()
240 };
241
242 /**
243 * helper namespace
244 * @type {{}}
245 */
246 showdown.helper = {};
247
248 /**
249 * TODO LEGACY SUPPORT CODE
250 * @type {{}}
251 */
252 showdown.extensions = {};
253
254 /**
255 * Set a global option
256 * @static
257 * @param {string} key
258 * @param {*} value
259 * @returns {showdown}
260 */
261 showdown.setOption = function (key, value) {
262 'use strict';
263 globalOptions[key] = value;
264 return this;
265 };
266
267 /**
268 * Get a global option
269 * @static
270 * @param {string} key
271 * @returns {*}
272 */
273 showdown.getOption = function (key) {
274 'use strict';
275 return globalOptions[key];
276 };
277
278 /**
279 * Get the global options
280 * @static
281 * @returns {{}}
282 */
283 showdown.getOptions = function () {
284 'use strict';
285 return globalOptions;
286 };
287
288 /**
289 * Reset global options to the default values
290 * @static
291 */
292 showdown.resetOptions = function () {
293 'use strict';
294 globalOptions = getDefaultOpts(true);
295 };
296
297 /**
298 * Set the flavor showdown should use as default
299 * @param {string} name
300 */
301 showdown.setFlavor = function (name) {
302 'use strict';
303 if (!flavor.hasOwnProperty(name)) {
304 throw Error(name + ' flavor was not found');
305 }
306 showdown.resetOptions();
307 var preset = flavor[name];
308 setFlavor = name;
309 for (var option in preset) {
310 if (preset.hasOwnProperty(option)) {
311 globalOptions[option] = preset[option];
312 }
313 }
314 };
315
316 /**
317 * Get the currently set flavor
318 * @returns {string}
319 */
320 showdown.getFlavor = function () {
321 'use strict';
322 return setFlavor;
323 };
324
325 /**
326 * Get the options of a specified flavor. Returns undefined if the flavor was not found
327 * @param {string} name Name of the flavor
328 * @returns {{}|undefined}
329 */
330 showdown.getFlavorOptions = function (name) {
331 'use strict';
332 if (flavor.hasOwnProperty(name)) {
333 return flavor[name];
334 }
335 };
336
337 /**
338 * Get the default options
339 * @static
340 * @param {boolean} [simple=true]
341 * @returns {{}}
342 */
343 showdown.getDefaultOptions = function (simple) {
344 'use strict';
345 return getDefaultOpts(simple);
346 };
347
348 /**
349 * Get or set a subParser
350 *
351 * subParser(name) - Get a registered subParser
352 * subParser(name, func) - Register a subParser
353 * @static
354 * @param {string} name
355 * @param {function} [func]
356 * @returns {*}
357 */
358 showdown.subParser = function (name, func) {
359 'use strict';
360 if (showdown.helper.isString(name)) {
361 if (typeof func !== 'undefined') {
362 parsers[name] = func;
363 } else {
364 if (parsers.hasOwnProperty(name)) {
365 return parsers[name];
366 } else {
367 throw Error('SubParser named ' + name + ' not registered!');
368 }
369 }
370 } else {
371 throw Error('showdown.subParser function first argument must be a string (the name of the subparser)');
372 }
373 };
374
375 /**
376 * Gets or registers an extension
377 * @static
378 * @param {string} name
379 * @param {object|function=} ext
380 * @returns {*}
381 */
382 showdown.extension = function (name, ext) {
383 'use strict';
384
385 if (!showdown.helper.isString(name)) {
386 throw Error('Extension \'name\' must be a string');
387 }
388
389 name = showdown.helper.stdExtName(name);
390
391 // Getter
392 if (showdown.helper.isUndefined(ext)) {
393 if (!extensions.hasOwnProperty(name)) {
394 throw Error('Extension named ' + name + ' is not registered!');
395 }
396 return extensions[name];
397
398 // Setter
399 } else {
400 // Expand extension if it's wrapped in a function
401 if (typeof ext === 'function') {
402 ext = ext();
403 }
404
405 // Ensure extension is an array
406 if (!showdown.helper.isArray(ext)) {
407 ext = [ext];
408 }
409
410 var validExtension = validate(ext, name);
411
412 if (validExtension.valid) {
413 extensions[name] = ext;
414 } else {
415 throw Error(validExtension.error);
416 }
417 }
418 };
419
420 /**
421 * Gets all extensions registered
422 * @returns {{}}
423 */
424 showdown.getAllExtensions = function () {
425 'use strict';
426 return extensions;
427 };
428
429 /**
430 * Remove an extension
431 * @param {string} name
432 */
433 showdown.removeExtension = function (name) {
434 'use strict';
435 delete extensions[name];
436 };
437
438 /**
439 * Removes all extensions
440 */
441 showdown.resetExtensions = function () {
442 'use strict';
443 extensions = {};
444 };
445
446 /**
447 * Validate extension
448 * @param {array} extension
449 * @param {string} name
450 * @returns {{valid: boolean, error: string}}
451 */
452 function validate (extension, name) {
453 'use strict';
454
455 var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
456 ret = {
457 valid: true,
458 error: ''
459 };
460
461 if (!showdown.helper.isArray(extension)) {
462 extension = [extension];
463 }
464
465 for (var i = 0; i < extension.length; ++i) {
466 var baseMsg = errMsg + ' sub-extension ' + i + ': ',
467 ext = extension[i];
468 if (typeof ext !== 'object') {
469 ret.valid = false;
470 ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
471 return ret;
472 }
473
474 if (!showdown.helper.isString(ext.type)) {
475 ret.valid = false;
476 ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
477 return ret;
478 }
479
480 var type = ext.type = ext.type.toLowerCase();
481
482 // normalize extension type
483 if (type === 'language') {
484 type = ext.type = 'lang';
485 }
486
487 if (type === 'html') {
488 type = ext.type = 'output';
489 }
490
491 if (type !== 'lang' && type !== 'output' && type !== 'listener') {
492 ret.valid = false;
493 ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
494 return ret;
495 }
496
497 if (type === 'listener') {
498 if (showdown.helper.isUndefined(ext.listeners)) {
499 ret.valid = false;
500 ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
501 return ret;
502 }
503 } else {
504 if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
505 ret.valid = false;
506 ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
507 return ret;
508 }
509 }
510
511 if (ext.listeners) {
512 if (typeof ext.listeners !== 'object') {
513 ret.valid = false;
514 ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
515 return ret;
516 }
517 for (var ln in ext.listeners) {
518 if (ext.listeners.hasOwnProperty(ln)) {
519 if (typeof ext.listeners[ln] !== 'function') {
520 ret.valid = false;
521 ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
522 ' must be a function but ' + typeof ext.listeners[ln] + ' given';
523 return ret;
524 }
525 }
526 }
527 }
528
529 if (ext.filter) {
530 if (typeof ext.filter !== 'function') {
531 ret.valid = false;
532 ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
533 return ret;
534 }
535 } else if (ext.regex) {
536 if (showdown.helper.isString(ext.regex)) {
537 ext.regex = new RegExp(ext.regex, 'g');
538 }
539 if (!(ext.regex instanceof RegExp)) {
540 ret.valid = false;
541 ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
542 return ret;
543 }
544 if (showdown.helper.isUndefined(ext.replace)) {
545 ret.valid = false;
546 ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
547 return ret;
548 }
549 }
550 }
551 return ret;
552 }
553
554 /**
555 * Validate extension
556 * @param {object} ext
557 * @returns {boolean}
558 */
559 showdown.validateExtension = function (ext) {
560 'use strict';
561
562 var validateExtension = validate(ext, null);
563 if (!validateExtension.valid) {
564 console.warn(validateExtension.error);
565 return false;
566 }
567 return true;
568 };
569
570 /**
571 * showdownjs helper functions
572 */
573
574 if (!showdown.hasOwnProperty('helper')) {
575 showdown.helper = {};
576 }
577
578 if (typeof this.document === 'undefined' && typeof this.window === 'undefined') {
579 var jsdom = require('jsdom');
580 this.window = new jsdom.JSDOM('', {}).window; // jshint ignore:line
581 }
582 showdown.helper.document = this.window.document;
583
584 /**
585 * Check if var is string
586 * @static
587 * @param {string} a
588 * @returns {boolean}
589 */
590 showdown.helper.isString = function (a) {
591 'use strict';
592 return (typeof a === 'string' || a instanceof String);
593 };
594
595 /**
596 * Check if var is a function
597 * @static
598 * @param {*} a
599 * @returns {boolean}
600 */
601 showdown.helper.isFunction = function (a) {
602 'use strict';
603 var getType = {};
604 return a && getType.toString.call(a) === '[object Function]';
605 };
606
607 /**
608 * isArray helper function
609 * @static
610 * @param {*} a
611 * @returns {boolean}
612 */
613 showdown.helper.isArray = function (a) {
614 'use strict';
615 return Array.isArray(a);
616 };
617
618 /**
619 * Check if value is undefined
620 * @static
621 * @param {*} value The value to check.
622 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
623 */
624 showdown.helper.isUndefined = function (value) {
625 'use strict';
626 return typeof value === 'undefined';
627 };
628
629 /**
630 * ForEach helper function
631 * Iterates over Arrays and Objects (own properties only)
632 * @static
633 * @param {*} obj
634 * @param {function} callback Accepts 3 params: 1. value, 2. key, 3. the original array/object
635 */
636 showdown.helper.forEach = function (obj, callback) {
637 'use strict';
638 // check if obj is defined
639 if (showdown.helper.isUndefined(obj)) {
640 throw new Error('obj param is required');
641 }
642
643 if (showdown.helper.isUndefined(callback)) {
644 throw new Error('callback param is required');
645 }
646
647 if (!showdown.helper.isFunction(callback)) {
648 throw new Error('callback param must be a function/closure');
649 }
650
651 if (typeof obj.forEach === 'function') {
652 obj.forEach(callback);
653 } else if (showdown.helper.isArray(obj)) {
654 for (var i = 0; i < obj.length; i++) {
655 callback(obj[i], i, obj);
656 }
657 } else if (typeof (obj) === 'object') {
658 for (var prop in obj) {
659 if (obj.hasOwnProperty(prop)) {
660 callback(obj[prop], prop, obj);
661 }
662 }
663 } else {
664 throw new Error('obj does not seem to be an array or an iterable object');
665 }
666 };
667
668 /**
669 * Standardidize extension name
670 * @static
671 * @param {string} s extension name
672 * @returns {string}
673 */
674 showdown.helper.stdExtName = function (s) {
675 'use strict';
676 return s.replace(/[_?*+\/\\.^-]/g, '').replace(/\s/g, '').toLowerCase();
677 };
678
679 function escapeCharactersCallback (wholeMatch, m1) {
680 'use strict';
681 var charCodeToEscape = m1.charCodeAt(0);
682 return '¨E' + charCodeToEscape + 'E';
683 }
684
685 /**
686 * Callback used to escape characters when passing through String.replace
687 * @static
688 * @param {string} wholeMatch
689 * @param {string} m1
690 * @returns {string}
691 */
692 showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
693
694 /**
695 * Escape characters in a string
696 * @static
697 * @param {string} text
698 * @param {string} charsToEscape
699 * @param {boolean} afterBackslash
700 * @returns {XML|string|void|*}
701 */
702 showdown.helper.escapeCharacters = function (text, charsToEscape, afterBackslash) {
703 'use strict';
704 // First we have to escape the escape characters so that
705 // we can build a character class out of them
706 var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
707
708 if (afterBackslash) {
709 regexString = '\\\\' + regexString;
710 }
711
712 var regex = new RegExp(regexString, 'g');
713 text = text.replace(regex, escapeCharactersCallback);
714
715 return text;
716 };
717
718 var rgxFindMatchPos = function (str, left, right, flags) {
719 'use strict';
720 var f = flags || '',
721 g = f.indexOf('g') > -1,
722 x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
723 l = new RegExp(left, f.replace(/g/g, '')),
724 pos = [],
725 t, s, m, start, end;
726
727 do {
728 t = 0;
729 while ((m = x.exec(str))) {
730 if (l.test(m[0])) {
731 if (!(t++)) {
732 s = x.lastIndex;
733 start = s - m[0].length;
734 }
735 } else if (t) {
736 if (!--t) {
737 end = m.index + m[0].length;
738 var obj = {
739 left: {start: start, end: s},
740 match: {start: s, end: m.index},
741 right: {start: m.index, end: end},
742 wholeMatch: {start: start, end: end}
743 };
744 pos.push(obj);
745 if (!g) {
746 return pos;
747 }
748 }
749 }
750 }
751 } while (t && (x.lastIndex = s));
752
753 return pos;
754 };
755
756 /**
757 * matchRecursiveRegExp
758 *
759 * (c) 2007 Steven Levithan <stevenlevithan.com>
760 * MIT License
761 *
762 * Accepts a string to search, a left and right format delimiter
763 * as regex patterns, and optional regex flags. Returns an array
764 * of matches, allowing nested instances of left/right delimiters.
765 * Use the "g" flag to return all matches, otherwise only the
766 * first is returned. Be careful to ensure that the left and
767 * right format delimiters produce mutually exclusive matches.
768 * Backreferences are not supported within the right delimiter
769 * due to how it is internally combined with the left delimiter.
770 * When matching strings whose format delimiters are unbalanced
771 * to the left or right, the output is intentionally as a
772 * conventional regex library with recursion support would
773 * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
774 * "<" and ">" as the delimiters (both strings contain a single,
775 * balanced instance of "<x>").
776 *
777 * examples:
778 * matchRecursiveRegExp("test", "\\(", "\\)")
779 * returns: []
780 * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
781 * returns: ["t<<e>><s>", ""]
782 * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
783 * returns: ["test"]
784 */
785 showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
786 'use strict';
787
788 var matchPos = rgxFindMatchPos (str, left, right, flags),
789 results = [];
790
791 for (var i = 0; i < matchPos.length; ++i) {
792 results.push([
793 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
794 str.slice(matchPos[i].match.start, matchPos[i].match.end),
795 str.slice(matchPos[i].left.start, matchPos[i].left.end),
796 str.slice(matchPos[i].right.start, matchPos[i].right.end)
797 ]);
798 }
799 return results;
800 };
801
802 /**
803 *
804 * @param {string} str
805 * @param {string|function} replacement
806 * @param {string} left
807 * @param {string} right
808 * @param {string} flags
809 * @returns {string}
810 */
811 showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
812 'use strict';
813
814 if (!showdown.helper.isFunction(replacement)) {
815 var repStr = replacement;
816 replacement = function () {
817 return repStr;
818 };
819 }
820
821 var matchPos = rgxFindMatchPos(str, left, right, flags),
822 finalStr = str,
823 lng = matchPos.length;
824
825 if (lng > 0) {
826 var bits = [];
827 if (matchPos[0].wholeMatch.start !== 0) {
828 bits.push(str.slice(0, matchPos[0].wholeMatch.start));
829 }
830 for (var i = 0; i < lng; ++i) {
831 bits.push(
832 replacement(
833 str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
834 str.slice(matchPos[i].match.start, matchPos[i].match.end),
835 str.slice(matchPos[i].left.start, matchPos[i].left.end),
836 str.slice(matchPos[i].right.start, matchPos[i].right.end)
837 )
838 );
839 if (i < lng - 1) {
840 bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
841 }
842 }
843 if (matchPos[lng - 1].wholeMatch.end < str.length) {
844 bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
845 }
846 finalStr = bits.join('');
847 }
848 return finalStr;
849 };
850
851 /**
852 * Returns the index within the passed String object of the first occurrence of the specified regex,
853 * starting the search at fromIndex. Returns -1 if the value is not found.
854 *
855 * @param {string} str string to search
856 * @param {RegExp} regex Regular expression to search
857 * @param {int} [fromIndex = 0] Index to start the search
858 * @returns {Number}
859 * @throws InvalidArgumentError
860 */
861 showdown.helper.regexIndexOf = function (str, regex, fromIndex) {
862 'use strict';
863 if (!showdown.helper.isString(str)) {
864 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
865 }
866 if (regex instanceof RegExp === false) {
867 throw 'InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp';
868 }
869 var indexOf = str.substring(fromIndex || 0).search(regex);
870 return (indexOf >= 0) ? (indexOf + (fromIndex || 0)) : indexOf;
871 };
872
873 /**
874 * Splits the passed string object at the defined index, and returns an array composed of the two substrings
875 * @param {string} str string to split
876 * @param {int} index index to split string at
877 * @returns {[string,string]}
878 * @throws InvalidArgumentError
879 */
880 showdown.helper.splitAtIndex = function (str, index) {
881 'use strict';
882 if (!showdown.helper.isString(str)) {
883 throw 'InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string';
884 }
885 return [str.substring(0, index), str.substring(index)];
886 };
887
888 /**
889 * Obfuscate an e-mail address through the use of Character Entities,
890 * transforming ASCII characters into their equivalent decimal or hex entities.
891 *
892 * Since it has a random component, subsequent calls to this function produce different results
893 *
894 * @param {string} mail
895 * @returns {string}
896 */
897 showdown.helper.encodeEmailAddress = function (mail) {
898 'use strict';
899 var encode = [
900 function (ch) {
901 return '&#' + ch.charCodeAt(0) + ';';
902 },
903 function (ch) {
904 return '&#x' + ch.charCodeAt(0).toString(16) + ';';
905 },
906 function (ch) {
907 return ch;
908 }
909 ];
910
911 mail = mail.replace(/./g, function (ch) {
912 if (ch === '@') {
913 // this *must* be encoded. I insist.
914 ch = encode[Math.floor(Math.random() * 2)](ch);
915 } else {
916 var r = Math.random();
917 // roughly 10% raw, 45% hex, 45% dec
918 ch = (
919 r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
920 );
921 }
922 return ch;
923 });
924
925 return mail;
926 };
927
928 /**
929 *
930 * @param str
931 * @param targetLength
932 * @param padString
933 * @returns {string}
934 */
935 showdown.helper.padEnd = function padEnd (str, targetLength, padString) {
936 'use strict';
937 /*jshint bitwise: false*/
938 // eslint-disable-next-line space-infix-ops
939 targetLength = targetLength>>0; //floor if number or convert non-number to 0;
940 /*jshint bitwise: true*/
941 padString = String(padString || ' ');
942 if (str.length > targetLength) {
943 return String(str);
944 } else {
945 targetLength = targetLength - str.length;
946 if (targetLength > padString.length) {
947 padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
948 }
949 return String(str) + padString.slice(0,targetLength);
950 }
951 };
952
953 /**
954 * Unescape HTML entities
955 * @param txt
956 * @returns {string}
957 */
958 showdown.helper.unescapeHTMLEntities = function (txt) {
959 'use strict';
960
961 return txt
962 .replace(/&quot;/g, '"')
963 .replace(/&lt;/g, '<')
964 .replace(/&gt;/g, '>')
965 .replace(/&amp;/g, '&');
966 };
967
968 showdown.helper._hashHTMLSpan = function (html, globals) {
969 return '¨C' + (globals.gHtmlSpans.push(html) - 1) + 'C';
970 };
971
972 /**
973 * Showdown's Event Object
974 * @param {string} name Name of the event
975 * @param {string} text Text
976 * @param {{}} params optional. params of the event
977 * @constructor
978 */
979 showdown.helper.Event = function (name, text, params) {
980 'use strict';
981
982 var regexp = params.regexp || null;
983 var matches = params.matches || {};
984 var options = params.options || {};
985 var converter = params.converter || null;
986 var globals = params.globals || {};
987
988 /**
989 * Get the name of the event
990 * @returns {string}
991 */
992 this.getName = function () {
993 return name;
994 };
995
996 this.getEventName = function () {
997 return name;
998 };
999
1000 this._stopExecution = false;
1001
1002 this.parsedText = params.parsedText || null;
1003
1004 this.getRegexp = function () {
1005 return regexp;
1006 };
1007
1008 this.getOptions = function () {
1009 return options;
1010 };
1011
1012 this.getConverter = function () {
1013 return converter;
1014 };
1015
1016 this.getGlobals = function () {
1017 return globals;
1018 };
1019
1020 this.getCapturedText = function () {
1021 return text;
1022 };
1023
1024 this.getText = function () {
1025 return text;
1026 };
1027
1028 this.setText = function (newText) {
1029 text = newText;
1030 };
1031
1032 this.getMatches = function () {
1033 return matches;
1034 };
1035
1036 this.setMatches = function (newMatches) {
1037 matches = newMatches;
1038 };
1039
1040 this.preventDefault = function (bool) {
1041 this._stopExecution = !bool;
1042 };
1043 };
1044
1045 /**
1046 * POLYFILLS
1047 */
1048 // use this instead of builtin is undefined for IE8 compatibility
1049 if (typeof(console) === 'undefined') {
1050 console = {
1051 warn: function (msg) {
1052 'use strict';
1053 alert(msg);
1054 },
1055 log: function (msg) {
1056 'use strict';
1057 alert(msg);
1058 },
1059 error: function (msg) {
1060 'use strict';
1061 throw msg;
1062 }
1063 };
1064 }
1065
1066 /**
1067 * Common regexes.
1068 * We declare some common regexes to improve performance
1069 */
1070 showdown.helper.regexes = {
1071 asteriskDashTildeAndColon: /([*_:~])/g,
1072 asteriskDashAndTilde: /([*_~])/g
1073 };
1074
1075 /**
1076 * EMOJIS LIST
1077 */
1078 showdown.helper.emojis = {
1079 '+1':'\ud83d\udc4d',
1080 '-1':'\ud83d\udc4e',
1081 '100':'\ud83d\udcaf',
1082 '1234':'\ud83d\udd22',
1083 '1st_place_medal':'\ud83e\udd47',
1084 '2nd_place_medal':'\ud83e\udd48',
1085 '3rd_place_medal':'\ud83e\udd49',
1086 '8ball':'\ud83c\udfb1',
1087 'a':'\ud83c\udd70\ufe0f',
1088 'ab':'\ud83c\udd8e',
1089 'abc':'\ud83d\udd24',
1090 'abcd':'\ud83d\udd21',
1091 'accept':'\ud83c\ude51',
1092 'aerial_tramway':'\ud83d\udea1',
1093 'airplane':'\u2708\ufe0f',
1094 'alarm_clock':'\u23f0',
1095 'alembic':'\u2697\ufe0f',
1096 'alien':'\ud83d\udc7d',
1097 'ambulance':'\ud83d\ude91',
1098 'amphora':'\ud83c\udffa',
1099 'anchor':'\u2693\ufe0f',
1100 'angel':'\ud83d\udc7c',
1101 'anger':'\ud83d\udca2',
1102 'angry':'\ud83d\ude20',
1103 'anguished':'\ud83d\ude27',
1104 'ant':'\ud83d\udc1c',
1105 'apple':'\ud83c\udf4e',
1106 'aquarius':'\u2652\ufe0f',
1107 'aries':'\u2648\ufe0f',
1108 'arrow_backward':'\u25c0\ufe0f',
1109 'arrow_double_down':'\u23ec',
1110 'arrow_double_up':'\u23eb',
1111 'arrow_down':'\u2b07\ufe0f',
1112 'arrow_down_small':'\ud83d\udd3d',
1113 'arrow_forward':'\u25b6\ufe0f',
1114 'arrow_heading_down':'\u2935\ufe0f',
1115 'arrow_heading_up':'\u2934\ufe0f',
1116 'arrow_left':'\u2b05\ufe0f',
1117 'arrow_lower_left':'\u2199\ufe0f',
1118 'arrow_lower_right':'\u2198\ufe0f',
1119 'arrow_right':'\u27a1\ufe0f',
1120 'arrow_right_hook':'\u21aa\ufe0f',
1121 'arrow_up':'\u2b06\ufe0f',
1122 'arrow_up_down':'\u2195\ufe0f',
1123 'arrow_up_small':'\ud83d\udd3c',
1124 'arrow_upper_left':'\u2196\ufe0f',
1125 'arrow_upper_right':'\u2197\ufe0f',
1126 'arrows_clockwise':'\ud83d\udd03',
1127 'arrows_counterclockwise':'\ud83d\udd04',
1128 'art':'\ud83c\udfa8',
1129 'articulated_lorry':'\ud83d\ude9b',
1130 'artificial_satellite':'\ud83d\udef0',
1131 'astonished':'\ud83d\ude32',
1132 'athletic_shoe':'\ud83d\udc5f',
1133 'atm':'\ud83c\udfe7',
1134 'atom_symbol':'\u269b\ufe0f',
1135 'avocado':'\ud83e\udd51',
1136 'b':'\ud83c\udd71\ufe0f',
1137 'baby':'\ud83d\udc76',
1138 'baby_bottle':'\ud83c\udf7c',
1139 'baby_chick':'\ud83d\udc24',
1140 'baby_symbol':'\ud83d\udebc',
1141 'back':'\ud83d\udd19',
1142 'bacon':'\ud83e\udd53',
1143 'badminton':'\ud83c\udff8',
1144 'baggage_claim':'\ud83d\udec4',
1145 'baguette_bread':'\ud83e\udd56',
1146 'balance_scale':'\u2696\ufe0f',
1147 'balloon':'\ud83c\udf88',
1148 'ballot_box':'\ud83d\uddf3',
1149 'ballot_box_with_check':'\u2611\ufe0f',
1150 'bamboo':'\ud83c\udf8d',
1151 'banana':'\ud83c\udf4c',
1152 'bangbang':'\u203c\ufe0f',
1153 'bank':'\ud83c\udfe6',
1154 'bar_chart':'\ud83d\udcca',
1155 'barber':'\ud83d\udc88',
1156 'baseball':'\u26be\ufe0f',
1157 'basketball':'\ud83c\udfc0',
1158 'basketball_man':'\u26f9\ufe0f',
1159 'basketball_woman':'\u26f9\ufe0f&zwj;\u2640\ufe0f',
1160 'bat':'\ud83e\udd87',
1161 'bath':'\ud83d\udec0',
1162 'bathtub':'\ud83d\udec1',
1163 'battery':'\ud83d\udd0b',
1164 'beach_umbrella':'\ud83c\udfd6',
1165 'bear':'\ud83d\udc3b',
1166 'bed':'\ud83d\udecf',
1167 'bee':'\ud83d\udc1d',
1168 'beer':'\ud83c\udf7a',
1169 'beers':'\ud83c\udf7b',
1170 'beetle':'\ud83d\udc1e',
1171 'beginner':'\ud83d\udd30',
1172 'bell':'\ud83d\udd14',
1173 'bellhop_bell':'\ud83d\udece',
1174 'bento':'\ud83c\udf71',
1175 'biking_man':'\ud83d\udeb4',
1176 'bike':'\ud83d\udeb2',
1177 'biking_woman':'\ud83d\udeb4&zwj;\u2640\ufe0f',
1178 'bikini':'\ud83d\udc59',
1179 'biohazard':'\u2623\ufe0f',
1180 'bird':'\ud83d\udc26',
1181 'birthday':'\ud83c\udf82',
1182 'black_circle':'\u26ab\ufe0f',
1183 'black_flag':'\ud83c\udff4',
1184 'black_heart':'\ud83d\udda4',
1185 'black_joker':'\ud83c\udccf',
1186 'black_large_square':'\u2b1b\ufe0f',
1187 'black_medium_small_square':'\u25fe\ufe0f',
1188 'black_medium_square':'\u25fc\ufe0f',
1189 'black_nib':'\u2712\ufe0f',
1190 'black_small_square':'\u25aa\ufe0f',
1191 'black_square_button':'\ud83d\udd32',
1192 'blonde_man':'\ud83d\udc71',
1193 'blonde_woman':'\ud83d\udc71&zwj;\u2640\ufe0f',
1194 'blossom':'\ud83c\udf3c',
1195 'blowfish':'\ud83d\udc21',
1196 'blue_book':'\ud83d\udcd8',
1197 'blue_car':'\ud83d\ude99',
1198 'blue_heart':'\ud83d\udc99',
1199 'blush':'\ud83d\ude0a',
1200 'boar':'\ud83d\udc17',
1201 'boat':'\u26f5\ufe0f',
1202 'bomb':'\ud83d\udca3',
1203 'book':'\ud83d\udcd6',
1204 'bookmark':'\ud83d\udd16',
1205 'bookmark_tabs':'\ud83d\udcd1',
1206 'books':'\ud83d\udcda',
1207 'boom':'\ud83d\udca5',
1208 'boot':'\ud83d\udc62',
1209 'bouquet':'\ud83d\udc90',
1210 'bowing_man':'\ud83d\ude47',
1211 'bow_and_arrow':'\ud83c\udff9',
1212 'bowing_woman':'\ud83d\ude47&zwj;\u2640\ufe0f',
1213 'bowling':'\ud83c\udfb3',
1214 'boxing_glove':'\ud83e\udd4a',
1215 'boy':'\ud83d\udc66',
1216 'bread':'\ud83c\udf5e',
1217 'bride_with_veil':'\ud83d\udc70',
1218 'bridge_at_night':'\ud83c\udf09',
1219 'briefcase':'\ud83d\udcbc',
1220 'broken_heart':'\ud83d\udc94',
1221 'bug':'\ud83d\udc1b',
1222 'building_construction':'\ud83c\udfd7',
1223 'bulb':'\ud83d\udca1',
1224 'bullettrain_front':'\ud83d\ude85',
1225 'bullettrain_side':'\ud83d\ude84',
1226 'burrito':'\ud83c\udf2f',
1227 'bus':'\ud83d\ude8c',
1228 'business_suit_levitating':'\ud83d\udd74',
1229 'busstop':'\ud83d\ude8f',
1230 'bust_in_silhouette':'\ud83d\udc64',
1231 'busts_in_silhouette':'\ud83d\udc65',
1232 'butterfly':'\ud83e\udd8b',
1233 'cactus':'\ud83c\udf35',
1234 'cake':'\ud83c\udf70',
1235 'calendar':'\ud83d\udcc6',
1236 'call_me_hand':'\ud83e\udd19',
1237 'calling':'\ud83d\udcf2',
1238 'camel':'\ud83d\udc2b',
1239 'camera':'\ud83d\udcf7',
1240 'camera_flash':'\ud83d\udcf8',
1241 'camping':'\ud83c\udfd5',
1242 'cancer':'\u264b\ufe0f',
1243 'candle':'\ud83d\udd6f',
1244 'candy':'\ud83c\udf6c',
1245 'canoe':'\ud83d\udef6',
1246 'capital_abcd':'\ud83d\udd20',
1247 'capricorn':'\u2651\ufe0f',
1248 'car':'\ud83d\ude97',
1249 'card_file_box':'\ud83d\uddc3',
1250 'card_index':'\ud83d\udcc7',
1251 'card_index_dividers':'\ud83d\uddc2',
1252 'carousel_horse':'\ud83c\udfa0',
1253 'carrot':'\ud83e\udd55',
1254 'cat':'\ud83d\udc31',
1255 'cat2':'\ud83d\udc08',
1256 'cd':'\ud83d\udcbf',
1257 'chains':'\u26d3',
1258 'champagne':'\ud83c\udf7e',
1259 'chart':'\ud83d\udcb9',
1260 'chart_with_downwards_trend':'\ud83d\udcc9',
1261 'chart_with_upwards_trend':'\ud83d\udcc8',
1262 'checkered_flag':'\ud83c\udfc1',
1263 'cheese':'\ud83e\uddc0',
1264 'cherries':'\ud83c\udf52',
1265 'cherry_blossom':'\ud83c\udf38',
1266 'chestnut':'\ud83c\udf30',
1267 'chicken':'\ud83d\udc14',
1268 'children_crossing':'\ud83d\udeb8',
1269 'chipmunk':'\ud83d\udc3f',
1270 'chocolate_bar':'\ud83c\udf6b',
1271 'christmas_tree':'\ud83c\udf84',
1272 'church':'\u26ea\ufe0f',
1273 'cinema':'\ud83c\udfa6',
1274 'circus_tent':'\ud83c\udfaa',
1275 'city_sunrise':'\ud83c\udf07',
1276 'city_sunset':'\ud83c\udf06',
1277 'cityscape':'\ud83c\udfd9',
1278 'cl':'\ud83c\udd91',
1279 'clamp':'\ud83d\udddc',
1280 'clap':'\ud83d\udc4f',
1281 'clapper':'\ud83c\udfac',
1282 'classical_building':'\ud83c\udfdb',
1283 'clinking_glasses':'\ud83e\udd42',
1284 'clipboard':'\ud83d\udccb',
1285 'clock1':'\ud83d\udd50',
1286 'clock10':'\ud83d\udd59',
1287 'clock1030':'\ud83d\udd65',
1288 'clock11':'\ud83d\udd5a',
1289 'clock1130':'\ud83d\udd66',
1290 'clock12':'\ud83d\udd5b',
1291 'clock1230':'\ud83d\udd67',
1292 'clock130':'\ud83d\udd5c',
1293 'clock2':'\ud83d\udd51',
1294 'clock230':'\ud83d\udd5d',
1295 'clock3':'\ud83d\udd52',
1296 'clock330':'\ud83d\udd5e',
1297 'clock4':'\ud83d\udd53',
1298 'clock430':'\ud83d\udd5f',
1299 'clock5':'\ud83d\udd54',
1300 'clock530':'\ud83d\udd60',
1301 'clock6':'\ud83d\udd55',
1302 'clock630':'\ud83d\udd61',
1303 'clock7':'\ud83d\udd56',
1304 'clock730':'\ud83d\udd62',
1305 'clock8':'\ud83d\udd57',
1306 'clock830':'\ud83d\udd63',
1307 'clock9':'\ud83d\udd58',
1308 'clock930':'\ud83d\udd64',
1309 'closed_book':'\ud83d\udcd5',
1310 'closed_lock_with_key':'\ud83d\udd10',
1311 'closed_umbrella':'\ud83c\udf02',
1312 'cloud':'\u2601\ufe0f',
1313 'cloud_with_lightning':'\ud83c\udf29',
1314 'cloud_with_lightning_and_rain':'\u26c8',
1315 'cloud_with_rain':'\ud83c\udf27',
1316 'cloud_with_snow':'\ud83c\udf28',
1317 'clown_face':'\ud83e\udd21',
1318 'clubs':'\u2663\ufe0f',
1319 'cocktail':'\ud83c\udf78',
1320 'coffee':'\u2615\ufe0f',
1321 'coffin':'\u26b0\ufe0f',
1322 'cold_sweat':'\ud83d\ude30',
1323 'comet':'\u2604\ufe0f',
1324 'computer':'\ud83d\udcbb',
1325 'computer_mouse':'\ud83d\uddb1',
1326 'confetti_ball':'\ud83c\udf8a',
1327 'confounded':'\ud83d\ude16',
1328 'confused':'\ud83d\ude15',
1329 'congratulations':'\u3297\ufe0f',
1330 'construction':'\ud83d\udea7',
1331 'construction_worker_man':'\ud83d\udc77',
1332 'construction_worker_woman':'\ud83d\udc77&zwj;\u2640\ufe0f',
1333 'control_knobs':'\ud83c\udf9b',
1334 'convenience_store':'\ud83c\udfea',
1335 'cookie':'\ud83c\udf6a',
1336 'cool':'\ud83c\udd92',
1337 'policeman':'\ud83d\udc6e',
1338 'copyright':'\u00a9\ufe0f',
1339 'corn':'\ud83c\udf3d',
1340 'couch_and_lamp':'\ud83d\udecb',
1341 'couple':'\ud83d\udc6b',
1342 'couple_with_heart_woman_man':'\ud83d\udc91',
1343 'couple_with_heart_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc68',
1344 'couple_with_heart_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc69',
1345 'couplekiss_man_man':'\ud83d\udc68&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc68',
1346 'couplekiss_man_woman':'\ud83d\udc8f',
1347 'couplekiss_woman_woman':'\ud83d\udc69&zwj;\u2764\ufe0f&zwj;\ud83d\udc8b&zwj;\ud83d\udc69',
1348 'cow':'\ud83d\udc2e',
1349 'cow2':'\ud83d\udc04',
1350 'cowboy_hat_face':'\ud83e\udd20',
1351 'crab':'\ud83e\udd80',
1352 'crayon':'\ud83d\udd8d',
1353 'credit_card':'\ud83d\udcb3',
1354 'crescent_moon':'\ud83c\udf19',
1355 'cricket':'\ud83c\udfcf',
1356 'crocodile':'\ud83d\udc0a',
1357 'croissant':'\ud83e\udd50',
1358 'crossed_fingers':'\ud83e\udd1e',
1359 'crossed_flags':'\ud83c\udf8c',
1360 'crossed_swords':'\u2694\ufe0f',
1361 'crown':'\ud83d\udc51',
1362 'cry':'\ud83d\ude22',
1363 'crying_cat_face':'\ud83d\ude3f',
1364 'crystal_ball':'\ud83d\udd2e',
1365 'cucumber':'\ud83e\udd52',
1366 'cupid':'\ud83d\udc98',
1367 'curly_loop':'\u27b0',
1368 'currency_exchange':'\ud83d\udcb1',
1369 'curry':'\ud83c\udf5b',
1370 'custard':'\ud83c\udf6e',
1371 'customs':'\ud83d\udec3',
1372 'cyclone':'\ud83c\udf00',
1373 'dagger':'\ud83d\udde1',
1374 'dancer':'\ud83d\udc83',
1375 'dancing_women':'\ud83d\udc6f',
1376 'dancing_men':'\ud83d\udc6f&zwj;\u2642\ufe0f',
1377 'dango':'\ud83c\udf61',
1378 'dark_sunglasses':'\ud83d\udd76',
1379 'dart':'\ud83c\udfaf',
1380 'dash':'\ud83d\udca8',
1381 'date':'\ud83d\udcc5',
1382 'deciduous_tree':'\ud83c\udf33',
1383 'deer':'\ud83e\udd8c',
1384 'department_store':'\ud83c\udfec',
1385 'derelict_house':'\ud83c\udfda',
1386 'desert':'\ud83c\udfdc',
1387 'desert_island':'\ud83c\udfdd',
1388 'desktop_computer':'\ud83d\udda5',
1389 'male_detective':'\ud83d\udd75\ufe0f',
1390 'diamond_shape_with_a_dot_inside':'\ud83d\udca0',
1391 'diamonds':'\u2666\ufe0f',
1392 'disappointed':'\ud83d\ude1e',
1393 'disappointed_relieved':'\ud83d\ude25',
1394 'dizzy':'\ud83d\udcab',
1395 'dizzy_face':'\ud83d\ude35',
1396 'do_not_litter':'\ud83d\udeaf',
1397 'dog':'\ud83d\udc36',
1398 'dog2':'\ud83d\udc15',
1399 'dollar':'\ud83d\udcb5',
1400 'dolls':'\ud83c\udf8e',
1401 'dolphin':'\ud83d\udc2c',
1402 'door':'\ud83d\udeaa',
1403 'doughnut':'\ud83c\udf69',
1404 'dove':'\ud83d\udd4a',
1405 'dragon':'\ud83d\udc09',
1406 'dragon_face':'\ud83d\udc32',
1407 'dress':'\ud83d\udc57',
1408 'dromedary_camel':'\ud83d\udc2a',
1409 'drooling_face':'\ud83e\udd24',
1410 'droplet':'\ud83d\udca7',
1411 'drum':'\ud83e\udd41',
1412 'duck':'\ud83e\udd86',
1413 'dvd':'\ud83d\udcc0',
1414 'e-mail':'\ud83d\udce7',
1415 'eagle':'\ud83e\udd85',
1416 'ear':'\ud83d\udc42',
1417 'ear_of_rice':'\ud83c\udf3e',
1418 'earth_africa':'\ud83c\udf0d',
1419 'earth_americas':'\ud83c\udf0e',
1420 'earth_asia':'\ud83c\udf0f',
1421 'egg':'\ud83e\udd5a',
1422 'eggplant':'\ud83c\udf46',
1423 'eight_pointed_black_star':'\u2734\ufe0f',
1424 'eight_spoked_asterisk':'\u2733\ufe0f',
1425 'electric_plug':'\ud83d\udd0c',
1426 'elephant':'\ud83d\udc18',
1427 'email':'\u2709\ufe0f',
1428 'end':'\ud83d\udd1a',
1429 'envelope_with_arrow':'\ud83d\udce9',
1430 'euro':'\ud83d\udcb6',
1431 'european_castle':'\ud83c\udff0',
1432 'european_post_office':'\ud83c\udfe4',
1433 'evergreen_tree':'\ud83c\udf32',
1434 'exclamation':'\u2757\ufe0f',
1435 'expressionless':'\ud83d\ude11',
1436 'eye':'\ud83d\udc41',
1437 'eye_speech_bubble':'\ud83d\udc41&zwj;\ud83d\udde8',
1438 'eyeglasses':'\ud83d\udc53',
1439 'eyes':'\ud83d\udc40',
1440 'face_with_head_bandage':'\ud83e\udd15',
1441 'face_with_thermometer':'\ud83e\udd12',
1442 'fist_oncoming':'\ud83d\udc4a',
1443 'factory':'\ud83c\udfed',
1444 'fallen_leaf':'\ud83c\udf42',
1445 'family_man_woman_boy':'\ud83d\udc6a',
1446 'family_man_boy':'\ud83d\udc68&zwj;\ud83d\udc66',
1447 'family_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1448 'family_man_girl':'\ud83d\udc68&zwj;\ud83d\udc67',
1449 'family_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1450 'family_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1451 'family_man_man_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66',
1452 'family_man_man_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1453 'family_man_man_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67',
1454 'family_man_man_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1455 'family_man_man_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc68&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1456 'family_man_woman_boy_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1457 'family_man_woman_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1458 'family_man_woman_girl_boy':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1459 'family_man_woman_girl_girl':'\ud83d\udc68&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1460 'family_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc66',
1461 'family_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1462 'family_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc67',
1463 'family_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1464 'family_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1465 'family_woman_woman_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66',
1466 'family_woman_woman_boy_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc66&zwj;\ud83d\udc66',
1467 'family_woman_woman_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67',
1468 'family_woman_woman_girl_boy':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc66',
1469 'family_woman_woman_girl_girl':'\ud83d\udc69&zwj;\ud83d\udc69&zwj;\ud83d\udc67&zwj;\ud83d\udc67',
1470 'fast_forward':'\u23e9',
1471 'fax':'\ud83d\udce0',
1472 'fearful':'\ud83d\ude28',
1473 'feet':'\ud83d\udc3e',
1474 'female_detective':'\ud83d\udd75\ufe0f&zwj;\u2640\ufe0f',
1475 'ferris_wheel':'\ud83c\udfa1',
1476 'ferry':'\u26f4',
1477 'field_hockey':'\ud83c\udfd1',
1478 'file_cabinet':'\ud83d\uddc4',
1479 'file_folder':'\ud83d\udcc1',
1480 'film_projector':'\ud83d\udcfd',
1481 'film_strip':'\ud83c\udf9e',
1482 'fire':'\ud83d\udd25',
1483 'fire_engine':'\ud83d\ude92',
1484 'fireworks':'\ud83c\udf86',
1485 'first_quarter_moon':'\ud83c\udf13',
1486 'first_quarter_moon_with_face':'\ud83c\udf1b',
1487 'fish':'\ud83d\udc1f',
1488 'fish_cake':'\ud83c\udf65',
1489 'fishing_pole_and_fish':'\ud83c\udfa3',
1490 'fist_raised':'\u270a',
1491 'fist_left':'\ud83e\udd1b',
1492 'fist_right':'\ud83e\udd1c',
1493 'flags':'\ud83c\udf8f',
1494 'flashlight':'\ud83d\udd26',
1495 'fleur_de_lis':'\u269c\ufe0f',
1496 'flight_arrival':'\ud83d\udeec',
1497 'flight_departure':'\ud83d\udeeb',
1498 'floppy_disk':'\ud83d\udcbe',
1499 'flower_playing_cards':'\ud83c\udfb4',
1500 'flushed':'\ud83d\ude33',
1501 'fog':'\ud83c\udf2b',
1502 'foggy':'\ud83c\udf01',
1503 'football':'\ud83c\udfc8',
1504 'footprints':'\ud83d\udc63',
1505 'fork_and_knife':'\ud83c\udf74',
1506 'fountain':'\u26f2\ufe0f',
1507 'fountain_pen':'\ud83d\udd8b',
1508 'four_leaf_clover':'\ud83c\udf40',
1509 'fox_face':'\ud83e\udd8a',
1510 'framed_picture':'\ud83d\uddbc',
1511 'free':'\ud83c\udd93',
1512 'fried_egg':'\ud83c\udf73',
1513 'fried_shrimp':'\ud83c\udf64',
1514 'fries':'\ud83c\udf5f',
1515 'frog':'\ud83d\udc38',
1516 'frowning':'\ud83d\ude26',
1517 'frowning_face':'\u2639\ufe0f',
1518 'frowning_man':'\ud83d\ude4d&zwj;\u2642\ufe0f',
1519 'frowning_woman':'\ud83d\ude4d',
1520 'middle_finger':'\ud83d\udd95',
1521 'fuelpump':'\u26fd\ufe0f',
1522 'full_moon':'\ud83c\udf15',
1523 'full_moon_with_face':'\ud83c\udf1d',
1524 'funeral_urn':'\u26b1\ufe0f',
1525 'game_die':'\ud83c\udfb2',
1526 'gear':'\u2699\ufe0f',
1527 'gem':'\ud83d\udc8e',
1528 'gemini':'\u264a\ufe0f',
1529 'ghost':'\ud83d\udc7b',
1530 'gift':'\ud83c\udf81',
1531 'gift_heart':'\ud83d\udc9d',
1532 'girl':'\ud83d\udc67',
1533 'globe_with_meridians':'\ud83c\udf10',
1534 'goal_net':'\ud83e\udd45',
1535 'goat':'\ud83d\udc10',
1536 'golf':'\u26f3\ufe0f',
1537 'golfing_man':'\ud83c\udfcc\ufe0f',
1538 'golfing_woman':'\ud83c\udfcc\ufe0f&zwj;\u2640\ufe0f',
1539 'gorilla':'\ud83e\udd8d',
1540 'grapes':'\ud83c\udf47',
1541 'green_apple':'\ud83c\udf4f',
1542 'green_book':'\ud83d\udcd7',
1543 'green_heart':'\ud83d\udc9a',
1544 'green_salad':'\ud83e\udd57',
1545 'grey_exclamation':'\u2755',
1546 'grey_question':'\u2754',
1547 'grimacing':'\ud83d\ude2c',
1548 'grin':'\ud83d\ude01',
1549 'grinning':'\ud83d\ude00',
1550 'guardsman':'\ud83d\udc82',
1551 'guardswoman':'\ud83d\udc82&zwj;\u2640\ufe0f',
1552 'guitar':'\ud83c\udfb8',
1553 'gun':'\ud83d\udd2b',
1554 'haircut_woman':'\ud83d\udc87',
1555 'haircut_man':'\ud83d\udc87&zwj;\u2642\ufe0f',
1556 'hamburger':'\ud83c\udf54',
1557 'hammer':'\ud83d\udd28',
1558 'hammer_and_pick':'\u2692',
1559 'hammer_and_wrench':'\ud83d\udee0',
1560 'hamster':'\ud83d\udc39',
1561 'hand':'\u270b',
1562 'handbag':'\ud83d\udc5c',
1563 'handshake':'\ud83e\udd1d',
1564 'hankey':'\ud83d\udca9',
1565 'hatched_chick':'\ud83d\udc25',
1566 'hatching_chick':'\ud83d\udc23',
1567 'headphones':'\ud83c\udfa7',
1568 'hear_no_evil':'\ud83d\ude49',
1569 'heart':'\u2764\ufe0f',
1570 'heart_decoration':'\ud83d\udc9f',
1571 'heart_eyes':'\ud83d\ude0d',
1572 'heart_eyes_cat':'\ud83d\ude3b',
1573 'heartbeat':'\ud83d\udc93',
1574 'heartpulse':'\ud83d\udc97',
1575 'hearts':'\u2665\ufe0f',
1576 'heavy_check_mark':'\u2714\ufe0f',
1577 'heavy_division_sign':'\u2797',
1578 'heavy_dollar_sign':'\ud83d\udcb2',
1579 'heavy_heart_exclamation':'\u2763\ufe0f',
1580 'heavy_minus_sign':'\u2796',
1581 'heavy_multiplication_x':'\u2716\ufe0f',
1582 'heavy_plus_sign':'\u2795',
1583 'helicopter':'\ud83d\ude81',
1584 'herb':'\ud83c\udf3f',
1585 'hibiscus':'\ud83c\udf3a',
1586 'high_brightness':'\ud83d\udd06',
1587 'high_heel':'\ud83d\udc60',
1588 'hocho':'\ud83d\udd2a',
1589 'hole':'\ud83d\udd73',
1590 'honey_pot':'\ud83c\udf6f',
1591 'horse':'\ud83d\udc34',
1592 'horse_racing':'\ud83c\udfc7',
1593 'hospital':'\ud83c\udfe5',
1594 'hot_pepper':'\ud83c\udf36',
1595 'hotdog':'\ud83c\udf2d',
1596 'hotel':'\ud83c\udfe8',
1597 'hotsprings':'\u2668\ufe0f',
1598 'hourglass':'\u231b\ufe0f',
1599 'hourglass_flowing_sand':'\u23f3',
1600 'house':'\ud83c\udfe0',
1601 'house_with_garden':'\ud83c\udfe1',
1602 'houses':'\ud83c\udfd8',
1603 'hugs':'\ud83e\udd17',
1604 'hushed':'\ud83d\ude2f',
1605 'ice_cream':'\ud83c\udf68',
1606 'ice_hockey':'\ud83c\udfd2',
1607 'ice_skate':'\u26f8',
1608 'icecream':'\ud83c\udf66',
1609 'id':'\ud83c\udd94',
1610 'ideograph_advantage':'\ud83c\ude50',
1611 'imp':'\ud83d\udc7f',
1612 'inbox_tray':'\ud83d\udce5',
1613 'incoming_envelope':'\ud83d\udce8',
1614 'tipping_hand_woman':'\ud83d\udc81',
1615 'information_source':'\u2139\ufe0f',
1616 'innocent':'\ud83d\ude07',
1617 'interrobang':'\u2049\ufe0f',
1618 'iphone':'\ud83d\udcf1',
1619 'izakaya_lantern':'\ud83c\udfee',
1620 'jack_o_lantern':'\ud83c\udf83',
1621 'japan':'\ud83d\uddfe',
1622 'japanese_castle':'\ud83c\udfef',
1623 'japanese_goblin':'\ud83d\udc7a',
1624 'japanese_ogre':'\ud83d\udc79',
1625 'jeans':'\ud83d\udc56',
1626 'joy':'\ud83d\ude02',
1627 'joy_cat':'\ud83d\ude39',
1628 'joystick':'\ud83d\udd79',
1629 'kaaba':'\ud83d\udd4b',
1630 'key':'\ud83d\udd11',
1631 'keyboard':'\u2328\ufe0f',
1632 'keycap_ten':'\ud83d\udd1f',
1633 'kick_scooter':'\ud83d\udef4',
1634 'kimono':'\ud83d\udc58',
1635 'kiss':'\ud83d\udc8b',
1636 'kissing':'\ud83d\ude17',
1637 'kissing_cat':'\ud83d\ude3d',
1638 'kissing_closed_eyes':'\ud83d\ude1a',
1639 'kissing_heart':'\ud83d\ude18',
1640 'kissing_smiling_eyes':'\ud83d\ude19',
1641 'kiwi_fruit':'\ud83e\udd5d',
1642 'koala':'\ud83d\udc28',
1643 'koko':'\ud83c\ude01',
1644 'label':'\ud83c\udff7',
1645 'large_blue_circle':'\ud83d\udd35',
1646 'large_blue_diamond':'\ud83d\udd37',
1647 'large_orange_diamond':'\ud83d\udd36',
1648 'last_quarter_moon':'\ud83c\udf17',
1649 'last_quarter_moon_with_face':'\ud83c\udf1c',
1650 'latin_cross':'\u271d\ufe0f',
1651 'laughing':'\ud83d\ude06',
1652 'leaves':'\ud83c\udf43',
1653 'ledger':'\ud83d\udcd2',
1654 'left_luggage':'\ud83d\udec5',
1655 'left_right_arrow':'\u2194\ufe0f',
1656 'leftwards_arrow_with_hook':'\u21a9\ufe0f',
1657 'lemon':'\ud83c\udf4b',
1658 'leo':'\u264c\ufe0f',
1659 'leopard':'\ud83d\udc06',
1660 'level_slider':'\ud83c\udf9a',
1661 'libra':'\u264e\ufe0f',
1662 'light_rail':'\ud83d\ude88',
1663 'link':'\ud83d\udd17',
1664 'lion':'\ud83e\udd81',
1665 'lips':'\ud83d\udc44',
1666 'lipstick':'\ud83d\udc84',
1667 'lizard':'\ud83e\udd8e',
1668 'lock':'\ud83d\udd12',
1669 'lock_with_ink_pen':'\ud83d\udd0f',
1670 'lollipop':'\ud83c\udf6d',
1671 'loop':'\u27bf',
1672 'loud_sound':'\ud83d\udd0a',
1673 'loudspeaker':'\ud83d\udce2',
1674 'love_hotel':'\ud83c\udfe9',
1675 'love_letter':'\ud83d\udc8c',
1676 'low_brightness':'\ud83d\udd05',
1677 'lying_face':'\ud83e\udd25',
1678 'm':'\u24c2\ufe0f',
1679 'mag':'\ud83d\udd0d',
1680 'mag_right':'\ud83d\udd0e',
1681 'mahjong':'\ud83c\udc04\ufe0f',
1682 'mailbox':'\ud83d\udceb',
1683 'mailbox_closed':'\ud83d\udcea',
1684 'mailbox_with_mail':'\ud83d\udcec',
1685 'mailbox_with_no_mail':'\ud83d\udced',
1686 'man':'\ud83d\udc68',
1687 'man_artist':'\ud83d\udc68&zwj;\ud83c\udfa8',
1688 'man_astronaut':'\ud83d\udc68&zwj;\ud83d\ude80',
1689 'man_cartwheeling':'\ud83e\udd38&zwj;\u2642\ufe0f',
1690 'man_cook':'\ud83d\udc68&zwj;\ud83c\udf73',
1691 'man_dancing':'\ud83d\udd7a',
1692 'man_facepalming':'\ud83e\udd26&zwj;\u2642\ufe0f',
1693 'man_factory_worker':'\ud83d\udc68&zwj;\ud83c\udfed',
1694 'man_farmer':'\ud83d\udc68&zwj;\ud83c\udf3e',
1695 'man_firefighter':'\ud83d\udc68&zwj;\ud83d\ude92',
1696 'man_health_worker':'\ud83d\udc68&zwj;\u2695\ufe0f',
1697 'man_in_tuxedo':'\ud83e\udd35',
1698 'man_judge':'\ud83d\udc68&zwj;\u2696\ufe0f',
1699 'man_juggling':'\ud83e\udd39&zwj;\u2642\ufe0f',
1700 'man_mechanic':'\ud83d\udc68&zwj;\ud83d\udd27',
1701 'man_office_worker':'\ud83d\udc68&zwj;\ud83d\udcbc',
1702 'man_pilot':'\ud83d\udc68&zwj;\u2708\ufe0f',
1703 'man_playing_handball':'\ud83e\udd3e&zwj;\u2642\ufe0f',
1704 'man_playing_water_polo':'\ud83e\udd3d&zwj;\u2642\ufe0f',
1705 'man_scientist':'\ud83d\udc68&zwj;\ud83d\udd2c',
1706 'man_shrugging':'\ud83e\udd37&zwj;\u2642\ufe0f',
1707 'man_singer':'\ud83d\udc68&zwj;\ud83c\udfa4',
1708 'man_student':'\ud83d\udc68&zwj;\ud83c\udf93',
1709 'man_teacher':'\ud83d\udc68&zwj;\ud83c\udfeb',
1710 'man_technologist':'\ud83d\udc68&zwj;\ud83d\udcbb',
1711 'man_with_gua_pi_mao':'\ud83d\udc72',
1712 'man_with_turban':'\ud83d\udc73',
1713 'tangerine':'\ud83c\udf4a',
1714 'mans_shoe':'\ud83d\udc5e',
1715 'mantelpiece_clock':'\ud83d\udd70',
1716 'maple_leaf':'\ud83c\udf41',
1717 'martial_arts_uniform':'\ud83e\udd4b',
1718 'mask':'\ud83d\ude37',
1719 'massage_woman':'\ud83d\udc86',
1720 'massage_man':'\ud83d\udc86&zwj;\u2642\ufe0f',
1721 'meat_on_bone':'\ud83c\udf56',
1722 'medal_military':'\ud83c\udf96',
1723 'medal_sports':'\ud83c\udfc5',
1724 'mega':'\ud83d\udce3',
1725 'melon':'\ud83c\udf48',
1726 'memo':'\ud83d\udcdd',
1727 'men_wrestling':'\ud83e\udd3c&zwj;\u2642\ufe0f',
1728 'menorah':'\ud83d\udd4e',
1729 'mens':'\ud83d\udeb9',
1730 'metal':'\ud83e\udd18',
1731 'metro':'\ud83d\ude87',
1732 'microphone':'\ud83c\udfa4',
1733 'microscope':'\ud83d\udd2c',
1734 'milk_glass':'\ud83e\udd5b',
1735 'milky_way':'\ud83c\udf0c',
1736 'minibus':'\ud83d\ude90',
1737 'minidisc':'\ud83d\udcbd',
1738 'mobile_phone_off':'\ud83d\udcf4',
1739 'money_mouth_face':'\ud83e\udd11',
1740 'money_with_wings':'\ud83d\udcb8',
1741 'moneybag':'\ud83d\udcb0',
1742 'monkey':'\ud83d\udc12',
1743 'monkey_face':'\ud83d\udc35',
1744 'monorail':'\ud83d\ude9d',
1745 'moon':'\ud83c\udf14',
1746 'mortar_board':'\ud83c\udf93',
1747 'mosque':'\ud83d\udd4c',
1748 'motor_boat':'\ud83d\udee5',
1749 'motor_scooter':'\ud83d\udef5',
1750 'motorcycle':'\ud83c\udfcd',
1751 'motorway':'\ud83d\udee3',
1752 'mount_fuji':'\ud83d\uddfb',
1753 'mountain':'\u26f0',
1754 'mountain_biking_man':'\ud83d\udeb5',
1755 'mountain_biking_woman':'\ud83d\udeb5&zwj;\u2640\ufe0f',
1756 'mountain_cableway':'\ud83d\udea0',
1757 'mountain_railway':'\ud83d\ude9e',
1758 'mountain_snow':'\ud83c\udfd4',
1759 'mouse':'\ud83d\udc2d',
1760 'mouse2':'\ud83d\udc01',
1761 'movie_camera':'\ud83c\udfa5',
1762 'moyai':'\ud83d\uddff',
1763 'mrs_claus':'\ud83e\udd36',
1764 'muscle':'\ud83d\udcaa',
1765 'mushroom':'\ud83c\udf44',
1766 'musical_keyboard':'\ud83c\udfb9',
1767 'musical_note':'\ud83c\udfb5',
1768 'musical_score':'\ud83c\udfbc',
1769 'mute':'\ud83d\udd07',
1770 'nail_care':'\ud83d\udc85',
1771 'name_badge':'\ud83d\udcdb',
1772 'national_park':'\ud83c\udfde',
1773 'nauseated_face':'\ud83e\udd22',
1774 'necktie':'\ud83d\udc54',
1775 'negative_squared_cross_mark':'\u274e',
1776 'nerd_face':'\ud83e\udd13',
1777 'neutral_face':'\ud83d\ude10',
1778 'new':'\ud83c\udd95',
1779 'new_moon':'\ud83c\udf11',
1780 'new_moon_with_face':'\ud83c\udf1a',
1781 'newspaper':'\ud83d\udcf0',
1782 'newspaper_roll':'\ud83d\uddde',
1783 'next_track_button':'\u23ed',
1784 'ng':'\ud83c\udd96',
1785 'no_good_man':'\ud83d\ude45&zwj;\u2642\ufe0f',
1786 'no_good_woman':'\ud83d\ude45',
1787 'night_with_stars':'\ud83c\udf03',
1788 'no_bell':'\ud83d\udd15',
1789 'no_bicycles':'\ud83d\udeb3',
1790 'no_entry':'\u26d4\ufe0f',
1791 'no_entry_sign':'\ud83d\udeab',
1792 'no_mobile_phones':'\ud83d\udcf5',
1793 'no_mouth':'\ud83d\ude36',
1794 'no_pedestrians':'\ud83d\udeb7',
1795 'no_smoking':'\ud83d\udead',
1796 'non-potable_water':'\ud83d\udeb1',
1797 'nose':'\ud83d\udc43',
1798 'notebook':'\ud83d\udcd3',
1799 'notebook_with_decorative_cover':'\ud83d\udcd4',
1800 'notes':'\ud83c\udfb6',
1801 'nut_and_bolt':'\ud83d\udd29',
1802 'o':'\u2b55\ufe0f',
1803 'o2':'\ud83c\udd7e\ufe0f',
1804 'ocean':'\ud83c\udf0a',
1805 'octopus':'\ud83d\udc19',
1806 'oden':'\ud83c\udf62',
1807 'office':'\ud83c\udfe2',
1808 'oil_drum':'\ud83d\udee2',
1809 'ok':'\ud83c\udd97',
1810 'ok_hand':'\ud83d\udc4c',
1811 'ok_man':'\ud83d\ude46&zwj;\u2642\ufe0f',
1812 'ok_woman':'\ud83d\ude46',
1813 'old_key':'\ud83d\udddd',
1814 'older_man':'\ud83d\udc74',
1815 'older_woman':'\ud83d\udc75',
1816 'om':'\ud83d\udd49',
1817 'on':'\ud83d\udd1b',
1818 'oncoming_automobile':'\ud83d\ude98',
1819 'oncoming_bus':'\ud83d\ude8d',
1820 'oncoming_police_car':'\ud83d\ude94',
1821 'oncoming_taxi':'\ud83d\ude96',
1822 'open_file_folder':'\ud83d\udcc2',
1823 'open_hands':'\ud83d\udc50',
1824 'open_mouth':'\ud83d\ude2e',
1825 'open_umbrella':'\u2602\ufe0f',
1826 'ophiuchus':'\u26ce',
1827 'orange_book':'\ud83d\udcd9',
1828 'orthodox_cross':'\u2626\ufe0f',
1829 'outbox_tray':'\ud83d\udce4',
1830 'owl':'\ud83e\udd89',
1831 'ox':'\ud83d\udc02',
1832 'package':'\ud83d\udce6',
1833 'page_facing_up':'\ud83d\udcc4',
1834 'page_with_curl':'\ud83d\udcc3',
1835 'pager':'\ud83d\udcdf',
1836 'paintbrush':'\ud83d\udd8c',
1837 'palm_tree':'\ud83c\udf34',
1838 'pancakes':'\ud83e\udd5e',
1839 'panda_face':'\ud83d\udc3c',
1840 'paperclip':'\ud83d\udcce',
1841 'paperclips':'\ud83d\udd87',
1842 'parasol_on_ground':'\u26f1',
1843 'parking':'\ud83c\udd7f\ufe0f',
1844 'part_alternation_mark':'\u303d\ufe0f',
1845 'partly_sunny':'\u26c5\ufe0f',
1846 'passenger_ship':'\ud83d\udef3',
1847 'passport_control':'\ud83d\udec2',
1848 'pause_button':'\u23f8',
1849 'peace_symbol':'\u262e\ufe0f',
1850 'peach':'\ud83c\udf51',
1851 'peanuts':'\ud83e\udd5c',
1852 'pear':'\ud83c\udf50',
1853 'pen':'\ud83d\udd8a',
1854 'pencil2':'\u270f\ufe0f',
1855 'penguin':'\ud83d\udc27',
1856 'pensive':'\ud83d\ude14',
1857 'performing_arts':'\ud83c\udfad',
1858 'persevere':'\ud83d\ude23',
1859 'person_fencing':'\ud83e\udd3a',
1860 'pouting_woman':'\ud83d\ude4e',
1861 'phone':'\u260e\ufe0f',
1862 'pick':'\u26cf',
1863 'pig':'\ud83d\udc37',
1864 'pig2':'\ud83d\udc16',
1865 'pig_nose':'\ud83d\udc3d',
1866 'pill':'\ud83d\udc8a',
1867 'pineapple':'\ud83c\udf4d',
1868 'ping_pong':'\ud83c\udfd3',
1869 'pisces':'\u2653\ufe0f',
1870 'pizza':'\ud83c\udf55',
1871 'place_of_worship':'\ud83d\uded0',
1872 'plate_with_cutlery':'\ud83c\udf7d',
1873 'play_or_pause_button':'\u23ef',
1874 'point_down':'\ud83d\udc47',
1875 'point_left':'\ud83d\udc48',
1876 'point_right':'\ud83d\udc49',
1877 'point_up':'\u261d\ufe0f',
1878 'point_up_2':'\ud83d\udc46',
1879 'police_car':'\ud83d\ude93',
1880 'policewoman':'\ud83d\udc6e&zwj;\u2640\ufe0f',
1881 'poodle':'\ud83d\udc29',
1882 'popcorn':'\ud83c\udf7f',
1883 'post_office':'\ud83c\udfe3',
1884 'postal_horn':'\ud83d\udcef',
1885 'postbox':'\ud83d\udcee',
1886 'potable_water':'\ud83d\udeb0',
1887 'potato':'\ud83e\udd54',
1888 'pouch':'\ud83d\udc5d',
1889 'poultry_leg':'\ud83c\udf57',
1890 'pound':'\ud83d\udcb7',
1891 'rage':'\ud83d\ude21',
1892 'pouting_cat':'\ud83d\ude3e',
1893 'pouting_man':'\ud83d\ude4e&zwj;\u2642\ufe0f',
1894 'pray':'\ud83d\ude4f',
1895 'prayer_beads':'\ud83d\udcff',
1896 'pregnant_woman':'\ud83e\udd30',
1897 'previous_track_button':'\u23ee',
1898 'prince':'\ud83e\udd34',
1899 'princess':'\ud83d\udc78',
1900 'printer':'\ud83d\udda8',
1901 'purple_heart':'\ud83d\udc9c',
1902 'purse':'\ud83d\udc5b',
1903 'pushpin':'\ud83d\udccc',
1904 'put_litter_in_its_place':'\ud83d\udeae',
1905 'question':'\u2753',
1906 'rabbit':'\ud83d\udc30',
1907 'rabbit2':'\ud83d\udc07',
1908 'racehorse':'\ud83d\udc0e',
1909 'racing_car':'\ud83c\udfce',
1910 'radio':'\ud83d\udcfb',
1911 'radio_button':'\ud83d\udd18',
1912 'radioactive':'\u2622\ufe0f',
1913 'railway_car':'\ud83d\ude83',
1914 'railway_track':'\ud83d\udee4',
1915 'rainbow':'\ud83c\udf08',
1916 'rainbow_flag':'\ud83c\udff3\ufe0f&zwj;\ud83c\udf08',
1917 'raised_back_of_hand':'\ud83e\udd1a',
1918 'raised_hand_with_fingers_splayed':'\ud83d\udd90',
1919 'raised_hands':'\ud83d\ude4c',
1920 'raising_hand_woman':'\ud83d\ude4b',
1921 'raising_hand_man':'\ud83d\ude4b&zwj;\u2642\ufe0f',
1922 'ram':'\ud83d\udc0f',
1923 'ramen':'\ud83c\udf5c',
1924 'rat':'\ud83d\udc00',
1925 'record_button':'\u23fa',
1926 'recycle':'\u267b\ufe0f',
1927 'red_circle':'\ud83d\udd34',
1928 'registered':'\u00ae\ufe0f',
1929 'relaxed':'\u263a\ufe0f',
1930 'relieved':'\ud83d\ude0c',
1931 'reminder_ribbon':'\ud83c\udf97',
1932 'repeat':'\ud83d\udd01',
1933 'repeat_one':'\ud83d\udd02',
1934 'rescue_worker_helmet':'\u26d1',
1935 'restroom':'\ud83d\udebb',
1936 'revolving_hearts':'\ud83d\udc9e',
1937 'rewind':'\u23ea',
1938 'rhinoceros':'\ud83e\udd8f',
1939 'ribbon':'\ud83c\udf80',
1940 'rice':'\ud83c\udf5a',
1941 'rice_ball':'\ud83c\udf59',
1942 'rice_cracker':'\ud83c\udf58',
1943 'rice_scene':'\ud83c\udf91',
1944 'right_anger_bubble':'\ud83d\uddef',
1945 'ring':'\ud83d\udc8d',
1946 'robot':'\ud83e\udd16',
1947 'rocket':'\ud83d\ude80',
1948 'rofl':'\ud83e\udd23',
1949 'roll_eyes':'\ud83d\ude44',
1950 'roller_coaster':'\ud83c\udfa2',
1951 'rooster':'\ud83d\udc13',
1952 'rose':'\ud83c\udf39',
1953 'rosette':'\ud83c\udff5',
1954 'rotating_light':'\ud83d\udea8',
1955 'round_pushpin':'\ud83d\udccd',
1956 'rowing_man':'\ud83d\udea3',
1957 'rowing_woman':'\ud83d\udea3&zwj;\u2640\ufe0f',
1958 'rugby_football':'\ud83c\udfc9',
1959 'running_man':'\ud83c\udfc3',
1960 'running_shirt_with_sash':'\ud83c\udfbd',
1961 'running_woman':'\ud83c\udfc3&zwj;\u2640\ufe0f',
1962 'sa':'\ud83c\ude02\ufe0f',
1963 'sagittarius':'\u2650\ufe0f',
1964 'sake':'\ud83c\udf76',
1965 'sandal':'\ud83d\udc61',
1966 'santa':'\ud83c\udf85',
1967 'satellite':'\ud83d\udce1',
1968 'saxophone':'\ud83c\udfb7',
1969 'school':'\ud83c\udfeb',
1970 'school_satchel':'\ud83c\udf92',
1971 'scissors':'\u2702\ufe0f',
1972 'scorpion':'\ud83e\udd82',
1973 'scorpius':'\u264f\ufe0f',
1974 'scream':'\ud83d\ude31',
1975 'scream_cat':'\ud83d\ude40',
1976 'scroll':'\ud83d\udcdc',
1977 'seat':'\ud83d\udcba',
1978 'secret':'\u3299\ufe0f',
1979 'see_no_evil':'\ud83d\ude48',
1980 'seedling':'\ud83c\udf31',
1981 'selfie':'\ud83e\udd33',
1982 'shallow_pan_of_food':'\ud83e\udd58',
1983 'shamrock':'\u2618\ufe0f',
1984 'shark':'\ud83e\udd88',
1985 'shaved_ice':'\ud83c\udf67',
1986 'sheep':'\ud83d\udc11',
1987 'shell':'\ud83d\udc1a',
1988 'shield':'\ud83d\udee1',
1989 'shinto_shrine':'\u26e9',
1990 'ship':'\ud83d\udea2',
1991 'shirt':'\ud83d\udc55',
1992 'shopping':'\ud83d\udecd',
1993 'shopping_cart':'\ud83d\uded2',
1994 'shower':'\ud83d\udebf',
1995 'shrimp':'\ud83e\udd90',
1996 'signal_strength':'\ud83d\udcf6',
1997 'six_pointed_star':'\ud83d\udd2f',
1998 'ski':'\ud83c\udfbf',
1999 'skier':'\u26f7',
2000 'skull':'\ud83d\udc80',
2001 'skull_and_crossbones':'\u2620\ufe0f',
2002 'sleeping':'\ud83d\ude34',
2003 'sleeping_bed':'\ud83d\udecc',
2004 'sleepy':'\ud83d\ude2a',
2005 'slightly_frowning_face':'\ud83d\ude41',
2006 'slightly_smiling_face':'\ud83d\ude42',
2007 'slot_machine':'\ud83c\udfb0',
2008 'small_airplane':'\ud83d\udee9',
2009 'small_blue_diamond':'\ud83d\udd39',
2010 'small_orange_diamond':'\ud83d\udd38',
2011 'small_red_triangle':'\ud83d\udd3a',
2012 'small_red_triangle_down':'\ud83d\udd3b',
2013 'smile':'\ud83d\ude04',
2014 'smile_cat':'\ud83d\ude38',
2015 'smiley':'\ud83d\ude03',
2016 'smiley_cat':'\ud83d\ude3a',
2017 'smiling_imp':'\ud83d\ude08',
2018 'smirk':'\ud83d\ude0f',
2019 'smirk_cat':'\ud83d\ude3c',
2020 'smoking':'\ud83d\udeac',
2021 'snail':'\ud83d\udc0c',
2022 'snake':'\ud83d\udc0d',
2023 'sneezing_face':'\ud83e\udd27',
2024 'snowboarder':'\ud83c\udfc2',
2025 'snowflake':'\u2744\ufe0f',
2026 'snowman':'\u26c4\ufe0f',
2027 'snowman_with_snow':'\u2603\ufe0f',
2028 'sob':'\ud83d\ude2d',
2029 'soccer':'\u26bd\ufe0f',
2030 'soon':'\ud83d\udd1c',
2031 'sos':'\ud83c\udd98',
2032 'sound':'\ud83d\udd09',
2033 'space_invader':'\ud83d\udc7e',
2034 'spades':'\u2660\ufe0f',
2035 'spaghetti':'\ud83c\udf5d',
2036 'sparkle':'\u2747\ufe0f',
2037 'sparkler':'\ud83c\udf87',
2038 'sparkles':'\u2728',
2039 'sparkling_heart':'\ud83d\udc96',
2040 'speak_no_evil':'\ud83d\ude4a',
2041 'speaker':'\ud83d\udd08',
2042 'speaking_head':'\ud83d\udde3',
2043 'speech_balloon':'\ud83d\udcac',
2044 'speedboat':'\ud83d\udea4',
2045 'spider':'\ud83d\udd77',
2046 'spider_web':'\ud83d\udd78',
2047 'spiral_calendar':'\ud83d\uddd3',
2048 'spiral_notepad':'\ud83d\uddd2',
2049 'spoon':'\ud83e\udd44',
2050 'squid':'\ud83e\udd91',
2051 'stadium':'\ud83c\udfdf',
2052 'star':'\u2b50\ufe0f',
2053 'star2':'\ud83c\udf1f',
2054 'star_and_crescent':'\u262a\ufe0f',
2055 'star_of_david':'\u2721\ufe0f',
2056 'stars':'\ud83c\udf20',
2057 'station':'\ud83d\ude89',
2058 'statue_of_liberty':'\ud83d\uddfd',
2059 'steam_locomotive':'\ud83d\ude82',
2060 'stew':'\ud83c\udf72',
2061 'stop_button':'\u23f9',
2062 'stop_sign':'\ud83d\uded1',
2063 'stopwatch':'\u23f1',
2064 'straight_ruler':'\ud83d\udccf',
2065 'strawberry':'\ud83c\udf53',
2066 'stuck_out_tongue':'\ud83d\ude1b',
2067 'stuck_out_tongue_closed_eyes':'\ud83d\ude1d',
2068 'stuck_out_tongue_winking_eye':'\ud83d\ude1c',
2069 'studio_microphone':'\ud83c\udf99',
2070 'stuffed_flatbread':'\ud83e\udd59',
2071 'sun_behind_large_cloud':'\ud83c\udf25',
2072 'sun_behind_rain_cloud':'\ud83c\udf26',
2073 'sun_behind_small_cloud':'\ud83c\udf24',
2074 'sun_with_face':'\ud83c\udf1e',
2075 'sunflower':'\ud83c\udf3b',
2076 'sunglasses':'\ud83d\ude0e',
2077 'sunny':'\u2600\ufe0f',
2078 'sunrise':'\ud83c\udf05',
2079 'sunrise_over_mountains':'\ud83c\udf04',
2080 'surfing_man':'\ud83c\udfc4',
2081 'surfing_woman':'\ud83c\udfc4&zwj;\u2640\ufe0f',
2082 'sushi':'\ud83c\udf63',
2083 'suspension_railway':'\ud83d\ude9f',
2084 'sweat':'\ud83d\ude13',
2085 'sweat_drops':'\ud83d\udca6',
2086 'sweat_smile':'\ud83d\ude05',
2087 'sweet_potato':'\ud83c\udf60',
2088 'swimming_man':'\ud83c\udfca',
2089 'swimming_woman':'\ud83c\udfca&zwj;\u2640\ufe0f',
2090 'symbols':'\ud83d\udd23',
2091 'synagogue':'\ud83d\udd4d',
2092 'syringe':'\ud83d\udc89',
2093 'taco':'\ud83c\udf2e',
2094 'tada':'\ud83c\udf89',
2095 'tanabata_tree':'\ud83c\udf8b',
2096 'taurus':'\u2649\ufe0f',
2097 'taxi':'\ud83d\ude95',
2098 'tea':'\ud83c\udf75',
2099 'telephone_receiver':'\ud83d\udcde',
2100 'telescope':'\ud83d\udd2d',
2101 'tennis':'\ud83c\udfbe',
2102 'tent':'\u26fa\ufe0f',
2103 'thermometer':'\ud83c\udf21',
2104 'thinking':'\ud83e\udd14',
2105 'thought_balloon':'\ud83d\udcad',
2106 'ticket':'\ud83c\udfab',
2107 'tickets':'\ud83c\udf9f',
2108 'tiger':'\ud83d\udc2f',
2109 'tiger2':'\ud83d\udc05',
2110 'timer_clock':'\u23f2',
2111 'tipping_hand_man':'\ud83d\udc81&zwj;\u2642\ufe0f',
2112 'tired_face':'\ud83d\ude2b',
2113 'tm':'\u2122\ufe0f',
2114 'toilet':'\ud83d\udebd',
2115 'tokyo_tower':'\ud83d\uddfc',
2116 'tomato':'\ud83c\udf45',
2117 'tongue':'\ud83d\udc45',
2118 'top':'\ud83d\udd1d',
2119 'tophat':'\ud83c\udfa9',
2120 'tornado':'\ud83c\udf2a',
2121 'trackball':'\ud83d\uddb2',
2122 'tractor':'\ud83d\ude9c',
2123 'traffic_light':'\ud83d\udea5',
2124 'train':'\ud83d\ude8b',
2125 'train2':'\ud83d\ude86',
2126 'tram':'\ud83d\ude8a',
2127 'triangular_flag_on_post':'\ud83d\udea9',
2128 'triangular_ruler':'\ud83d\udcd0',
2129 'trident':'\ud83d\udd31',
2130 'triumph':'\ud83d\ude24',
2131 'trolleybus':'\ud83d\ude8e',
2132 'trophy':'\ud83c\udfc6',
2133 'tropical_drink':'\ud83c\udf79',
2134 'tropical_fish':'\ud83d\udc20',
2135 'truck':'\ud83d\ude9a',
2136 'trumpet':'\ud83c\udfba',
2137 'tulip':'\ud83c\udf37',
2138 'tumbler_glass':'\ud83e\udd43',
2139 'turkey':'\ud83e\udd83',
2140 'turtle':'\ud83d\udc22',
2141 'tv':'\ud83d\udcfa',
2142 'twisted_rightwards_arrows':'\ud83d\udd00',
2143 'two_hearts':'\ud83d\udc95',
2144 'two_men_holding_hands':'\ud83d\udc6c',
2145 'two_women_holding_hands':'\ud83d\udc6d',
2146 'u5272':'\ud83c\ude39',
2147 'u5408':'\ud83c\ude34',
2148 'u55b6':'\ud83c\ude3a',
2149 'u6307':'\ud83c\ude2f\ufe0f',
2150 'u6708':'\ud83c\ude37\ufe0f',
2151 'u6709':'\ud83c\ude36',
2152 'u6e80':'\ud83c\ude35',
2153 'u7121':'\ud83c\ude1a\ufe0f',
2154 'u7533':'\ud83c\ude38',
2155 'u7981':'\ud83c\ude32',
2156 'u7a7a':'\ud83c\ude33',
2157 'umbrella':'\u2614\ufe0f',
2158 'unamused':'\ud83d\ude12',
2159 'underage':'\ud83d\udd1e',
2160 'unicorn':'\ud83e\udd84',
2161 'unlock':'\ud83d\udd13',
2162 'up':'\ud83c\udd99',
2163 'upside_down_face':'\ud83d\ude43',
2164 'v':'\u270c\ufe0f',
2165 'vertical_traffic_light':'\ud83d\udea6',
2166 'vhs':'\ud83d\udcfc',
2167 'vibration_mode':'\ud83d\udcf3',
2168 'video_camera':'\ud83d\udcf9',
2169 'video_game':'\ud83c\udfae',
2170 'violin':'\ud83c\udfbb',
2171 'virgo':'\u264d\ufe0f',
2172 'volcano':'\ud83c\udf0b',
2173 'volleyball':'\ud83c\udfd0',
2174 'vs':'\ud83c\udd9a',
2175 'vulcan_salute':'\ud83d\udd96',
2176 'walking_man':'\ud83d\udeb6',
2177 'walking_woman':'\ud83d\udeb6&zwj;\u2640\ufe0f',
2178 'waning_crescent_moon':'\ud83c\udf18',
2179 'waning_gibbous_moon':'\ud83c\udf16',
2180 'warning':'\u26a0\ufe0f',
2181 'wastebasket':'\ud83d\uddd1',
2182 'watch':'\u231a\ufe0f',
2183 'water_buffalo':'\ud83d\udc03',
2184 'watermelon':'\ud83c\udf49',
2185 'wave':'\ud83d\udc4b',
2186 'wavy_dash':'\u3030\ufe0f',
2187 'waxing_crescent_moon':'\ud83c\udf12',
2188 'wc':'\ud83d\udebe',
2189 'weary':'\ud83d\ude29',
2190 'wedding':'\ud83d\udc92',
2191 'weight_lifting_man':'\ud83c\udfcb\ufe0f',
2192 'weight_lifting_woman':'\ud83c\udfcb\ufe0f&zwj;\u2640\ufe0f',
2193 'whale':'\ud83d\udc33',
2194 'whale2':'\ud83d\udc0b',
2195 'wheel_of_dharma':'\u2638\ufe0f',
2196 'wheelchair':'\u267f\ufe0f',
2197 'white_check_mark':'\u2705',
2198 'white_circle':'\u26aa\ufe0f',
2199 'white_flag':'\ud83c\udff3\ufe0f',
2200 'white_flower':'\ud83d\udcae',
2201 'white_large_square':'\u2b1c\ufe0f',
2202 'white_medium_small_square':'\u25fd\ufe0f',
2203 'white_medium_square':'\u25fb\ufe0f',
2204 'white_small_square':'\u25ab\ufe0f',
2205 'white_square_button':'\ud83d\udd33',
2206 'wilted_flower':'\ud83e\udd40',
2207 'wind_chime':'\ud83c\udf90',
2208 'wind_face':'\ud83c\udf2c',
2209 'wine_glass':'\ud83c\udf77',
2210 'wink':'\ud83d\ude09',
2211 'wolf':'\ud83d\udc3a',
2212 'woman':'\ud83d\udc69',
2213 'woman_artist':'\ud83d\udc69&zwj;\ud83c\udfa8',
2214 'woman_astronaut':'\ud83d\udc69&zwj;\ud83d\ude80',
2215 'woman_cartwheeling':'\ud83e\udd38&zwj;\u2640\ufe0f',
2216 'woman_cook':'\ud83d\udc69&zwj;\ud83c\udf73',
2217 'woman_facepalming':'\ud83e\udd26&zwj;\u2640\ufe0f',
2218 'woman_factory_worker':'\ud83d\udc69&zwj;\ud83c\udfed',
2219 'woman_farmer':'\ud83d\udc69&zwj;\ud83c\udf3e',
2220 'woman_firefighter':'\ud83d\udc69&zwj;\ud83d\ude92',
2221 'woman_health_worker':'\ud83d\udc69&zwj;\u2695\ufe0f',
2222 'woman_judge':'\ud83d\udc69&zwj;\u2696\ufe0f',
2223 'woman_juggling':'\ud83e\udd39&zwj;\u2640\ufe0f',
2224 'woman_mechanic':'\ud83d\udc69&zwj;\ud83d\udd27',
2225 'woman_office_worker':'\ud83d\udc69&zwj;\ud83d\udcbc',
2226 'woman_pilot':'\ud83d\udc69&zwj;\u2708\ufe0f',
2227 'woman_playing_handball':'\ud83e\udd3e&zwj;\u2640\ufe0f',
2228 'woman_playing_water_polo':'\ud83e\udd3d&zwj;\u2640\ufe0f',
2229 'woman_scientist':'\ud83d\udc69&zwj;\ud83d\udd2c',
2230 'woman_shrugging':'\ud83e\udd37&zwj;\u2640\ufe0f',
2231 'woman_singer':'\ud83d\udc69&zwj;\ud83c\udfa4',
2232 'woman_student':'\ud83d\udc69&zwj;\ud83c\udf93',
2233 'woman_teacher':'\ud83d\udc69&zwj;\ud83c\udfeb',
2234 'woman_technologist':'\ud83d\udc69&zwj;\ud83d\udcbb',
2235 'woman_with_turban':'\ud83d\udc73&zwj;\u2640\ufe0f',
2236 'womans_clothes':'\ud83d\udc5a',
2237 'womans_hat':'\ud83d\udc52',
2238 'women_wrestling':'\ud83e\udd3c&zwj;\u2640\ufe0f',
2239 'womens':'\ud83d\udeba',
2240 'world_map':'\ud83d\uddfa',
2241 'worried':'\ud83d\ude1f',
2242 'wrench':'\ud83d\udd27',
2243 'writing_hand':'\u270d\ufe0f',
2244 'x':'\u274c',
2245 'yellow_heart':'\ud83d\udc9b',
2246 'yen':'\ud83d\udcb4',
2247 'yin_yang':'\u262f\ufe0f',
2248 'yum':'\ud83d\ude0b',
2249 'zap':'\u26a1\ufe0f',
2250 'zipper_mouth_face':'\ud83e\udd10',
2251 'zzz':'\ud83d\udca4',
2252
2253 /* special emojis :P */
2254 /* 'octocat': '<img width="20" height="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">',*/
2255 'showdown': '<img width="20" height="20" align="absmiddle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAS1BMVEX///8jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS3b1q3b1q3b1q3b1q3b1q3b1q3b1q3b1q0565CIAAAAGXRSTlMAQHCAYCCw/+DQwPCQUBAwoHCAEP+wwFBgS2fvBgAAAUZJREFUeAHs1cGy7BAUheFFsEDw/k97VTq3T6ge2EmdM+pvrP6Iwd74XV9Kb52xuMU4/uc1YNgZLFOeV8FGdhGrNk5SEgUyPxAEdj4LlMRDyhVAMVEa2M7TBSeVZAFPdqHgzSZJwPKgcLFLAooHDJo4EDCw4gAtBoJA5UFj4Ng5LOGLwVXZuoIlji/jeQHFk7+baHxrCjeUwB9+s88KndvlhcyBN5BSkYNQIVVb4pV+Npm7hhuKDs/uMP5KxT3WzSNNLIuuoDpMmuAVMruMSeDyQBi24DTr43LAY7ILA1QYaWkgfHzFthYYzg67SQsCbB8GhJUEGCtO9n0rSaCLxgJQjS/JSgMTg2eBDEHAJ+H350AsjYNYscrErgI2e/l+mdR967TCX/v6N0EhPECYCP0i+IAoYQOE8BogNhQMEMdrgAQWHaMAAGi5I5euoY9NAAAAAElFTkSuQmCC">'
2256 };
2257
2258 /**
2259 * These are all the transformations that form block-level
2260 * tags like paragraphs, headers, and list items.
2261 */
2262 showdown.subParser('makehtml.blockGamut', function (text, options, globals) {
2263 'use strict';
2264
2265 text = globals.converter._dispatch('makehtml.blockGamut.before', text, options, globals).getText();
2266
2267 // we parse blockquotes first so that we can have headings and hrs
2268 // inside blockquotes
2269 text = showdown.subParser('makehtml.blockQuotes')(text, options, globals);
2270 text = showdown.subParser('makehtml.headers')(text, options, globals);
2271
2272 // Do Horizontal Rules:
2273 text = showdown.subParser('makehtml.horizontalRule')(text, options, globals);
2274
2275 text = showdown.subParser('makehtml.lists')(text, options, globals);
2276 text = showdown.subParser('makehtml.codeBlocks')(text, options, globals);
2277 text = showdown.subParser('makehtml.tables')(text, options, globals);
2278
2279 // We already ran _HashHTMLBlocks() before, in Markdown(), but that
2280 // was to escape raw HTML in the original Markdown source. This time,
2281 // we're escaping the markup we've just created, so that we don't wrap
2282 // <p> tags around block-level tags.
2283 text = showdown.subParser('makehtml.hashHTMLBlocks')(text, options, globals);
2284 text = showdown.subParser('makehtml.paragraphs')(text, options, globals);
2285
2286 text = globals.converter._dispatch('makehtml.blockGamut.after', text, options, globals).getText();
2287
2288 return text;
2289 });
2290
2291 showdown.subParser('makehtml.blockQuotes', function (text, options, globals) {
2292 'use strict';
2293
2294 text = globals.converter._dispatch('makehtml.blockQuotes.before', text, options, globals).getText();
2295
2296 // add a couple extra lines after the text and endtext mark
2297 text = text + '\n\n';
2298
2299 var rgx = /(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;
2300
2301 if (options.splitAdjacentBlockquotes) {
2302 rgx = /^ {0,3}>[\s\S]*?(?:\n\n)/gm;
2303 }
2304
2305 text = text.replace(rgx, function (bq) {
2306 // attacklab: hack around Konqueror 3.5.4 bug:
2307 // "----------bug".replace(/^-/g,"") == "bug"
2308 bq = bq.replace(/^[ \t]*>[ \t]?/gm, ''); // trim one level of quoting
2309
2310 // attacklab: clean up hack
2311 bq = bq.replace(/¨0/g, '');
2312
2313 bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
2314 bq = showdown.subParser('makehtml.githubCodeBlocks')(bq, options, globals);
2315 bq = showdown.subParser('makehtml.blockGamut')(bq, options, globals); // recurse
2316
2317 bq = bq.replace(/(^|\n)/g, '$1 ');
2318 // These leading spaces screw with <pre> content, so we need to fix that:
2319 bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
2320 var pre = m1;
2321 // attacklab: hack around Konqueror 3.5.4 bug:
2322 pre = pre.replace(/^ /mg, '¨0');
2323 pre = pre.replace(/¨0/g, '');
2324 return pre;
2325 });
2326
2327 return showdown.subParser('makehtml.hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
2328 });
2329
2330 text = globals.converter._dispatch('makehtml.blockQuotes.after', text, options, globals).getText();
2331 return text;
2332 });
2333
2334 /**
2335 * Process Markdown `<pre><code>` blocks.
2336 */
2337 showdown.subParser('makehtml.codeBlocks', function (text, options, globals) {
2338 'use strict';
2339
2340 text = globals.converter._dispatch('makehtml.codeBlocks.before', text, options, globals).getText();
2341
2342 // sentinel workarounds for lack of \A and \Z, safari\khtml bug
2343 text += '¨0';
2344
2345 var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g;
2346 text = text.replace(pattern, function (wholeMatch, m1, m2) {
2347 var codeblock = m1,
2348 nextChar = m2,
2349 end = '\n';
2350
2351 codeblock = showdown.subParser('makehtml.outdent')(codeblock, options, globals);
2352 codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals);
2353 codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals);
2354 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
2355 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
2356
2357 if (options.omitExtraWLInCodeBlocks) {
2358 end = '';
2359 }
2360
2361 codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
2362
2363 return showdown.subParser('makehtml.hashBlock')(codeblock, options, globals) + nextChar;
2364 });
2365
2366 // strip sentinel
2367 text = text.replace(/¨0/, '');
2368
2369 text = globals.converter._dispatch('makehtml.codeBlocks.after', text, options, globals).getText();
2370 return text;
2371 });
2372
2373 /**
2374 *
2375 * * Backtick quotes are used for <code></code> spans.
2376 *
2377 * * You can use multiple backticks as the delimiters if you want to
2378 * include literal backticks in the code span. So, this input:
2379 *
2380 * Just type ``foo `bar` baz`` at the prompt.
2381 *
2382 * Will translate to:
2383 *
2384 * <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
2385 *
2386 * There's no arbitrary limit to the number of backticks you
2387 * can use as delimters. If you need three consecutive backticks
2388 * in your code, use four for delimiters, etc.
2389 *
2390 * * You can use spaces to get literal backticks at the edges:
2391 *
2392 * ... type `` `bar` `` ...
2393 *
2394 * Turns to:
2395 *
2396 * ... type <code>`bar`</code> ...
2397 */
2398 showdown.subParser('makehtml.codeSpans', function (text, options, globals) {
2399 'use strict';
2400
2401 text = globals.converter._dispatch('makehtml.codeSpans.before', text, options, globals).getText();
2402
2403 if (typeof(text) === 'undefined') {
2404 text = '';
2405 }
2406 text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
2407 function (wholeMatch, m1, m2, m3) {
2408 var c = m3;
2409 c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
2410 c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
2411 c = showdown.subParser('makehtml.encodeCode')(c, options, globals);
2412 c = m1 + '<code>' + c + '</code>';
2413 c = showdown.subParser('makehtml.hashHTMLSpans')(c, options, globals);
2414 return c;
2415 }
2416 );
2417
2418 text = globals.converter._dispatch('makehtml.codeSpans.after', text, options, globals).getText();
2419 return text;
2420 });
2421
2422 /**
2423 * Create a full HTML document from the processed markdown
2424 */
2425 showdown.subParser('makehtml.completeHTMLDocument', function (text, options, globals) {
2426 'use strict';
2427
2428 if (!options.completeHTMLDocument) {
2429 return text;
2430 }
2431
2432 text = globals.converter._dispatch('makehtml.completeHTMLDocument.before', text, options, globals).getText();
2433
2434 var doctype = 'html',
2435 doctypeParsed = '<!DOCTYPE HTML>\n',
2436 title = '',
2437 charset = '<meta charset="utf-8">\n',
2438 lang = '',
2439 metadata = '';
2440
2441 if (typeof globals.metadata.parsed.doctype !== 'undefined') {
2442 doctypeParsed = '<!DOCTYPE ' + globals.metadata.parsed.doctype + '>\n';
2443 doctype = globals.metadata.parsed.doctype.toString().toLowerCase();
2444 if (doctype === 'html' || doctype === 'html5') {
2445 charset = '<meta charset="utf-8">';
2446 }
2447 }
2448
2449 for (var meta in globals.metadata.parsed) {
2450 if (globals.metadata.parsed.hasOwnProperty(meta)) {
2451 switch (meta.toLowerCase()) {
2452 case 'doctype':
2453 break;
2454
2455 case 'title':
2456 title = '<title>' + globals.metadata.parsed.title + '</title>\n';
2457 break;
2458
2459 case 'charset':
2460 if (doctype === 'html' || doctype === 'html5') {
2461 charset = '<meta charset="' + globals.metadata.parsed.charset + '">\n';
2462 } else {
2463 charset = '<meta name="charset" content="' + globals.metadata.parsed.charset + '">\n';
2464 }
2465 break;
2466
2467 case 'language':
2468 case 'lang':
2469 lang = ' lang="' + globals.metadata.parsed[meta] + '"';
2470 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
2471 break;
2472
2473 default:
2474 metadata += '<meta name="' + meta + '" content="' + globals.metadata.parsed[meta] + '">\n';
2475 }
2476 }
2477 }
2478
2479 text = doctypeParsed + '<html' + lang + '>\n<head>\n' + title + charset + metadata + '</head>\n<body>\n' + text.trim() + '\n</body>\n</html>';
2480
2481 text = globals.converter._dispatch('makehtml.completeHTMLDocument.after', text, options, globals).getText();
2482 return text;
2483 });
2484
2485 /**
2486 * Convert all tabs to spaces
2487 */
2488 showdown.subParser('makehtml.detab', function (text, options, globals) {
2489 'use strict';
2490 text = globals.converter._dispatch('makehtml.detab.before', text, options, globals).getText();
2491
2492 // expand first n-1 tabs
2493 text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width
2494
2495 // replace the nth with two sentinels
2496 text = text.replace(/\t/g, '¨A¨B');
2497
2498 // use the sentinel to anchor our regex so it doesn't explode
2499 text = text.replace(/¨B(.+?)¨A/g, function (wholeMatch, m1) {
2500 var leadingText = m1,
2501 numSpaces = 4 - leadingText.length % 4; // g_tab_width
2502
2503 // there *must* be a better way to do this:
2504 for (var i = 0; i < numSpaces; i++) {
2505 leadingText += ' ';
2506 }
2507
2508 return leadingText;
2509 });
2510
2511 // clean up sentinels
2512 text = text.replace(/¨A/g, ' '); // g_tab_width
2513 text = text.replace(/¨B/g, '');
2514
2515 text = globals.converter._dispatch('makehtml.detab.after', text, options, globals).getText();
2516 return text;
2517 });
2518
2519 showdown.subParser('makehtml.ellipsis', function (text, options, globals) {
2520 'use strict';
2521
2522 text = globals.converter._dispatch('makehtml.ellipsis.before', text, options, globals).getText();
2523
2524 text = text.replace(/\.\.\./g, '…');
2525
2526 text = globals.converter._dispatch('makehtml.ellipsis.after', text, options, globals).getText();
2527
2528 return text;
2529 });
2530
2531 /**
2532 * These are all the transformations that occur *within* block-level
2533 * tags like paragraphs, headers, and list items.
2534 */
2535 showdown.subParser('makehtml.emoji', function (text, options, globals) {
2536 'use strict';
2537
2538 if (!options.emoji) {
2539 return text;
2540 }
2541
2542 text = globals.converter._dispatch('makehtml.emoji.before', text, options, globals).getText();
2543
2544 var emojiRgx = /:([\S]+?):/g;
2545
2546 text = text.replace(emojiRgx, function (wm, emojiCode) {
2547 if (showdown.helper.emojis.hasOwnProperty(emojiCode)) {
2548 return showdown.helper.emojis[emojiCode];
2549 }
2550 return wm;
2551 });
2552
2553 text = globals.converter._dispatch('makehtml.emoji.after', text, options, globals).getText();
2554
2555 return text;
2556 });
2557
2558 /**
2559 * Smart processing for ampersands and angle brackets that need to be encoded.
2560 */
2561 showdown.subParser('makehtml.encodeAmpsAndAngles', function (text, options, globals) {
2562 'use strict';
2563 text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.before', text, options, globals).getText();
2564
2565 // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
2566 // http://bumppo.net/projects/amputator/
2567 text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
2568
2569 // Encode naked <'s
2570 text = text.replace(/<(?![a-z\/?$!])/gi, '&lt;');
2571
2572 // Encode <
2573 text = text.replace(/</g, '&lt;');
2574
2575 // Encode >
2576 text = text.replace(/>/g, '&gt;');
2577
2578 text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.after', text, options, globals).getText();
2579 return text;
2580 });
2581
2582 /**
2583 * Returns the string, with after processing the following backslash escape sequences.
2584 *
2585 * attacklab: The polite way to do this is with the new escapeCharacters() function:
2586 *
2587 * text = escapeCharacters(text,"\\",true);
2588 * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
2589 *
2590 * ...but we're sidestepping its use of the (slow) RegExp constructor
2591 * as an optimization for Firefox. This function gets called a LOT.
2592 */
2593 showdown.subParser('makehtml.encodeBackslashEscapes', function (text, options, globals) {
2594 'use strict';
2595 text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.before', text, options, globals).getText();
2596
2597 text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
2598 text = text.replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g, showdown.helper.escapeCharactersCallback);
2599
2600 text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.after', text, options, globals).getText();
2601 return text;
2602 });
2603
2604 /**
2605 * Encode/escape certain characters inside Markdown code runs.
2606 * The point is that in code, these characters are literals,
2607 * and lose their special Markdown meanings.
2608 */
2609 showdown.subParser('makehtml.encodeCode', function (text, options, globals) {
2610 'use strict';
2611
2612 text = globals.converter._dispatch('makehtml.encodeCode.before', text, options, globals).getText();
2613
2614 // Encode all ampersands; HTML entities are not
2615 // entities within a Markdown code span.
2616 text = text
2617 .replace(/&/g, '&amp;')
2618 // Do the angle bracket song and dance:
2619 .replace(/</g, '&lt;')
2620 .replace(/>/g, '&gt;')
2621 // Now, escape characters that are magic in Markdown:
2622 .replace(/([*_{}\[\]\\=~-])/g, showdown.helper.escapeCharactersCallback);
2623
2624 text = globals.converter._dispatch('makehtml.encodeCode.after', text, options, globals).getText();
2625 return text;
2626 });
2627
2628 /**
2629 * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they
2630 * don't conflict with their use in Markdown for code, italics and strong.
2631 */
2632 showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes', function (text, options, globals) {
2633 'use strict';
2634 text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.before', text, options, globals).getText();
2635
2636 // Build a regex to find HTML tags.
2637 var tags = /<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,
2638 comments = /<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi;
2639
2640 text = text.replace(tags, function (wholeMatch) {
2641 return wholeMatch
2642 .replace(/(.)<\/?code>(?=.)/g, '$1`')
2643 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
2644 });
2645
2646 text = text.replace(comments, function (wholeMatch) {
2647 return wholeMatch
2648 .replace(/([\\`*_~=|])/g, showdown.helper.escapeCharactersCallback);
2649 });
2650
2651 text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.after', text, options, globals).getText();
2652 return text;
2653 });
2654
2655 /**
2656 * Handle github codeblocks prior to running HashHTML so that
2657 * HTML contained within the codeblock gets escaped properly
2658 * Example:
2659 * ```ruby
2660 * def hello_world(x)
2661 * puts "Hello, #{x}"
2662 * end
2663 * ```
2664 */
2665 showdown.subParser('makehtml.githubCodeBlocks', function (text, options, globals) {
2666 'use strict';
2667
2668 // early exit if option is not enabled
2669 if (!options.ghCodeBlocks) {
2670 return text;
2671 }
2672
2673 text = globals.converter._dispatch('makehtml.githubCodeBlocks.before', text, options, globals).getText();
2674
2675 text += '¨0';
2676
2677 text = text.replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g, function (wholeMatch, delim, language, codeblock) {
2678 var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
2679
2680 // First parse the github code block
2681 codeblock = showdown.subParser('makehtml.encodeCode')(codeblock, options, globals);
2682 codeblock = showdown.subParser('makehtml.detab')(codeblock, options, globals);
2683 codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
2684 codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
2685
2686 codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
2687
2688 codeblock = showdown.subParser('makehtml.hashBlock')(codeblock, options, globals);
2689
2690 // Since GHCodeblocks can be false positives, we need to
2691 // store the primitive text and the parsed text in a global var,
2692 // and then return a token
2693 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
2694 });
2695
2696 // attacklab: strip sentinel
2697 text = text.replace(/¨0/, '');
2698
2699 return globals.converter._dispatch('makehtml.githubCodeBlocks.after', text, options, globals).getText();
2700 });
2701
2702 showdown.subParser('makehtml.hashBlock', function (text, options, globals) {
2703 'use strict';
2704 text = globals.converter._dispatch('makehtml.hashBlock.before', text, options, globals).getText();
2705 text = text.replace(/(^\n+|\n+$)/g, '');
2706 text = '\n\n¨K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
2707 text = globals.converter._dispatch('makehtml.hashBlock.after', text, options, globals).getText();
2708 return text;
2709 });
2710
2711 /**
2712 * Hash and escape <code> elements that should not be parsed as markdown
2713 */
2714 showdown.subParser('makehtml.hashCodeTags', function (text, options, globals) {
2715 'use strict';
2716 text = globals.converter._dispatch('makehtml.hashCodeTags.before', text, options, globals).getText();
2717
2718 var repFunc = function (wholeMatch, match, left, right) {
2719 var codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right;
2720 return '¨C' + (globals.gHtmlSpans.push(codeblock) - 1) + 'C';
2721 };
2722
2723 // Hash naked <code>
2724 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '<code\\b[^>]*>', '</code>', 'gim');
2725
2726 text = globals.converter._dispatch('makehtml.hashCodeTags.after', text, options, globals).getText();
2727 return text;
2728 });
2729
2730 showdown.subParser('makehtml.hashElement', function (text, options, globals) {
2731 'use strict';
2732
2733 return function (wholeMatch, m1) {
2734 var blockText = m1;
2735
2736 // Undo double lines
2737 blockText = blockText.replace(/\n\n/g, '\n');
2738 blockText = blockText.replace(/^\n/, '');
2739
2740 // strip trailing blank lines
2741 blockText = blockText.replace(/\n+$/g, '');
2742
2743 // Replace the element text with a marker ("¨KxK" where x is its key)
2744 blockText = '\n\n¨K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
2745
2746 return blockText;
2747 };
2748 });
2749
2750 showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) {
2751 'use strict';
2752 text = globals.converter._dispatch('makehtml.hashHTMLBlocks.before', text, options, globals).getText();
2753
2754 var blockTags = [
2755 'pre',
2756 'div',
2757 'h1',
2758 'h2',
2759 'h3',
2760 'h4',
2761 'h5',
2762 'h6',
2763 'blockquote',
2764 'table',
2765 'dl',
2766 'ol',
2767 'ul',
2768 'script',
2769 'noscript',
2770 'form',
2771 'fieldset',
2772 'iframe',
2773 'math',
2774 'style',
2775 'section',
2776 'header',
2777 'footer',
2778 'nav',
2779 'article',
2780 'aside',
2781 'address',
2782 'audio',
2783 'canvas',
2784 'figure',
2785 'hgroup',
2786 'output',
2787 'video',
2788 'p'
2789 ],
2790 repFunc = function (wholeMatch, match, left, right) {
2791 var txt = wholeMatch;
2792 // check if this html element is marked as markdown
2793 // if so, it's contents should be parsed as markdown
2794 if (left.search(/\bmarkdown\b/) !== -1) {
2795 txt = left + globals.converter.makeHtml(match) + right;
2796 }
2797 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
2798 };
2799
2800 if (options.backslashEscapesHTMLTags) {
2801 // encode backslash escaped HTML tags
2802 text = text.replace(/\\<(\/?[^>]+?)>/g, function (wm, inside) {
2803 return '&lt;' + inside + '&gt;';
2804 });
2805 }
2806
2807 // hash HTML Blocks
2808 for (var i = 0; i < blockTags.length; ++i) {
2809
2810 var opTagPos,
2811 rgx1 = new RegExp('^ {0,3}(<' + blockTags[i] + '\\b[^>]*>)', 'im'),
2812 patLeft = '<' + blockTags[i] + '\\b[^>]*>',
2813 patRight = '</' + blockTags[i] + '>';
2814 // 1. Look for the first position of the first opening HTML tag in the text
2815 while ((opTagPos = showdown.helper.regexIndexOf(text, rgx1)) !== -1) {
2816
2817 // if the HTML tag is \ escaped, we need to escape it and break
2818
2819
2820 //2. Split the text in that position
2821 var subTexts = showdown.helper.splitAtIndex(text, opTagPos),
2822 //3. Match recursively
2823 newSubText1 = showdown.helper.replaceRecursiveRegExp(subTexts[1], repFunc, patLeft, patRight, 'im');
2824
2825 // prevent an infinite loop
2826 if (newSubText1 === subTexts[1]) {
2827 break;
2828 }
2829 text = subTexts[0].concat(newSubText1);
2830 }
2831 }
2832 // HR SPECIAL CASE
2833 text = text.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
2834 showdown.subParser('makehtml.hashElement')(text, options, globals));
2835
2836 // Special case for standalone HTML comments
2837 text = showdown.helper.replaceRecursiveRegExp(text, function (txt) {
2838 return '\n\n¨K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
2839 }, '^ {0,3}<!--', '-->', 'gm');
2840
2841 // PHP and ASP-style processor instructions (<?...?> and <%...%>)
2842 text = text.replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
2843 showdown.subParser('makehtml.hashElement')(text, options, globals));
2844
2845 text = globals.converter._dispatch('makehtml.hashHTMLBlocks.after', text, options, globals).getText();
2846 return text;
2847 });
2848
2849 /**
2850 * Hash span elements that should not be parsed as markdown
2851 */
2852 showdown.subParser('makehtml.hashHTMLSpans', function (text, options, globals) {
2853 'use strict';
2854 text = globals.converter._dispatch('makehtml.hashHTMLSpans.before', text, options, globals).getText();
2855
2856 // Hash Self Closing tags
2857 text = text.replace(/<[^>]+?\/>/gi, function (wm) {
2858 return showdown.helper._hashHTMLSpan(wm, globals);
2859 });
2860
2861 // Hash tags without properties
2862 text = text.replace(/<([^>]+?)>[\s\S]*?<\/\1>/g, function (wm) {
2863 return showdown.helper._hashHTMLSpan(wm, globals);
2864 });
2865
2866 // Hash tags with properties
2867 text = text.replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g, function (wm) {
2868 return showdown.helper._hashHTMLSpan(wm, globals);
2869 });
2870
2871 // Hash self closing tags without />
2872 text = text.replace(/<[^>]+?>/gi, function (wm) {
2873 return showdown.helper._hashHTMLSpan(wm, globals);
2874 });
2875
2876 text = globals.converter._dispatch('makehtml.hashHTMLSpans.after', text, options, globals).getText();
2877 return text;
2878 });
2879
2880 /**
2881 * Unhash HTML spans
2882 */
2883 showdown.subParser('makehtml.unhashHTMLSpans', function (text, options, globals) {
2884 'use strict';
2885 text = globals.converter._dispatch('makehtml.unhashHTMLSpans.before', text, options, globals).getText();
2886
2887 for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
2888 var repText = globals.gHtmlSpans[i],
2889 // limiter to prevent infinite loop (assume 10 as limit for recurse)
2890 limit = 0;
2891
2892 while (/¨C(\d+)C/.test(repText)) {
2893 var num = RegExp.$1;
2894 repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
2895 if (limit === 10) {
2896 console.error('maximum nesting of 10 spans reached!!!');
2897 break;
2898 }
2899 ++limit;
2900 }
2901 text = text.replace('¨C' + i + 'C', repText);
2902 }
2903
2904 text = globals.converter._dispatch('makehtml.unhashHTMLSpans.after', text, options, globals).getText();
2905 return text;
2906 });
2907
2908 /**
2909 * Hash and escape <pre><code> elements that should not be parsed as markdown
2910 */
2911 showdown.subParser('makehtml.hashPreCodeTags', function (text, options, globals) {
2912 'use strict';
2913 text = globals.converter._dispatch('makehtml.hashPreCodeTags.before', text, options, globals).getText();
2914
2915 var repFunc = function (wholeMatch, match, left, right) {
2916 // encode html entities
2917 var codeblock = left + showdown.subParser('makehtml.encodeCode')(match, options, globals) + right;
2918 return '\n\n¨G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
2919 };
2920
2921 // Hash <pre><code>
2922 text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^ {0,3}</code>\\s*</pre>', 'gim');
2923
2924 text = globals.converter._dispatch('makehtml.hashPreCodeTags.after', text, options, globals).getText();
2925 return text;
2926 });
2927
2928 showdown.subParser('makehtml.headers', function (text, options, globals) {
2929 'use strict';
2930
2931 text = globals.converter._dispatch('makehtml.headers.before', text, options, globals).getText();
2932
2933 var headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
2934
2935 // Set text-style headers:
2936 // Header 1
2937 // ========
2938 //
2939 // Header 2
2940 // --------
2941 //
2942 setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
2943 setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
2944
2945 text = text.replace(setextRegexH1, function (wholeMatch, m1) {
2946
2947 var spanGamut = showdown.subParser('makehtml.spanGamut')(m1, options, globals),
2948 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
2949 hLevel = headerLevelStart,
2950 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
2951 return showdown.subParser('makehtml.hashBlock')(hashBlock, options, globals);
2952 });
2953
2954 text = text.replace(setextRegexH2, function (matchFound, m1) {
2955 var spanGamut = showdown.subParser('makehtml.spanGamut')(m1, options, globals),
2956 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
2957 hLevel = headerLevelStart + 1,
2958 hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
2959 return showdown.subParser('makehtml.hashBlock')(hashBlock, options, globals);
2960 });
2961
2962 // atx-style headers:
2963 // # Header 1
2964 // ## Header 2
2965 // ## Header 2 with closing hashes ##
2966 // ...
2967 // ###### Header 6
2968 //
2969 var atxStyle = (options.requireSpaceBeforeHeadingText) ? /^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm : /^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;
2970
2971 text = text.replace(atxStyle, function (wholeMatch, m1, m2) {
2972 var hText = m2;
2973 if (options.customizedHeaderId) {
2974 hText = m2.replace(/\s?\{([^{]+?)}\s*$/, '');
2975 }
2976
2977 var span = showdown.subParser('makehtml.spanGamut')(hText, options, globals),
2978 hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
2979 hLevel = headerLevelStart - 1 + m1.length,
2980 header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
2981
2982 return showdown.subParser('makehtml.hashBlock')(header, options, globals);
2983 });
2984
2985 function headerId (m) {
2986 var title,
2987 prefix;
2988
2989 // It is separate from other options to allow combining prefix and customized
2990 if (options.customizedHeaderId) {
2991 var match = m.match(/\{([^{]+?)}\s*$/);
2992 if (match && match[1]) {
2993 m = match[1];
2994 }
2995 }
2996
2997 title = m;
2998
2999 // Prefix id to prevent causing inadvertent pre-existing style matches.
3000 if (showdown.helper.isString(options.prefixHeaderId)) {
3001 prefix = options.prefixHeaderId;
3002 } else if (options.prefixHeaderId === true) {
3003 prefix = 'section-';
3004 } else {
3005 prefix = '';
3006 }
3007
3008 if (!options.rawPrefixHeaderId) {
3009 title = prefix + title;
3010 }
3011
3012 if (options.ghCompatibleHeaderId) {
3013 title = title
3014 .replace(/ /g, '-')
3015 // replace previously escaped chars (&, ¨ and $)
3016 .replace(/&amp;/g, '')
3017 .replace(/¨T/g, '')
3018 .replace(/¨D/g, '')
3019 // replace rest of the chars (&~$ are repeated as they might have been escaped)
3020 // borrowed from github's redcarpet (some they should produce similar results)
3021 .replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g, '')
3022 .toLowerCase();
3023 } else if (options.rawHeaderId) {
3024 title = title
3025 .replace(/ /g, '-')
3026 // replace previously escaped chars (&, ¨ and $)
3027 .replace(/&amp;/g, '&')
3028 .replace(/¨T/g, '¨')
3029 .replace(/¨D/g, '$')
3030 // replace " and '
3031 .replace(/["']/g, '-')
3032 .toLowerCase();
3033 } else {
3034 title = title
3035 .replace(/[^\w]/g, '')
3036 .toLowerCase();
3037 }
3038
3039 if (options.rawPrefixHeaderId) {
3040 title = prefix + title;
3041 }
3042
3043 if (globals.hashLinkCounts[title]) {
3044 title = title + '-' + (globals.hashLinkCounts[title]++);
3045 } else {
3046 globals.hashLinkCounts[title] = 1;
3047 }
3048 return title;
3049 }
3050
3051 text = globals.converter._dispatch('makehtml.headers.after', text, options, globals).getText();
3052 return text;
3053 });
3054
3055 /**
3056 * Turn Markdown horizontal rule shortcuts into <hr /> tags.
3057 *
3058 * Any 3 or more unindented consecutive hyphens, asterisks or underscores with or without a space beetween them
3059 * in a single line is considered a horizontal rule
3060 */
3061 showdown.subParser('makehtml.horizontalRule', function (text, options, globals) {
3062 'use strict';
3063 text = globals.converter._dispatch('makehtml.horizontalRule.before', text, options, globals).getText();
3064
3065 var key = showdown.subParser('makehtml.hashBlock')('<hr />', options, globals);
3066 text = text.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm, key);
3067 text = text.replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm, key);
3068 text = text.replace(/^ {0,2}( ?_){3,}[ \t]*$/gm, key);
3069
3070 text = globals.converter._dispatch('makehtml.horizontalRule.after', text, options, globals).getText();
3071 return text;
3072 });
3073
3074 /**
3075 * Turn Markdown image shortcuts into <img> tags.
3076 */
3077 showdown.subParser('makehtml.images', function (text, options, globals) {
3078 'use strict';
3079
3080 text = globals.converter._dispatch('makehtml.images.before', text, options, globals).getText();
3081
3082 var inlineRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
3083 crazyRegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,
3084 base64RegExp = /!\[([^\]]*?)][ \t]*()\([ \t]?<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,
3085 referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,
3086 refShortcutRegExp = /!\[([^\[\]]+)]()()()()()/g;
3087
3088 function writeImageTagBase64 (wholeMatch, altText, linkId, url, width, height, m5, title) {
3089 url = url.replace(/\s/g, '');
3090 return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
3091 }
3092
3093 function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
3094
3095 var gUrls = globals.gUrls,
3096 gTitles = globals.gTitles,
3097 gDims = globals.gDimensions;
3098
3099 linkId = linkId.toLowerCase();
3100
3101 if (!title) {
3102 title = '';
3103 }
3104 // Special case for explicit empty url
3105 if (wholeMatch.search(/\(<?\s*>? ?(['"].*['"])?\)$/m) > -1) {
3106 url = '';
3107
3108 } else if (url === '' || url === null) {
3109 if (linkId === '' || linkId === null) {
3110 // lower-case and turn embedded newlines into spaces
3111 linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
3112 }
3113 url = '#' + linkId;
3114
3115 if (!showdown.helper.isUndefined(gUrls[linkId])) {
3116 url = gUrls[linkId];
3117 if (!showdown.helper.isUndefined(gTitles[linkId])) {
3118 title = gTitles[linkId];
3119 }
3120 if (!showdown.helper.isUndefined(gDims[linkId])) {
3121 width = gDims[linkId].width;
3122 height = gDims[linkId].height;
3123 }
3124 } else {
3125 return wholeMatch;
3126 }
3127 }
3128
3129 altText = altText
3130 .replace(/"/g, '&quot;')
3131 //altText = showdown.helper.escapeCharacters(altText, '*_', false);
3132 .replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
3133 //url = showdown.helper.escapeCharacters(url, '*_', false);
3134 url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
3135 var result = '<img src="' + url + '" alt="' + altText + '"';
3136
3137 if (title && showdown.helper.isString(title)) {
3138 title = title
3139 .replace(/"/g, '&quot;')
3140 //title = showdown.helper.escapeCharacters(title, '*_', false);
3141 .replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
3142 result += ' title="' + title + '"';
3143 }
3144
3145 if (width && height) {
3146 width = (width === '*') ? 'auto' : width;
3147 height = (height === '*') ? 'auto' : height;
3148
3149 result += ' width="' + width + '"';
3150 result += ' height="' + height + '"';
3151 }
3152
3153 result += ' />';
3154
3155 return result;
3156 }
3157
3158 // First, handle reference-style labeled images: ![alt text][id]
3159 text = text.replace(referenceRegExp, writeImageTag);
3160
3161 // Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
3162
3163 // base64 encoded images
3164 text = text.replace(base64RegExp, writeImageTagBase64);
3165
3166 // cases with crazy urls like ./image/cat1).png
3167 text = text.replace(crazyRegExp, writeImageTag);
3168
3169 // normal cases
3170 text = text.replace(inlineRegExp, writeImageTag);
3171
3172 // handle reference-style shortcuts: ![img text]
3173 text = text.replace(refShortcutRegExp, writeImageTag);
3174
3175 text = globals.converter._dispatch('makehtml.images.after', text, options, globals).getText();
3176 return text;
3177 });
3178
3179 showdown.subParser('makehtml.italicsAndBold', function (text, options, globals) {
3180 'use strict';
3181
3182 text = globals.converter._dispatch('makehtml.italicsAndBold.before', text, options, globals).getText();
3183
3184 // it's faster to have 3 separate regexes for each case than have just one
3185 // because of backtracing, in some cases, it could lead to an exponential effect
3186 // called "catastrophic backtrace". Ominous!
3187
3188 function parseInside (txt, left, right) {
3189 return left + txt + right;
3190 }
3191
3192 // Parse underscores
3193 if (options.literalMidWordUnderscores) {
3194 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
3195 return parseInside (txt, '<strong><em>', '</em></strong>');
3196 });
3197 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
3198 return parseInside (txt, '<strong>', '</strong>');
3199 });
3200 text = text.replace(/\b_(\S[\s\S]*?)_\b/g, function (wm, txt) {
3201 return parseInside (txt, '<em>', '</em>');
3202 });
3203 } else {
3204 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
3205 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
3206 });
3207 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
3208 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
3209 });
3210 text = text.replace(/_([^\s_][\s\S]*?)_/g, function (wm, m) {
3211 // !/^_[^_]/.test(m) - test if it doesn't start with __ (since it seems redundant, we removed it)
3212 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
3213 });
3214 }
3215
3216 // Now parse asterisks
3217 /*
3218 if (options.literalMidWordAsterisks) {
3219 text = text.replace(/([^*]|^)\B\*\*\*(\S[\s\S]+?)\*\*\*\B(?!\*)/g, function (wm, lead, txt) {
3220 return parseInside (txt, lead + '<strong><em>', '</em></strong>');
3221 });
3222 text = text.replace(/([^*]|^)\B\*\*(\S[\s\S]+?)\*\*\B(?!\*)/g, function (wm, lead, txt) {
3223 return parseInside (txt, lead + '<strong>', '</strong>');
3224 });
3225 text = text.replace(/([^*]|^)\B\*(\S[\s\S]+?)\*\B(?!\*)/g, function (wm, lead, txt) {
3226 return parseInside (txt, lead + '<em>', '</em>');
3227 });
3228 } else {
3229 */
3230 text = text.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g, function (wm, m) {
3231 return (/\S$/.test(m)) ? parseInside (m, '<strong><em>', '</em></strong>') : wm;
3232 });
3233 text = text.replace(/\*\*(\S[\s\S]*?)\*\*/g, function (wm, m) {
3234 return (/\S$/.test(m)) ? parseInside (m, '<strong>', '</strong>') : wm;
3235 });
3236 text = text.replace(/\*([^\s*][\s\S]*?)\*/g, function (wm, m) {
3237 // !/^\*[^*]/.test(m) - test if it doesn't start with ** (since it seems redundant, we removed it)
3238 return (/\S$/.test(m)) ? parseInside (m, '<em>', '</em>') : wm;
3239 });
3240 //}
3241
3242 text = globals.converter._dispatch('makehtml.italicsAndBold.after', text, options, globals).getText();
3243 return text;
3244 });
3245
3246 ////
3247 // makehtml/links.js
3248 // Copyright (c) 2018 ShowdownJS
3249 //
3250 // Transforms MD links into `<a>` html anchors
3251 //
3252 // A link contains link text (the visible text), a link destination (the URI that is the link destination), and
3253 // optionally a link title. There are two basic kinds of links in Markdown.
3254 // In inline links the destination and title are given immediately after the link text.
3255 // In reference links the destination and title are defined elsewhere in the document.
3256 //
3257 // ***Author:***
3258 // - Estevão Soares dos Santos (Tivie) <https://github.com/tivie>
3259 ////
3260
3261 (function () {
3262 /**
3263 * Helper function: Wrapper function to pass as second replace parameter
3264 *
3265 * @param {RegExp} rgx
3266 * @param {string} evtRootName
3267 * @param {{}} options
3268 * @param {{}} globals
3269 * @returns {Function}
3270 */
3271 function replaceAnchorTag (rgx, evtRootName, options, globals, emptyCase) {
3272 emptyCase = !!emptyCase;
3273 return function (wholeMatch, text, id, url, m5, m6, title) {
3274 // bail we we find 2 newlines somewhere
3275 if (/\n\n/.test(wholeMatch)) {
3276 return wholeMatch;
3277 }
3278
3279 var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals);
3280 return writeAnchorTag(evt, options, globals, emptyCase);
3281 };
3282 }
3283
3284 /**
3285 * TODO Normalize this
3286 * Helper function: Create a capture event
3287 * @param {RegExp} rgx
3288 * @param {String} evtName Event name
3289 * @param {String} wholeMatch
3290 * @param {String} text
3291 * @param {String} id
3292 * @param {String} url
3293 * @param {String} title
3294 * @param {{}} options
3295 * @param {{}} globals
3296 * @returns {showdown.helper.Event|*}
3297 */
3298 function createEvent (rgx, evtName, wholeMatch, text, id, url, title, options, globals) {
3299 return globals.converter._dispatch(evtName, wholeMatch, options, globals, {
3300 regexp: rgx,
3301 matches: {
3302 wholeMatch: wholeMatch,
3303 text: text,
3304 id: id,
3305 url: url,
3306 title: title
3307 }
3308 });
3309 }
3310
3311 /**
3312 * Helper Function: Normalize and write an anchor tag based on passed parameters
3313 * @param evt
3314 * @param options
3315 * @param globals
3316 * @param {boolean} emptyCase
3317 * @returns {string}
3318 */
3319 function writeAnchorTag (evt, options, globals, emptyCase) {
3320
3321 var wholeMatch = evt.getMatches().wholeMatch;
3322 var text = evt.getMatches().text;
3323 var id = evt.getMatches().id;
3324 var url = evt.getMatches().url;
3325 var title = evt.getMatches().title;
3326 var target = '';
3327
3328 if (!title) {
3329 title = '';
3330 }
3331 id = (id) ? id.toLowerCase() : '';
3332
3333 if (emptyCase) {
3334 url = '';
3335 } else if (!url) {
3336 if (!id) {
3337 // lower-case and turn embedded newlines into spaces
3338 id = text.toLowerCase().replace(/ ?\n/g, ' ');
3339 }
3340 url = '#' + id;
3341
3342 if (!showdown.helper.isUndefined(globals.gUrls[id])) {
3343 url = globals.gUrls[id];
3344 if (!showdown.helper.isUndefined(globals.gTitles[id])) {
3345 title = globals.gTitles[id];
3346 }
3347 } else {
3348 return wholeMatch;
3349 }
3350 }
3351 //url = showdown.helper.escapeCharacters(url, '*_:~', false); // replaced line to improve performance
3352 url = url.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
3353
3354 if (title !== '' && title !== null) {
3355 title = title.replace(/"/g, '&quot;');
3356 //title = showdown.helper.escapeCharacters(title, '*_', false); // replaced line to improve performance
3357 title = title.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
3358 title = ' title="' + title + '"';
3359 }
3360
3361 // optionLinksInNewWindow only applies
3362 // to external links. Hash links (#) open in same page
3363 if (options.openLinksInNewWindow && !/^#/.test(url)) {
3364 // escaped _
3365 target = ' target="¨E95Eblank"';
3366 }
3367
3368 // Text can be a markdown element, so we run through the appropriate parsers
3369 text = showdown.subParser('makehtml.codeSpans')(text, options, globals);
3370 text = showdown.subParser('makehtml.emoji')(text, options, globals);
3371 text = showdown.subParser('makehtml.underline')(text, options, globals);
3372 text = showdown.subParser('makehtml.italicsAndBold')(text, options, globals);
3373 text = showdown.subParser('makehtml.strikethrough')(text, options, globals);
3374 text = showdown.subParser('makehtml.ellipsis')(text, options, globals);
3375 text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals);
3376
3377 //evt = createEvent(rgx, evtRootName + '.captureEnd', wholeMatch, text, id, url, title, options, globals);
3378
3379 var result = '<a href="' + url + '"' + title + target + '>' + text + '</a>';
3380
3381 //evt = createEvent(rgx, evtRootName + '.beforeHash', wholeMatch, text, id, url, title, options, globals);
3382
3383 result = showdown.subParser('makehtml.hashHTMLSpans')(result, options, globals);
3384
3385 return result;
3386 }
3387
3388 var evtRootName = 'makehtml.links';
3389
3390 /**
3391 * Turn Markdown link shortcuts into XHTML <a> tags.
3392 */
3393 showdown.subParser('makehtml.links', function (text, options, globals) {
3394
3395 text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
3396
3397 // 1. Handle reference-style links: [link text] [id]
3398 text = showdown.subParser('makehtml.links.reference')(text, options, globals);
3399
3400 // 2. Handle inline-style links: [link text](url "optional title")
3401 text = showdown.subParser('makehtml.links.inline')(text, options, globals);
3402
3403 // 3. Handle reference-style shortcuts: [link text]
3404 // These must come last in case there's a [link text][1] or [link text](/foo)
3405 text = showdown.subParser('makehtml.links.referenceShortcut')(text, options, globals);
3406
3407 // 4. Handle angle brackets links -> `<http://example.com/>`
3408 // Must come after links, because you can use < and > delimiters in inline links like [this](<url>).
3409 text = showdown.subParser('makehtml.links.angleBrackets')(text, options, globals);
3410
3411 // 5. Handle GithubMentions (if option is enabled)
3412 text = showdown.subParser('makehtml.links.ghMentions')(text, options, globals);
3413
3414 // 6. Handle <a> tags and img tags
3415 text = text.replace(/<a\s[^>]*>[\s\S]*<\/a>/g, function (wholeMatch) {
3416 return showdown.helper._hashHTMLSpan(wholeMatch, globals);
3417 });
3418
3419 text = text.replace(/<img\s[^>]*\/?>/g, function (wholeMatch) {
3420 return showdown.helper._hashHTMLSpan(wholeMatch, globals);
3421 });
3422
3423 // 7. Handle naked links (if option is enabled)
3424 text = showdown.subParser('makehtml.links.naked')(text, options, globals);
3425
3426 text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
3427 return text;
3428 });
3429
3430 /**
3431 * TODO WRITE THIS DOCUMENTATION
3432 */
3433 showdown.subParser('makehtml.links.inline', function (text, options, globals) {
3434 var evtRootName = evtRootName + '.inline';
3435
3436 text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
3437
3438 // 1. Look for empty cases: []() and [empty]() and []("title")
3439 var rgxEmpty = /\[(.*?)]()()()()\(<? ?>? ?(?:["'](.*)["'])?\)/g;
3440 text = text.replace(rgxEmpty, replaceAnchorTag(rgxEmpty, evtRootName, options, globals, true));
3441
3442 // 2. Look for cases with crazy urls like ./image/cat1).png
3443 var rgxCrazy = /\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g;
3444 text = text.replace(rgxCrazy, replaceAnchorTag(rgxCrazy, evtRootName, options, globals));
3445
3446 // 3. inline links with no title or titles wrapped in ' or ":
3447 // [text](url.com) || [text](<url.com>) || [text](url.com "title") || [text](<url.com> "title")
3448 //var rgx2 = /\[[ ]*[\s]?[ ]*([^\n\[\]]*?)[ ]*[\s]?[ ]*] ?()\(<?[ ]*[\s]?[ ]*([^\s'"]*)>?(?:[ ]*[\n]?[ ]*()(['"])(.*?)\5)?[ ]*[\s]?[ ]*\)/; // this regex is too slow!!!
3449 var rgx2 = /\[([\S ]*?)]\s?()\( *<?([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s*(?:()(['"])(.*?)\5)? *\)/g;
3450 text = text.replace(rgx2, replaceAnchorTag(rgx2, evtRootName, options, globals));
3451
3452 // 4. inline links with titles wrapped in (): [foo](bar.com (title))
3453 var rgx3 = /\[([\S ]*?)]\s?()\( *<?([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s+()()\((.*?)\) *\)/g;
3454 text = text.replace(rgx3, replaceAnchorTag(rgx3, evtRootName, options, globals));
3455
3456 text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
3457
3458 return text;
3459 });
3460
3461 /**
3462 * TODO WRITE THIS DOCUMENTATION
3463 */
3464 showdown.subParser('makehtml.links.reference', function (text, options, globals) {
3465 var evtRootName = evtRootName + '.reference';
3466
3467 text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
3468
3469 var rgx = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g;
3470 text = text.replace(rgx, replaceAnchorTag(rgx, evtRootName, options, globals));
3471
3472 text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
3473
3474 return text;
3475 });
3476
3477 /**
3478 * TODO WRITE THIS DOCUMENTATION
3479 */
3480 showdown.subParser('makehtml.links.referenceShortcut', function (text, options, globals) {
3481 var evtRootName = evtRootName + '.referenceShortcut';
3482
3483 text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
3484
3485 var rgx = /\[([^\[\]]+)]()()()()()/g;
3486 text = text.replace(rgx, replaceAnchorTag(rgx, evtRootName, options, globals));
3487
3488 text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
3489
3490 return text;
3491 });
3492
3493 /**
3494 * TODO WRITE THIS DOCUMENTATION
3495 */
3496 showdown.subParser('makehtml.links.ghMentions', function (text, options, globals) {
3497 var evtRootName = evtRootName + 'ghMentions';
3498
3499 if (!options.ghMentions) {
3500 return text;
3501 }
3502
3503 text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
3504
3505 var rgx = /(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi;
3506
3507 text = text.replace(rgx, function (wholeMatch, st, escape, mentions, username) {
3508 // bail if the mentions was escaped
3509 if (escape === '\\') {
3510 return st + mentions;
3511 }
3512
3513 // check if options.ghMentionsLink is a string
3514 // TODO Validation should be done at initialization not at runtime
3515 if (!showdown.helper.isString(options.ghMentionsLink)) {
3516 throw new Error('ghMentionsLink option must be a string');
3517 }
3518 var url = options.ghMentionsLink.replace(/{u}/g, username);
3519 var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, mentions, null, url, null, options, globals);
3520 // captureEnd Event is triggered inside writeAnchorTag function
3521 return st + writeAnchorTag(evt, options, globals);
3522 });
3523
3524 text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
3525
3526 return text;
3527 });
3528
3529 /**
3530 * TODO WRITE THIS DOCUMENTATION
3531 */
3532 showdown.subParser('makehtml.links.angleBrackets', function (text, options, globals) {
3533 var evtRootName = 'makehtml.links.angleBrackets';
3534
3535 text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
3536
3537 // 1. Parse links first
3538 var urlRgx = /<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi;
3539 text = text.replace(urlRgx, function (wholeMatch, url, urlStart) {
3540 var text = url;
3541 url = (urlStart === 'www.') ? 'http://' + url : url;
3542 var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals);
3543 return writeAnchorTag(evt, options, globals);
3544 });
3545
3546 // 2. Then Mail Addresses
3547 var mailRgx = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
3548 text = text.replace(mailRgx, function (wholeMatch, mail) {
3549 var url = 'mailto:';
3550 mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals);
3551 if (options.encodeEmails) {
3552 url = showdown.helper.encodeEmailAddress(url + mail);
3553 mail = showdown.helper.encodeEmailAddress(mail);
3554 } else {
3555 url = url + mail;
3556 }
3557 var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals);
3558 return writeAnchorTag(evt, options, globals);
3559 });
3560
3561 text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
3562 return text;
3563 });
3564
3565 /**
3566 * TODO MAKE THIS WORK (IT'S NOT ACTIVATED)
3567 * TODO WRITE THIS DOCUMENTATION
3568 */
3569 showdown.subParser('makehtml.links.naked', function (text, options, globals) {
3570 if (!options.simplifiedAutoLink) {
3571 return text;
3572 }
3573
3574 var evtRootName = 'makehtml.links.naked';
3575
3576 text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
3577
3578 // 2. Now we check for
3579 // we also include leading markdown magic chars [_*~] for cases like __https://www.google.com/foobar__
3580 var urlRgx = /([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi;
3581 text = text.replace(urlRgx, function (wholeMatch, leadingMDChars, url, urlPrefix) {
3582
3583 // we now will start traversing the url from the front to back, looking for punctuation chars [_*~,;:.!?\)\]]
3584 var len = url.length;
3585 var suffix = '';
3586 for (var i = len - 1; i >= 0; --i) {
3587 var char = url.charAt(i);
3588
3589 if (/[_*~,;:.!?]/.test(char)) {
3590 // it's a punctuation char
3591 // we remove it from the url
3592 url = url.slice(0, -1);
3593 // and prepend it to the suffix
3594 suffix = char + suffix;
3595 } else if (/\)/.test(char)) {
3596 var opPar = url.match(/\(/g) || [];
3597 var clPar = url.match(/\)/g);
3598
3599 // it's a curved parenthesis so we need to check for "balance" (kinda)
3600 if (opPar.length < clPar.length) {
3601 // there are more closing Parenthesis than opening so chop it!!!!!
3602 url = url.slice(0, -1);
3603 // and prepend it to the suffix
3604 suffix = char + suffix;
3605 } else {
3606 // it's (kinda) balanced so our work is done
3607 break;
3608 }
3609 } else if (/]/.test(char)) {
3610 var opPar2 = url.match(/\[/g) || [];
3611 var clPar2 = url.match(/\]/g);
3612 // it's a squared parenthesis so we need to check for "balance" (kinda)
3613 if (opPar2.length < clPar2.length) {
3614 // there are more closing Parenthesis than opening so chop it!!!!!
3615 url = url.slice(0, -1);
3616 // and prepend it to the suffix
3617 suffix = char + suffix;
3618 } else {
3619 // it's (kinda) balanced so our work is done
3620 break;
3621 }
3622 } else {
3623 // it's not a punctuation or a parenthesis so our work is done
3624 break;
3625 }
3626 }
3627
3628 // we copy the treated url to the text variable
3629 var text = url;
3630 // finally, if it's a www shortcut, we prepend http
3631 url = (urlPrefix === 'www.') ? 'http://' + url : url;
3632
3633 // url part is done so let's take care of text now
3634 // we need to escape the text (because of links such as www.example.com/foo__bar__baz)
3635 text = text.replace(showdown.helper.regexes.asteriskDashTildeAndColon, showdown.helper.escapeCharactersCallback);
3636
3637 // finally we dispatch the event
3638 var evt = createEvent(urlRgx, evtRootName + '.captureStart', wholeMatch, text, null, url, null, options, globals);
3639
3640 // and return the link tag, with the leadingMDChars and suffix. The leadingMDChars are added at the end too because
3641 // we consumed those characters in the regexp
3642 return leadingMDChars + writeAnchorTag(evt, options, globals) + suffix + leadingMDChars;
3643 });
3644
3645 // 2. Then mails
3646 var mailRgx = /(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gmi;
3647 text = text.replace(mailRgx, function (wholeMatch, leadingChar, mail) {
3648 var url = 'mailto:';
3649 mail = showdown.subParser('makehtml.unescapeSpecialChars')(mail, options, globals);
3650 if (options.encodeEmails) {
3651 url = showdown.helper.encodeEmailAddress(url + mail);
3652 mail = showdown.helper.encodeEmailAddress(mail);
3653 } else {
3654 url = url + mail;
3655 }
3656 var evt = createEvent(mailRgx, evtRootName + '.captureStart', wholeMatch, mail, null, url, null, options, globals);
3657 return leadingChar + writeAnchorTag(evt, options, globals);
3658 });
3659
3660
3661 text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
3662 return text;
3663 });
3664 })();
3665
3666 /**
3667 * Form HTML ordered (numbered) and unordered (bulleted) lists.
3668 */
3669 showdown.subParser('makehtml.lists', function (text, options, globals) {
3670 'use strict';
3671
3672 /**
3673 * Process the contents of a single ordered or unordered list, splitting it
3674 * into individual list items.
3675 * @param {string} listStr
3676 * @param {boolean} trimTrailing
3677 * @returns {string}
3678 */
3679 function processListItems (listStr, trimTrailing) {
3680 // The $g_list_level global keeps track of when we're inside a list.
3681 // Each time we enter a list, we increment it; when we leave a list,
3682 // we decrement. If it's zero, we're not in a list anymore.
3683 //
3684 // We do this because when we're not inside a list, we want to treat
3685 // something like this:
3686 //
3687 // I recommend upgrading to version
3688 // 8. Oops, now this line is treated
3689 // as a sub-list.
3690 //
3691 // As a single paragraph, despite the fact that the second line starts
3692 // with a digit-period-space sequence.
3693 //
3694 // Whereas when we're inside a list (or sub-list), that line will be
3695 // treated as the start of a sub-list. What a kludge, huh? This is
3696 // an aspect of Markdown's syntax that's hard to parse perfectly
3697 // without resorting to mind-reading. Perhaps the solution is to
3698 // change the syntax rules such that sub-lists must start with a
3699 // starting cardinal number; e.g. "1." or "a.".
3700 globals.gListLevel++;
3701
3702 // trim trailing blank lines:
3703 listStr = listStr.replace(/\n{2,}$/, '\n');
3704
3705 // attacklab: add sentinel to emulate \z
3706 listStr += '¨0';
3707
3708 var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
3709 isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr));
3710
3711 // Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation,
3712 // which is a syntax breaking change
3713 // activating this option reverts to old behavior
3714 // This will be removed in version 2.0
3715 if (options.disableForced4SpacesIndentedSublists) {
3716 rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
3717 }
3718
3719 listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
3720 checked = (checked && checked.trim() !== '');
3721
3722 var item = showdown.subParser('makehtml.outdent')(m4, options, globals),
3723 bulletStyle = '';
3724
3725 // Support for github tasklists
3726 if (taskbtn && options.tasklists) {
3727 bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
3728 item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
3729 var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
3730 if (checked) {
3731 otp += ' checked';
3732 }
3733 otp += '>';
3734 return otp;
3735 });
3736 }
3737
3738 // ISSUE #312
3739 // This input: - - - a
3740 // causes trouble to the parser, since it interprets it as:
3741 // <ul><li><li><li>a</li></li></li></ul>
3742 // instead of:
3743 // <ul><li>- - a</li></ul>
3744 // So, to prevent it, we will put a marker (¨A)in the beginning of the line
3745 // Kind of hackish/monkey patching, but seems more effective than overcomplicating the list parser
3746 item = item.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g, function (wm2) {
3747 return '¨A' + wm2;
3748 });
3749
3750 // SPECIAL CASE: an heading followed by a paragraph of text that is not separated by a double newline
3751 // or/nor indented. ex:
3752 //
3753 // - # foo
3754 // bar is great
3755 //
3756 // While this does now follow the spec per se, not allowing for this might cause confusion since
3757 // header blocks don't need double newlines after
3758 if (/^#+.+\n.+/.test(item)) {
3759 item = item.replace(/^(#+.+)$/m, '$1\n');
3760 }
3761
3762 // m1 - Leading line or
3763 // Has a double return (multi paragraph)
3764 if (m1 || (item.search(/\n{2,}/) > -1)) {
3765 item = showdown.subParser('makehtml.githubCodeBlocks')(item, options, globals);
3766 item = showdown.subParser('makehtml.blockGamut')(item, options, globals);
3767 } else {
3768
3769 // Recursion for sub-lists:
3770 item = showdown.subParser('makehtml.lists')(item, options, globals);
3771 item = item.replace(/\n$/, ''); // chomp(item)
3772 item = showdown.subParser('makehtml.hashHTMLBlocks')(item, options, globals);
3773
3774 // Colapse double linebreaks
3775 item = item.replace(/\n\n+/g, '\n\n');
3776
3777 if (isParagraphed) {
3778 item = showdown.subParser('makehtml.paragraphs')(item, options, globals);
3779 } else {
3780 item = showdown.subParser('makehtml.spanGamut')(item, options, globals);
3781 }
3782 }
3783
3784 // now we need to remove the marker (¨A)
3785 item = item.replace('¨A', '');
3786 // we can finally wrap the line in list item tags
3787 item = '<li' + bulletStyle + '>' + item + '</li>\n';
3788
3789 return item;
3790 });
3791
3792 // attacklab: strip sentinel
3793 listStr = listStr.replace(/¨0/g, '');
3794
3795 globals.gListLevel--;
3796
3797 if (trimTrailing) {
3798 listStr = listStr.replace(/\s+$/, '');
3799 }
3800
3801 return listStr;
3802 }
3803
3804 function styleStartNumber (list, listType) {
3805 // check if ol and starts by a number different than 1
3806 if (listType === 'ol') {
3807 var res = list.match(/^ *(\d+)\./);
3808 if (res && res[1] !== '1') {
3809 return ' start="' + res[1] + '"';
3810 }
3811 }
3812 return '';
3813 }
3814
3815 /**
3816 * Check and parse consecutive lists (better fix for issue #142)
3817 * @param {string} list
3818 * @param {string} listType
3819 * @param {boolean} trimTrailing
3820 * @returns {string}
3821 */
3822 function parseConsecutiveLists (list, listType, trimTrailing) {
3823 // check if we caught 2 or more consecutive lists by mistake
3824 // we use the counterRgx, meaning if listType is UL we look for OL and vice versa
3825 var olRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?\d+\.[ \t]/gm : /^ {0,3}\d+\.[ \t]/gm,
3826 ulRgx = (options.disableForced4SpacesIndentedSublists) ? /^ ?[*+-][ \t]/gm : /^ {0,3}[*+-][ \t]/gm,
3827 counterRxg = (listType === 'ul') ? olRgx : ulRgx,
3828 result = '';
3829
3830 if (list.search(counterRxg) !== -1) {
3831 (function parseCL (txt) {
3832 var pos = txt.search(counterRxg),
3833 style = styleStartNumber(list, listType);
3834 if (pos !== -1) {
3835 // slice
3836 result += '\n\n<' + listType + style + '>\n' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n';
3837
3838 // invert counterType and listType
3839 listType = (listType === 'ul') ? 'ol' : 'ul';
3840 counterRxg = (listType === 'ul') ? olRgx : ulRgx;
3841
3842 //recurse
3843 parseCL(txt.slice(pos));
3844 } else {
3845 result += '\n\n<' + listType + style + '>\n' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n';
3846 }
3847 })(list);
3848 } else {
3849 var style = styleStartNumber(list, listType);
3850 result = '\n\n<' + listType + style + '>\n' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n';
3851 }
3852
3853 return result;
3854 }
3855
3856 // Start of list parsing
3857 var subListRgx = /^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
3858 var mainListRgx = /(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
3859
3860 text = globals.converter._dispatch('lists.before', text, options, globals).getText();
3861 // add sentinel to hack around khtml/safari bug:
3862 // http://bugs.webkit.org/show_bug.cgi?id=11231
3863 text += '¨0';
3864
3865 if (globals.gListLevel) {
3866 text = text.replace(subListRgx, function (wholeMatch, list, m2) {
3867 var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
3868 return parseConsecutiveLists(list, listType, true);
3869 });
3870 } else {
3871 text = text.replace(mainListRgx, function (wholeMatch, m1, list, m3) {
3872 var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
3873 return parseConsecutiveLists(list, listType, false);
3874 });
3875 }
3876
3877 // strip sentinel
3878 text = text.replace(/¨0/, '');
3879 text = globals.converter._dispatch('makehtml.lists.after', text, options, globals).getText();
3880 return text;
3881 });
3882
3883 /**
3884 * Parse metadata at the top of the document
3885 */
3886 showdown.subParser('makehtml.metadata', function (text, options, globals) {
3887 'use strict';
3888
3889 if (!options.metadata) {
3890 return text;
3891 }
3892
3893 text = globals.converter._dispatch('makehtml.metadata.before', text, options, globals).getText();
3894
3895 function parseMetadataContents (content) {
3896 // raw is raw so it's not changed in any way
3897 globals.metadata.raw = content;
3898
3899 // escape chars forbidden in html attributes
3900 // double quotes
3901 content = content
3902 // ampersand first
3903 .replace(/&/g, '&amp;')
3904 // double quotes
3905 .replace(/"/g, '&quot;');
3906
3907 content = content.replace(/\n {4}/g, ' ');
3908 content.replace(/^([\S ]+): +([\s\S]+?)$/gm, function (wm, key, value) {
3909 globals.metadata.parsed[key] = value;
3910 return '';
3911 });
3912 }
3913
3914 text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) {
3915 parseMetadataContents(content);
3916 return '¨M';
3917 });
3918
3919 text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) {
3920 if (format) {
3921 globals.metadata.format = format;
3922 }
3923 parseMetadataContents(content);
3924 return '¨M';
3925 });
3926
3927 text = text.replace(/¨M/g, '');
3928
3929 text = globals.converter._dispatch('makehtml.metadata.after', text, options, globals).getText();
3930 return text;
3931 });
3932
3933 /**
3934 * Remove one level of line-leading tabs or spaces
3935 */
3936 showdown.subParser('makehtml.outdent', function (text, options, globals) {
3937 'use strict';
3938 text = globals.converter._dispatch('makehtml.outdent.before', text, options, globals).getText();
3939
3940 // attacklab: hack around Konqueror 3.5.4 bug:
3941 // "----------bug".replace(/^-/g,"") == "bug"
3942 text = text.replace(/^(\t|[ ]{1,4})/gm, '¨0'); // attacklab: g_tab_width
3943
3944 // attacklab: clean up hack
3945 text = text.replace(/¨0/g, '');
3946
3947 text = globals.converter._dispatch('makehtml.outdent.after', text, options, globals).getText();
3948 return text;
3949 });
3950
3951 /**
3952 *
3953 */
3954 showdown.subParser('makehtml.paragraphs', function (text, options, globals) {
3955 'use strict';
3956
3957 text = globals.converter._dispatch('makehtml.paragraphs.before', text, options, globals).getText();
3958 // Strip leading and trailing lines:
3959 text = text.replace(/^\n+/g, '');
3960 text = text.replace(/\n+$/g, '');
3961
3962 var grafs = text.split(/\n{2,}/g),
3963 grafsOut = [],
3964 end = grafs.length; // Wrap <p> tags
3965
3966 for (var i = 0; i < end; i++) {
3967 var str = grafs[i];
3968 // if this is an HTML marker, copy it
3969 if (str.search(/¨(K|G)(\d+)\1/g) >= 0) {
3970 grafsOut.push(str);
3971
3972 // test for presence of characters to prevent empty lines being parsed
3973 // as paragraphs (resulting in undesired extra empty paragraphs)
3974 } else if (str.search(/\S/) >= 0) {
3975 str = showdown.subParser('makehtml.spanGamut')(str, options, globals);
3976 str = str.replace(/^([ \t]*)/g, '<p>');
3977 str += '</p>';
3978 grafsOut.push(str);
3979 }
3980 }
3981
3982 /** Unhashify HTML blocks */
3983 end = grafsOut.length;
3984 for (i = 0; i < end; i++) {
3985 var blockText = '',
3986 grafsOutIt = grafsOut[i],
3987 codeFlag = false;
3988 // if this is a marker for an html block...
3989 // use RegExp.test instead of string.search because of QML bug
3990 while (/¨(K|G)(\d+)\1/.test(grafsOutIt)) {
3991 var delim = RegExp.$1,
3992 num = RegExp.$2;
3993
3994 if (delim === 'K') {
3995 blockText = globals.gHtmlBlocks[num];
3996 } else {
3997 // we need to check if ghBlock is a false positive
3998 if (codeFlag) {
3999 // use encoded version of all text
4000 blockText = showdown.subParser('makehtml.encodeCode')(globals.ghCodeBlocks[num].text, options, globals);
4001 } else {
4002 blockText = globals.ghCodeBlocks[num].codeblock;
4003 }
4004 }
4005 blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
4006
4007 grafsOutIt = grafsOutIt.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/, blockText);
4008 // Check if grafsOutIt is a pre->code
4009 if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
4010 codeFlag = true;
4011 }
4012 }
4013 grafsOut[i] = grafsOutIt;
4014 }
4015 text = grafsOut.join('\n');
4016 // Strip leading and trailing lines:
4017 text = text.replace(/^\n+/g, '');
4018 text = text.replace(/\n+$/g, '');
4019 return globals.converter._dispatch('makehtml.paragraphs.after', text, options, globals).getText();
4020 });
4021
4022 /**
4023 * Run extension
4024 */
4025 showdown.subParser('makehtml.runExtension', function (ext, text, options, globals) {
4026 'use strict';
4027
4028 if (ext.filter) {
4029 text = ext.filter(text, globals.converter, options);
4030
4031 } else if (ext.regex) {
4032 // TODO remove this when old extension loading mechanism is deprecated
4033 var re = ext.regex;
4034 if (!(re instanceof RegExp)) {
4035 re = new RegExp(re, 'g');
4036 }
4037 text = text.replace(re, ext.replace);
4038 }
4039
4040 return text;
4041 });
4042
4043 /**
4044 * These are all the transformations that occur *within* block-level
4045 * tags like paragraphs, headers, and list items.
4046 */
4047 showdown.subParser('makehtml.spanGamut', function (text, options, globals) {
4048 'use strict';
4049
4050 text = globals.converter._dispatch('makehtml.span.before', text, options, globals).getText();
4051
4052 text = showdown.subParser('makehtml.codeSpans')(text, options, globals);
4053 text = showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes')(text, options, globals);
4054 text = showdown.subParser('makehtml.encodeBackslashEscapes')(text, options, globals);
4055
4056 // Process link and image tags. Images must come first,
4057 // because ![foo][f] looks like a link.
4058 text = showdown.subParser('makehtml.images')(text, options, globals);
4059
4060 text = globals.converter._dispatch('smakehtml.links.before', text, options, globals).getText();
4061 text = showdown.subParser('makehtml.links')(text, options, globals);
4062 text = globals.converter._dispatch('smakehtml.links.after', text, options, globals).getText();
4063
4064 //text = showdown.subParser('makehtml.autoLinks')(text, options, globals);
4065 //text = showdown.subParser('makehtml.simplifiedAutoLinks')(text, options, globals);
4066 text = showdown.subParser('makehtml.emoji')(text, options, globals);
4067 text = showdown.subParser('makehtml.underline')(text, options, globals);
4068 text = showdown.subParser('makehtml.italicsAndBold')(text, options, globals);
4069 text = showdown.subParser('makehtml.strikethrough')(text, options, globals);
4070 text = showdown.subParser('makehtml.ellipsis')(text, options, globals);
4071
4072 // we need to hash HTML tags inside spans
4073 text = showdown.subParser('makehtml.hashHTMLSpans')(text, options, globals);
4074
4075 // now we encode amps and angles
4076 text = showdown.subParser('makehtml.encodeAmpsAndAngles')(text, options, globals);
4077
4078 // Do hard breaks
4079 if (options.simpleLineBreaks) {
4080 // GFM style hard breaks
4081 // only add line breaks if the text does not contain a block (special case for lists)
4082 if (!/\n\n¨K/.test(text)) {
4083 text = text.replace(/\n+/g, '<br />\n');
4084 }
4085 } else {
4086 // Vanilla hard breaks
4087 text = text.replace(/ +\n/g, '<br />\n');
4088 }
4089
4090 text = globals.converter._dispatch('makehtml.spanGamut.after', text, options, globals).getText();
4091 return text;
4092 });
4093
4094 showdown.subParser('makehtml.strikethrough', function (text, options, globals) {
4095 'use strict';
4096
4097 if (options.strikethrough) {
4098 text = globals.converter._dispatch('makehtml.strikethrough.before', text, options, globals).getText();
4099 text = text.replace(/(?:~){2}([\s\S]+?)(?:~){2}/g, function (wm, txt) { return '<del>' + txt + '</del>'; });
4100 text = globals.converter._dispatch('makehtml.strikethrough.after', text, options, globals).getText();
4101 }
4102
4103 return text;
4104 });
4105
4106 /**
4107 * Strips link definitions from text, stores the URLs and titles in
4108 * hash references.
4109 * Link defs are in the form: ^[id]: url "optional title"
4110 */
4111 showdown.subParser('makehtml.stripLinkDefinitions', function (text, options, globals) {
4112 'use strict';
4113
4114 var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,
4115 base64Regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm;
4116
4117 // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
4118 text += '¨0';
4119
4120 var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
4121 linkId = linkId.toLowerCase();
4122 if (url.match(/^data:.+?\/.+?;base64,/)) {
4123 // remove newlines
4124 globals.gUrls[linkId] = url.replace(/\s/g, '');
4125 } else {
4126 globals.gUrls[linkId] = showdown.subParser('makehtml.encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
4127 }
4128
4129 if (blankLines) {
4130 // Oops, found blank lines, so it's not a title.
4131 // Put back the parenthetical statement we stole.
4132 return blankLines + title;
4133
4134 } else {
4135 if (title) {
4136 globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
4137 }
4138 if (options.parseImgDimensions && width && height) {
4139 globals.gDimensions[linkId] = {
4140 width: width,
4141 height: height
4142 };
4143 }
4144 }
4145 // Completely remove the definition from the text
4146 return '';
4147 };
4148
4149 // first we try to find base64 link references
4150 text = text.replace(base64Regex, replaceFunc);
4151
4152 text = text.replace(regex, replaceFunc);
4153
4154 // attacklab: strip sentinel
4155 text = text.replace(/¨0/, '');
4156
4157 return text;
4158 });
4159
4160 showdown.subParser('makehtml.tables', function (text, options, globals) {
4161 'use strict';
4162
4163 if (!options.tables) {
4164 return text;
4165 }
4166
4167 var tableRgx = /^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,
4168 //singeColTblRgx = /^ {0,3}\|.+\|\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n(?: {0,3}\|.+\|\n)+(?:\n\n|¨0)/gm;
4169 singeColTblRgx = /^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm;
4170
4171 function parseStyles (sLine) {
4172 if (/^:[ \t]*--*$/.test(sLine)) {
4173 return ' style="text-align:left;"';
4174 } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
4175 return ' style="text-align:right;"';
4176 } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
4177 return ' style="text-align:center;"';
4178 } else {
4179 return '';
4180 }
4181 }
4182
4183 function parseHeaders (header, style) {
4184 var id = '';
4185 header = header.trim();
4186 // support both tablesHeaderId and tableHeaderId due to error in documentation so we don't break backwards compatibility
4187 if (options.tablesHeaderId || options.tableHeaderId) {
4188 id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
4189 }
4190 header = showdown.subParser('makehtml.spanGamut')(header, options, globals);
4191
4192 return '<th' + id + style + '>' + header + '</th>\n';
4193 }
4194
4195 function parseCells (cell, style) {
4196 var subText = showdown.subParser('makehtml.spanGamut')(cell, options, globals);
4197 return '<td' + style + '>' + subText + '</td>\n';
4198 }
4199
4200 function buildTable (headers, cells) {
4201 var tb = '<table>\n<thead>\n<tr>\n',
4202 tblLgn = headers.length;
4203
4204 for (var i = 0; i < tblLgn; ++i) {
4205 tb += headers[i];
4206 }
4207 tb += '</tr>\n</thead>\n<tbody>\n';
4208
4209 for (i = 0; i < cells.length; ++i) {
4210 tb += '<tr>\n';
4211 for (var ii = 0; ii < tblLgn; ++ii) {
4212 tb += cells[i][ii];
4213 }
4214 tb += '</tr>\n';
4215 }
4216 tb += '</tbody>\n</table>\n';
4217 return tb;
4218 }
4219
4220 function parseTable (rawTable) {
4221 var i, tableLines = rawTable.split('\n');
4222
4223 for (i = 0; i < tableLines.length; ++i) {
4224 // strip wrong first and last column if wrapped tables are used
4225 if (/^ {0,3}\|/.test(tableLines[i])) {
4226 tableLines[i] = tableLines[i].replace(/^ {0,3}\|/, '');
4227 }
4228 if (/\|[ \t]*$/.test(tableLines[i])) {
4229 tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
4230 }
4231 // parse code spans first, but we only support one line code spans
4232
4233 tableLines[i] = showdown.subParser('makehtml.codeSpans')(tableLines[i], options, globals);
4234 }
4235
4236 var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
4237 rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
4238 rawCells = [],
4239 headers = [],
4240 styles = [],
4241 cells = [];
4242
4243 tableLines.shift();
4244 tableLines.shift();
4245
4246 for (i = 0; i < tableLines.length; ++i) {
4247 if (tableLines[i].trim() === '') {
4248 continue;
4249 }
4250 rawCells.push(
4251 tableLines[i]
4252 .split('|')
4253 .map(function (s) {
4254 return s.trim();
4255 })
4256 );
4257 }
4258
4259 if (rawHeaders.length < rawStyles.length) {
4260 return rawTable;
4261 }
4262
4263 for (i = 0; i < rawStyles.length; ++i) {
4264 styles.push(parseStyles(rawStyles[i]));
4265 }
4266
4267 for (i = 0; i < rawHeaders.length; ++i) {
4268 if (showdown.helper.isUndefined(styles[i])) {
4269 styles[i] = '';
4270 }
4271 headers.push(parseHeaders(rawHeaders[i], styles[i]));
4272 }
4273
4274 for (i = 0; i < rawCells.length; ++i) {
4275 var row = [];
4276 for (var ii = 0; ii < headers.length; ++ii) {
4277 if (showdown.helper.isUndefined(rawCells[i][ii])) {
4278
4279 }
4280 row.push(parseCells(rawCells[i][ii], styles[ii]));
4281 }
4282 cells.push(row);
4283 }
4284
4285 return buildTable(headers, cells);
4286 }
4287
4288 text = globals.converter._dispatch('makehtml.tables.before', text, options, globals).getText();
4289
4290 // find escaped pipe characters
4291 text = text.replace(/\\(\|)/g, showdown.helper.escapeCharactersCallback);
4292
4293 // parse multi column tables
4294 text = text.replace(tableRgx, parseTable);
4295
4296 // parse one column tables
4297 text = text.replace(singeColTblRgx, parseTable);
4298
4299 text = globals.converter._dispatch('makehtml.tables.after', text, options, globals).getText();
4300
4301 return text;
4302 });
4303
4304 showdown.subParser('makehtml.underline', function (text, options, globals) {
4305 'use strict';
4306
4307 if (!options.underline) {
4308 return text;
4309 }
4310
4311 text = globals.converter._dispatch('makehtml.underline.before', text, options, globals).getText();
4312
4313 if (options.literalMidWordUnderscores) {
4314 text = text.replace(/\b___(\S[\s\S]*?)___\b/g, function (wm, txt) {
4315 return '<u>' + txt + '</u>';
4316 });
4317 text = text.replace(/\b__(\S[\s\S]*?)__\b/g, function (wm, txt) {
4318 return '<u>' + txt + '</u>';
4319 });
4320 } else {
4321 text = text.replace(/___(\S[\s\S]*?)___/g, function (wm, m) {
4322 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
4323 });
4324 text = text.replace(/__(\S[\s\S]*?)__/g, function (wm, m) {
4325 return (/\S$/.test(m)) ? '<u>' + m + '</u>' : wm;
4326 });
4327 }
4328
4329 // escape remaining underscores to prevent them being parsed by italic and bold
4330 text = text.replace(/(_)/g, showdown.helper.escapeCharactersCallback);
4331
4332 text = globals.converter._dispatch('makehtml.underline.after', text, options, globals).getText();
4333
4334 return text;
4335 });
4336
4337 /**
4338 * Swap back in all the special characters we've hidden.
4339 */
4340 showdown.subParser('makehtml.unescapeSpecialChars', function (text, options, globals) {
4341 'use strict';
4342 text = globals.converter._dispatch('makehtml.unescapeSpecialChars.before', text, options, globals).getText();
4343
4344 text = text.replace(/¨E(\d+)E/g, function (wholeMatch, m1) {
4345 var charCodeToReplace = parseInt(m1);
4346 return String.fromCharCode(charCodeToReplace);
4347 });
4348
4349 text = globals.converter._dispatch('makehtml.unescapeSpecialChars.after', text, options, globals).getText();
4350 return text;
4351 });
4352
4353 showdown.subParser('makeMarkdown.blockquote', function (node, globals) {
4354 'use strict';
4355
4356 var txt = '';
4357 if (node.hasChildNodes()) {
4358 var children = node.childNodes,
4359 childrenLength = children.length;
4360
4361 for (var i = 0; i < childrenLength; ++i) {
4362 var innerTxt = showdown.subParser('makeMarkdown.node')(children[i], globals);
4363
4364 if (innerTxt === '') {
4365 continue;
4366 }
4367 txt += innerTxt;
4368 }
4369 }
4370 // cleanup
4371 txt = txt.trim();
4372 txt = '> ' + txt.split('\n').join('\n> ');
4373 return txt;
4374 });
4375
4376 showdown.subParser('makeMarkdown.codeBlock', function (node, globals) {
4377 'use strict';
4378
4379 var lang = node.getAttribute('language'),
4380 num = node.getAttribute('precodenum');
4381 return '```' + lang + '\n' + globals.preList[num] + '\n```';
4382 });
4383
4384 showdown.subParser('makeMarkdown.codeSpan', function (node) {
4385 'use strict';
4386
4387 return '`' + node.innerHTML + '`';
4388 });
4389
4390 showdown.subParser('makeMarkdown.emphasis', function (node, globals) {
4391 'use strict';
4392
4393 var txt = '';
4394 if (node.hasChildNodes()) {
4395 txt += '*';
4396 var children = node.childNodes,
4397 childrenLength = children.length;
4398 for (var i = 0; i < childrenLength; ++i) {
4399 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4400 }
4401 txt += '*';
4402 }
4403 return txt;
4404 });
4405
4406 showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) {
4407 'use strict';
4408
4409 var headerMark = new Array(headerLevel + 1).join('#'),
4410 txt = '';
4411
4412 if (node.hasChildNodes()) {
4413 txt = headerMark + ' ';
4414 var children = node.childNodes,
4415 childrenLength = children.length;
4416
4417 for (var i = 0; i < childrenLength; ++i) {
4418 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4419 }
4420 }
4421 return txt;
4422 });
4423
4424 showdown.subParser('makeMarkdown.hr', function () {
4425 'use strict';
4426
4427 return '---';
4428 });
4429
4430 showdown.subParser('makeMarkdown.image', function (node) {
4431 'use strict';
4432
4433 var txt = '';
4434 if (node.hasAttribute('src')) {
4435 txt += '![' + node.getAttribute('alt') + '](';
4436 txt += '<' + node.getAttribute('src') + '>';
4437 if (node.hasAttribute('width') && node.hasAttribute('height')) {
4438 txt += ' =' + node.getAttribute('width') + 'x' + node.getAttribute('height');
4439 }
4440
4441 if (node.hasAttribute('title')) {
4442 txt += ' "' + node.getAttribute('title') + '"';
4443 }
4444 txt += ')';
4445 }
4446 return txt;
4447 });
4448
4449 showdown.subParser('makeMarkdown.links', function (node, globals) {
4450 'use strict';
4451
4452 var txt = '';
4453 if (node.hasChildNodes() && node.hasAttribute('href')) {
4454 var children = node.childNodes,
4455 childrenLength = children.length;
4456 txt = '[';
4457 for (var i = 0; i < childrenLength; ++i) {
4458 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4459 }
4460 txt += '](';
4461 txt += '<' + node.getAttribute('href') + '>';
4462 if (node.hasAttribute('title')) {
4463 txt += ' "' + node.getAttribute('title') + '"';
4464 }
4465 txt += ')';
4466 }
4467 return txt;
4468 });
4469
4470 showdown.subParser('makeMarkdown.list', function (node, globals, type) {
4471 'use strict';
4472
4473 var txt = '';
4474 if (!node.hasChildNodes()) {
4475 return '';
4476 }
4477 var listItems = node.childNodes,
4478 listItemsLenght = listItems.length,
4479 listNum = node.getAttribute('start') || 1;
4480
4481 for (var i = 0; i < listItemsLenght; ++i) {
4482 if (typeof listItems[i].tagName === 'undefined' || listItems[i].tagName.toLowerCase() !== 'li') {
4483 continue;
4484 }
4485
4486 // define the bullet to use in list
4487 var bullet = '';
4488 if (type === 'ol') {
4489 bullet = listNum.toString() + '. ';
4490 } else {
4491 bullet = '- ';
4492 }
4493
4494 // parse list item
4495 txt += bullet + showdown.subParser('makeMarkdown.listItem')(listItems[i], globals);
4496 ++listNum;
4497 }
4498
4499 return txt.trim();
4500 });
4501
4502 showdown.subParser('makeMarkdown.listItem', function (node, globals) {
4503 'use strict';
4504
4505 var listItemTxt = '';
4506
4507 var children = node.childNodes,
4508 childrenLenght = children.length;
4509
4510 for (var i = 0; i < childrenLenght; ++i) {
4511 listItemTxt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4512 }
4513 // if it's only one liner, we need to add a newline at the end
4514 if (!/\n$/.test(listItemTxt)) {
4515 listItemTxt += '\n';
4516 } else {
4517 // it's multiparagraph, so we need to indent
4518 listItemTxt = listItemTxt
4519 .split('\n')
4520 .join('\n ')
4521 .replace(/^ {4}$/gm, '')
4522 .replace(/\n\n+/g, '\n\n');
4523 }
4524
4525 return listItemTxt;
4526 });
4527
4528
4529
4530 showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) {
4531 'use strict';
4532
4533 spansOnly = spansOnly || false;
4534
4535 var txt = '';
4536
4537 // edge case of text without wrapper paragraph
4538 if (node.nodeType === 3) {
4539 return showdown.subParser('makeMarkdown.txt')(node, globals);
4540 }
4541
4542 // HTML comment
4543 if (node.nodeType === 8) {
4544 return '<!--' + node.data + '-->\n\n';
4545 }
4546
4547 // process only node elements
4548 if (node.nodeType !== 1) {
4549 return '';
4550 }
4551
4552 var tagName = node.tagName.toLowerCase();
4553
4554 switch (tagName) {
4555
4556 //
4557 // BLOCKS
4558 //
4559 case 'h1':
4560 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 1) + '\n\n'; }
4561 break;
4562 case 'h2':
4563 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 2) + '\n\n'; }
4564 break;
4565 case 'h3':
4566 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 3) + '\n\n'; }
4567 break;
4568 case 'h4':
4569 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 4) + '\n\n'; }
4570 break;
4571 case 'h5':
4572 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 5) + '\n\n'; }
4573 break;
4574 case 'h6':
4575 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.header')(node, globals, 6) + '\n\n'; }
4576 break;
4577
4578 case 'p':
4579 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.paragraph')(node, globals) + '\n\n'; }
4580 break;
4581
4582 case 'blockquote':
4583 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.blockquote')(node, globals) + '\n\n'; }
4584 break;
4585
4586 case 'hr':
4587 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.hr')(node, globals) + '\n\n'; }
4588 break;
4589
4590 case 'ol':
4591 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ol') + '\n\n'; }
4592 break;
4593
4594 case 'ul':
4595 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.list')(node, globals, 'ul') + '\n\n'; }
4596 break;
4597
4598 case 'precode':
4599 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.codeBlock')(node, globals) + '\n\n'; }
4600 break;
4601
4602 case 'pre':
4603 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.pre')(node, globals) + '\n\n'; }
4604 break;
4605
4606 case 'table':
4607 if (!spansOnly) { txt = showdown.subParser('makeMarkdown.table')(node, globals) + '\n\n'; }
4608 break;
4609
4610 //
4611 // SPANS
4612 //
4613 case 'code':
4614 txt = showdown.subParser('makeMarkdown.codeSpan')(node, globals);
4615 break;
4616
4617 case 'em':
4618 case 'i':
4619 txt = showdown.subParser('makeMarkdown.emphasis')(node, globals);
4620 break;
4621
4622 case 'strong':
4623 case 'b':
4624 txt = showdown.subParser('makeMarkdown.strong')(node, globals);
4625 break;
4626
4627 case 'del':
4628 txt = showdown.subParser('makeMarkdown.strikethrough')(node, globals);
4629 break;
4630
4631 case 'a':
4632 txt = showdown.subParser('makeMarkdown.links')(node, globals);
4633 break;
4634
4635 case 'img':
4636 txt = showdown.subParser('makeMarkdown.image')(node, globals);
4637 break;
4638
4639 default:
4640 txt = node.outerHTML + '\n\n';
4641 }
4642
4643 // common normalization
4644 // TODO eventually
4645
4646 return txt;
4647 });
4648
4649 showdown.subParser('makeMarkdown.paragraph', function (node, globals) {
4650 'use strict';
4651
4652 var txt = '';
4653 if (node.hasChildNodes()) {
4654 var children = node.childNodes,
4655 childrenLength = children.length;
4656 for (var i = 0; i < childrenLength; ++i) {
4657 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4658 }
4659 }
4660
4661 // some text normalization
4662 txt = txt.trim();
4663
4664 return txt;
4665 });
4666
4667 showdown.subParser('makeMarkdown.pre', function (node, globals) {
4668 'use strict';
4669
4670 var num = node.getAttribute('prenum');
4671 return '<pre>' + globals.preList[num] + '</pre>';
4672 });
4673
4674 showdown.subParser('makeMarkdown.strikethrough', function (node, globals) {
4675 'use strict';
4676
4677 var txt = '';
4678 if (node.hasChildNodes()) {
4679 txt += '~~';
4680 var children = node.childNodes,
4681 childrenLength = children.length;
4682 for (var i = 0; i < childrenLength; ++i) {
4683 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4684 }
4685 txt += '~~';
4686 }
4687 return txt;
4688 });
4689
4690 showdown.subParser('makeMarkdown.strong', function (node, globals) {
4691 'use strict';
4692
4693 var txt = '';
4694 if (node.hasChildNodes()) {
4695 txt += '**';
4696 var children = node.childNodes,
4697 childrenLength = children.length;
4698 for (var i = 0; i < childrenLength; ++i) {
4699 txt += showdown.subParser('makeMarkdown.node')(children[i], globals);
4700 }
4701 txt += '**';
4702 }
4703 return txt;
4704 });
4705
4706 showdown.subParser('makeMarkdown.table', function (node, globals) {
4707 'use strict';
4708
4709 var txt = '',
4710 tableArray = [[], []],
4711 headings = node.querySelectorAll('thead>tr>th'),
4712 rows = node.querySelectorAll('tbody>tr'),
4713 i, ii;
4714 for (i = 0; i < headings.length; ++i) {
4715 var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals),
4716 allign = '---';
4717
4718 if (headings[i].hasAttribute('style')) {
4719 var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, '');
4720 switch (style) {
4721 case 'text-align:left;':
4722 allign = ':---';
4723 break;
4724 case 'text-align:right;':
4725 allign = '---:';
4726 break;
4727 case 'text-align:center;':
4728 allign = ':---:';
4729 break;
4730 }
4731 }
4732 tableArray[0][i] = headContent.trim();
4733 tableArray[1][i] = allign;
4734 }
4735
4736 for (i = 0; i < rows.length; ++i) {
4737 var r = tableArray.push([]) - 1,
4738 cols = rows[i].getElementsByTagName('td');
4739
4740 for (ii = 0; ii < headings.length; ++ii) {
4741 var cellContent = ' ';
4742 if (typeof cols[ii] !== 'undefined') {
4743 cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], globals);
4744 }
4745 tableArray[r].push(cellContent);
4746 }
4747 }
4748
4749 var cellSpacesCount = 3;
4750 for (i = 0; i < tableArray.length; ++i) {
4751 for (ii = 0; ii < tableArray[i].length; ++ii) {
4752 var strLen = tableArray[i][ii].length;
4753 if (strLen > cellSpacesCount) {
4754 cellSpacesCount = strLen;
4755 }
4756 }
4757 }
4758
4759 for (i = 0; i < tableArray.length; ++i) {
4760 for (ii = 0; ii < tableArray[i].length; ++ii) {
4761 if (i === 1) {
4762 if (tableArray[i][ii].slice(-1) === ':') {
4763 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(-1), cellSpacesCount - 1, '-') + ':';
4764 } else {
4765 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-');
4766 }
4767 } else {
4768 tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount);
4769 }
4770 }
4771 txt += '| ' + tableArray[i].join(' | ') + ' |\n';
4772 }
4773
4774 return txt.trim();
4775 });
4776
4777 showdown.subParser('makeMarkdown.tableCell', function (node, globals) {
4778 'use strict';
4779
4780 var txt = '';
4781 if (!node.hasChildNodes()) {
4782 return '';
4783 }
4784 var children = node.childNodes,
4785 childrenLength = children.length;
4786
4787 for (var i = 0; i < childrenLength; ++i) {
4788 txt += showdown.subParser('makeMarkdown.node')(children[i], globals, true);
4789 }
4790 return txt.trim();
4791 });
4792
4793 showdown.subParser('makeMarkdown.txt', function (node) {
4794 'use strict';
4795
4796 var txt = node.nodeValue;
4797
4798 // multiple spaces are collapsed
4799 txt = txt.replace(/ +/g, ' ');
4800
4801 // replace the custom ¨NBSP; with a space
4802 txt = txt.replace(/¨NBSP;/g, ' ');
4803
4804 // ", <, > and & should replace escaped html entities
4805 txt = showdown.helper.unescapeHTMLEntities(txt);
4806
4807 // escape markdown magic characters
4808 // emphasis, strong and strikethrough - can appear everywhere
4809 // we also escape pipe (|) because of tables
4810 // and escape ` because of code blocks and spans
4811 txt = txt.replace(/([*_~|`])/g, '\\$1');
4812
4813 // escape > because of blockquotes
4814 txt = txt.replace(/^(\s*)>/g, '\\$1>');
4815
4816 // hash character, only troublesome at the beginning of a line because of headers
4817 txt = txt.replace(/^#/gm, '\\#');
4818
4819 // horizontal rules
4820 txt = txt.replace(/^(\s*)([-=]{3,})(\s*)$/, '$1\\$2$3');
4821
4822 // dot, because of ordered lists, only troublesome at the beginning of a line when preceded by an integer
4823 txt = txt.replace(/^( {0,3}\d+)\./gm, '$1\\.');
4824
4825 // +, * and -, at the beginning of a line becomes a list, so we need to escape them also (asterisk was already escaped)
4826 txt = txt.replace(/^( {0,3})([+-])/gm, '$1\\$2');
4827
4828 // images and links, ] followed by ( is problematic, so we escape it
4829 txt = txt.replace(/]([\s]*)\(/g, '\\]$1\\(');
4830
4831 // reference URIs must also be escaped
4832 txt = txt.replace(/^ {0,3}\[([\S \t]*?)]:/gm, '\\[$1]:');
4833
4834 return txt;
4835 });
4836
4837 /**
4838 * Created by Estevao on 31-05-2015.
4839 */
4840
4841 /**
4842 * Showdown Converter class
4843 * @class
4844 * @param {object} [converterOptions]
4845 * @returns {Converter}
4846 */
4847 showdown.Converter = function (converterOptions) {
4848 'use strict';
4849
4850 var
4851 /**
4852 * Options used by this converter
4853 * @private
4854 * @type {{}}
4855 */
4856 options = {},
4857
4858 /**
4859 * Language extensions used by this converter
4860 * @private
4861 * @type {Array}
4862 */
4863 langExtensions = [],
4864
4865 /**
4866 * Output modifiers extensions used by this converter
4867 * @private
4868 * @type {Array}
4869 */
4870 outputModifiers = [],
4871
4872 /**
4873 * Event listeners
4874 * @private
4875 * @type {{}}
4876 */
4877 listeners = {},
4878
4879 /**
4880 * The flavor set in this converter
4881 */
4882 setConvFlavor = setFlavor,
4883
4884 /**
4885 * Metadata of the document
4886 * @type {{parsed: {}, raw: string, format: string}}
4887 */
4888 metadata = {
4889 parsed: {},
4890 raw: '',
4891 format: ''
4892 };
4893
4894 _constructor();
4895
4896 /**
4897 * Converter constructor
4898 * @private
4899 */
4900 function _constructor () {
4901 converterOptions = converterOptions || {};
4902
4903 for (var gOpt in globalOptions) {
4904 if (globalOptions.hasOwnProperty(gOpt)) {
4905 options[gOpt] = globalOptions[gOpt];
4906 }
4907 }
4908
4909 // Merge options
4910 if (typeof converterOptions === 'object') {
4911 for (var opt in converterOptions) {
4912 if (converterOptions.hasOwnProperty(opt)) {
4913 options[opt] = converterOptions[opt];
4914 }
4915 }
4916 } else {
4917 throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
4918 ' was passed instead.');
4919 }
4920
4921 if (options.extensions) {
4922 showdown.helper.forEach(options.extensions, _parseExtension);
4923 }
4924 }
4925
4926 /**
4927 * Parse extension
4928 * @param {*} ext
4929 * @param {string} [name='']
4930 * @private
4931 */
4932 function _parseExtension (ext, name) {
4933
4934 name = name || null;
4935 // If it's a string, the extension was previously loaded
4936 if (showdown.helper.isString(ext)) {
4937 ext = showdown.helper.stdExtName(ext);
4938 name = ext;
4939
4940 // LEGACY_SUPPORT CODE
4941 if (showdown.extensions[ext]) {
4942 console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
4943 'Please inform the developer that the extension should be updated!');
4944 legacyExtensionLoading(showdown.extensions[ext], ext);
4945 return;
4946 // END LEGACY SUPPORT CODE
4947
4948 } else if (!showdown.helper.isUndefined(extensions[ext])) {
4949 ext = extensions[ext];
4950
4951 } else {
4952 throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
4953 }
4954 }
4955
4956 if (typeof ext === 'function') {
4957 ext = ext();
4958 }
4959
4960 if (!showdown.helper.isArray(ext)) {
4961 ext = [ext];
4962 }
4963
4964 var validExt = validate(ext, name);
4965 if (!validExt.valid) {
4966 throw Error(validExt.error);
4967 }
4968
4969 for (var i = 0; i < ext.length; ++i) {
4970 switch (ext[i].type) {
4971
4972 case 'lang':
4973 langExtensions.push(ext[i]);
4974 break;
4975
4976 case 'output':
4977 outputModifiers.push(ext[i]);
4978 break;
4979 }
4980 if (ext[i].hasOwnProperty('listeners')) {
4981 for (var ln in ext[i].listeners) {
4982 if (ext[i].listeners.hasOwnProperty(ln)) {
4983 listen(ln, ext[i].listeners[ln]);
4984 }
4985 }
4986 }
4987 }
4988
4989 }
4990
4991 /**
4992 * LEGACY_SUPPORT
4993 * @param {*} ext
4994 * @param {string} name
4995 */
4996 function legacyExtensionLoading (ext, name) {
4997 if (typeof ext === 'function') {
4998 ext = ext(new showdown.Converter());
4999 }
5000 if (!showdown.helper.isArray(ext)) {
5001 ext = [ext];
5002 }
5003 var valid = validate(ext, name);
5004
5005 if (!valid.valid) {
5006 throw Error(valid.error);
5007 }
5008
5009 for (var i = 0; i < ext.length; ++i) {
5010 switch (ext[i].type) {
5011 case 'lang':
5012 langExtensions.push(ext[i]);
5013 break;
5014 case 'output':
5015 outputModifiers.push(ext[i]);
5016 break;
5017 default:// should never reach here
5018 throw Error('Extension loader error: Type unrecognized!!!');
5019 }
5020 }
5021 }
5022
5023 /**
5024 * Listen to an event
5025 * @param {string} name
5026 * @param {function} callback
5027 */
5028 function listen (name, callback) {
5029 if (!showdown.helper.isString(name)) {
5030 throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
5031 }
5032
5033 if (typeof callback !== 'function') {
5034 throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
5035 }
5036 name = name.toLowerCase();
5037 if (!listeners.hasOwnProperty(name)) {
5038 listeners[name] = [];
5039 }
5040 listeners[name].push(callback);
5041 }
5042
5043 function rTrimInputText (text) {
5044 var rsp = text.match(/^\s*/)[0].length,
5045 rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
5046 return text.replace(rgx, '');
5047 }
5048
5049 /**
5050 *
5051 * @param {string} evtName Event name
5052 * @param {string} text Text
5053 * @param {{}} options Converter Options
5054 * @param {{}} globals Converter globals
5055 * @param {{}} pParams extra params for event
5056 * @returns showdown.helper.Event
5057 * @private
5058 */
5059 this._dispatch = function dispatch (evtName, text, options, globals, pParams) {
5060 evtName = evtName.toLowerCase();
5061 var params = pParams || {};
5062 params.converter = this;
5063 params.text = text;
5064 params.options = options;
5065 params.globals = globals;
5066 var event = new showdown.helper.Event(evtName, text, params);
5067
5068 if (listeners.hasOwnProperty(evtName)) {
5069 for (var ei = 0; ei < listeners[evtName].length; ++ei) {
5070 var nText = listeners[evtName][ei](event);
5071 if (nText && typeof nText !== 'undefined') {
5072 event.setText(nText);
5073 }
5074 }
5075 }
5076 return event;
5077 };
5078
5079 /**
5080 * Listen to an event
5081 * @param {string} name
5082 * @param {function} callback
5083 * @returns {showdown.Converter}
5084 */
5085 this.listen = function (name, callback) {
5086 listen(name, callback);
5087 return this;
5088 };
5089
5090 /**
5091 * Converts a markdown string into HTML string
5092 * @param {string} text
5093 * @returns {*}
5094 */
5095 this.makeHtml = function (text) {
5096 //check if text is not falsy
5097 if (!text) {
5098 return text;
5099 }
5100
5101 var globals = {
5102 gHtmlBlocks: [],
5103 gHtmlMdBlocks: [],
5104 gHtmlSpans: [],
5105 gUrls: {},
5106 gTitles: {},
5107 gDimensions: {},
5108 gListLevel: 0,
5109 hashLinkCounts: {},
5110 langExtensions: langExtensions,
5111 outputModifiers: outputModifiers,
5112 converter: this,
5113 ghCodeBlocks: [],
5114 metadata: {
5115 parsed: {},
5116 raw: '',
5117 format: ''
5118 }
5119 };
5120
5121 // This lets us use ¨ trema as an escape char to avoid md5 hashes
5122 // The choice of character is arbitrary; anything that isn't
5123 // magic in Markdown will work.
5124 text = text.replace(/¨/g, '¨T');
5125
5126 // Replace $ with ¨D
5127 // RegExp interprets $ as a special character
5128 // when it's in a replacement string
5129 text = text.replace(/\$/g, '¨D');
5130
5131 // Standardize line endings
5132 text = text.replace(/\r\n/g, '\n'); // DOS to Unix
5133 text = text.replace(/\r/g, '\n'); // Mac to Unix
5134
5135 // Stardardize line spaces
5136 text = text.replace(/\u00A0/g, '&nbsp;');
5137
5138 if (options.smartIndentationFix) {
5139 text = rTrimInputText(text);
5140 }
5141
5142 // Make sure text begins and ends with a couple of newlines:
5143 text = '\n\n' + text + '\n\n';
5144
5145 // detab
5146 text = showdown.subParser('makehtml.detab')(text, options, globals);
5147
5148 /**
5149 * Strip any lines consisting only of spaces and tabs.
5150 * This makes subsequent regexs easier to write, because we can
5151 * match consecutive blank lines with /\n+/ instead of something
5152 * contorted like /[ \t]*\n+/
5153 */
5154 text = text.replace(/^[ \t]+$/mg, '');
5155
5156 //run languageExtensions
5157 showdown.helper.forEach(langExtensions, function (ext) {
5158 text = showdown.subParser('makehtml.runExtension')(ext, text, options, globals);
5159 });
5160
5161 // run the sub parsers
5162 text = showdown.subParser('makehtml.metadata')(text, options, globals);
5163 text = showdown.subParser('makehtml.hashPreCodeTags')(text, options, globals);
5164 text = showdown.subParser('makehtml.githubCodeBlocks')(text, options, globals);
5165 text = showdown.subParser('makehtml.hashHTMLBlocks')(text, options, globals);
5166 text = showdown.subParser('makehtml.hashCodeTags')(text, options, globals);
5167 text = showdown.subParser('makehtml.stripLinkDefinitions')(text, options, globals);
5168 text = showdown.subParser('makehtml.blockGamut')(text, options, globals);
5169 text = showdown.subParser('makehtml.unhashHTMLSpans')(text, options, globals);
5170 text = showdown.subParser('makehtml.unescapeSpecialChars')(text, options, globals);
5171
5172 // attacklab: Restore dollar signs
5173 text = text.replace(/¨D/g, '$$');
5174
5175 // attacklab: Restore tremas
5176 text = text.replace(/¨T/g, '¨');
5177
5178 // render a complete html document instead of a partial if the option is enabled
5179 text = showdown.subParser('makehtml.completeHTMLDocument')(text, options, globals);
5180
5181 // Run output modifiers
5182 showdown.helper.forEach(outputModifiers, function (ext) {
5183 text = showdown.subParser('makehtml.runExtension')(ext, text, options, globals);
5184 });
5185
5186 // update metadata
5187 metadata = globals.metadata;
5188 return text;
5189 };
5190
5191 /**
5192 * Converts an HTML string into a markdown string
5193 * @param src
5194 * @returns {string}
5195 */
5196 this.makeMarkdown = function (src) {
5197
5198 // replace \r\n with \n
5199 src = src.replace(/\r\n/g, '\n');
5200 src = src.replace(/\r/g, '\n'); // old macs
5201
5202 // due to an edge case, we need to find this: > <
5203 // to prevent removing of non silent white spaces
5204 // ex: <em>this is</em> <strong>sparta</strong>
5205 src = src.replace(/>[ \t]+</, '>¨NBSP;<');
5206
5207 var doc = showdown.helper.document.createElement('div');
5208 doc.innerHTML = src;
5209
5210 var globals = {
5211 preList: substitutePreCodeTags(doc)
5212 };
5213
5214 // remove all newlines and collapse spaces
5215 clean(doc);
5216
5217 // some stuff, like accidental reference links must now be escaped
5218 // TODO
5219 // doc.innerHTML = doc.innerHTML.replace(/\[[\S\t ]]/);
5220
5221 var nodes = doc.childNodes,
5222 mdDoc = '';
5223
5224 for (var i = 0; i < nodes.length; i++) {
5225 mdDoc += showdown.subParser('makeMarkdown.node')(nodes[i], globals);
5226 }
5227
5228 function clean (node) {
5229 for (var n = 0; n < node.childNodes.length; ++n) {
5230 var child = node.childNodes[n];
5231 if (child.nodeType === 3) {
5232 if (!/\S/.test(child.nodeValue)) {
5233 node.removeChild(child);
5234 --n;
5235 } else {
5236 child.nodeValue = child.nodeValue.split('\n').join(' ');
5237 child.nodeValue = child.nodeValue.replace(/(\s)+/g, '$1');
5238 }
5239 } else if (child.nodeType === 1) {
5240 clean(child);
5241 }
5242 }
5243 }
5244
5245 // find all pre tags and replace contents with placeholder
5246 // we need this so that we can remove all indentation from html
5247 // to ease up parsing
5248 function substitutePreCodeTags (doc) {
5249
5250 var pres = doc.querySelectorAll('pre'),
5251 presPH = [];
5252
5253 for (var i = 0; i < pres.length; ++i) {
5254
5255 if (pres[i].childElementCount === 1 && pres[i].firstChild.tagName.toLowerCase() === 'code') {
5256 var content = pres[i].firstChild.innerHTML.trim(),
5257 language = pres[i].firstChild.getAttribute('data-language') || '';
5258
5259 // if data-language attribute is not defined, then we look for class language-*
5260 if (language === '') {
5261 var classes = pres[i].firstChild.className.split(' ');
5262 for (var c = 0; c < classes.length; ++c) {
5263 var matches = classes[c].match(/^language-(.+)$/);
5264 if (matches !== null) {
5265 language = matches[1];
5266 break;
5267 }
5268 }
5269 }
5270
5271 // unescape html entities in content
5272 content = showdown.helper.unescapeHTMLEntities(content);
5273
5274 presPH.push(content);
5275 pres[i].outerHTML = '<precode language="' + language + '" precodenum="' + i.toString() + '"></precode>';
5276 } else {
5277 presPH.push(pres[i].innerHTML);
5278 pres[i].innerHTML = '';
5279 pres[i].setAttribute('prenum', i.toString());
5280 }
5281 }
5282 return presPH;
5283 }
5284
5285 return mdDoc;
5286 };
5287
5288 /**
5289 * Set an option of this Converter instance
5290 * @param {string} key
5291 * @param {*} value
5292 */
5293 this.setOption = function (key, value) {
5294 options[key] = value;
5295 };
5296
5297 /**
5298 * Get the option of this Converter instance
5299 * @param {string} key
5300 * @returns {*}
5301 */
5302 this.getOption = function (key) {
5303 return options[key];
5304 };
5305
5306 /**
5307 * Get the options of this Converter instance
5308 * @returns {{}}
5309 */
5310 this.getOptions = function () {
5311 return options;
5312 };
5313
5314 /**
5315 * Add extension to THIS converter
5316 * @param {{}} extension
5317 * @param {string} [name=null]
5318 */
5319 this.addExtension = function (extension, name) {
5320 name = name || null;
5321 _parseExtension(extension, name);
5322 };
5323
5324 /**
5325 * Use a global registered extension with THIS converter
5326 * @param {string} extensionName Name of the previously registered extension
5327 */
5328 this.useExtension = function (extensionName) {
5329 _parseExtension(extensionName);
5330 };
5331
5332 /**
5333 * Set the flavor THIS converter should use
5334 * @param {string} name
5335 */
5336 this.setFlavor = function (name) {
5337 if (!flavor.hasOwnProperty(name)) {
5338 throw Error(name + ' flavor was not found');
5339 }
5340 var preset = flavor[name];
5341 setConvFlavor = name;
5342 for (var option in preset) {
5343 if (preset.hasOwnProperty(option)) {
5344 options[option] = preset[option];
5345 }
5346 }
5347 };
5348
5349 /**
5350 * Get the currently set flavor of this converter
5351 * @returns {string}
5352 */
5353 this.getFlavor = function () {
5354 return setConvFlavor;
5355 };
5356
5357 /**
5358 * Remove an extension from THIS converter.
5359 * Note: This is a costly operation. It's better to initialize a new converter
5360 * and specify the extensions you wish to use
5361 * @param {Array} extension
5362 */
5363 this.removeExtension = function (extension) {
5364 if (!showdown.helper.isArray(extension)) {
5365 extension = [extension];
5366 }
5367 for (var a = 0; a < extension.length; ++a) {
5368 var ext = extension[a];
5369 for (var i = 0; i < langExtensions.length; ++i) {
5370 if (langExtensions[i] === ext) {
5371 langExtensions[i].splice(i, 1);
5372 }
5373 }
5374 for (var ii = 0; ii < outputModifiers.length; ++i) {
5375 if (outputModifiers[ii] === ext) {
5376 outputModifiers[ii].splice(i, 1);
5377 }
5378 }
5379 }
5380 };
5381
5382 /**
5383 * Get all extension of THIS converter
5384 * @returns {{language: Array, output: Array}}
5385 */
5386 this.getAllExtensions = function () {
5387 return {
5388 language: langExtensions,
5389 output: outputModifiers
5390 };
5391 };
5392
5393 /**
5394 * Get the metadata of the previously parsed document
5395 * @param raw
5396 * @returns {string|{}}
5397 */
5398 this.getMetadata = function (raw) {
5399 if (raw) {
5400 return metadata.raw;
5401 } else {
5402 return metadata.parsed;
5403 }
5404 };
5405
5406 /**
5407 * Get the metadata format of the previously parsed document
5408 * @returns {string}
5409 */
5410 this.getMetadataFormat = function () {
5411 return metadata.format;
5412 };
5413
5414 /**
5415 * Private: set a single key, value metadata pair
5416 * @param {string} key
5417 * @param {string} value
5418 */
5419 this._setMetadataPair = function (key, value) {
5420 metadata.parsed[key] = value;
5421 };
5422
5423 /**
5424 * Private: set metadata format
5425 * @param {string} format
5426 */
5427 this._setMetadataFormat = function (format) {
5428 metadata.format = format;
5429 };
5430
5431 /**
5432 * Private: set metadata raw text
5433 * @param {string} raw
5434 */
5435 this._setMetadataRaw = function (raw) {
5436 metadata.raw = raw;
5437 };
5438 };
5439
5440 var root = this;
5441
5442 // AMD Loader
5443 if (typeof define === 'function' && define.amd) {
5444 define(function () {
5445 'use strict';
5446 return showdown;
5447 });
5448
5449 // CommonJS/nodeJS Loader
5450 } else if (typeof module !== 'undefined' && module.exports) {
5451 module.exports = showdown;
5452
5453 // Regular Browser loader
5454 } else {
5455 root.showdown = showdown;
5456 }
5457 }).call(this);
5458
5459 //# sourceMappingURL=showdown.js.map
+0
-3
faraday/server/www/script/showdown.min.js less more
0 /*! showdown v 2.0.0-alpha1 - 24-10-2018 */
1 (function(){function a(e){"use strict";var r={omitExtraWLInCodeBlocks:{defaultValue:!1,describe:"Omit the default extra whiteline added to code blocks",type:"boolean"},noHeaderId:{defaultValue:!1,describe:"Turn on/off generated header id",type:"boolean"},prefixHeaderId:{defaultValue:!1,describe:"Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic 'section-' prefix",type:"string"},rawPrefixHeaderId:{defaultValue:!1,describe:'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',type:"boolean"},ghCompatibleHeaderId:{defaultValue:!1,describe:"Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)",type:"boolean"},rawHeaderId:{defaultValue:!1,describe:"Remove only spaces, ' and \" from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids",type:"boolean"},headerLevelStart:{defaultValue:!1,describe:"The header blocks level start",type:"integer"},parseImgDimensions:{defaultValue:!1,describe:"Turn on/off image dimension parsing",type:"boolean"},simplifiedAutoLink:{defaultValue:!1,describe:"Turn on/off GFM autolink style",type:"boolean"},literalMidWordUnderscores:{defaultValue:!1,describe:"Parse midword underscores as literal underscores",type:"boolean"},literalMidWordAsterisks:{defaultValue:!1,describe:"Parse midword asterisks as literal asterisks",type:"boolean"},strikethrough:{defaultValue:!1,describe:"Turn on/off strikethrough support",type:"boolean"},tables:{defaultValue:!1,describe:"Turn on/off tables support",type:"boolean"},tablesHeaderId:{defaultValue:!1,describe:"Add an id to table headers",type:"boolean"},ghCodeBlocks:{defaultValue:!0,describe:"Turn on/off GFM fenced code blocks support",type:"boolean"},tasklists:{defaultValue:!1,describe:"Turn on/off GFM tasklist support",type:"boolean"},smoothLivePreview:{defaultValue:!1,describe:"Prevents weird effects in live previews due to incomplete input",type:"boolean"},smartIndentationFix:{defaultValue:!1,description:"Tries to smartly fix indentation in es6 strings",type:"boolean"},disableForced4SpacesIndentedSublists:{defaultValue:!1,description:"Disables the requirement of indenting nested sublists by 4 spaces",type:"boolean"},simpleLineBreaks:{defaultValue:!1,description:"Parses simple line breaks as <br> (GFM Style)",type:"boolean"},requireSpaceBeforeHeadingText:{defaultValue:!1,description:"Makes adding a space between `#` and the header text mandatory (GFM Style)",type:"boolean"},ghMentions:{defaultValue:!1,description:"Enables github @mentions",type:"boolean"},ghMentionsLink:{defaultValue:"https://github.com/{u}",description:"Changes the link generated by @mentions. Only applies if ghMentions option is enabled.",type:"string"},encodeEmails:{defaultValue:!0,description:"Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities",type:"boolean"},openLinksInNewWindow:{defaultValue:!1,description:"Open all links in new windows",type:"boolean"},backslashEscapesHTMLTags:{defaultValue:!1,description:"Support for HTML Tag escaping. ex: <div>foo</div>",type:"boolean"},emoji:{defaultValue:!1,description:"Enable emoji support. Ex: `this is a :smile: emoji`",type:"boolean"},underline:{defaultValue:!1,description:"Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `<em>` and `<strong>`",type:"boolean"},completeHTMLDocument:{defaultValue:!1,description:"Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags",type:"boolean"},metadata:{defaultValue:!1,description:"Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).",type:"boolean"},splitAdjacentBlockquotes:{defaultValue:!1,description:"Split adjacent blockquote blocks",type:"boolean"}};if(!1===e)return JSON.parse(JSON.stringify(r));var t={};for(var a in r)r.hasOwnProperty(a)&&(t[a]=r[a].defaultValue);return t}var b={},t={},h={},m=a(!0),d="vanilla",p={github:{omitExtraWLInCodeBlocks:!0,simplifiedAutoLink:!0,literalMidWordUnderscores:!0,strikethrough:!0,tables:!0,tablesHeaderId:!0,ghCodeBlocks:!0,tasklists:!0,disableForced4SpacesIndentedSublists:!0,simpleLineBreaks:!0,requireSpaceBeforeHeadingText:!0,ghCompatibleHeaderId:!0,ghMentions:!0,backslashEscapesHTMLTags:!0,emoji:!0,splitAdjacentBlockquotes:!0},original:{noHeaderId:!0,ghCodeBlocks:!1},ghost:{omitExtraWLInCodeBlocks:!0,parseImgDimensions:!0,simplifiedAutoLink:!0,literalMidWordUnderscores:!0,strikethrough:!0,tables:!0,tablesHeaderId:!0,ghCodeBlocks:!0,tasklists:!0,smoothLivePreview:!0,simpleLineBreaks:!0,requireSpaceBeforeHeadingText:!0,ghMentions:!1,encodeEmails:!0},vanilla:a(!0),allOn:function(){"use strict";var e=a(!0),r={};for(var t in e)e.hasOwnProperty(t)&&(r[t]=!0);return r}()};function g(e,r){"use strict";var t=r?"Error in "+r+" extension->":"Error in unnamed extension",a={valid:!0,error:""};b.helper.isArray(e)||(e=[e]);for(var n=0;n<e.length;++n){var s=t+" sub-extension "+n+": ",o=e[n];if("object"!=typeof o)return a.valid=!1,a.error=s+"must be an object, but "+typeof o+" given",a;if(!b.helper.isString(o.type))return a.valid=!1,a.error=s+'property "type" must be a string, but '+typeof o.type+" given",a;var i=o.type=o.type.toLowerCase();if("language"===i&&(i=o.type="lang"),"html"===i&&(i=o.type="output"),"lang"!==i&&"output"!==i&&"listener"!==i)return a.valid=!1,a.error=s+"type "+i+' is not recognized. Valid values: "lang/language", "output/html" or "listener"',a;if("listener"===i){if(b.helper.isUndefined(o.listeners))return a.valid=!1,a.error=s+'. Extensions of type "listener" must have a property called "listeners"',a}else if(b.helper.isUndefined(o.filter)&&b.helper.isUndefined(o.regex))return a.valid=!1,a.error=s+i+' extensions must define either a "regex" property or a "filter" method',a;if(o.listeners){if("object"!=typeof o.listeners)return a.valid=!1,a.error=s+'"listeners" property must be an object but '+typeof o.listeners+" given",a;for(var l in o.listeners)if(o.listeners.hasOwnProperty(l)&&"function"!=typeof o.listeners[l])return a.valid=!1,a.error=s+'"listeners" property must be an hash of [event name]: [callback]. listeners.'+l+" must be a function but "+typeof o.listeners[l]+" given",a}if(o.filter){if("function"!=typeof o.filter)return a.valid=!1,a.error=s+'"filter" must be a function, but '+typeof o.filter+" given",a}else if(o.regex){if(b.helper.isString(o.regex)&&(o.regex=new RegExp(o.regex,"g")),!(o.regex instanceof RegExp))return a.valid=!1,a.error=s+'"regex" property must either be a string or a RegExp object, but '+typeof o.regex+" given",a;if(b.helper.isUndefined(o.replace))return a.valid=!1,a.error=s+'"regex" extensions must implement a replace string or function',a}}return a}if(b.helper={},b.extensions={},b.setOption=function(e,r){"use strict";return m[e]=r,this},b.getOption=function(e){"use strict";return m[e]},b.getOptions=function(){"use strict";return m},b.resetOptions=function(){"use strict";m=a(!0)},b.setFlavor=function(e){"use strict";if(!p.hasOwnProperty(e))throw Error(e+" flavor was not found");b.resetOptions();var r=p[e];for(var t in d=e,r)r.hasOwnProperty(t)&&(m[t]=r[t])},b.getFlavor=function(){"use strict";return d},b.getFlavorOptions=function(e){"use strict";if(p.hasOwnProperty(e))return p[e]},b.getDefaultOptions=function(e){"use strict";return a(e)},b.subParser=function(e,r){"use strict";if(!b.helper.isString(e))throw Error("showdown.subParser function first argument must be a string (the name of the subparser)");if(void 0===r){if(t.hasOwnProperty(e))return t[e];throw Error("SubParser named "+e+" not registered!")}t[e]=r},b.extension=function(e,r){"use strict";if(!b.helper.isString(e))throw Error("Extension 'name' must be a string");if(e=b.helper.stdExtName(e),b.helper.isUndefined(r)){if(!h.hasOwnProperty(e))throw Error("Extension named "+e+" is not registered!");return h[e]}"function"==typeof r&&(r=r()),b.helper.isArray(r)||(r=[r]);var t=g(r,e);if(!t.valid)throw Error(t.error);h[e]=r},b.getAllExtensions=function(){"use strict";return h},b.removeExtension=function(e){"use strict";delete h[e]},b.resetExtensions=function(){"use strict";h={}},b.validateExtension=function(e){"use strict";var r=g(e,null);return!!r.valid||(console.warn(r.error),!1)},b.hasOwnProperty("helper")||(b.helper={}),void 0===this.document&&void 0===this.window){var e=require("jsdom");this.window=new e.JSDOM("",{}).window}function s(e,r){"use strict";return"¨E"+r.charCodeAt(0)+"E"}b.helper.document=this.window.document,b.helper.isString=function(e){"use strict";return"string"==typeof e||e instanceof String},b.helper.isFunction=function(e){"use strict";return e&&"[object Function]"==={}.toString.call(e)},b.helper.isArray=function(e){"use strict";return Array.isArray(e)},b.helper.isUndefined=function(e){"use strict";return void 0===e},b.helper.forEach=function(e,r){"use strict";if(b.helper.isUndefined(e))throw new Error("obj param is required");if(b.helper.isUndefined(r))throw new Error("callback param is required");if(!b.helper.isFunction(r))throw new Error("callback param must be a function/closure");if("function"==typeof e.forEach)e.forEach(r);else if(b.helper.isArray(e))for(var t=0;t<e.length;t++)r(e[t],t,e);else{if("object"!=typeof e)throw new Error("obj does not seem to be an array or an iterable object");for(var a in e)e.hasOwnProperty(a)&&r(e[a],a,e)}},b.helper.stdExtName=function(e){"use strict";return e.replace(/[_?*+\/\\.^-]/g,"").replace(/\s/g,"").toLowerCase()},b.helper.escapeCharactersCallback=s,b.helper.escapeCharacters=function(e,r,t){"use strict";var a="(["+r.replace(/([\[\]\\])/g,"\\$1")+"])";t&&(a="\\\\"+a);var n=new RegExp(a,"g");return e=e.replace(n,s)};var _=function(e,r,t,a){"use strict";var n,s,o,i,l,c=a||"",u=-1<c.indexOf("g"),h=new RegExp(r+"|"+t,"g"+c.replace(/g/g,"")),m=new RegExp(r,c.replace(/g/g,"")),d=[];do{for(n=0;o=h.exec(e);)if(m.test(o[0]))n++||(i=(s=h.lastIndex)-o[0].length);else if(n&&!--n){l=o.index+o[0].length;var p={left:{start:i,end:s},match:{start:s,end:o.index},right:{start:o.index,end:l},wholeMatch:{start:i,end:l}};if(d.push(p),!u)return d}}while(n&&(h.lastIndex=s));return d};b.helper.matchRecursiveRegExp=function(e,r,t,a){"use strict";for(var n=_(e,r,t,a),s=[],o=0;o<n.length;++o)s.push([e.slice(n[o].wholeMatch.start,n[o].wholeMatch.end),e.slice(n[o].match.start,n[o].match.end),e.slice(n[o].left.start,n[o].left.end),e.slice(n[o].right.start,n[o].right.end)]);return s},b.helper.replaceRecursiveRegExp=function(e,r,t,a,n){"use strict";if(!b.helper.isFunction(r)){var s=r;r=function(){return s}}var o=_(e,t,a,n),i=e,l=o.length;if(0<l){var c=[];0!==o[0].wholeMatch.start&&c.push(e.slice(0,o[0].wholeMatch.start));for(var u=0;u<l;++u)c.push(r(e.slice(o[u].wholeMatch.start,o[u].wholeMatch.end),e.slice(o[u].match.start,o[u].match.end),e.slice(o[u].left.start,o[u].left.end),e.slice(o[u].right.start,o[u].right.end))),u<l-1&&c.push(e.slice(o[u].wholeMatch.end,o[u+1].wholeMatch.start));o[l-1].wholeMatch.end<e.length&&c.push(e.slice(o[l-1].wholeMatch.end)),i=c.join("")}return i},b.helper.regexIndexOf=function(e,r,t){"use strict";if(!b.helper.isString(e))throw"InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string";if(r instanceof RegExp==!1)throw"InvalidArgumentError: second parameter of showdown.helper.regexIndexOf function must be an instance of RegExp";var a=e.substring(t||0).search(r);return 0<=a?a+(t||0):a},b.helper.splitAtIndex=function(e,r){"use strict";if(!b.helper.isString(e))throw"InvalidArgumentError: first parameter of showdown.helper.regexIndexOf function must be a string";return[e.substring(0,r),e.substring(r)]},b.helper.encodeEmailAddress=function(e){"use strict";var t=[function(e){return"&#"+e.charCodeAt(0)+";"},function(e){return"&#x"+e.charCodeAt(0).toString(16)+";"},function(e){return e}];return e=e.replace(/./g,function(e){if("@"===e)e=t[Math.floor(2*Math.random())](e);else{var r=Math.random();e=.9<r?t[2](e):.45<r?t[1](e):t[0](e)}return e})},b.helper.padEnd=function(e,r,t){"use strict";return r>>=0,t=String(t||" "),e.length>r?String(e):((r-=e.length)>t.length&&(t+=t.repeat(r/t.length)),String(e)+t.slice(0,r))},b.helper.unescapeHTMLEntities=function(e){"use strict";return e.replace(/&quot;/g,'"').replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&")},b.helper._hashHTMLSpan=function(e,r){return"¨C"+(r.gHtmlSpans.push(e)-1)+"C"},b.helper.Event=function(e,r,t){"use strict";var a=t.regexp||null,n=t.matches||{},s=t.options||{},o=t.converter||null,i=t.globals||{};this.getName=function(){return e},this.getEventName=function(){return e},this._stopExecution=!1,this.parsedText=t.parsedText||null,this.getRegexp=function(){return a},this.getOptions=function(){return s},this.getConverter=function(){return o},this.getGlobals=function(){return i},this.getCapturedText=function(){return r},this.getText=function(){return r},this.setText=function(e){r=e},this.getMatches=function(){return n},this.setMatches=function(e){n=e},this.preventDefault=function(e){this._stopExecution=!e}},"undefined"==typeof console&&(console={warn:function(e){"use strict";alert(e)},log:function(e){"use strict";alert(e)},error:function(e){"use strict";throw e}}),b.helper.regexes={asteriskDashTildeAndColon:/([*_:~])/g,asteriskDashAndTilde:/([*_~])/g},b.helper.emojis={"+1":"👍","-1":"👎",100:"💯",1234:"🔢","1st_place_medal":"🥇","2nd_place_medal":"🥈","3rd_place_medal":"🥉","8ball":"🎱",a:"🅰️",ab:"🆎",abc:"🔤",abcd:"🔡",accept:"🉑",aerial_tramway:"🚡",airplane:"✈️",alarm_clock:"⏰",alembic:"⚗️",alien:"👽",ambulance:"🚑",amphora:"🏺",anchor:"⚓️",angel:"👼",anger:"💢",angry:"😠",anguished:"😧",ant:"🐜",apple:"🍎",aquarius:"♒️",aries:"♈️",arrow_backward:"◀️",arrow_double_down:"⏬",arrow_double_up:"⏫",arrow_down:"⬇️",arrow_down_small:"🔽",arrow_forward:"▶️",arrow_heading_down:"⤵️",arrow_heading_up:"⤴️",arrow_left:"⬅️",arrow_lower_left:"↙️",arrow_lower_right:"↘️",arrow_right:"➡️",arrow_right_hook:"↪️",arrow_up:"⬆️",arrow_up_down:"↕️",arrow_up_small:"🔼",arrow_upper_left:"↖️",arrow_upper_right:"↗️",arrows_clockwise:"🔃",arrows_counterclockwise:"🔄",art:"🎨",articulated_lorry:"🚛",artificial_satellite:"🛰",astonished:"😲",athletic_shoe:"👟",atm:"🏧",atom_symbol:"⚛️",avocado:"🥑",b:"🅱️",baby:"👶",baby_bottle:"🍼",baby_chick:"🐤",baby_symbol:"🚼",back:"🔙",bacon:"🥓",badminton:"🏸",baggage_claim:"🛄",baguette_bread:"🥖",balance_scale:"⚖️",balloon:"🎈",ballot_box:"🗳",ballot_box_with_check:"☑️",bamboo:"🎍",banana:"🍌",bangbang:"‼️",bank:"🏦",bar_chart:"📊",barber:"💈",baseball:"⚾️",basketball:"🏀",basketball_man:"⛹️",basketball_woman:"⛹️&zwj;♀️",bat:"🦇",bath:"🛀",bathtub:"🛁",battery:"🔋",beach_umbrella:"🏖",bear:"🐻",bed:"🛏",bee:"🐝",beer:"🍺",beers:"🍻",beetle:"🐞",beginner:"🔰",bell:"🔔",bellhop_bell:"🛎",bento:"🍱",biking_man:"🚴",bike:"🚲",biking_woman:"🚴&zwj;♀️",bikini:"👙",biohazard:"☣️",bird:"🐦",birthday:"🎂",black_circle:"⚫️",black_flag:"🏴",black_heart:"🖤",black_joker:"🃏",black_large_square:"⬛️",black_medium_small_square:"◾️",black_medium_square:"◼️",black_nib:"✒️",black_small_square:"▪️",black_square_button:"🔲",blonde_man:"👱",blonde_woman:"👱&zwj;♀️",blossom:"🌼",blowfish:"🐡",blue_book:"📘",blue_car:"🚙",blue_heart:"💙",blush:"😊",boar:"🐗",boat:"⛵️",bomb:"💣",book:"📖",bookmark:"🔖",bookmark_tabs:"📑",books:"📚",boom:"💥",boot:"👢",bouquet:"💐",bowing_man:"🙇",bow_and_arrow:"🏹",bowing_woman:"🙇&zwj;♀️",bowling:"🎳",boxing_glove:"🥊",boy:"👦",bread:"🍞",bride_with_veil:"👰",bridge_at_night:"🌉",briefcase:"💼",broken_heart:"💔",bug:"🐛",building_construction:"🏗",bulb:"💡",bullettrain_front:"🚅",bullettrain_side:"🚄",burrito:"🌯",bus:"🚌",business_suit_levitating:"🕴",busstop:"🚏",bust_in_silhouette:"👤",busts_in_silhouette:"👥",butterfly:"🦋",cactus:"🌵",cake:"🍰",calendar:"📆",call_me_hand:"🤙",calling:"📲",camel:"🐫",camera:"📷",camera_flash:"📸",camping:"🏕",cancer:"♋️",candle:"🕯",candy:"🍬",canoe:"🛶",capital_abcd:"🔠",capricorn:"♑️",car:"🚗",card_file_box:"🗃",card_index:"📇",card_index_dividers:"🗂",carousel_horse:"🎠",carrot:"🥕",cat:"🐱",cat2:"🐈",cd:"💿",chains:"⛓",champagne:"🍾",chart:"💹",chart_with_downwards_trend:"📉",chart_with_upwards_trend:"📈",checkered_flag:"🏁",cheese:"🧀",cherries:"🍒",cherry_blossom:"🌸",chestnut:"🌰",chicken:"🐔",children_crossing:"🚸",chipmunk:"🐿",chocolate_bar:"🍫",christmas_tree:"🎄",church:"⛪️",cinema:"🎦",circus_tent:"🎪",city_sunrise:"🌇",city_sunset:"🌆",cityscape:"🏙",cl:"🆑",clamp:"🗜",clap:"👏",clapper:"🎬",classical_building:"🏛",clinking_glasses:"🥂",clipboard:"📋",clock1:"🕐",clock10:"🕙",clock1030:"🕥",clock11:"🕚",clock1130:"🕦",clock12:"🕛",clock1230:"🕧",clock130:"🕜",clock2:"🕑",clock230:"🕝",clock3:"🕒",clock330:"🕞",clock4:"🕓",clock430:"🕟",clock5:"🕔",clock530:"🕠",clock6:"🕕",clock630:"🕡",clock7:"🕖",clock730:"🕢",clock8:"🕗",clock830:"🕣",clock9:"🕘",clock930:"🕤",closed_book:"📕",closed_lock_with_key:"🔐",closed_umbrella:"🌂",cloud:"☁️",cloud_with_lightning:"🌩",cloud_with_lightning_and_rain:"⛈",cloud_with_rain:"🌧",cloud_with_snow:"🌨",clown_face:"🤡",clubs:"♣️",cocktail:"🍸",coffee:"☕️",coffin:"⚰️",cold_sweat:"😰",comet:"☄️",computer:"💻",computer_mouse:"🖱",confetti_ball:"🎊",confounded:"😖",confused:"😕",congratulations:"㊗️",construction:"🚧",construction_worker_man:"👷",construction_worker_woman:"👷&zwj;♀️",control_knobs:"🎛",convenience_store:"🏪",cookie:"🍪",cool:"🆒",policeman:"👮",copyright:"©️",corn:"🌽",couch_and_lamp:"🛋",couple:"👫",couple_with_heart_woman_man:"💑",couple_with_heart_man_man:"👨&zwj;❤️&zwj;👨",couple_with_heart_woman_woman:"👩&zwj;❤️&zwj;👩",couplekiss_man_man:"👨&zwj;❤️&zwj;💋&zwj;👨",couplekiss_man_woman:"💏",couplekiss_woman_woman:"👩&zwj;❤️&zwj;💋&zwj;👩",cow:"🐮",cow2:"🐄",cowboy_hat_face:"🤠",crab:"🦀",crayon:"🖍",credit_card:"💳",crescent_moon:"🌙",cricket:"🏏",crocodile:"🐊",croissant:"🥐",crossed_fingers:"🤞",crossed_flags:"🎌",crossed_swords:"⚔️",crown:"👑",cry:"😢",crying_cat_face:"😿",crystal_ball:"🔮",cucumber:"🥒",cupid:"💘",curly_loop:"➰",currency_exchange:"💱",curry:"🍛",custard:"🍮",customs:"🛃",cyclone:"🌀",dagger:"🗡",dancer:"💃",dancing_women:"👯",dancing_men:"👯&zwj;♂️",dango:"🍡",dark_sunglasses:"🕶",dart:"🎯",dash:"💨",date:"📅",deciduous_tree:"🌳",deer:"🦌",department_store:"🏬",derelict_house:"🏚",desert:"🏜",desert_island:"🏝",desktop_computer:"🖥",male_detective:"🕵️",diamond_shape_with_a_dot_inside:"💠",diamonds:"♦️",disappointed:"😞",disappointed_relieved:"😥",dizzy:"💫",dizzy_face:"😵",do_not_litter:"🚯",dog:"🐶",dog2:"🐕",dollar:"💵",dolls:"🎎",dolphin:"🐬",door:"🚪",doughnut:"🍩",dove:"🕊",dragon:"🐉",dragon_face:"🐲",dress:"👗",dromedary_camel:"🐪",drooling_face:"🤤",droplet:"💧",drum:"🥁",duck:"🦆",dvd:"📀","e-mail":"📧",eagle:"🦅",ear:"👂",ear_of_rice:"🌾",earth_africa:"🌍",earth_americas:"🌎",earth_asia:"🌏",egg:"🥚",eggplant:"🍆",eight_pointed_black_star:"✴️",eight_spoked_asterisk:"✳️",electric_plug:"🔌",elephant:"🐘",email:"✉️",end:"🔚",envelope_with_arrow:"📩",euro:"💶",european_castle:"🏰",european_post_office:"🏤",evergreen_tree:"🌲",exclamation:"❗️",expressionless:"😑",eye:"👁",eye_speech_bubble:"👁&zwj;🗨",eyeglasses:"👓",eyes:"👀",face_with_head_bandage:"🤕",face_with_thermometer:"🤒",fist_oncoming:"👊",factory:"🏭",fallen_leaf:"🍂",family_man_woman_boy:"👪",family_man_boy:"👨&zwj;👦",family_man_boy_boy:"👨&zwj;👦&zwj;👦",family_man_girl:"👨&zwj;👧",family_man_girl_boy:"👨&zwj;👧&zwj;👦",family_man_girl_girl:"👨&zwj;👧&zwj;👧",family_man_man_boy:"👨&zwj;👨&zwj;👦",family_man_man_boy_boy:"👨&zwj;👨&zwj;👦&zwj;👦",family_man_man_girl:"👨&zwj;👨&zwj;👧",family_man_man_girl_boy:"👨&zwj;👨&zwj;👧&zwj;👦",family_man_man_girl_girl:"👨&zwj;👨&zwj;👧&zwj;👧",family_man_woman_boy_boy:"👨&zwj;👩&zwj;👦&zwj;👦",family_man_woman_girl:"👨&zwj;👩&zwj;👧",family_man_woman_girl_boy:"👨&zwj;👩&zwj;👧&zwj;👦",family_man_woman_girl_girl:"👨&zwj;👩&zwj;👧&zwj;👧",family_woman_boy:"👩&zwj;👦",family_woman_boy_boy:"👩&zwj;👦&zwj;👦",family_woman_girl:"👩&zwj;👧",family_woman_girl_boy:"👩&zwj;👧&zwj;👦",family_woman_girl_girl:"👩&zwj;👧&zwj;👧",family_woman_woman_boy:"👩&zwj;👩&zwj;👦",family_woman_woman_boy_boy:"👩&zwj;👩&zwj;👦&zwj;👦",family_woman_woman_girl:"👩&zwj;👩&zwj;👧",family_woman_woman_girl_boy:"👩&zwj;👩&zwj;👧&zwj;👦",family_woman_woman_girl_girl:"👩&zwj;👩&zwj;👧&zwj;👧",fast_forward:"⏩",fax:"📠",fearful:"😨",feet:"🐾",female_detective:"🕵️&zwj;♀️",ferris_wheel:"🎡",ferry:"⛴",field_hockey:"🏑",file_cabinet:"🗄",file_folder:"📁",film_projector:"📽",film_strip:"🎞",fire:"🔥",fire_engine:"🚒",fireworks:"🎆",first_quarter_moon:"🌓",first_quarter_moon_with_face:"🌛",fish:"🐟",fish_cake:"🍥",fishing_pole_and_fish:"🎣",fist_raised:"✊",fist_left:"🤛",fist_right:"🤜",flags:"🎏",flashlight:"🔦",fleur_de_lis:"⚜️",flight_arrival:"🛬",flight_departure:"🛫",floppy_disk:"💾",flower_playing_cards:"🎴",flushed:"😳",fog:"🌫",foggy:"🌁",football:"🏈",footprints:"👣",fork_and_knife:"🍴",fountain:"⛲️",fountain_pen:"🖋",four_leaf_clover:"🍀",fox_face:"🦊",framed_picture:"🖼",free:"🆓",fried_egg:"🍳",fried_shrimp:"🍤",fries:"🍟",frog:"🐸",frowning:"😦",frowning_face:"☹️",frowning_man:"🙍&zwj;♂️",frowning_woman:"🙍",middle_finger:"🖕",fuelpump:"⛽️",full_moon:"🌕",full_moon_with_face:"🌝",funeral_urn:"⚱️",game_die:"🎲",gear:"⚙️",gem:"💎",gemini:"♊️",ghost:"👻",gift:"🎁",gift_heart:"💝",girl:"👧",globe_with_meridians:"🌐",goal_net:"🥅",goat:"🐐",golf:"⛳️",golfing_man:"🏌️",golfing_woman:"🏌️&zwj;♀️",gorilla:"🦍",grapes:"🍇",green_apple:"🍏",green_book:"📗",green_heart:"💚",green_salad:"🥗",grey_exclamation:"❕",grey_question:"❔",grimacing:"😬",grin:"😁",grinning:"😀",guardsman:"💂",guardswoman:"💂&zwj;♀️",guitar:"🎸",gun:"🔫",haircut_woman:"💇",haircut_man:"💇&zwj;♂️",hamburger:"🍔",hammer:"🔨",hammer_and_pick:"⚒",hammer_and_wrench:"🛠",hamster:"🐹",hand:"✋",handbag:"👜",handshake:"🤝",hankey:"💩",hatched_chick:"🐥",hatching_chick:"🐣",headphones:"🎧",hear_no_evil:"🙉",heart:"❤️",heart_decoration:"💟",heart_eyes:"😍",heart_eyes_cat:"😻",heartbeat:"💓",heartpulse:"💗",hearts:"♥️",heavy_check_mark:"✔️",heavy_division_sign:"➗",heavy_dollar_sign:"💲",heavy_heart_exclamation:"❣️",heavy_minus_sign:"➖",heavy_multiplication_x:"✖️",heavy_plus_sign:"➕",helicopter:"🚁",herb:"🌿",hibiscus:"🌺",high_brightness:"🔆",high_heel:"👠",hocho:"🔪",hole:"🕳",honey_pot:"🍯",horse:"🐴",horse_racing:"🏇",hospital:"🏥",hot_pepper:"🌶",hotdog:"🌭",hotel:"🏨",hotsprings:"♨️",hourglass:"⌛️",hourglass_flowing_sand:"⏳",house:"🏠",house_with_garden:"🏡",houses:"🏘",hugs:"🤗",hushed:"😯",ice_cream:"🍨",ice_hockey:"🏒",ice_skate:"⛸",icecream:"🍦",id:"🆔",ideograph_advantage:"🉐",imp:"👿",inbox_tray:"📥",incoming_envelope:"📨",tipping_hand_woman:"💁",information_source:"ℹ️",innocent:"😇",interrobang:"⁉️",iphone:"📱",izakaya_lantern:"🏮",jack_o_lantern:"🎃",japan:"🗾",japanese_castle:"🏯",japanese_goblin:"👺",japanese_ogre:"👹",jeans:"👖",joy:"😂",joy_cat:"😹",joystick:"🕹",kaaba:"🕋",key:"🔑",keyboard:"⌨️",keycap_ten:"🔟",kick_scooter:"🛴",kimono:"👘",kiss:"💋",kissing:"😗",kissing_cat:"😽",kissing_closed_eyes:"😚",kissing_heart:"😘",kissing_smiling_eyes:"😙",kiwi_fruit:"🥝",koala:"🐨",koko:"🈁",label:"🏷",large_blue_circle:"🔵",large_blue_diamond:"🔷",large_orange_diamond:"🔶",last_quarter_moon:"🌗",last_quarter_moon_with_face:"🌜",latin_cross:"✝️",laughing:"😆",leaves:"🍃",ledger:"📒",left_luggage:"🛅",left_right_arrow:"↔️",leftwards_arrow_with_hook:"↩️",lemon:"🍋",leo:"♌️",leopard:"🐆",level_slider:"🎚",libra:"♎️",light_rail:"🚈",link:"🔗",lion:"🦁",lips:"👄",lipstick:"💄",lizard:"🦎",lock:"🔒",lock_with_ink_pen:"🔏",lollipop:"🍭",loop:"➿",loud_sound:"🔊",loudspeaker:"📢",love_hotel:"🏩",love_letter:"💌",low_brightness:"🔅",lying_face:"🤥",m:"Ⓜ️",mag:"🔍",mag_right:"🔎",mahjong:"🀄️",mailbox:"📫",mailbox_closed:"📪",mailbox_with_mail:"📬",mailbox_with_no_mail:"📭",man:"👨",man_artist:"👨&zwj;🎨",man_astronaut:"👨&zwj;🚀",man_cartwheeling:"🤸&zwj;♂️",man_cook:"👨&zwj;🍳",man_dancing:"🕺",man_facepalming:"🤦&zwj;♂️",man_factory_worker:"👨&zwj;🏭",man_farmer:"👨&zwj;🌾",man_firefighter:"👨&zwj;🚒",man_health_worker:"👨&zwj;⚕️",man_in_tuxedo:"🤵",man_judge:"👨&zwj;⚖️",man_juggling:"🤹&zwj;♂️",man_mechanic:"👨&zwj;🔧",man_office_worker:"👨&zwj;💼",man_pilot:"👨&zwj;✈️",man_playing_handball:"🤾&zwj;♂️",man_playing_water_polo:"🤽&zwj;♂️",man_scientist:"👨&zwj;🔬",man_shrugging:"🤷&zwj;♂️",man_singer:"👨&zwj;🎤",man_student:"👨&zwj;🎓",man_teacher:"👨&zwj;🏫",man_technologist:"👨&zwj;💻",man_with_gua_pi_mao:"👲",man_with_turban:"👳",tangerine:"🍊",mans_shoe:"👞",mantelpiece_clock:"🕰",maple_leaf:"🍁",martial_arts_uniform:"🥋",mask:"😷",massage_woman:"💆",massage_man:"💆&zwj;♂️",meat_on_bone:"🍖",medal_military:"🎖",medal_sports:"🏅",mega:"📣",melon:"🍈",memo:"📝",men_wrestling:"🤼&zwj;♂️",menorah:"🕎",mens:"🚹",metal:"🤘",metro:"🚇",microphone:"🎤",microscope:"🔬",milk_glass:"🥛",milky_way:"🌌",minibus:"🚐",minidisc:"💽",mobile_phone_off:"📴",money_mouth_face:"🤑",money_with_wings:"💸",moneybag:"💰",monkey:"🐒",monkey_face:"🐵",monorail:"🚝",moon:"🌔",mortar_board:"🎓",mosque:"🕌",motor_boat:"🛥",motor_scooter:"🛵",motorcycle:"🏍",motorway:"🛣",mount_fuji:"🗻",mountain:"⛰",mountain_biking_man:"🚵",mountain_biking_woman:"🚵&zwj;♀️",mountain_cableway:"🚠",mountain_railway:"🚞",mountain_snow:"🏔",mouse:"🐭",mouse2:"🐁",movie_camera:"🎥",moyai:"🗿",mrs_claus:"🤶",muscle:"💪",mushroom:"🍄",musical_keyboard:"🎹",musical_note:"🎵",musical_score:"🎼",mute:"🔇",nail_care:"💅",name_badge:"📛",national_park:"🏞",nauseated_face:"🤢",necktie:"👔",negative_squared_cross_mark:"❎",nerd_face:"🤓",neutral_face:"😐",new:"🆕",new_moon:"🌑",new_moon_with_face:"🌚",newspaper:"📰",newspaper_roll:"🗞",next_track_button:"⏭",ng:"🆖",no_good_man:"🙅&zwj;♂️",no_good_woman:"🙅",night_with_stars:"🌃",no_bell:"🔕",no_bicycles:"🚳",no_entry:"⛔️",no_entry_sign:"🚫",no_mobile_phones:"📵",no_mouth:"😶",no_pedestrians:"🚷",no_smoking:"🚭","non-potable_water":"🚱",nose:"👃",notebook:"📓",notebook_with_decorative_cover:"📔",notes:"🎶",nut_and_bolt:"🔩",o:"⭕️",o2:"🅾️",ocean:"🌊",octopus:"🐙",oden:"🍢",office:"🏢",oil_drum:"🛢",ok:"🆗",ok_hand:"👌",ok_man:"🙆&zwj;♂️",ok_woman:"🙆",old_key:"🗝",older_man:"👴",older_woman:"👵",om:"🕉",on:"🔛",oncoming_automobile:"🚘",oncoming_bus:"🚍",oncoming_police_car:"🚔",oncoming_taxi:"🚖",open_file_folder:"📂",open_hands:"👐",open_mouth:"😮",open_umbrella:"☂️",ophiuchus:"⛎",orange_book:"📙",orthodox_cross:"☦️",outbox_tray:"📤",owl:"🦉",ox:"🐂",package:"📦",page_facing_up:"📄",page_with_curl:"📃",pager:"📟",paintbrush:"🖌",palm_tree:"🌴",pancakes:"🥞",panda_face:"🐼",paperclip:"📎",paperclips:"🖇",parasol_on_ground:"⛱",parking:"🅿️",part_alternation_mark:"〽️",partly_sunny:"⛅️",passenger_ship:"🛳",passport_control:"🛂",pause_button:"⏸",peace_symbol:"☮️",peach:"🍑",peanuts:"🥜",pear:"🍐",pen:"🖊",pencil2:"✏️",penguin:"🐧",pensive:"😔",performing_arts:"🎭",persevere:"😣",person_fencing:"🤺",pouting_woman:"🙎",phone:"☎️",pick:"⛏",pig:"🐷",pig2:"🐖",pig_nose:"🐽",pill:"💊",pineapple:"🍍",ping_pong:"🏓",pisces:"♓️",pizza:"🍕",place_of_worship:"🛐",plate_with_cutlery:"🍽",play_or_pause_button:"⏯",point_down:"👇",point_left:"👈",point_right:"👉",point_up:"☝️",point_up_2:"👆",police_car:"🚓",policewoman:"👮&zwj;♀️",poodle:"🐩",popcorn:"🍿",post_office:"🏣",postal_horn:"📯",postbox:"📮",potable_water:"🚰",potato:"🥔",pouch:"👝",poultry_leg:"🍗",pound:"💷",rage:"😡",pouting_cat:"😾",pouting_man:"🙎&zwj;♂️",pray:"🙏",prayer_beads:"📿",pregnant_woman:"🤰",previous_track_button:"⏮",prince:"🤴",princess:"👸",printer:"🖨",purple_heart:"💜",purse:"👛",pushpin:"📌",put_litter_in_its_place:"🚮",question:"❓",rabbit:"🐰",rabbit2:"🐇",racehorse:"🐎",racing_car:"🏎",radio:"📻",radio_button:"🔘",radioactive:"☢️",railway_car:"🚃",railway_track:"🛤",rainbow:"🌈",rainbow_flag:"🏳️&zwj;🌈",raised_back_of_hand:"🤚",raised_hand_with_fingers_splayed:"🖐",raised_hands:"🙌",raising_hand_woman:"🙋",raising_hand_man:"🙋&zwj;♂️",ram:"🐏",ramen:"🍜",rat:"🐀",record_button:"⏺",recycle:"♻️",red_circle:"🔴",registered:"®️",relaxed:"☺️",relieved:"😌",reminder_ribbon:"🎗",repeat:"🔁",repeat_one:"🔂",rescue_worker_helmet:"⛑",restroom:"🚻",revolving_hearts:"💞",rewind:"⏪",rhinoceros:"🦏",ribbon:"🎀",rice:"🍚",rice_ball:"🍙",rice_cracker:"🍘",rice_scene:"🎑",right_anger_bubble:"🗯",ring:"💍",robot:"🤖",rocket:"🚀",rofl:"🤣",roll_eyes:"🙄",roller_coaster:"🎢",rooster:"🐓",rose:"🌹",rosette:"🏵",rotating_light:"🚨",round_pushpin:"📍",rowing_man:"🚣",rowing_woman:"🚣&zwj;♀️",rugby_football:"🏉",running_man:"🏃",running_shirt_with_sash:"🎽",running_woman:"🏃&zwj;♀️",sa:"🈂️",sagittarius:"♐️",sake:"🍶",sandal:"👡",santa:"🎅",satellite:"📡",saxophone:"🎷",school:"🏫",school_satchel:"🎒",scissors:"✂️",scorpion:"🦂",scorpius:"♏️",scream:"😱",scream_cat:"🙀",scroll:"📜",seat:"💺",secret:"㊙️",see_no_evil:"🙈",seedling:"🌱",selfie:"🤳",shallow_pan_of_food:"🥘",shamrock:"☘️",shark:"🦈",shaved_ice:"🍧",sheep:"🐑",shell:"🐚",shield:"🛡",shinto_shrine:"⛩",ship:"🚢",shirt:"👕",shopping:"🛍",shopping_cart:"🛒",shower:"🚿",shrimp:"🦐",signal_strength:"📶",six_pointed_star:"🔯",ski:"🎿",skier:"⛷",skull:"💀",skull_and_crossbones:"☠️",sleeping:"😴",sleeping_bed:"🛌",sleepy:"😪",slightly_frowning_face:"🙁",slightly_smiling_face:"🙂",slot_machine:"🎰",small_airplane:"🛩",small_blue_diamond:"🔹",small_orange_diamond:"🔸",small_red_triangle:"🔺",small_red_triangle_down:"🔻",smile:"😄",smile_cat:"😸",smiley:"😃",smiley_cat:"😺",smiling_imp:"😈",smirk:"😏",smirk_cat:"😼",smoking:"🚬",snail:"🐌",snake:"🐍",sneezing_face:"🤧",snowboarder:"🏂",snowflake:"❄️",snowman:"⛄️",snowman_with_snow:"☃️",sob:"😭",soccer:"⚽️",soon:"🔜",sos:"🆘",sound:"🔉",space_invader:"👾",spades:"♠️",spaghetti:"🍝",sparkle:"❇️",sparkler:"🎇",sparkles:"✨",sparkling_heart:"💖",speak_no_evil:"🙊",speaker:"🔈",speaking_head:"🗣",speech_balloon:"💬",speedboat:"🚤",spider:"🕷",spider_web:"🕸",spiral_calendar:"🗓",spiral_notepad:"🗒",spoon:"🥄",squid:"🦑",stadium:"🏟",star:"⭐️",star2:"🌟",star_and_crescent:"☪️",star_of_david:"✡️",stars:"🌠",station:"🚉",statue_of_liberty:"🗽",steam_locomotive:"🚂",stew:"🍲",stop_button:"⏹",stop_sign:"🛑",stopwatch:"⏱",straight_ruler:"📏",strawberry:"🍓",stuck_out_tongue:"😛",stuck_out_tongue_closed_eyes:"😝",stuck_out_tongue_winking_eye:"😜",studio_microphone:"🎙",stuffed_flatbread:"🥙",sun_behind_large_cloud:"🌥",sun_behind_rain_cloud:"🌦",sun_behind_small_cloud:"🌤",sun_with_face:"🌞",sunflower:"🌻",sunglasses:"😎",sunny:"☀️",sunrise:"🌅",sunrise_over_mountains:"🌄",surfing_man:"🏄",surfing_woman:"🏄&zwj;♀️",sushi:"🍣",suspension_railway:"🚟",sweat:"😓",sweat_drops:"💦",sweat_smile:"😅",sweet_potato:"🍠",swimming_man:"🏊",swimming_woman:"🏊&zwj;♀️",symbols:"🔣",synagogue:"🕍",syringe:"💉",taco:"🌮",tada:"🎉",tanabata_tree:"🎋",taurus:"♉️",taxi:"🚕",tea:"🍵",telephone_receiver:"📞",telescope:"🔭",tennis:"🎾",tent:"⛺️",thermometer:"🌡",thinking:"🤔",thought_balloon:"💭",ticket:"🎫",tickets:"🎟",tiger:"🐯",tiger2:"🐅",timer_clock:"⏲",tipping_hand_man:"💁&zwj;♂️",tired_face:"😫",tm:"™️",toilet:"🚽",tokyo_tower:"🗼",tomato:"🍅",tongue:"👅",top:"🔝",tophat:"🎩",tornado:"🌪",trackball:"🖲",tractor:"🚜",traffic_light:"🚥",train:"🚋",train2:"🚆",tram:"🚊",triangular_flag_on_post:"🚩",triangular_ruler:"📐",trident:"🔱",triumph:"😤",trolleybus:"🚎",trophy:"🏆",tropical_drink:"🍹",tropical_fish:"🐠",truck:"🚚",trumpet:"🎺",tulip:"🌷",tumbler_glass:"🥃",turkey:"🦃",turtle:"🐢",tv:"📺",twisted_rightwards_arrows:"🔀",two_hearts:"💕",two_men_holding_hands:"👬",two_women_holding_hands:"👭",u5272:"🈹",u5408:"🈴",u55b6:"🈺",u6307:"🈯️",u6708:"🈷️",u6709:"🈶",u6e80:"🈵",u7121:"🈚️",u7533:"🈸",u7981:"🈲",u7a7a:"🈳",umbrella:"☔️",unamused:"😒",underage:"🔞",unicorn:"🦄",unlock:"🔓",up:"🆙",upside_down_face:"🙃",v:"✌️",vertical_traffic_light:"🚦",vhs:"📼",vibration_mode:"📳",video_camera:"📹",video_game:"🎮",violin:"🎻",virgo:"♍️",volcano:"🌋",volleyball:"🏐",vs:"🆚",vulcan_salute:"🖖",walking_man:"🚶",walking_woman:"🚶&zwj;♀️",waning_crescent_moon:"🌘",waning_gibbous_moon:"🌖",warning:"⚠️",wastebasket:"🗑",watch:"⌚️",water_buffalo:"🐃",watermelon:"🍉",wave:"👋",wavy_dash:"〰️",waxing_crescent_moon:"🌒",wc:"🚾",weary:"😩",wedding:"💒",weight_lifting_man:"🏋️",weight_lifting_woman:"🏋️&zwj;♀️",whale:"🐳",whale2:"🐋",wheel_of_dharma:"☸️",wheelchair:"♿️",white_check_mark:"✅",white_circle:"⚪️",white_flag:"🏳️",white_flower:"💮",white_large_square:"⬜️",white_medium_small_square:"◽️",white_medium_square:"◻️",white_small_square:"▫️",white_square_button:"🔳",wilted_flower:"🥀",wind_chime:"🎐",wind_face:"🌬",wine_glass:"🍷",wink:"😉",wolf:"🐺",woman:"👩",woman_artist:"👩&zwj;🎨",woman_astronaut:"👩&zwj;🚀",woman_cartwheeling:"🤸&zwj;♀️",woman_cook:"👩&zwj;🍳",woman_facepalming:"🤦&zwj;♀️",woman_factory_worker:"👩&zwj;🏭",woman_farmer:"👩&zwj;🌾",woman_firefighter:"👩&zwj;🚒",woman_health_worker:"👩&zwj;⚕️",woman_judge:"👩&zwj;⚖️",woman_juggling:"🤹&zwj;♀️",woman_mechanic:"👩&zwj;🔧",woman_office_worker:"👩&zwj;💼",woman_pilot:"👩&zwj;✈️",woman_playing_handball:"🤾&zwj;♀️",woman_playing_water_polo:"🤽&zwj;♀️",woman_scientist:"👩&zwj;🔬",woman_shrugging:"🤷&zwj;♀️",woman_singer:"👩&zwj;🎤",woman_student:"👩&zwj;🎓",woman_teacher:"👩&zwj;🏫",woman_technologist:"👩&zwj;💻",woman_with_turban:"👳&zwj;♀️",womans_clothes:"👚",womans_hat:"👒",women_wrestling:"🤼&zwj;♀️",womens:"🚺",world_map:"🗺",worried:"😟",wrench:"🔧",writing_hand:"✍️",x:"❌",yellow_heart:"💛",yen:"💴",yin_yang:"☯️",yum:"😋",zap:"⚡️",zipper_mouth_face:"🤐",zzz:"💤",octocat:'<img width="20" height="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png">',showdown:'<img width="20" height="20" align="absmiddle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAS1BMVEX///8jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS3b1q3b1q3b1q3b1q3b1q3b1q3b1q3b1q0565CIAAAAGXRSTlMAQHCAYCCw/+DQwPCQUBAwoHCAEP+wwFBgS2fvBgAAAUZJREFUeAHs1cGy7BAUheFFsEDw/k97VTq3T6ge2EmdM+pvrP6Iwd74XV9Kb52xuMU4/uc1YNgZLFOeV8FGdhGrNk5SEgUyPxAEdj4LlMRDyhVAMVEa2M7TBSeVZAFPdqHgzSZJwPKgcLFLAooHDJo4EDCw4gAtBoJA5UFj4Ng5LOGLwVXZuoIlji/jeQHFk7+baHxrCjeUwB9+s88KndvlhcyBN5BSkYNQIVVb4pV+Npm7hhuKDs/uMP5KxT3WzSNNLIuuoDpMmuAVMruMSeDyQBi24DTr43LAY7ILA1QYaWkgfHzFthYYzg67SQsCbB8GhJUEGCtO9n0rSaCLxgJQjS/JSgMTg2eBDEHAJ+H350AsjYNYscrErgI2e/l+mdR967TCX/v6N0EhPECYCP0i+IAoYQOE8BogNhQMEMdrgAQWHaMAAGi5I5euoY9NAAAAAElFTkSuQmCC">'},b.subParser("makehtml.blockGamut",function(e,r,t){"use strict";return e=t.converter._dispatch("makehtml.blockGamut.before",e,r,t).getText(),e=b.subParser("makehtml.blockQuotes")(e,r,t),e=b.subParser("makehtml.headers")(e,r,t),e=b.subParser("makehtml.horizontalRule")(e,r,t),e=b.subParser("makehtml.lists")(e,r,t),e=b.subParser("makehtml.codeBlocks")(e,r,t),e=b.subParser("makehtml.tables")(e,r,t),e=b.subParser("makehtml.hashHTMLBlocks")(e,r,t),e=b.subParser("makehtml.paragraphs")(e,r,t),e=t.converter._dispatch("makehtml.blockGamut.after",e,r,t).getText()}),b.subParser("makehtml.blockQuotes",function(e,r,t){"use strict";e=t.converter._dispatch("makehtml.blockQuotes.before",e,r,t).getText(),e+="\n\n";var a=/(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;return r.splitAdjacentBlockquotes&&(a=/^ {0,3}>[\s\S]*?(?:\n\n)/gm),e=e.replace(a,function(e){return e=(e=(e=e.replace(/^[ \t]*>[ \t]?/gm,"")).replace(/¨0/g,"")).replace(/^[ \t]+$/gm,""),e=b.subParser("makehtml.githubCodeBlocks")(e,r,t),e=(e=(e=b.subParser("makehtml.blockGamut")(e,r,t)).replace(/(^|\n)/g,"$1 ")).replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(e,r){var t=r;return t=(t=t.replace(/^ /gm,"¨0")).replace(/¨0/g,"")}),b.subParser("makehtml.hashBlock")("<blockquote>\n"+e+"\n</blockquote>",r,t)}),e=t.converter._dispatch("makehtml.blockQuotes.after",e,r,t).getText()}),b.subParser("makehtml.codeBlocks",function(e,o,i){"use strict";e=i.converter._dispatch("makehtml.codeBlocks.before",e,o,i).getText();return e=(e=(e+="¨0").replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g,function(e,r,t){var a=r,n=t,s="\n";return a=b.subParser("makehtml.outdent")(a,o,i),a=b.subParser("makehtml.encodeCode")(a,o,i),a=(a=(a=b.subParser("makehtml.detab")(a,o,i)).replace(/^\n+/g,"")).replace(/\n+$/g,""),o.omitExtraWLInCodeBlocks&&(s=""),a="<pre><code>"+a+s+"</code></pre>",b.subParser("makehtml.hashBlock")(a,o,i)+n})).replace(/¨0/,""),e=i.converter._dispatch("makehtml.codeBlocks.after",e,o,i).getText()}),b.subParser("makehtml.codeSpans",function(e,s,o){"use strict";return void 0===(e=o.converter._dispatch("makehtml.codeSpans.before",e,s,o).getText())&&(e=""),e=e.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(e,r,t,a){var n=a;return n=(n=n.replace(/^([ \t]*)/g,"")).replace(/[ \t]*$/g,""),n=r+"<code>"+(n=b.subParser("makehtml.encodeCode")(n,s,o))+"</code>",n=b.subParser("makehtml.hashHTMLSpans")(n,s,o)}),e=o.converter._dispatch("makehtml.codeSpans.after",e,s,o).getText()}),b.subParser("makehtml.completeHTMLDocument",function(e,r,t){"use strict";if(!r.completeHTMLDocument)return e;e=t.converter._dispatch("makehtml.completeHTMLDocument.before",e,r,t).getText();var a="html",n="<!DOCTYPE HTML>\n",s="",o='<meta charset="utf-8">\n',i="",l="";for(var c in void 0!==t.metadata.parsed.doctype&&(n="<!DOCTYPE "+t.metadata.parsed.doctype+">\n","html"!==(a=t.metadata.parsed.doctype.toString().toLowerCase())&&"html5"!==a||(o='<meta charset="utf-8">')),t.metadata.parsed)if(t.metadata.parsed.hasOwnProperty(c))switch(c.toLowerCase()){case"doctype":break;case"title":s="<title>"+t.metadata.parsed.title+"</title>\n";break;case"charset":o="html"===a||"html5"===a?'<meta charset="'+t.metadata.parsed.charset+'">\n':'<meta name="charset" content="'+t.metadata.parsed.charset+'">\n';break;case"language":case"lang":i=' lang="'+t.metadata.parsed[c]+'"',l+='<meta name="'+c+'" content="'+t.metadata.parsed[c]+'">\n';break;default:l+='<meta name="'+c+'" content="'+t.metadata.parsed[c]+'">\n'}return e=n+"<html"+i+">\n<head>\n"+s+o+l+"</head>\n<body>\n"+e.trim()+"\n</body>\n</html>",e=t.converter._dispatch("makehtml.completeHTMLDocument.after",e,r,t).getText()}),b.subParser("makehtml.detab",function(e,r,t){"use strict";return e=(e=(e=(e=(e=(e=t.converter._dispatch("makehtml.detab.before",e,r,t).getText()).replace(/\t(?=\t)/g," ")).replace(/\t/g,"¨A¨B")).replace(/¨B(.+?)¨A/g,function(e,r){for(var t=r,a=4-t.length%4,n=0;n<a;n++)t+=" ";return t})).replace(/¨A/g," ")).replace(/¨B/g,""),e=t.converter._dispatch("makehtml.detab.after",e,r,t).getText()}),b.subParser("makehtml.ellipsis",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("makehtml.ellipsis.before",e,r,t).getText()).replace(/\.\.\./g,"…"),e=t.converter._dispatch("makehtml.ellipsis.after",e,r,t).getText()}),b.subParser("makehtml.emoji",function(e,r,t){"use strict";if(!r.emoji)return e;return e=(e=t.converter._dispatch("makehtml.emoji.before",e,r,t).getText()).replace(/:([\S]+?):/g,function(e,r){return b.helper.emojis.hasOwnProperty(r)?b.helper.emojis[r]:e}),e=t.converter._dispatch("makehtml.emoji.after",e,r,t).getText()}),b.subParser("makehtml.encodeAmpsAndAngles",function(e,r,t){"use strict";return e=(e=(e=(e=(e=t.converter._dispatch("makehtml.encodeAmpsAndAngles.before",e,r,t).getText()).replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&amp;")).replace(/<(?![a-z\/?$!])/gi,"&lt;")).replace(/</g,"&lt;")).replace(/>/g,"&gt;"),e=t.converter._dispatch("makehtml.encodeAmpsAndAngles.after",e,r,t).getText()}),b.subParser("makehtml.encodeBackslashEscapes",function(e,r,t){"use strict";return e=(e=(e=t.converter._dispatch("makehtml.encodeBackslashEscapes.before",e,r,t).getText()).replace(/\\(\\)/g,b.helper.escapeCharactersCallback)).replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g,b.helper.escapeCharactersCallback),e=t.converter._dispatch("makehtml.encodeBackslashEscapes.after",e,r,t).getText()}),b.subParser("makehtml.encodeCode",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("makehtml.encodeCode.before",e,r,t).getText()).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/([*_{}\[\]\\=~-])/g,b.helper.escapeCharactersCallback),e=t.converter._dispatch("makehtml.encodeCode.after",e,r,t).getText()}),b.subParser("makehtml.escapeSpecialCharsWithinTagAttributes",function(e,r,t){"use strict";return e=(e=(e=t.converter._dispatch("makehtml.escapeSpecialCharsWithinTagAttributes.before",e,r,t).getText()).replace(/<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,function(e){return e.replace(/(.)<\/?code>(?=.)/g,"$1`").replace(/([\\`*_~=|])/g,b.helper.escapeCharactersCallback)})).replace(/<!(--(?:(?:[^>-]|-[^>])(?:[^-]|-[^-])*)--)>/gi,function(e){return e.replace(/([\\`*_~=|])/g,b.helper.escapeCharactersCallback)}),e=t.converter._dispatch("makehtml.escapeSpecialCharsWithinTagAttributes.after",e,r,t).getText()}),b.subParser("makehtml.githubCodeBlocks",function(e,s,o){"use strict";return s.ghCodeBlocks?(e=o.converter._dispatch("makehtml.githubCodeBlocks.before",e,s,o).getText(),e=(e=(e+="¨0").replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g,function(e,r,t,a){var n=s.omitExtraWLInCodeBlocks?"":"\n";return a=b.subParser("makehtml.encodeCode")(a,s,o),a="<pre><code"+(t?' class="'+t+" language-"+t+'"':"")+">"+(a=(a=(a=b.subParser("makehtml.detab")(a,s,o)).replace(/^\n+/g,"")).replace(/\n+$/g,""))+n+"</code></pre>",a=b.subParser("makehtml.hashBlock")(a,s,o),"\n\n¨G"+(o.ghCodeBlocks.push({text:e,codeblock:a})-1)+"G\n\n"})).replace(/¨0/,""),o.converter._dispatch("makehtml.githubCodeBlocks.after",e,s,o).getText()):e}),b.subParser("makehtml.hashBlock",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("makehtml.hashBlock.before",e,r,t).getText()).replace(/(^\n+|\n+$)/g,""),e="\n\n¨K"+(t.gHtmlBlocks.push(e)-1)+"K\n\n",e=t.converter._dispatch("makehtml.hashBlock.after",e,r,t).getText()}),b.subParser("makehtml.hashCodeTags",function(e,s,o){"use strict";e=o.converter._dispatch("makehtml.hashCodeTags.before",e,s,o).getText();return e=b.helper.replaceRecursiveRegExp(e,function(e,r,t,a){var n=t+b.subParser("makehtml.encodeCode")(r,s,o)+a;return"¨C"+(o.gHtmlSpans.push(n)-1)+"C"},"<code\\b[^>]*>","</code>","gim"),e=o.converter._dispatch("makehtml.hashCodeTags.after",e,s,o).getText()}),b.subParser("makehtml.hashElement",function(e,r,a){"use strict";return function(e,r){var t=r;return t=(t=(t=t.replace(/\n\n/g,"\n")).replace(/^\n/,"")).replace(/\n+$/g,""),t="\n\n¨K"+(a.gHtmlBlocks.push(t)-1)+"K\n\n"}}),b.subParser("makehtml.hashHTMLBlocks",function(e,r,s){"use strict";e=s.converter._dispatch("makehtml.hashHTMLBlocks.before",e,r,s).getText();var t=["pre","div","h1","h2","h3","h4","h5","h6","blockquote","table","dl","ol","ul","script","noscript","form","fieldset","iframe","math","style","section","header","footer","nav","article","aside","address","audio","canvas","figure","hgroup","output","video","p"],a=function(e,r,t,a){var n=e;return-1!==t.search(/\bmarkdown\b/)&&(n=t+s.converter.makeHtml(r)+a),"\n\n¨K"+(s.gHtmlBlocks.push(n)-1)+"K\n\n"};r.backslashEscapesHTMLTags&&(e=e.replace(/\\<(\/?[^>]+?)>/g,function(e,r){return"&lt;"+r+"&gt;"}));for(var n=0;n<t.length;++n)for(var o,i=new RegExp("^ {0,3}(<"+t[n]+"\\b[^>]*>)","im"),l="<"+t[n]+"\\b[^>]*>",c="</"+t[n]+">";-1!==(o=b.helper.regexIndexOf(e,i));){var u=b.helper.splitAtIndex(e,o),h=b.helper.replaceRecursiveRegExp(u[1],a,l,c,"im");if(h===u[1])break;e=u[0].concat(h)}return e=e.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,b.subParser("makehtml.hashElement")(e,r,s)),e=(e=b.helper.replaceRecursiveRegExp(e,function(e){return"\n\n¨K"+(s.gHtmlBlocks.push(e)-1)+"K\n\n"},"^ {0,3}\x3c!--","--\x3e","gm")).replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,b.subParser("makehtml.hashElement")(e,r,s)),e=s.converter._dispatch("makehtml.hashHTMLBlocks.after",e,r,s).getText()}),b.subParser("makehtml.hashHTMLSpans",function(e,r,t){"use strict";return e=(e=(e=(e=(e=t.converter._dispatch("makehtml.hashHTMLSpans.before",e,r,t).getText()).replace(/<[^>]+?\/>/gi,function(e){return b.helper._hashHTMLSpan(e,t)})).replace(/<([^>]+?)>[\s\S]*?<\/\1>/g,function(e){return b.helper._hashHTMLSpan(e,t)})).replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g,function(e){return b.helper._hashHTMLSpan(e,t)})).replace(/<[^>]+?>/gi,function(e){return b.helper._hashHTMLSpan(e,t)}),e=t.converter._dispatch("makehtml.hashHTMLSpans.after",e,r,t).getText()}),b.subParser("makehtml.unhashHTMLSpans",function(e,r,t){"use strict";e=t.converter._dispatch("makehtml.unhashHTMLSpans.before",e,r,t).getText();for(var a=0;a<t.gHtmlSpans.length;++a){for(var n=t.gHtmlSpans[a],s=0;/¨C(\d+)C/.test(n);){var o=RegExp.$1;if(n=n.replace("¨C"+o+"C",t.gHtmlSpans[o]),10===s){console.error("maximum nesting of 10 spans reached!!!");break}++s}e=e.replace("¨C"+a+"C",n)}return e=t.converter._dispatch("makehtml.unhashHTMLSpans.after",e,r,t).getText()}),b.subParser("makehtml.hashPreCodeTags",function(e,s,o){"use strict";e=o.converter._dispatch("makehtml.hashPreCodeTags.before",e,s,o).getText();return e=b.helper.replaceRecursiveRegExp(e,function(e,r,t,a){var n=t+b.subParser("makehtml.encodeCode")(r,s,o)+a;return"\n\n¨G"+(o.ghCodeBlocks.push({text:e,codeblock:n})-1)+"G\n\n"},"^ {0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>","^ {0,3}</code>\\s*</pre>","gim"),e=o.converter._dispatch("makehtml.hashPreCodeTags.after",e,s,o).getText()}),b.subParser("makehtml.headers",function(e,l,c){"use strict";e=c.converter._dispatch("makehtml.headers.before",e,l,c).getText();var u=isNaN(parseInt(l.headerLevelStart))?1:parseInt(l.headerLevelStart),r=l.smoothLivePreview?/^(.+)[ \t]*\n={2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n=+[ \t]*\n+/gm,t=l.smoothLivePreview?/^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n-+[ \t]*\n+/gm;e=(e=e.replace(r,function(e,r){var t=b.subParser("makehtml.spanGamut")(r,l,c),a=l.noHeaderId?"":' id="'+h(r)+'"',n="<h"+u+a+">"+t+"</h"+u+">";return b.subParser("makehtml.hashBlock")(n,l,c)})).replace(t,function(e,r){var t=b.subParser("makehtml.spanGamut")(r,l,c),a=l.noHeaderId?"":' id="'+h(r)+'"',n=u+1,s="<h"+n+a+">"+t+"</h"+n+">";return b.subParser("makehtml.hashBlock")(s,l,c)});var a=l.requireSpaceBeforeHeadingText?/^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm:/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm;function h(e){var r,t;if(l.customizedHeaderId){var a=e.match(/\{([^{]+?)}\s*$/);a&&a[1]&&(e=a[1])}return r=e,t=b.helper.isString(l.prefixHeaderId)?l.prefixHeaderId:!0===l.prefixHeaderId?"section-":"",l.rawPrefixHeaderId||(r=t+r),r=l.ghCompatibleHeaderId?r.replace(/ /g,"-").replace(/&amp;/g,"").replace(/¨T/g,"").replace(/¨D/g,"").replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g,"").toLowerCase():l.rawHeaderId?r.replace(/ /g,"-").replace(/&amp;/g,"&").replace(/¨T/g,"¨").replace(/¨D/g,"$").replace(/["']/g,"-").toLowerCase():r.replace(/[^\w]/g,"").toLowerCase(),l.rawPrefixHeaderId&&(r=t+r),c.hashLinkCounts[r]?r=r+"-"+c.hashLinkCounts[r]++:c.hashLinkCounts[r]=1,r}return e=e.replace(a,function(e,r,t){var a=t;l.customizedHeaderId&&(a=t.replace(/\s?\{([^{]+?)}\s*$/,""));var n=b.subParser("makehtml.spanGamut")(a,l,c),s=l.noHeaderId?"":' id="'+h(t)+'"',o=u-1+r.length,i="<h"+o+s+">"+n+"</h"+o+">";return b.subParser("makehtml.hashBlock")(i,l,c)}),e=c.converter._dispatch("makehtml.headers.after",e,l,c).getText()}),b.subParser("makehtml.horizontalRule",function(e,r,t){"use strict";e=t.converter._dispatch("makehtml.horizontalRule.before",e,r,t).getText();var a=b.subParser("makehtml.hashBlock")("<hr />",r,t);return e=(e=(e=e.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm,a)).replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm,a)).replace(/^ {0,2}( ?_){3,}[ \t]*$/gm,a),e=t.converter._dispatch("makehtml.horizontalRule.after",e,r,t).getText()}),b.subParser("makehtml.images",function(e,r,m){"use strict";function l(e,r,t,a,n,s,o,i){var l=m.gUrls,c=m.gTitles,u=m.gDimensions;if(t=t.toLowerCase(),i||(i=""),-1<e.search(/\(<?\s*>? ?(['"].*['"])?\)$/m))a="";else if(""===a||null===a){if(""!==t&&null!==t||(t=r.toLowerCase().replace(/ ?\n/g," ")),a="#"+t,b.helper.isUndefined(l[t]))return e;a=l[t],b.helper.isUndefined(c[t])||(i=c[t]),b.helper.isUndefined(u[t])||(n=u[t].width,s=u[t].height)}r=r.replace(/"/g,"&quot;").replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback);var h='<img src="'+(a=a.replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback))+'" alt="'+r+'"';return i&&b.helper.isString(i)&&(h+=' title="'+(i=i.replace(/"/g,"&quot;").replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback))+'"'),n&&s&&(h+=' width="'+(n="*"===n?"auto":n)+'"',h+=' height="'+(s="*"===s?"auto":s)+'"'),h+=" />"}return e=(e=(e=(e=(e=(e=m.converter._dispatch("makehtml.images.before",e,r,m).getText()).replace(/!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,l)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,function(e,r,t,a,n,s,o,i){return l(e,r,t,a=a.replace(/\s/g,""),n,s,0,i)})).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,l)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?<?([\S]+?(?:\([\S]*?\)[\S]*?)?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,l)).replace(/!\[([^\[\]]+)]()()()()()/g,l),e=m.converter._dispatch("makehtml.images.after",e,r,m).getText()}),b.subParser("makehtml.italicsAndBold",function(e,r,t){"use strict";function a(e,r,t){return r+e+t}return e=t.converter._dispatch("makehtml.italicsAndBold.before",e,r,t).getText(),e=(e=(e=(e=r.literalMidWordUnderscores?(e=(e=e.replace(/\b___(\S[\s\S]*?)___\b/g,function(e,r){return a(r,"<strong><em>","</em></strong>")})).replace(/\b__(\S[\s\S]*?)__\b/g,function(e,r){return a(r,"<strong>","</strong>")})).replace(/\b_(\S[\s\S]*?)_\b/g,function(e,r){return a(r,"<em>","</em>")}):(e=(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,r){return/\S$/.test(r)?a(r,"<strong><em>","</em></strong>"):e})).replace(/__(\S[\s\S]*?)__/g,function(e,r){return/\S$/.test(r)?a(r,"<strong>","</strong>"):e})).replace(/_([^\s_][\s\S]*?)_/g,function(e,r){return/\S$/.test(r)?a(r,"<em>","</em>"):e})).replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g,function(e,r){return/\S$/.test(r)?a(r,"<strong><em>","</em></strong>"):e})).replace(/\*\*(\S[\s\S]*?)\*\*/g,function(e,r){return/\S$/.test(r)?a(r,"<strong>","</strong>"):e})).replace(/\*([^\s*][\s\S]*?)\*/g,function(e,r){return/\S$/.test(r)?a(r,"<em>","</em>"):e}),e=t.converter._dispatch("makehtml.italicsAndBold.after",e,r,t).getText()}),function(){function l(i,l,c,u,h){return h=!!h,function(e,r,t,a,n,s,o){return/\n\n/.test(e)?e:f(_(i,l+".captureStart",e,r,t,a,o,c,u),c,u,h)}}function _(e,r,t,a,n,s,o,i,l){return l.converter._dispatch(r,t,i,l,{regexp:e,matches:{wholeMatch:t,text:a,id:n,url:s,title:o}})}function f(e,r,t,a){var n=e.getMatches().wholeMatch,s=e.getMatches().text,o=e.getMatches().id,i=e.getMatches().url,l=e.getMatches().title,c="";if(l||(l=""),o=o?o.toLowerCase():"",a)i="";else if(!i){if(o||(o=s.toLowerCase().replace(/ ?\n/g," ")),i="#"+o,b.helper.isUndefined(t.gUrls[o]))return n;i=t.gUrls[o],b.helper.isUndefined(t.gTitles[o])||(l=t.gTitles[o])}i=i.replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback),""!==l&&null!==l&&(l=' title="'+(l=(l=l.replace(/"/g,"&quot;")).replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback))+'"'),r.openLinksInNewWindow&&!/^#/.test(i)&&(c=' target="¨E95Eblank"'),s=b.subParser("makehtml.codeSpans")(s,r,t),s=b.subParser("makehtml.emoji")(s,r,t),s=b.subParser("makehtml.underline")(s,r,t),s=b.subParser("makehtml.italicsAndBold")(s,r,t),s=b.subParser("makehtml.strikethrough")(s,r,t),s=b.subParser("makehtml.ellipsis")(s,r,t);var u='<a href="'+i+'"'+l+c+">"+(s=b.subParser("makehtml.hashHTMLSpans")(s,r,t))+"</a>";return u=b.subParser("makehtml.hashHTMLSpans")(u,r,t)}var a="makehtml.links";b.subParser("makehtml.links",function(e,r,t){return e=t.converter._dispatch(a+".start",e,r,t).getText(),e=b.subParser("makehtml.links.reference")(e,r,t),e=b.subParser("makehtml.links.inline")(e,r,t),e=b.subParser("makehtml.links.referenceShortcut")(e,r,t),e=b.subParser("makehtml.links.angleBrackets")(e,r,t),e=(e=(e=b.subParser("makehtml.links.ghMentions")(e,r,t)).replace(/<a\s[^>]*>[\s\S]*<\/a>/g,function(e){return b.helper._hashHTMLSpan(e,t)})).replace(/<img\s[^>]*\/?>/g,function(e){return b.helper._hashHTMLSpan(e,t)}),e=b.subParser("makehtml.links.naked")(e,r,t),e=t.converter._dispatch(a+".end",e,r,t).getText()}),b.subParser("makehtml.links.inline",function(e,r,t){var a=a+".inline",n=/\[(.*?)]()()()()\(<? ?>? ?(?:["'](.*)["'])?\)/g,s=/\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,o=/\[([\S ]*?)]\s?()\( *<?([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s*(?:()(['"])(.*?)\5)? *\)/g,i=/\[([\S ]*?)]\s?()\( *<?([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s+()()\((.*?)\) *\)/g;return e=(e=(e=(e=(e=t.converter._dispatch(a+".start",e,r,t).getText()).replace(n,l(n,a,r,t,!0))).replace(s,l(s,a,r,t))).replace(o,l(o,a,r,t))).replace(i,l(i,a,r,t)),e=t.converter._dispatch(a+".end",e,r,t).getText()}),b.subParser("makehtml.links.reference",function(e,r,t){var a=a+".reference",n=/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g;return e=(e=t.converter._dispatch(a+".start",e,r,t).getText()).replace(n,l(n,a,r,t)),e=t.converter._dispatch(a+".end",e,r,t).getText()}),b.subParser("makehtml.links.referenceShortcut",function(e,r,t){var a=a+".referenceShortcut",n=/\[([^\[\]]+)]()()()()()/g;return e=(e=t.converter._dispatch(a+".start",e,r,t).getText()).replace(n,l(n,a,r,t)),e=t.converter._dispatch(a+".end",e,r,t).getText()}),b.subParser("makehtml.links.ghMentions",function(e,o,i){var l=l+"ghMentions";if(!o.ghMentions)return e;e=i.converter._dispatch(l+".start",e,o,i).getText();var c=/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d._-]+?[a-z\d]+)*))/gi;return e=e.replace(c,function(e,r,t,a,n){if("\\"===t)return r+a;if(!b.helper.isString(o.ghMentionsLink))throw new Error("ghMentionsLink option must be a string");var s=o.ghMentionsLink.replace(/{u}/g,n);return r+f(_(c,l+".captureStart",e,a,null,s,null,o,i),o,i)}),e=i.converter._dispatch(l+".end",e,o,i).getText()}),b.subParser("makehtml.links.angleBrackets",function(e,a,n){var s="makehtml.links.angleBrackets";e=n.converter._dispatch(s+".start",e,a,n).getText();var o=/<(((?:https?|ftp):\/\/|www\.)[^'">\s]+)>/gi;e=e.replace(o,function(e,r,t){return f(_(o,s+".captureStart",e,r,null,r="www."===t?"http://"+r:r,null,a,n),a,n)});var i=/<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;return e=e.replace(i,function(e,r){var t="mailto:";return r=b.subParser("makehtml.unescapeSpecialChars")(r,a,n),a.encodeEmails?(t=b.helper.encodeEmailAddress(t+r),r=b.helper.encodeEmailAddress(r)):t+=r,f(_(i,s+".captureStart",e,r,null,t,null,a,n),a,n)}),e=n.converter._dispatch(s+".end",e,a,n).getText()}),b.subParser("makehtml.links.naked",function(e,m,d){if(!m.simplifiedAutoLink)return e;var p="makehtml.links.naked";e=d.converter._dispatch(p+".start",e,m,d).getText();var g=/([_*~]*?)(((?:https?|ftp):\/\/|www\.)[^\s<>"'`´.-][^\s<>"'`´]*?\.[a-z\d.]+[^\s<>"']*)\1/gi;e=e.replace(g,function(e,r,t,a){for(var n="",s=t.length-1;0<=s;--s){var o=t.charAt(s);if(/[_*~,;:.!?]/.test(o))t=t.slice(0,-1),n=o+n;else if(/\)/.test(o)){var i=t.match(/\(/g)||[],l=t.match(/\)/g);if(!(i.length<l.length))break;t=t.slice(0,-1),n=o+n}else{if(!/]/.test(o))break;var c=t.match(/\[/g)||[],u=t.match(/\]/g);if(!(c.length<u.length))break;t=t.slice(0,-1),n=o+n}}var h=t;return t="www."===a?"http://"+t:t,h=h.replace(b.helper.regexes.asteriskDashTildeAndColon,b.helper.escapeCharactersCallback),r+f(_(g,p+".captureStart",e,h,null,t,null,m,d),m,d)+n+r});var n=/(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gim;return e=e.replace(n,function(e,r,t){var a="mailto:";return t=b.subParser("makehtml.unescapeSpecialChars")(t,m,d),m.encodeEmails?(a=b.helper.encodeEmailAddress(a+t),t=b.helper.encodeEmailAddress(t)):a+=t,r+f(_(n,p+".captureStart",e,t,null,a,null,m,d),m,d)}),e=d.converter._dispatch(p+".end",e,m,d).getText()})}(),b.subParser("makehtml.lists",function(e,h,u){"use strict";function m(e,r){u.gListLevel++,e=e.replace(/\n{2,}$/,"\n");var t=/(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,c=/\n[ \t]*\n(?!¨0)/.test(e+="¨0");return h.disableForced4SpacesIndentedSublists&&(t=/(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm),e=(e=e.replace(t,function(e,r,t,a,n,s,o){o=o&&""!==o.trim();var i=b.subParser("makehtml.outdent")(n,h,u),l="";return s&&h.tasklists&&(l=' class="task-list-item" style="list-style-type: none;"',i=i.replace(/^[ \t]*\[(x|X| )?]/m,function(){var e='<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';return o&&(e+=" checked"),e+=">"})),i=i.replace(/^([-*+]|\d\.)[ \t]+[\S\n ]*/g,function(e){return"¨A"+e}),/^#+.+\n.+/.test(i)&&(i=i.replace(/^(#+.+)$/m,"$1\n")),r||-1<i.search(/\n{2,}/)?(i=b.subParser("makehtml.githubCodeBlocks")(i,h,u),i=b.subParser("makehtml.blockGamut")(i,h,u)):(i=(i=b.subParser("makehtml.lists")(i,h,u)).replace(/\n$/,""),i=(i=b.subParser("makehtml.hashHTMLBlocks")(i,h,u)).replace(/\n\n+/g,"\n\n"),i=c?b.subParser("makehtml.paragraphs")(i,h,u):b.subParser("makehtml.spanGamut")(i,h,u)),i="<li"+l+">"+(i=i.replace("¨A",""))+"</li>\n"})).replace(/¨0/g,""),u.gListLevel--,r&&(e=e.replace(/\s+$/,"")),e}function d(e,r){if("ol"===r){var t=e.match(/^ *(\d+)\./);if(t&&"1"!==t[1])return' start="'+t[1]+'"'}return""}function n(n,s,o){var i=h.disableForced4SpacesIndentedSublists?/^ ?\d+\.[ \t]/gm:/^ {0,3}\d+\.[ \t]/gm,l=h.disableForced4SpacesIndentedSublists?/^ ?[*+-][ \t]/gm:/^ {0,3}[*+-][ \t]/gm,c="ul"===s?i:l,u="";if(-1!==n.search(c))!function e(r){var t=r.search(c),a=d(n,s);-1!==t?(u+="\n\n<"+s+a+">\n"+m(r.slice(0,t),!!o)+"</"+s+">\n",c="ul"===(s="ul"===s?"ol":"ul")?i:l,e(r.slice(t))):u+="\n\n<"+s+a+">\n"+m(r,!!o)+"</"+s+">\n"}(n);else{var e=d(n,s);u="\n\n<"+s+e+">\n"+m(n,!!o)+"</"+s+">\n"}return u}return e=u.converter._dispatch("lists.before",e,h,u).getText(),e+="¨0",e=(e=u.gListLevel?e.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(e,r,t){return n(r,-1<t.search(/[*+-]/g)?"ul":"ol",!0)}):e.replace(/(\n\n|^\n?)(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(e,r,t,a){return n(t,-1<a.search(/[*+-]/g)?"ul":"ol",!1)})).replace(/¨0/,""),e=u.converter._dispatch("makehtml.lists.after",e,h,u).getText()}),b.subParser("makehtml.metadata",function(e,r,a){"use strict";if(!r.metadata)return e;function n(e){(e=(e=(a.metadata.raw=e).replace(/&/g,"&amp;").replace(/"/g,"&quot;")).replace(/\n {4}/g," ")).replace(/^([\S ]+): +([\s\S]+?)$/gm,function(e,r,t){return a.metadata.parsed[r]=t,""})}return e=(e=(e=(e=a.converter._dispatch("makehtml.metadata.before",e,r,a).getText()).replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/,function(e,r,t){return n(t),"¨M"})).replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/,function(e,r,t){return r&&(a.metadata.format=r),n(t),"¨M"})).replace(/¨M/g,""),e=a.converter._dispatch("makehtml.metadata.after",e,r,a).getText()}),b.subParser("makehtml.outdent",function(e,r,t){"use strict";return e=(e=(e=t.converter._dispatch("makehtml.outdent.before",e,r,t).getText()).replace(/^(\t|[ ]{1,4})/gm,"¨0")).replace(/¨0/g,""),e=t.converter._dispatch("makehtml.outdent.after",e,r,t).getText()}),b.subParser("makehtml.paragraphs",function(e,r,t){"use strict";for(var a=(e=(e=(e=t.converter._dispatch("makehtml.paragraphs.before",e,r,t).getText()).replace(/^\n+/g,"")).replace(/\n+$/g,"")).split(/\n{2,}/g),n=[],s=a.length,o=0;o<s;o++){var i=a[o];0<=i.search(/¨(K|G)(\d+)\1/g)?n.push(i):0<=i.search(/\S/)&&(i=(i=b.subParser("makehtml.spanGamut")(i,r,t)).replace(/^([ \t]*)/g,"<p>"),i+="</p>",n.push(i))}for(s=n.length,o=0;o<s;o++){for(var l="",c=n[o],u=!1;/¨(K|G)(\d+)\1/.test(c);){var h=RegExp.$1,m=RegExp.$2;l=(l="K"===h?t.gHtmlBlocks[m]:u?b.subParser("makehtml.encodeCode")(t.ghCodeBlocks[m].text,r,t):t.ghCodeBlocks[m].codeblock).replace(/\$/g,"$$$$"),c=c.replace(/(\n\n)?¨(K|G)\d+\2(\n\n)?/,l),/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(c)&&(u=!0)}n[o]=c}return e=(e=(e=n.join("\n")).replace(/^\n+/g,"")).replace(/\n+$/g,""),t.converter._dispatch("makehtml.paragraphs.after",e,r,t).getText()}),b.subParser("makehtml.runExtension",function(e,r,t,a){"use strict";if(e.filter)r=e.filter(r,a.converter,t);else if(e.regex){var n=e.regex;n instanceof RegExp||(n=new RegExp(n,"g")),r=r.replace(n,e.replace)}return r}),b.subParser("makehtml.spanGamut",function(e,r,t){"use strict";return e=t.converter._dispatch("makehtml.span.before",e,r,t).getText(),e=b.subParser("makehtml.codeSpans")(e,r,t),e=b.subParser("makehtml.escapeSpecialCharsWithinTagAttributes")(e,r,t),e=b.subParser("makehtml.encodeBackslashEscapes")(e,r,t),e=b.subParser("makehtml.images")(e,r,t),e=t.converter._dispatch("smakehtml.links.before",e,r,t).getText(),e=b.subParser("makehtml.links")(e,r,t),e=t.converter._dispatch("smakehtml.links.after",e,r,t).getText(),e=b.subParser("makehtml.emoji")(e,r,t),e=b.subParser("makehtml.underline")(e,r,t),e=b.subParser("makehtml.italicsAndBold")(e,r,t),e=b.subParser("makehtml.strikethrough")(e,r,t),e=b.subParser("makehtml.ellipsis")(e,r,t),e=b.subParser("makehtml.hashHTMLSpans")(e,r,t),e=b.subParser("makehtml.encodeAmpsAndAngles")(e,r,t),r.simpleLineBreaks?/\n\n¨K/.test(e)||(e=e.replace(/\n+/g,"<br />\n")):e=e.replace(/ +\n/g,"<br />\n"),e=t.converter._dispatch("makehtml.spanGamut.after",e,r,t).getText()}),b.subParser("makehtml.strikethrough",function(e,r,t){"use strict";return r.strikethrough&&(e=(e=t.converter._dispatch("makehtml.strikethrough.before",e,r,t).getText()).replace(/(?:~){2}([\s\S]+?)(?:~){2}/g,function(e,r){return"<del>"+r+"</del>"}),e=t.converter._dispatch("makehtml.strikethrough.after",e,r,t).getText()),e}),b.subParser("makehtml.stripLinkDefinitions",function(e,i,l){"use strict";var r=function(e,r,t,a,n,s,o){return r=r.toLowerCase(),t.match(/^data:.+?\/.+?;base64,/)?l.gUrls[r]=t.replace(/\s/g,""):l.gUrls[r]=b.subParser("makehtml.encodeAmpsAndAngles")(t,i,l),s?s+o:(o&&(l.gTitles[r]=o.replace(/"|'/g,"&quot;")),i.parseImgDimensions&&a&&n&&(l.gDimensions[r]={width:a,height:n}),"")};return e=(e=(e=(e+="¨0").replace(/^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm,r)).replace(/^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,r)).replace(/¨0/,"")}),b.subParser("makehtml.tables",function(e,_,f){"use strict";if(!_.tables)return e;function r(e){var r,t=e.split("\n");for(r=0;r<t.length;++r)/^ {0,3}\|/.test(t[r])&&(t[r]=t[r].replace(/^ {0,3}\|/,"")),/\|[ \t]*$/.test(t[r])&&(t[r]=t[r].replace(/\|[ \t]*$/,"")),t[r]=b.subParser("makehtml.codeSpans")(t[r],_,f);var a,n,s,o,i,l=t[0].split("|").map(function(e){return e.trim()}),c=t[1].split("|").map(function(e){return e.trim()}),u=[],h=[],m=[],d=[];for(t.shift(),t.shift(),r=0;r<t.length;++r)""!==t[r].trim()&&u.push(t[r].split("|").map(function(e){return e.trim()}));if(l.length<c.length)return e;for(r=0;r<c.length;++r)m.push((a=c[r],/^:[ \t]*--*$/.test(a)?' style="text-align:left;"':/^--*[ \t]*:[ \t]*$/.test(a)?' style="text-align:right;"':/^:[ \t]*--*[ \t]*:$/.test(a)?' style="text-align:center;"':""));for(r=0;r<l.length;++r)b.helper.isUndefined(m[r])&&(m[r]=""),h.push((n=l[r],s=m[r],o=void 0,o="",n=n.trim(),(_.tablesHeaderId||_.tableHeaderId)&&(o=' id="'+n.replace(/ /g,"_").toLowerCase()+'"'),"<th"+o+s+">"+(n=b.subParser("makehtml.spanGamut")(n,_,f))+"</th>\n"));for(r=0;r<u.length;++r){for(var p=[],g=0;g<h.length;++g)b.helper.isUndefined(u[r][g]),p.push((i=u[r][g],"<td"+m[g]+">"+b.subParser("makehtml.spanGamut")(i,_,f)+"</td>\n"));d.push(p)}return function(e,r){for(var t="<table>\n<thead>\n<tr>\n",a=e.length,n=0;n<a;++n)t+=e[n];for(t+="</tr>\n</thead>\n<tbody>\n",n=0;n<r.length;++n){t+="<tr>\n";for(var s=0;s<a;++s)t+=r[n][s];t+="</tr>\n"}return t+="</tbody>\n</table>\n"}(h,d)}return e=(e=(e=(e=f.converter._dispatch("makehtml.tables.before",e,_,f).getText()).replace(/\\(\|)/g,b.helper.escapeCharactersCallback)).replace(/^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,r)).replace(/^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm,r),e=f.converter._dispatch("makehtml.tables.after",e,_,f).getText()}),b.subParser("makehtml.underline",function(e,r,t){"use strict";return r.underline?(e=t.converter._dispatch("makehtml.underline.before",e,r,t).getText(),e=(e=r.literalMidWordUnderscores?(e=e.replace(/\b___(\S[\s\S]*?)___\b/g,function(e,r){return"<u>"+r+"</u>"})).replace(/\b__(\S[\s\S]*?)__\b/g,function(e,r){return"<u>"+r+"</u>"}):(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,r){return/\S$/.test(r)?"<u>"+r+"</u>":e})).replace(/__(\S[\s\S]*?)__/g,function(e,r){return/\S$/.test(r)?"<u>"+r+"</u>":e})).replace(/(_)/g,b.helper.escapeCharactersCallback),e=t.converter._dispatch("makehtml.underline.after",e,r,t).getText()):e}),b.subParser("makehtml.unescapeSpecialChars",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("makehtml.unescapeSpecialChars.before",e,r,t).getText()).replace(/¨E(\d+)E/g,function(e,r){var t=parseInt(r);return String.fromCharCode(t)}),e=t.converter._dispatch("makehtml.unescapeSpecialChars.after",e,r,t).getText()}),b.subParser("makeMarkdown.blockquote",function(e,r){"use strict";var t="";if(e.hasChildNodes())for(var a=e.childNodes,n=a.length,s=0;s<n;++s){var o=b.subParser("makeMarkdown.node")(a[s],r);""!==o&&(t+=o)}return t="> "+(t=t.trim()).split("\n").join("\n> ")}),b.subParser("makeMarkdown.codeBlock",function(e,r){"use strict";var t=e.getAttribute("language"),a=e.getAttribute("precodenum");return"```"+t+"\n"+r.preList[a]+"\n```"}),b.subParser("makeMarkdown.codeSpan",function(e){"use strict";return"`"+e.innerHTML+"`"}),b.subParser("makeMarkdown.emphasis",function(e,r){"use strict";var t="";if(e.hasChildNodes()){t+="*";for(var a=e.childNodes,n=a.length,s=0;s<n;++s)t+=b.subParser("makeMarkdown.node")(a[s],r);t+="*"}return t}),b.subParser("makeMarkdown.header",function(e,r,t){"use strict";var a=new Array(t+1).join("#"),n="";if(e.hasChildNodes()){n=a+" ";for(var s=e.childNodes,o=s.length,i=0;i<o;++i)n+=b.subParser("makeMarkdown.node")(s[i],r)}return n}),b.subParser("makeMarkdown.hr",function(){"use strict";return"---"}),b.subParser("makeMarkdown.image",function(e){"use strict";var r="";return e.hasAttribute("src")&&(r+="!["+e.getAttribute("alt")+"](",r+="<"+e.getAttribute("src")+">",e.hasAttribute("width")&&e.hasAttribute("height")&&(r+=" ="+e.getAttribute("width")+"x"+e.getAttribute("height")),e.hasAttribute("title")&&(r+=' "'+e.getAttribute("title")+'"'),r+=")"),r}),b.subParser("makeMarkdown.links",function(e,r){"use strict";var t="";if(e.hasChildNodes()&&e.hasAttribute("href")){var a=e.childNodes,n=a.length;t="[";for(var s=0;s<n;++s)t+=b.subParser("makeMarkdown.node")(a[s],r);t+="](",t+="<"+e.getAttribute("href")+">",e.hasAttribute("title")&&(t+=' "'+e.getAttribute("title")+'"'),t+=")"}return t}),b.subParser("makeMarkdown.list",function(e,r,t){"use strict";var a="";if(!e.hasChildNodes())return"";for(var n=e.childNodes,s=n.length,o=e.getAttribute("start")||1,i=0;i<s;++i)if(void 0!==n[i].tagName&&"li"===n[i].tagName.toLowerCase()){a+=("ol"===t?o.toString()+". ":"- ")+b.subParser("makeMarkdown.listItem")(n[i],r),++o}return a.trim()}),b.subParser("makeMarkdown.listItem",function(e,r){"use strict";for(var t="",a=e.childNodes,n=a.length,s=0;s<n;++s)t+=b.subParser("makeMarkdown.node")(a[s],r);return/\n$/.test(t)?t=t.split("\n").join("\n ").replace(/^ {4}$/gm,"").replace(/\n\n+/g,"\n\n"):t+="\n",t}),b.subParser("makeMarkdown.node",function(e,r,t){"use strict";t=t||!1;var a="";if(3===e.nodeType)return b.subParser("makeMarkdown.txt")(e,r);if(8===e.nodeType)return"\x3c!--"+e.data+"--\x3e\n\n";if(1!==e.nodeType)return"";switch(e.tagName.toLowerCase()){case"h1":t||(a=b.subParser("makeMarkdown.header")(e,r,1)+"\n\n");break;case"h2":t||(a=b.subParser("makeMarkdown.header")(e,r,2)+"\n\n");break;case"h3":t||(a=b.subParser("makeMarkdown.header")(e,r,3)+"\n\n");break;case"h4":t||(a=b.subParser("makeMarkdown.header")(e,r,4)+"\n\n");break;case"h5":t||(a=b.subParser("makeMarkdown.header")(e,r,5)+"\n\n");break;case"h6":t||(a=b.subParser("makeMarkdown.header")(e,r,6)+"\n\n");break;case"p":t||(a=b.subParser("makeMarkdown.paragraph")(e,r)+"\n\n");break;case"blockquote":t||(a=b.subParser("makeMarkdown.blockquote")(e,r)+"\n\n");break;case"hr":t||(a=b.subParser("makeMarkdown.hr")(e,r)+"\n\n");break;case"ol":t||(a=b.subParser("makeMarkdown.list")(e,r,"ol")+"\n\n");break;case"ul":t||(a=b.subParser("makeMarkdown.list")(e,r,"ul")+"\n\n");break;case"precode":t||(a=b.subParser("makeMarkdown.codeBlock")(e,r)+"\n\n");break;case"pre":t||(a=b.subParser("makeMarkdown.pre")(e,r)+"\n\n");break;case"table":t||(a=b.subParser("makeMarkdown.table")(e,r)+"\n\n");break;case"code":a=b.subParser("makeMarkdown.codeSpan")(e,r);break;case"em":case"i":a=b.subParser("makeMarkdown.emphasis")(e,r);break;case"strong":case"b":a=b.subParser("makeMarkdown.strong")(e,r);break;case"del":a=b.subParser("makeMarkdown.strikethrough")(e,r);break;case"a":a=b.subParser("makeMarkdown.links")(e,r);break;case"img":a=b.subParser("makeMarkdown.image")(e,r);break;default:a=e.outerHTML+"\n\n"}return a}),b.subParser("makeMarkdown.paragraph",function(e,r){"use strict";var t="";if(e.hasChildNodes())for(var a=e.childNodes,n=a.length,s=0;s<n;++s)t+=b.subParser("makeMarkdown.node")(a[s],r);return t=t.trim()}),b.subParser("makeMarkdown.pre",function(e,r){"use strict";var t=e.getAttribute("prenum");return"<pre>"+r.preList[t]+"</pre>"}),b.subParser("makeMarkdown.strikethrough",function(e,r){"use strict";var t="";if(e.hasChildNodes()){t+="~~";for(var a=e.childNodes,n=a.length,s=0;s<n;++s)t+=b.subParser("makeMarkdown.node")(a[s],r);t+="~~"}return t}),b.subParser("makeMarkdown.strong",function(e,r){"use strict";var t="";if(e.hasChildNodes()){t+="**";for(var a=e.childNodes,n=a.length,s=0;s<n;++s)t+=b.subParser("makeMarkdown.node")(a[s],r);t+="**"}return t}),b.subParser("makeMarkdown.table",function(e,r){"use strict";var t,a,n="",s=[[],[]],o=e.querySelectorAll("thead>tr>th"),i=e.querySelectorAll("tbody>tr");for(t=0;t<o.length;++t){var l=b.subParser("makeMarkdown.tableCell")(o[t],r),c="---";if(o[t].hasAttribute("style"))switch(o[t].getAttribute("style").toLowerCase().replace(/\s/g,"")){case"text-align:left;":c=":---";break;case"text-align:right;":c="---:";break;case"text-align:center;":c=":---:"}s[0][t]=l.trim(),s[1][t]=c}for(t=0;t<i.length;++t){var u=s.push([])-1,h=i[t].getElementsByTagName("td");for(a=0;a<o.length;++a){var m=" ";void 0!==h[a]&&(m=b.subParser("makeMarkdown.tableCell")(h[a],r)),s[u].push(m)}}var d=3;for(t=0;t<s.length;++t)for(a=0;a<s[t].length;++a){var p=s[t][a].length;d<p&&(d=p)}for(t=0;t<s.length;++t){for(a=0;a<s[t].length;++a)1===t?":"===s[t][a].slice(-1)?s[t][a]=b.helper.padEnd(s[t][a].slice(-1),d-1,"-")+":":s[t][a]=b.helper.padEnd(s[t][a],d,"-"):s[t][a]=b.helper.padEnd(s[t][a],d);n+="| "+s[t].join(" | ")+" |\n"}return n.trim()}),b.subParser("makeMarkdown.tableCell",function(e,r){"use strict";var t="";if(!e.hasChildNodes())return"";for(var a=e.childNodes,n=a.length,s=0;s<n;++s)t+=b.subParser("makeMarkdown.node")(a[s],r,!0);return t.trim()}),b.subParser("makeMarkdown.txt",function(e){"use strict";var r=e.nodeValue;return r=(r=r.replace(/ +/g," ")).replace(/¨NBSP;/g," "),r=(r=(r=(r=(r=(r=(r=(r=(r=b.helper.unescapeHTMLEntities(r)).replace(/([*_~|`])/g,"\\$1")).replace(/^(\s*)>/g,"\\$1>")).replace(/^#/gm,"\\#")).replace(/^(\s*)([-=]{3,})(\s*)$/,"$1\\$2$3")).replace(/^( {0,3}\d+)\./gm,"$1\\.")).replace(/^( {0,3})([+-])/gm,"$1\\$2")).replace(/]([\s]*)\(/g,"\\]$1\\(")).replace(/^ {0,3}\[([\S \t]*?)]:/gm,"\\[$1]:")}),b.Converter=function(t){"use strict";var s={},o=[],i=[],c={},a=d,l={parsed:{},raw:"",format:""};function n(e,r){if(r=r||null,b.helper.isString(e)){if(r=e=b.helper.stdExtName(e),b.extensions[e])return console.warn("DEPRECATION WARNING: "+e+" is an old extension that uses a deprecated loading method.Please inform the developer that the extension should be updated!"),void function(e,r){"function"==typeof e&&(e=e(new b.Converter));b.helper.isArray(e)||(e=[e]);var t=g(e,r);if(!t.valid)throw Error(t.error);for(var a=0;a<e.length;++a)switch(e[a].type){case"lang":o.push(e[a]);break;case"output":i.push(e[a]);break;default:throw Error("Extension loader error: Type unrecognized!!!")}}(b.extensions[e],e);if(b.helper.isUndefined(h[e]))throw Error('Extension "'+e+'" could not be loaded. It was either not found or is not a valid extension.');e=h[e]}"function"==typeof e&&(e=e()),b.helper.isArray(e)||(e=[e]);var t=g(e,r);if(!t.valid)throw Error(t.error);for(var a=0;a<e.length;++a){switch(e[a].type){case"lang":o.push(e[a]);break;case"output":i.push(e[a])}if(e[a].hasOwnProperty("listeners"))for(var n in e[a].listeners)e[a].listeners.hasOwnProperty(n)&&u(n,e[a].listeners[n])}}function u(e,r){if(!b.helper.isString(e))throw Error("Invalid argument in converter.listen() method: name must be a string, but "+typeof e+" given");if("function"!=typeof r)throw Error("Invalid argument in converter.listen() method: callback must be a function, but "+typeof r+" given");e=e.toLowerCase(),c.hasOwnProperty(e)||(c[e]=[]),c[e].push(r)}!function(){for(var e in t=t||{},m)m.hasOwnProperty(e)&&(s[e]=m[e]);{if("object"!=typeof t)throw Error("Converter expects the passed parameter to be an object, but "+typeof t+" was passed instead.");for(var r in t)t.hasOwnProperty(r)&&(s[r]=t[r])}s.extensions&&b.helper.forEach(s.extensions,n)}(),this._dispatch=function(e,r,t,a,n){e=e.toLowerCase();var s=n||{};s.converter=this,s.text=r,s.options=t,s.globals=a;var o=new b.helper.Event(e,r,s);if(c.hasOwnProperty(e))for(var i=0;i<c[e].length;++i){var l=c[e][i](o);l&&void 0!==l&&o.setText(l)}return o},this.listen=function(e,r){return u(e,r),this},this.makeHtml=function(r){if(!r)return r;var e,t,a,n={gHtmlBlocks:[],gHtmlMdBlocks:[],gHtmlSpans:[],gUrls:{},gTitles:{},gDimensions:{},gListLevel:0,hashLinkCounts:{},langExtensions:o,outputModifiers:i,converter:this,ghCodeBlocks:[],metadata:{parsed:{},raw:"",format:""}};return r=(r=(r=(r=(r=r.replace(/¨/g,"¨T")).replace(/\$/g,"¨D")).replace(/\r\n/g,"\n")).replace(/\r/g,"\n")).replace(/\u00A0/g,"&nbsp;"),s.smartIndentationFix&&(t=(e=r).match(/^\s*/)[0].length,a=new RegExp("^\\s{0,"+t+"}","gm"),r=e.replace(a,"")),r="\n\n"+r+"\n\n",r=(r=b.subParser("makehtml.detab")(r,s,n)).replace(/^[ \t]+$/gm,""),b.helper.forEach(o,function(e){r=b.subParser("makehtml.runExtension")(e,r,s,n)}),r=b.subParser("makehtml.metadata")(r,s,n),r=b.subParser("makehtml.hashPreCodeTags")(r,s,n),r=b.subParser("makehtml.githubCodeBlocks")(r,s,n),r=b.subParser("makehtml.hashHTMLBlocks")(r,s,n),r=b.subParser("makehtml.hashCodeTags")(r,s,n),r=b.subParser("makehtml.stripLinkDefinitions")(r,s,n),r=b.subParser("makehtml.blockGamut")(r,s,n),r=b.subParser("makehtml.unhashHTMLSpans")(r,s,n),r=(r=(r=b.subParser("makehtml.unescapeSpecialChars")(r,s,n)).replace(/¨D/g,"$$")).replace(/¨T/g,"¨"),r=b.subParser("makehtml.completeHTMLDocument")(r,s,n),b.helper.forEach(i,function(e){r=b.subParser("makehtml.runExtension")(e,r,s,n)}),l=n.metadata,r},this.makeMarkdown=function(e){e=(e=(e=e.replace(/\r\n/g,"\n")).replace(/\r/g,"\n")).replace(/>[ \t]+</,">¨NBSP;<");var r=b.helper.document.createElement("div");r.innerHTML=e;var t={preList:function(e){for(var r=e.querySelectorAll("pre"),t=[],a=0;a<r.length;++a)if(1===r[a].childElementCount&&"code"===r[a].firstChild.tagName.toLowerCase()){var n=r[a].firstChild.innerHTML.trim(),s=r[a].firstChild.getAttribute("data-language")||"";if(""===s)for(var o=r[a].firstChild.className.split(" "),i=0;i<o.length;++i){var l=o[i].match(/^language-(.+)$/);if(null!==l){s=l[1];break}}n=b.helper.unescapeHTMLEntities(n),t.push(n),r[a].outerHTML='<precode language="'+s+'" precodenum="'+a.toString()+'"></precode>'}else t.push(r[a].innerHTML),r[a].innerHTML="",r[a].setAttribute("prenum",a.toString());return t}(r)};!function e(r){for(var t=0;t<r.childNodes.length;++t){var a=r.childNodes[t];3===a.nodeType?/\S/.test(a.nodeValue)?(a.nodeValue=a.nodeValue.split("\n").join(" "),a.nodeValue=a.nodeValue.replace(/(\s)+/g,"$1")):(r.removeChild(a),--t):1===a.nodeType&&e(a)}}(r);for(var a=r.childNodes,n="",s=0;s<a.length;s++)n+=b.subParser("makeMarkdown.node")(a[s],t);return n},this.setOption=function(e,r){s[e]=r},this.getOption=function(e){return s[e]},this.getOptions=function(){return s},this.addExtension=function(e,r){n(e,r=r||null)},this.useExtension=function(e){n(e)},this.setFlavor=function(e){if(!p.hasOwnProperty(e))throw Error(e+" flavor was not found");var r=p[e];for(var t in a=e,r)r.hasOwnProperty(t)&&(s[t]=r[t])},this.getFlavor=function(){return a},this.removeExtension=function(e){b.helper.isArray(e)||(e=[e]);for(var r=0;r<e.length;++r){for(var t=e[r],a=0;a<o.length;++a)o[a]===t&&o[a].splice(a,1);for(;0<i.length;++a)i[0]===t&&i[0].splice(a,1)}},this.getAllExtensions=function(){return{language:o,output:i}},this.getMetadata=function(e){return e?l.raw:l.parsed},this.getMetadataFormat=function(){return l.format},this._setMetadataPair=function(e,r){l.parsed[e]=r},this._setMetadataFormat=function(e){l.format=e},this._setMetadataRaw=function(e){l.raw=e}};"function"==typeof define&&define.amd?define(function(){"use strict";return b}):"undefined"!=typeof module&&module.exports?module.exports=b:this.showdown=b}).call(this);
2 //# sourceMappingURL=showdown.min.js.map
+0
-12
faraday/server/www/script/ui-bootstrap-tpls-0.14.1.min.js less more
0 /*
1 * angular-ui-bootstrap
2 * http://angular-ui.github.io/bootstrap/
3
4 * Version: 0.14.1 - 2015-10-11
5 * License: MIT
6 */
7 angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-popup.html","template/tooltip/tooltip-popup.html","template/tooltip/tooltip-template-popup.html","template/popover/popover-html.html","template/popover/popover-template.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.collapse",[]).directive("uibCollapse",["$animate","$injector",function(a,b){var c=b.has("$animateCss")?b.get("$animateCss"):null;return{link:function(b,d,e){function f(){d.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),c?c(d,{addClass:"in",easing:"ease",to:{height:d[0].scrollHeight+"px"}}).start().done(g):a.addClass(d,"in",{to:{height:d[0].scrollHeight+"px"}}).then(g)}function g(){d.removeClass("collapsing").addClass("collapse").css({height:"auto"})}function h(){return d.hasClass("collapse")||d.hasClass("in")?(d.css({height:d[0].scrollHeight+"px"}).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),void(c?c(d,{removeClass:"in",to:{height:"0"}}).start().done(i):a.removeClass(d,"in",{to:{height:"0"}}).then(i))):i()}function i(){d.css({height:"0"}),d.removeClass("collapsing").addClass("collapse")}b.$watch(e.uibCollapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.collapse").value("$collapseSuppressWarning",!1).directive("collapse",["$animate","$injector","$log","$collapseSuppressWarning",function(a,b,c,d){var e=b.has("$animateCss")?b.get("$animateCss"):null;return{link:function(b,f,g){function h(){f.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),e?e(f,{addClass:"in",easing:"ease",to:{height:f[0].scrollHeight+"px"}}).start().done(i):a.addClass(f,"in",{to:{height:f[0].scrollHeight+"px"}}).then(i)}function i(){f.removeClass("collapsing").addClass("collapse").css({height:"auto"})}function j(){return f.hasClass("collapse")||f.hasClass("in")?(f.css({height:f[0].scrollHeight+"px"}).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),void(e?e(f,{removeClass:"in",to:{height:"0"}}).start().done(k):a.removeClass(f,"in",{to:{height:"0"}}).then(k))):k()}function k(){f.css({height:"0"}),f.removeClass("collapsing").addClass("collapse")}d||c.warn("collapse is now deprecated. Use uib-collapse instead."),b.$watch(g.collapse,function(a){a?j():h()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("uibAccordionConfig",{closeOthers:!0}).controller("UibAccordionController",["$scope","$attrs","uibAccordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(c){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("uibAccordion",function(){return{controller:"UibAccordionController",controllerAs:"accordion",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/accordion/accordion.html"}}}).directive("uibAccordionGroup",function(){return{require:"^uibAccordion",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/accordion/accordion-group.html"},scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.openClass=c.openClass||"panel-open",a.panelClass=c.panelClass,a.$watch("isOpen",function(c){b.toggleClass(a.openClass,!!c),c&&d.closeOthers(a)}),a.toggleOpen=function(b){a.isDisabled||b&&32!==b.which||(a.isOpen=!a.isOpen)}}}}).directive("uibAccordionHeading",function(){return{transclude:!0,template:"",replace:!0,require:"^uibAccordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("uibAccordionTransclude",function(){return{require:["?^uibAccordionGroup","?^accordionGroup"],link:function(a,b,c,d){d=d[0]?d[0]:d[1],a.$watch(function(){return d[c.uibAccordionTransclude]},function(a){a&&(b.find("span").html(""),b.find("span").append(a))})}}}),angular.module("ui.bootstrap.accordion").value("$accordionSuppressWarning",!1).controller("AccordionController",["$scope","$attrs","$controller","$log","$accordionSuppressWarning",function(a,b,c,d,e){e||d.warn("AccordionController is now deprecated. Use UibAccordionController instead."),angular.extend(this,c("UibAccordionController",{$scope:a,$attrs:b}))}]).directive("accordion",["$log","$accordionSuppressWarning",function(a,b){return{restrict:"EA",controller:"AccordionController",controllerAs:"accordion",transclude:!0,replace:!1,templateUrl:function(a,b){return b.templateUrl||"template/accordion/accordion.html"},link:function(){b||a.warn("accordion is now deprecated. Use uib-accordion instead.")}}}]).directive("accordionGroup",["$log","$accordionSuppressWarning",function(a,b){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/accordion/accordion-group.html"},scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(c,d,e,f){b||a.warn("accordion-group is now deprecated. Use uib-accordion-group instead."),f.addGroup(c),c.openClass=e.openClass||"panel-open",c.panelClass=e.panelClass,c.$watch("isOpen",function(a){d.toggleClass(c.openClass,!!a),a&&f.closeOthers(c)}),c.toggleOpen=function(a){c.isDisabled||a&&32!==a.which||(c.isOpen=!c.isOpen)}}}}]).directive("accordionHeading",["$log","$accordionSuppressWarning",function(a,b){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(c,d,e,f,g){b||a.warn("accordion-heading is now deprecated. Use uib-accordion-heading instead."),f.setHeading(g(c,angular.noop))}}}]).directive("accordionTransclude",["$log","$accordionSuppressWarning",function(a,b){return{require:"^accordionGroup",link:function(c,d,e,f){b||a.warn("accordion-transclude is now deprecated. Use uib-accordion-transclude instead."),c.$watch(function(){return f[e.accordionTransclude]},function(a){a&&(d.find("span").html(""),d.find("span").append(a))})}}}]),angular.module("ui.bootstrap.alert",[]).controller("UibAlertController",["$scope","$attrs","$timeout",function(a,b,c){a.closeable=!!b.close,angular.isDefined(b.dismissOnTimeout)&&c(function(){a.close()},parseInt(b.dismissOnTimeout,10))}]).directive("uibAlert",function(){return{controller:"UibAlertController",controllerAs:"alert",templateUrl:function(a,b){return b.templateUrl||"template/alert/alert.html"},transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}),angular.module("ui.bootstrap.alert").value("$alertSuppressWarning",!1).controller("AlertController",["$scope","$attrs","$controller","$log","$alertSuppressWarning",function(a,b,c,d,e){e||d.warn("AlertController is now deprecated. Use UibAlertController instead."),angular.extend(this,c("UibAlertController",{$scope:a,$attrs:b}))}]).directive("alert",["$log","$alertSuppressWarning",function(a,b){return{controller:"AlertController",controllerAs:"alert",templateUrl:function(a,b){return b.templateUrl||"template/alert/alert.html"},transclude:!0,replace:!0,scope:{type:"@",close:"&"},link:function(){b||a.warn("alert is now deprecated. Use uib-alert instead.")}}}]),angular.module("ui.bootstrap.buttons",[]).constant("uibButtonConfig",{activeClass:"active",toggleEvent:"click"}).controller("UibButtonsController",["uibButtonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("uibBtnRadio",function(){return{require:["uibBtnRadio","ngModel"],controller:"UibButtonsController",controllerAs:"buttons",link:function(a,b,c,d){var e=d[0],f=d[1];b.find("input").css({display:"none"}),f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.uibBtnRadio)))},b.on(e.toggleEvent,function(){if(!c.disabled){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.uibBtnRadio)),f.$render()})}})}}}).directive("uibBtnCheckbox",["$document",function(a){return{require:["uibBtnCheckbox","ngModel"],controller:"UibButtonsController",controllerAs:"button",link:function(b,c,d,e){function f(){return h(d.btnCheckboxTrue,!0)}function g(){return h(d.btnCheckboxFalse,!1)}function h(a,c){return angular.isDefined(a)?b.$eval(a):c}var i=e[0],j=e[1];c.find("input").css({display:"none"}),j.$render=function(){c.toggleClass(i.activeClass,angular.equals(j.$modelValue,f()))},c.on(i.toggleEvent,function(){d.disabled||b.$apply(function(){j.$setViewValue(c.hasClass(i.activeClass)?g():f()),j.$render()})}),c.on("keypress",function(e){d.disabled||32!==e.which||a[0].activeElement!==c[0]||b.$apply(function(){j.$setViewValue(c.hasClass(i.activeClass)?g():f()),j.$render()})})}}}]),angular.module("ui.bootstrap.buttons").value("$buttonsSuppressWarning",!1).controller("ButtonsController",["$controller","$log","$buttonsSuppressWarning",function(a,b,c){c||b.warn("ButtonsController is now deprecated. Use UibButtonsController instead."),angular.extend(this,a("UibButtonsController"))}]).directive("btnRadio",["$log","$buttonsSuppressWarning",function(a,b){return{require:["btnRadio","ngModel"],controller:"ButtonsController",controllerAs:"buttons",link:function(c,d,e,f){b||a.warn("btn-radio is now deprecated. Use uib-btn-radio instead.");var g=f[0],h=f[1];d.find("input").css({display:"none"}),h.$render=function(){d.toggleClass(g.activeClass,angular.equals(h.$modelValue,c.$eval(e.btnRadio)))},d.bind(g.toggleEvent,function(){if(!e.disabled){var a=d.hasClass(g.activeClass);(!a||angular.isDefined(e.uncheckable))&&c.$apply(function(){h.$setViewValue(a?null:c.$eval(e.btnRadio)),h.$render()})}})}}}]).directive("btnCheckbox",["$document","$log","$buttonsSuppressWarning",function(a,b,c){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",controllerAs:"button",link:function(d,e,f,g){function h(){return j(f.btnCheckboxTrue,!0)}function i(){return j(f.btnCheckboxFalse,!1)}function j(a,b){var c=d.$eval(a);return angular.isDefined(c)?c:b}c||b.warn("btn-checkbox is now deprecated. Use uib-btn-checkbox instead.");var k=g[0],l=g[1];e.find("input").css({display:"none"}),l.$render=function(){e.toggleClass(k.activeClass,angular.equals(l.$modelValue,h()))},e.bind(k.toggleEvent,function(){f.disabled||d.$apply(function(){l.$setViewValue(e.hasClass(k.activeClass)?i():h()),l.$render()})}),e.on("keypress",function(b){f.disabled||32!==b.which||a[0].activeElement!==e[0]||d.$apply(function(){l.$setViewValue(e.hasClass(k.activeClass)?i():h()),l.$render()})})}}}]),angular.module("ui.bootstrap.carousel",[]).controller("UibCarouselController",["$scope","$element","$interval","$animate",function(a,b,c,d){function e(b,c,e){s||(angular.extend(b,{direction:e,active:!0}),angular.extend(m.currentSlide||{},{direction:e,active:!1}),d.enabled()&&!a.noTransition&&!a.$currentTransition&&b.$element&&m.slides.length>1&&(b.$element.data(q,b.direction),m.currentSlide&&m.currentSlide.$element&&m.currentSlide.$element.data(q,b.direction),a.$currentTransition=!0,o?d.on("addClass",b.$element,function(b,c){"close"===c&&(a.$currentTransition=null,d.off("addClass",b))}):b.$element.one("$animate:close",function(){a.$currentTransition=null})),m.currentSlide=b,r=c,g())}function f(a){if(angular.isUndefined(n[a].index))return n[a];var b;n.length;for(b=0;b<n.length;++b)if(n[b].index==a)return n[b]}function g(){h();var b=+a.interval;!isNaN(b)&&b>0&&(k=c(i,b))}function h(){k&&(c.cancel(k),k=null)}function i(){var b=+a.interval;l&&!isNaN(b)&&b>0&&n.length?a.next():a.pause()}function j(b){b.length||(a.$currentTransition=null)}var k,l,m=this,n=m.slides=a.slides=[],o=angular.version.minor>=4,p="uib-noTransition",q="uib-slideDirection",r=-1;m.currentSlide=null;var s=!1;m.select=a.select=function(b,c){var d=a.indexOfSlide(b);void 0===c&&(c=d>m.getCurrentIndex()?"next":"prev"),b&&b!==m.currentSlide&&!a.$currentTransition&&e(b,d,c)},a.$on("$destroy",function(){s=!0}),m.getCurrentIndex=function(){return m.currentSlide&&angular.isDefined(m.currentSlide.index)?+m.currentSlide.index:r},a.indexOfSlide=function(a){return angular.isDefined(a.index)?+a.index:n.indexOf(a)},a.next=function(){var b=(m.getCurrentIndex()+1)%n.length;return 0===b&&a.noWrap()?void a.pause():m.select(f(b),"next")},a.prev=function(){var b=m.getCurrentIndex()-1<0?n.length-1:m.getCurrentIndex()-1;return a.noWrap()&&b===n.length-1?void a.pause():m.select(f(b),"prev")},a.isActive=function(a){return m.currentSlide===a},a.$watch("interval",g),a.$watchCollection("slides",j),a.$on("$destroy",h),a.play=function(){l||(l=!0,g())},a.pause=function(){a.noPause||(l=!1,h())},m.addSlide=function(b,c){b.$element=c,n.push(b),1===n.length||b.active?(m.select(n[n.length-1]),1===n.length&&a.play()):b.active=!1},m.removeSlide=function(a){angular.isDefined(a.index)&&n.sort(function(a,b){return+a.index>+b.index});var b=n.indexOf(a);n.splice(b,1),n.length>0&&a.active?b>=n.length?m.select(n[b-1]):m.select(n[b]):r>b&&r--,0===n.length&&(m.currentSlide=null)},a.$watch("noTransition",function(a){b.data(p,a)})}]).directive("uibCarousel",[function(){return{transclude:!0,replace:!0,controller:"UibCarouselController",controllerAs:"carousel",require:"carousel",templateUrl:function(a,b){return b.templateUrl||"template/carousel/carousel.html"},scope:{interval:"=",noTransition:"=",noPause:"=",noWrap:"&"}}}]).directive("uibSlide",function(){return{require:"^uibCarousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/carousel/slide.html"},scope:{active:"=?",actual:"=?",index:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}).animation(".item",["$injector","$animate",function(a,b){function c(a,b,c){a.removeClass(b),c&&c()}var d="uib-noTransition",e="uib-slideDirection",f=null;return a.has("$animateCss")&&(f=a.get("$animateCss")),{beforeAddClass:function(a,g,h){if("active"==g&&a.parent()&&a.parent().parent()&&!a.parent().parent().data(d)){var i=!1,j=a.data(e),k="next"==j?"left":"right",l=c.bind(this,a,k+" "+j,h);return a.addClass(j),f?f(a,{addClass:k}).start().done(l):b.addClass(a,k).then(function(){i||l(),h()}),function(){i=!0}}h()},beforeRemoveClass:function(a,g,h){if("active"===g&&a.parent()&&a.parent().parent()&&!a.parent().parent().data(d)){var i=!1,j=a.data(e),k="next"==j?"left":"right",l=c.bind(this,a,k,h);return f?f(a,{addClass:k}).start().done(l):b.addClass(a,k).then(function(){i||l(),h()}),function(){i=!0}}h()}}}]),angular.module("ui.bootstrap.carousel").value("$carouselSuppressWarning",!1).controller("CarouselController",["$scope","$element","$controller","$log","$carouselSuppressWarning",function(a,b,c,d,e){e||d.warn("CarouselController is now deprecated. Use UibCarouselController instead."),angular.extend(this,c("UibCarouselController",{$scope:a,$element:b}))}]).directive("carousel",["$log","$carouselSuppressWarning",function(a,b){return{transclude:!0,replace:!0,controller:"CarouselController",controllerAs:"carousel",require:"carousel",templateUrl:function(a,b){return b.templateUrl||"template/carousel/carousel.html"},scope:{interval:"=",noTransition:"=",noPause:"=",noWrap:"&"},link:function(){b||a.warn("carousel is now deprecated. Use uib-carousel instead.")}}}]).directive("slide",["$log","$carouselSuppressWarning",function(a,b){return{require:"^carousel",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/carousel/slide.html"},scope:{active:"=?",actual:"=?",index:"=?"},link:function(c,d,e,f){b||a.warn("slide is now deprecated. Use uib-slide instead."),f.addSlide(c,d),c.$on("$destroy",function(){f.removeSlide(c)}),c.$watch("active",function(a){a&&f.select(c)})}}}]),angular.module("ui.bootstrap.dateparser",[]).service("uibDateParser",["$log","$locale","orderByFilter",function(a,b,c){function d(a){var b=[],d=a.split("");return angular.forEach(g,function(c,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+c.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),b.push({index:f,apply:c.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:c(b,"index")}}function e(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}var f,g,h=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.init=function(){f=b.id,this.parsers={},g={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:b.DATETIME_FORMATS.MONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.MONTH.indexOf(a)}},MMM:{regex:b.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.SHORTMONTH.indexOf(a)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:b.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:b.DATETIME_FORMATS.SHORTDAY.join("|")},HH:{regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a}},hh:{regex:"0[0-9]|1[0-2]",apply:function(a){this.hours=+a}},H:{regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a}},h:{regex:"[0-9]|1[0-2]",apply:function(a){this.hours=+a}},mm:{regex:"[0-5][0-9]",apply:function(a){this.minutes=+a}},m:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a}},sss:{regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a}},ss:{regex:"[0-5][0-9]",apply:function(a){this.seconds=+a}},s:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a}},a:{regex:b.DATETIME_FORMATS.AMPMS.join("|"),apply:function(a){12===this.hours&&(this.hours=0),"PM"===a&&(this.hours+=12)}}}},this.init(),this.parse=function(c,g,i){if(!angular.isString(c)||!g)return c;g=b.DATETIME_FORMATS[g]||g,g=g.replace(h,"\\$&"),b.id!==f&&this.init(),this.parsers[g]||(this.parsers[g]=d(g));var j=this.parsers[g],k=j.regex,l=j.map,m=c.match(k);if(m&&m.length){var n,o;angular.isDate(i)&&!isNaN(i.getTime())?n={year:i.getFullYear(),month:i.getMonth(),date:i.getDate(),hours:i.getHours(),minutes:i.getMinutes(),seconds:i.getSeconds(),milliseconds:i.getMilliseconds()}:(i&&a.warn("dateparser:","baseDate is not a valid date"),n={year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0});for(var p=1,q=m.length;q>p;p++){var r=l[p-1];r.apply&&r.apply.call(n,m[p])}return e(n.year,n.month,n.date)&&(o=new Date(n.year,n.month,n.date,n.hours,n.minutes,n.seconds,n.milliseconds||0)),o}}}]),angular.module("ui.bootstrap.dateparser").value("$dateParserSuppressWarning",!1).service("dateParser",["$log","$dateParserSuppressWarning","uibDateParser",function(a,b,c){b||a.warn("dateParser is now deprecated. Use uibDateParser instead."),angular.extend(this,c)}]),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.position").value("$positionSuppressWarning",!1).service("$position",["$log","$positionSuppressWarning","$uibPosition",function(a,b,c){b||a.warn("$position is now deprecated. Use $uibPosition instead."),angular.extend(this,c)}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).value("$datepickerSuppressError",!1).constant("uibDatepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null,shortcutPropagation:!1}).controller("UibDatepickerController",["$scope","$attrs","$parse","$interpolate","$log","dateFilter","uibDatepickerConfig","$datepickerSuppressError",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","showWeeks","startingDay","yearRange","shortcutPropagation"],function(c,e){i[c]=angular.isDefined(b[c])?6>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):g[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=g[d]?new Date(g[d]):null}),angular.forEach(["minMode","maxMode"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(c){i[d]=angular.isDefined(c)?c:b[d],a[d]=i[d],("minMode"==d&&i.modes.indexOf(a.datepickerMode)<i.modes.indexOf(i[d])||"maxMode"==d&&i.modes.indexOf(a.datepickerMode)>i.modes.indexOf(i[d]))&&(a.datepickerMode=i[d])}):(i[d]=g[d]||null,a[d]=i[d])}),a.datepickerMode=a.datepickerMode||g.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(j.$isEmpty(j.$modelValue)||j.$invalid)&&(i.activeDate=a,i.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$viewValue){var a=new Date(j.$viewValue),b=!isNaN(a);b?this.activeDate=a:h||e.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$viewValue?new Date(j.$viewValue):null;j.$setValidity("dateDisabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$viewValue?new Date(j.$viewValue):null;return{date:a,label:f(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},this.fixTimeZone=function(a){var b=a.getHours();a.setHours(23===b?b+2:0)},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$viewValue?new Date(j.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){i.element[0].focus()};a.$on("uib:datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),i.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):a.toggleMode("up"===c?1:-1)}}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;b>f;)c=new Date(e),this.fixTimeZone(c),d[f++]=c,e.setDate(e.getDate()+1);return d},this._refreshView=function(){var b=this.activeDate.getFullYear(),d=this.activeDate.getMonth(),f=new Date(b,d,1),g=this.startingDay-f.getDay(),h=g>0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;42>k;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;7>l;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;n>o;o++)a.weekNumbers.push(e(a.rows[o][m].date))}},this.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},this.handleKeyDown=function(a,b){var c=this.activeDate.getDate();if("left"===a)c-=1;else if("up"===a)c-=7;else if("right"===a)c+=1;else if("down"===a)c+=7;else if("pageup"===a||"pagedown"===a){var e=this.activeDate.getMonth()+("pageup"===a?-1:1);this.activeDate.setMonth(e,1),c=Math.min(d(this.activeDate.getFullYear(),this.activeDate.getMonth()),c)}else"home"===a?c=1:"end"===a&&(c=d(this.activeDate.getFullYear(),this.activeDate.getMonth()));this.activeDate.setDate(c)}}]).controller("UibMonthpickerController",["$scope","$element","dateFilter",function(a,b,c){this.step={years:1},this.element=b,this.init=function(a){angular.extend(a,this),a.refreshView()},this._refreshView=function(){for(var b,d=new Array(12),e=this.activeDate.getFullYear(),f=0;12>f;f++)b=new Date(e,f,1),this.fixTimeZone(b),d[f]=angular.extend(this.createDateObject(b,this.formatMonth),{uid:a.uniqueId+"-"+f});a.title=c(this.activeDate,this.formatMonthTitle),a.rows=this.split(d,3)},this.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},this.handleKeyDown=function(a,b){var c=this.activeDate.getMonth();if("left"===a)c-=1;else if("up"===a)c-=3;else if("right"===a)c+=1;else if("down"===a)c+=3;else if("pageup"===a||"pagedown"===a){var d=this.activeDate.getFullYear()+("pageup"===a?-1:1);this.activeDate.setFullYear(d)}else"home"===a?c=0:"end"===a&&(c=11);this.activeDate.setMonth(c)}}]).controller("UibYearpickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a){return parseInt((a-1)/e,10)*e+1}var e;this.element=b,this.yearpickerInit=function(){e=this.yearRange,this.step={years:e}},this._refreshView=function(){for(var b,c=new Array(e),f=0,g=d(this.activeDate.getFullYear());e>f;f++)b=new Date(g+f,0,1),this.fixTimeZone(b),c[f]=angular.extend(this.createDateObject(b,this.formatYear),{uid:a.uniqueId+"-"+f});a.title=[c[0].label,c[e-1].label].join(" - "),a.rows=this.split(c,5)},this.compare=function(a,b){return a.getFullYear()-b.getFullYear()},this.handleKeyDown=function(a,b){var c=this.activeDate.getFullYear();"left"===a?c-=1:"up"===a?c-=5:"right"===a?c+=1:"down"===a?c+=5:"pageup"===a||"pagedown"===a?c+=("pageup"===a?-1:1)*this.step.years:"home"===a?c=d(this.activeDate.getFullYear()):"end"===a&&(c=d(this.activeDate.getFullYear())+e-1),this.activeDate.setFullYear(c)}}]).directive("uibDatepicker",function(){return{replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/datepicker.html"},scope:{datepickerMode:"=?",dateDisabled:"&",customClass:"&",shortcutPropagation:"&?"},require:["uibDatepicker","^ngModel"],controller:"UibDatepickerController",controllerAs:"datepicker",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}).directive("uibDaypicker",function(){return{replace:!0,templateUrl:"template/datepicker/day.html",require:["^?uibDatepicker","uibDaypicker","^?datepicker"],controller:"UibDaypickerController",link:function(a,b,c,d){var e=d[0]||d[2],f=d[1];f.init(e)}}}).directive("uibMonthpicker",function(){return{replace:!0,templateUrl:"template/datepicker/month.html",require:["^?uibDatepicker","uibMonthpicker","^?datepicker"],controller:"UibMonthpickerController",link:function(a,b,c,d){var e=d[0]||d[2],f=d[1];f.init(e)}}}).directive("uibYearpicker",function(){return{replace:!0,templateUrl:"template/datepicker/year.html",require:["^?uibDatepicker","uibYearpicker","^?datepicker"],controller:"UibYearpickerController",link:function(a,b,c,d){var e=d[0]||d[2];angular.extend(e,d[1]),e.yearpickerInit(),e.refreshView()}}}).constant("uibDatepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",datepickerPopupTemplateUrl:"template/datepicker/popup.html",datepickerTemplateUrl:"template/datepicker/datepicker.html",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0,onOpenFocus:!0}).controller("UibDatepickerPopupController",["$scope","$element","$attrs","$compile","$parse","$document","$rootScope","$uibPosition","dateFilter","uibDateParser","uibDatepickerPopupConfig","$timeout",function(a,b,c,d,e,f,g,h,i,j,k,l){
8 function m(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function n(b){if(angular.isNumber(b)&&(b=new Date(b)),b){if(angular.isDate(b)&&!isNaN(b))return b;if(angular.isString(b)){var c=j.parse(b,r,a.date);return isNaN(c)?void 0:c}return void 0}return null}function o(a,b){var d=a||b;if(!c.ngRequired&&!d)return!0;if(angular.isNumber(d)&&(d=new Date(d)),d){if(angular.isDate(d)&&!isNaN(d))return!0;if(angular.isString(d)){var e=j.parse(d,r);return!isNaN(e)}return!1}return!0}function p(c){var d=A[0],e=b[0].contains(c.target),f=void 0!==d.contains&&d.contains(c.target);!a.isOpen||e||f||a.$apply(function(){a.isOpen=!1})}function q(c){27===c.which&&a.isOpen?(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!1}),b[0].focus()):40!==c.which||a.isOpen||(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!0}))}var r,s,t,u,v,w,x,y,z,A,B={},C=!1;a.watchData={},this.init=function(h){if(z=h,s=angular.isDefined(c.closeOnDateSelection)?a.$parent.$eval(c.closeOnDateSelection):k.closeOnDateSelection,t=angular.isDefined(c.datepickerAppendToBody)?a.$parent.$eval(c.datepickerAppendToBody):k.appendToBody,u=angular.isDefined(c.onOpenFocus)?a.$parent.$eval(c.onOpenFocus):k.onOpenFocus,v=angular.isDefined(c.datepickerPopupTemplateUrl)?c.datepickerPopupTemplateUrl:k.datepickerPopupTemplateUrl,w=angular.isDefined(c.datepickerTemplateUrl)?c.datepickerTemplateUrl:k.datepickerTemplateUrl,a.showButtonBar=angular.isDefined(c.showButtonBar)?a.$parent.$eval(c.showButtonBar):k.showButtonBar,k.html5Types[c.type]?(r=k.html5Types[c.type],C=!0):(r=c.datepickerPopup||k.datepickerPopup,c.$observe("uibDatepickerPopup",function(a,b){var c=a||k.datepickerPopup;if(c!==r&&(r=c,z.$modelValue=null,!r))throw new Error("uibDatepickerPopup must have a date format specified.")})),!r)throw new Error("uibDatepickerPopup must have a date format specified.");if(C&&c.datepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");if(x=angular.element("<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>"),x.attr({"ng-model":"date","ng-change":"dateSelection(date)","template-url":v}),y=angular.element(x.children()[0]),y.attr("template-url",w),C&&"month"===c.type&&(y.attr("datepicker-mode",'"month"'),y.attr("min-mode","month")),c.datepickerOptions){var l=a.$parent.$eval(c.datepickerOptions);l&&l.initDate&&(a.initDate=l.initDate,y.attr("init-date","initDate"),delete l.initDate),angular.forEach(l,function(a,b){y.attr(m(b),a)})}angular.forEach(["minMode","maxMode","minDate","maxDate","datepickerMode","initDate","shortcutPropagation"],function(b){if(c[b]){var d=e(c[b]);if(a.$parent.$watch(d,function(c){a.watchData[b]=c,("minDate"===b||"maxDate"===b)&&(B[b]=new Date(c))}),y.attr(m(b),"watchData."+b),"datepickerMode"===b){var f=d.assign;a.$watch("watchData."+b,function(b,c){angular.isFunction(f)&&b!==c&&f(a.$parent,b)})}}}),c.dateDisabled&&y.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),c.showWeeks&&y.attr("show-weeks",c.showWeeks),c.customClass&&y.attr("custom-class","customClass({ date: date, mode: mode })"),C?z.$formatters.push(function(b){return a.date=b,b}):(z.$$parserName="date",z.$validators.date=o,z.$parsers.unshift(n),z.$formatters.push(function(b){return a.date=b,z.$isEmpty(b)?b:i(b,r)})),z.$viewChangeListeners.push(function(){a.date=j.parse(z.$viewValue,r,a.date)}),b.bind("keydown",q),A=d(x)(a),x.remove(),t?f.find("body").append(A):b.after(A),a.$on("$destroy",function(){a.isOpen===!0&&(g.$$phase||a.$apply(function(){a.isOpen=!1})),A.remove(),b.unbind("keydown",q),f.unbind("click",p)})},a.getText=function(b){return a[b+"Text"]||k[b+"Text"]},a.isDisabled=function(b){return"today"===b&&(b=new Date),a.watchData.minDate&&a.compare(b,B.minDate)<0||a.watchData.maxDate&&a.compare(b,B.maxDate)>0},a.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},a.dateSelection=function(c){angular.isDefined(c)&&(a.date=c);var d=a.date?i(a.date,r):null;b.val(d),z.$setViewValue(d),s&&(a.isOpen=!1,b[0].focus())},a.keydown=function(c){27===c.which&&(a.isOpen=!1,b[0].focus())},a.select=function(b){if("today"===b){var c=new Date;angular.isDate(a.date)?(b=new Date(a.date),b.setFullYear(c.getFullYear(),c.getMonth(),c.getDate())):b=new Date(c.setHours(0,0,0,0))}a.dateSelection(b)},a.close=function(){a.isOpen=!1,b[0].focus()},a.$watch("isOpen",function(c){c?(a.position=t?h.offset(b):h.position(b),a.position.top=a.position.top+b.prop("offsetHeight"),l(function(){u&&a.$broadcast("uib:datepicker.focus"),f.bind("click",p)},0,!1)):f.unbind("click",p)})}]).directive("uibDatepickerPopup",function(){return{require:["ngModel","uibDatepickerPopup"],controller:"UibDatepickerPopupController",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibDatepickerPopupWrap",function(){return{replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/popup.html"}}}),angular.module("ui.bootstrap.datepicker").value("$datepickerSuppressWarning",!1).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$log","dateFilter","uibDatepickerConfig","$datepickerSuppressError","$datepickerSuppressWarning",function(a,b,c,d,e,f,g,h,i){i||e.warn("DatepickerController is now deprecated. Use UibDatepickerController instead.");var j=this,k={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","showWeeks","startingDay","yearRange","shortcutPropagation"],function(c,e){j[c]=angular.isDefined(b[c])?6>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):g[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){j[d]=a?new Date(a):null,j.refreshView()}):j[d]=g[d]?new Date(g[d]):null}),angular.forEach(["minMode","maxMode"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(c){j[d]=angular.isDefined(c)?c:b[d],a[d]=j[d],("minMode"==d&&j.modes.indexOf(a.datepickerMode)<j.modes.indexOf(j[d])||"maxMode"==d&&j.modes.indexOf(a.datepickerMode)>j.modes.indexOf(j[d]))&&(a.datepickerMode=j[d])}):(j[d]=g[d]||null,a[d]=j[d])}),a.datepickerMode=a.datepickerMode||g.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(k.$isEmpty(k.$modelValue)||k.$invalid)&&(j.activeDate=a,j.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===j.compare(b.date,j.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){k=a,k.$render=function(){j.render()}},this.render=function(){if(k.$viewValue){var a=new Date(k.$viewValue),b=!isNaN(a);b?this.activeDate=a:h||e.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=k.$viewValue?new Date(k.$viewValue):null;k.$setValidity("dateDisabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=k.$viewValue?new Date(k.$viewValue):null;return{date:a,label:f(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},this.fixTimeZone=function(a){var b=a.getHours();a.setHours(23===b?b+2:0)},a.select=function(b){if(a.datepickerMode===j.minMode){var c=k.$viewValue?new Date(k.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),k.$setViewValue(c),k.$render()}else j.activeDate=b,a.datepickerMode=j.modes[j.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=j.activeDate.getFullYear()+a*(j.step.years||0),c=j.activeDate.getMonth()+a*(j.step.months||0);j.activeDate.setFullYear(b,c,1),j.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===j.maxMode&&1===b||a.datepickerMode===j.minMode&&-1===b||(a.datepickerMode=j.modes[j.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var l=function(){j.element[0].focus()};a.$on("uib:datepicker.focus",l),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),j.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(j.isDisabled(j.activeDate))return;a.select(j.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(j.handleKeyDown(c,b),j.refreshView()):a.toggleMode("up"===c?1:-1)}}]).directive("datepicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/datepicker.html"},scope:{datepickerMode:"=?",dateDisabled:"&",customClass:"&",shortcutPropagation:"&?"},require:["datepicker","^ngModel"],controller:"DatepickerController",controllerAs:"datepicker",link:function(c,d,e,f){b||a.warn("datepicker is now deprecated. Use uib-datepicker instead.");var g=f[0],h=f[1];g.init(h)}}}]).directive("daypicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/day.html",require:["^datepicker","daypicker"],controller:"UibDaypickerController",link:function(c,d,e,f){b||a.warn("daypicker is now deprecated. Use uib-daypicker instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("monthpicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/month.html",require:["^datepicker","monthpicker"],controller:"UibMonthpickerController",link:function(c,d,e,f){b||a.warn("monthpicker is now deprecated. Use uib-monthpicker instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("yearpicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/year.html",require:["^datepicker","yearpicker"],controller:"UibYearpickerController",link:function(c,d,e,f){b||a.warn("yearpicker is now deprecated. Use uib-yearpicker instead.");var g=f[0];angular.extend(g,f[1]),g.yearpickerInit(),g.refreshView()}}}]).directive("datepickerPopup",["$log","$datepickerSuppressWarning",function(a,b){return{require:["ngModel","datepickerPopup"],controller:"UibDatepickerPopupController",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(c,d,e,f){b||a.warn("datepicker-popup is now deprecated. Use uib-datepicker-popup instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("datepickerPopupWrap",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/popup.html"},link:function(){b||a.warn("datepicker-popup-wrap is now deprecated. Use uib-datepicker-popup-wrap instead.")}}}]),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.position"]).constant("uibDropdownConfig",{openClass:"open"}).service("uibDropdownService",["$document","$rootScope",function(a,b){var c=null;this.open=function(b){c||(a.bind("click",d),a.bind("keydown",e)),c&&c!==b&&(c.isOpen=!1),c=b},this.close=function(b){c===b&&(c=null,a.unbind("click",d),a.unbind("keydown",e))};var d=function(a){if(c&&(!a||"disabled"!==c.getAutoClose())){var d=c.getToggleElement();if(!(a&&d&&d[0].contains(a.target))){var e=c.getDropdownElement();a&&"outsideClick"===c.getAutoClose()&&e&&e[0].contains(a.target)||(c.isOpen=!1,b.$$phase||c.$apply())}}},e=function(a){27===a.which?(c.focusToggleElement(),d()):c.isKeynavEnabled()&&/(38|40)/.test(a.which)&&c.isOpen&&(a.preventDefault(),a.stopPropagation(),c.focusDropdownEntry(a.which))}}]).controller("UibDropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest",function(a,b,c,d,e,f,g,h,i,j,k){var l,m,n=this,o=a.$new(),p=e.openClass,q=angular.noop,r=c.onToggle?d(c.onToggle):angular.noop,s=!1,t=!1;b.addClass("dropdown"),this.init=function(){c.isOpen&&(m=d(c.isOpen),q=m.assign,a.$watch(m,function(a){o.isOpen=!!a})),s=angular.isDefined(c.dropdownAppendToBody),t=angular.isDefined(c.uibKeyboardNav),s&&n.dropdownMenu&&(i.find("body").append(n.dropdownMenu),b.on("$destroy",function(){n.dropdownMenu.remove()}))},this.toggle=function(a){return o.isOpen=arguments.length?!!a:!o.isOpen},this.isOpen=function(){return o.isOpen},o.getToggleElement=function(){return n.toggleElement},o.getAutoClose=function(){return c.autoClose||"always"},o.getElement=function(){return b},o.isKeynavEnabled=function(){return t},o.focusDropdownEntry=function(a){var c=n.dropdownMenu?angular.element(n.dropdownMenu).find("a"):angular.element(b).find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(n.selectedOption)?n.selectedOption=n.selectedOption===c.length-1?n.selectedOption:n.selectedOption+1:n.selectedOption=0;break;case 38:angular.isNumber(n.selectedOption)?n.selectedOption=0===n.selectedOption?0:n.selectedOption-1:n.selectedOption=c.length-1}c[n.selectedOption].focus()},o.getDropdownElement=function(){return n.dropdownMenu},o.focusToggleElement=function(){n.toggleElement&&n.toggleElement[0].focus()},o.$watch("isOpen",function(c,d){if(s&&n.dropdownMenu){var e=h.positionElements(b,n.dropdownMenu,"bottom-left",!0),i={top:e.top+"px",display:c?"block":"none"},m=n.dropdownMenu.hasClass("dropdown-menu-right");m?(i.left="auto",i.right=window.innerWidth-(e.left+b.prop("offsetWidth"))+"px"):(i.left=e.left+"px",i.right="auto"),n.dropdownMenu.css(i)}if(g[c?"addClass":"removeClass"](b,p).then(function(){angular.isDefined(c)&&c!==d&&r(a,{open:!!c})}),c)n.dropdownMenuTemplateUrl&&k(n.dropdownMenuTemplateUrl).then(function(a){l=o.$new(),j(a.trim())(l,function(a){var b=a;n.dropdownMenu.replaceWith(b),n.dropdownMenu=b})}),o.focusToggleElement(),f.open(o);else{if(n.dropdownMenuTemplateUrl){l&&l.$destroy();var t=angular.element('<ul class="dropdown-menu"></ul>');n.dropdownMenu.replaceWith(t),n.dropdownMenu=t}f.close(o),n.selectedOption=null}angular.isFunction(q)&&q(a,c)}),a.$on("$locationChangeSuccess",function(){"disabled"!==o.getAutoClose()&&(o.isOpen=!1)});var u=a.$on("$destroy",function(){o.$destroy()});o.$on("$destroy",u)}]).directive("uibDropdown",function(){return{controller:"UibDropdownController",link:function(a,b,c,d){d.init()}}}).directive("uibDropdownMenu",function(){return{restrict:"AC",require:"?^uibDropdown",link:function(a,b,c,d){if(d&&!angular.isDefined(c.dropdownNested)){b.addClass("dropdown-menu");var e=c.templateUrl;e&&(d.dropdownMenuTemplateUrl=e),d.dropdownMenu||(d.dropdownMenu=b)}}}}).directive("uibKeyboardNav",function(){return{restrict:"A",require:"?^uibDropdown",link:function(a,b,c,d){b.bind("keydown",function(a){if(-1!==[38,40].indexOf(a.which)){a.preventDefault(),a.stopPropagation();var b=d.dropdownMenu.find("a");switch(a.which){case 40:angular.isNumber(d.selectedOption)?d.selectedOption=d.selectedOption===b.length-1?d.selectedOption:d.selectedOption+1:d.selectedOption=0;break;case 38:angular.isNumber(d.selectedOption)?d.selectedOption=0===d.selectedOption?0:d.selectedOption-1:d.selectedOption=b.length-1}b[d.selectedOption].focus()}})}}}).directive("uibDropdownToggle",function(){return{require:"?^uibDropdown",link:function(a,b,c,d){if(d){b.addClass("dropdown-toggle"),d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.dropdown").value("$dropdownSuppressWarning",!1).service("dropdownService",["$log","$dropdownSuppressWarning","uibDropdownService",function(a,b,c){b||a.warn("dropdownService is now deprecated. Use uibDropdownService instead."),angular.extend(this,c)}]).controller("DropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest","$log","$dropdownSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k,l,m){m||l.warn("DropdownController is now deprecated. Use UibDropdownController instead.");var n,o,p=this,q=a.$new(),r=e.openClass,s=angular.noop,t=c.onToggle?d(c.onToggle):angular.noop,u=!1,v=!1;b.addClass("dropdown"),this.init=function(){c.isOpen&&(o=d(c.isOpen),s=o.assign,a.$watch(o,function(a){q.isOpen=!!a})),u=angular.isDefined(c.dropdownAppendToBody),v=angular.isDefined(c.uibKeyboardNav),u&&p.dropdownMenu&&(i.find("body").append(p.dropdownMenu),b.on("$destroy",function(){p.dropdownMenu.remove()}))},this.toggle=function(a){return q.isOpen=arguments.length?!!a:!q.isOpen},this.isOpen=function(){return q.isOpen},q.getToggleElement=function(){return p.toggleElement},q.getAutoClose=function(){return c.autoClose||"always"},q.getElement=function(){return b},q.isKeynavEnabled=function(){return v},q.focusDropdownEntry=function(a){var c=p.dropdownMenu?angular.element(p.dropdownMenu).find("a"):angular.element(b).find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(p.selectedOption)?p.selectedOption=p.selectedOption===c.length-1?p.selectedOption:p.selectedOption+1:p.selectedOption=0;break;case 38:angular.isNumber(p.selectedOption)?p.selectedOption=0===p.selectedOption?0:p.selectedOption-1:p.selectedOption=c.length-1}c[p.selectedOption].focus()},q.getDropdownElement=function(){return p.dropdownMenu},q.focusToggleElement=function(){p.toggleElement&&p.toggleElement[0].focus()},q.$watch("isOpen",function(c,d){if(u&&p.dropdownMenu){var e=h.positionElements(b,p.dropdownMenu,"bottom-left",!0),i={top:e.top+"px",display:c?"block":"none"},l=p.dropdownMenu.hasClass("dropdown-menu-right");l?(i.left="auto",i.right=window.innerWidth-(e.left+b.prop("offsetWidth"))+"px"):(i.left=e.left+"px",i.right="auto"),p.dropdownMenu.css(i)}if(g[c?"addClass":"removeClass"](b,r).then(function(){angular.isDefined(c)&&c!==d&&t(a,{open:!!c})}),c)p.dropdownMenuTemplateUrl&&k(p.dropdownMenuTemplateUrl).then(function(a){n=q.$new(),j(a.trim())(n,function(a){var b=a;p.dropdownMenu.replaceWith(b),p.dropdownMenu=b})}),q.focusToggleElement(),f.open(q);else{if(p.dropdownMenuTemplateUrl){n&&n.$destroy();var m=angular.element('<ul class="dropdown-menu"></ul>');p.dropdownMenu.replaceWith(m),p.dropdownMenu=m}f.close(q),p.selectedOption=null}angular.isFunction(s)&&s(a,c)}),a.$on("$locationChangeSuccess",function(){"disabled"!==q.getAutoClose()&&(q.isOpen=!1)});var w=a.$on("$destroy",function(){q.$destroy()});q.$on("$destroy",w)}]).directive("dropdown",["$log","$dropdownSuppressWarning",function(a,b){return{controller:"DropdownController",link:function(c,d,e,f){b||a.warn("dropdown is now deprecated. Use uib-dropdown instead."),f.init()}}}]).directive("dropdownMenu",["$log","$dropdownSuppressWarning",function(a,b){return{restrict:"AC",require:"?^dropdown",link:function(c,d,e,f){if(f){b||a.warn("dropdown-menu is now deprecated. Use uib-dropdown-menu instead."),d.addClass("dropdown-menu");var g=e.templateUrl;g&&(f.dropdownMenuTemplateUrl=g),f.dropdownMenu||(f.dropdownMenu=d)}}}}]).directive("keyboardNav",["$log","$dropdownSuppressWarning",function(a,b){return{restrict:"A",require:"?^dropdown",link:function(c,d,e,f){b||a.warn("keyboard-nav is now deprecated. Use uib-keyboard-nav instead."),d.bind("keydown",function(a){if(-1!==[38,40].indexOf(a.which)){a.preventDefault(),a.stopPropagation();var b=f.dropdownMenu.find("a");switch(a.which){case 40:angular.isNumber(f.selectedOption)?f.selectedOption=f.selectedOption===b.length-1?f.selectedOption:f.selectedOption+1:f.selectedOption=0;break;case 38:angular.isNumber(f.selectedOption)?f.selectedOption=0===f.selectedOption?0:f.selectedOption-1:f.selectedOption=b.length-1}b[f.selectedOption].focus()}})}}}]).directive("dropdownToggle",["$log","$dropdownSuppressWarning",function(a,b){return{require:"?^dropdown",link:function(c,d,e,f){if(b||a.warn("dropdown-toggle is now deprecated. Use uib-dropdown-toggle instead."),f){d.addClass("dropdown-toggle"),f.toggleElement=d;var g=function(a){a.preventDefault(),d.hasClass("disabled")||e.disabled||c.$apply(function(){f.toggle()})};d.bind("click",g),d.attr({"aria-haspopup":!0,"aria-expanded":!1}),c.$watch(f.isOpen,function(a){d.attr("aria-expanded",!!a)}),c.$on("$destroy",function(){d.unbind("click",g)})}}}}]),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b==a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b==a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.splice(a.length-1,1)[0]},length:function(){return a.length}}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.stackedMap"]).factory("$$multiMap",function(){return{createNew:function(){var a={};return{entries:function(){return Object.keys(a).map(function(b){return{key:b,value:a[b]}})},get:function(b){return a[b]},hasKey:function(b){return!!a[b]},keys:function(){return Object.keys(a)},put:function(b,c){a[b]||(a[b]=[]),a[b].push(c)},remove:function(b,c){var d=a[b];if(d){var e=d.indexOf(c);-1!==e&&d.splice(e,1),d.length||delete a[b]}}}}}}).directive("uibModalBackdrop",["$animate","$injector","$uibModalStack",function(a,b,c){function d(b,d,f){d.addClass("modal-backdrop"),f.modalInClass&&(e?e(d,{addClass:f.modalInClass}).start():a.addClass(d,f.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(b,c){var g=c();e?e(d,{removeClass:f.modalInClass}).start().then(g):a.removeClass(d,f.modalInClass).then(g)}))}var e=null;return b.has("$animateCss")&&(e=b.get("$animateCss")),{replace:!0,templateUrl:"template/modal/backdrop.html",compile:function(a,b){return a.addClass(b.backdropClass),d}}}]).directive("uibModalWindow",["$uibModalStack","$q","$animate","$injector",function(a,b,c,d){var e=null;return d.has("$animateCss")&&(e=d.get("$animateCss")),{scope:{index:"@"},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(d,f,g){f.addClass(g.windowClass||""),f.addClass(g.windowTopClass||""),d.size=g.size,d.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},f.on("click",d.close),d.$isRendered=!0;var h=b.defer();g.$observe("modalRender",function(a){"true"==a&&h.resolve()}),h.promise.then(function(){var h=null;g.modalInClass&&(h=e?e(f,{addClass:g.modalInClass}).start():c.addClass(f,g.modalInClass),d.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();e?e(f,{removeClass:g.modalInClass}).start().then(d):c.removeClass(f,g.modalInClass).then(d)})),b.when(h).then(function(){var a=f[0].querySelectorAll("[autofocus]");a.length?a[0].focus():f[0].focus()});var i=a.getTop();i&&a.modalRendered(i.key)})}}}]).directive("uibModalAnimationClass",[function(){return{compile:function(a,b){b.modalAnimation&&a.addClass(b.uibModalAnimationClass)}}}]).directive("uibModalTransclude",function(){return{link:function(a,b,c,d,e){e(a.$parent,function(a){b.empty(),b.append(a)})}}}).factory("$uibModalStack",["$animate","$timeout","$document","$compile","$rootScope","$q","$injector","$$multiMap","$$stackedMap",function(a,b,c,d,e,f,g,h,i){function j(){for(var a=-1,b=u.keys(),c=0;c<b.length;c++)u.get(b[c]).value.backdrop&&(a=c);return a}function k(a,b){var d=c.find("body").eq(0),e=u.get(a).value;u.remove(a),n(e.modalDomEl,e.modalScope,function(){var b=e.openedClass||t;v.remove(b,a),d.toggleClass(b,v.hasKey(b)),l(!0)}),m(),b&&b.focus?b.focus():d.focus()}function l(a){var b;u.length()>0&&(b=u.top().value,b.modalDomEl.toggleClass(b.windowTopClass||"",a))}function m(){if(q&&-1==j()){var a=r;n(q,r,function(){a=null}),q=void 0,r=void 0}}function n(b,c,d){function e(){e.done||(e.done=!0,p?p(b,{event:"leave"}).start().then(function(){b.remove()}):a.leave(b),c.$destroy(),d&&d())}var g,h=null,i=function(){return g||(g=f.defer(),h=g.promise),function(){g.resolve()}};return c.$broadcast(w.NOW_CLOSING_EVENT,i),f.when(h).then(e)}function o(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}var p=null;g.has("$animateCss")&&(p=g.get("$animateCss"));var q,r,s,t="modal-open",u=i.createNew(),v=h.createNew(),w={NOW_CLOSING_EVENT:"modal.stack.now-closing"},x=0,y="a[href], area[href], input:not([disabled]), button:not([disabled]),select:not([disabled]), textarea:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable=true]";return e.$watch(j,function(a){r&&(r.index=a)}),c.bind("keydown",function(a){if(a.isDefaultPrevented())return a;var b=u.top();if(b&&b.value.keyboard)switch(a.which){case 27:a.preventDefault(),e.$apply(function(){w.dismiss(b.key,"escape key press")});break;case 9:w.loadFocusElementList(b);var c=!1;a.shiftKey?w.isFocusInFirstItem(a)&&(c=w.focusLastFocusableElement()):w.isFocusInLastItem(a)&&(c=w.focusFirstFocusableElement()),c&&(a.preventDefault(),a.stopPropagation())}}),w.open=function(a,b){var f=c[0].activeElement,g=b.openedClass||t;l(!1),u.add(a,{deferred:b.deferred,renderDeferred:b.renderDeferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard,openedClass:b.openedClass,windowTopClass:b.windowTopClass}),v.put(g,a);var h=c.find("body").eq(0),i=j();if(i>=0&&!q){r=e.$new(!0),r.index=i;var k=angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');k.attr("backdrop-class",b.backdropClass),b.animation&&k.attr("modal-animation","true"),q=d(k)(r),h.append(q)}var m=angular.element('<div uib-modal-window="modal-window"></div>');m.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,"window-top-class":b.windowTopClass,size:b.size,index:u.length()-1,animate:"animate"}).html(b.content),b.animation&&m.attr("modal-animation","true");var n=d(m)(b.scope);u.top().value.modalDomEl=n,u.top().value.modalOpener=f,h.append(n),h.addClass(g),w.clearFocusListCache()},w.close=function(a,b){var c=u.get(a);return c&&o(c,b,!0)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.resolve(b),k(a,c.value.modalOpener),!0):!c},w.dismiss=function(a,b){var c=u.get(a);return c&&o(c,b,!1)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.reject(b),k(a,c.value.modalOpener),!0):!c},w.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},w.getTop=function(){return u.top()},w.modalRendered=function(a){var b=u.get(a);b&&b.value.renderDeferred.resolve()},w.focusFirstFocusableElement=function(){return s.length>0?(s[0].focus(),!0):!1},w.focusLastFocusableElement=function(){return s.length>0?(s[s.length-1].focus(),!0):!1},w.isFocusInFirstItem=function(a){return s.length>0?(a.target||a.srcElement)==s[0]:!1},w.isFocusInLastItem=function(a){return s.length>0?(a.target||a.srcElement)==s[s.length-1]:!1},w.clearFocusListCache=function(){s=[],x=0},w.loadFocusElementList=function(a){if((void 0===s||!s.length0)&&a){var b=a.value.modalDomEl;b&&b.length&&(s=b[0].querySelectorAll(y))}},w}]).provider("$uibModal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$templateRequest","$controller","$uibModalStack",function(b,c,d,e,f,g){function h(a){return a.template?d.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}function i(a){var c=[];return angular.forEach(a,function(a){angular.isFunction(a)||angular.isArray(a)?c.push(d.when(b.invoke(a))):angular.isString(a)?c.push(d.when(b.get(a))):c.push(d.when(a))}),c}var j={},k=null;return j.getPromiseChain=function(){return k},j.open=function(b){var e=d.defer(),j=d.defer(),l=d.defer(),m={result:e.promise,opened:j.promise,rendered:l.promise,close:function(a){return g.close(m,a)},dismiss:function(a){return g.dismiss(m,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var n,o=d.all([h(b)].concat(i(b.resolve)));return n=k=d.all([k]).then(function(){return o},function(){return o}).then(function(a){var d=(b.scope||c).$new();d.$close=m.close,d.$dismiss=m.dismiss,d.$on("$destroy",function(){d.$$uibDestructionScheduled||d.$dismiss("$uibUnscheduledDestruction")});var h,i={},k=1;b.controller&&(i.$scope=d,i.$modalInstance=m,angular.forEach(b.resolve,function(b,c){i[c]=a[k++]}),h=f(b.controller,i),b.controllerAs&&(b.bindToController&&angular.extend(h,d),d[b.controllerAs]=h)),g.open(m,{scope:d,deferred:e,renderDeferred:l,content:a[0],animation:b.animation,backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowTopClass:b.windowTopClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size,openedClass:b.openedClass}),j.resolve(!0)},function(a){j.reject(a),e.reject(a)})["finally"](function(){k===n&&(k=null)}),m},j}]};return a}),angular.module("ui.bootstrap.modal").value("$modalSuppressWarning",!1).directive("modalBackdrop",["$animate","$injector","$modalStack","$log","$modalSuppressWarning",function(a,b,c,d,e){function f(b,f,h){e||d.warn("modal-backdrop is now deprecated. Use uib-modal-backdrop instead."),f.addClass("modal-backdrop"),h.modalInClass&&(g?g(f,{addClass:h.modalInClass}).start():a.addClass(f,h.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(b,c){var d=c();g?g(f,{removeClass:h.modalInClass}).start().then(d):a.removeClass(f,h.modalInClass).then(d)}))}var g=null;return b.has("$animateCss")&&(g=b.get("$animateCss")),{replace:!0,templateUrl:"template/modal/backdrop.html",compile:function(a,b){return a.addClass(b.backdropClass),f}}}]).directive("modalWindow",["$modalStack","$q","$animate","$injector","$log","$modalSuppressWarning",function(a,b,c,d,e,f){var g=null;return d.has("$animateCss")&&(g=d.get("$animateCss")),{scope:{index:"@"},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(d,h,i){f||e.warn("modal-window is now deprecated. Use uib-modal-window instead."),h.addClass(i.windowClass||""),h.addClass(i.windowTopClass||""),d.size=i.size,d.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},h.on("click",d.close),d.$isRendered=!0;var j=b.defer();i.$observe("modalRender",function(a){"true"==a&&j.resolve()}),j.promise.then(function(){var e=null;i.modalInClass&&(e=g?g(h,{addClass:i.modalInClass}).start():c.addClass(h,i.modalInClass),d.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();g?g(h,{removeClass:i.modalInClass}).start().then(d):c.removeClass(h,i.modalInClass).then(d)})),b.when(e).then(function(){var a=h[0].querySelectorAll("[autofocus]");a.length?a[0].focus():h[0].focus()});var f=a.getTop();f&&a.modalRendered(f.key)})}}}]).directive("modalAnimationClass",["$log","$modalSuppressWarning",function(a,b){return{compile:function(c,d){b||a.warn("modal-animation-class is now deprecated. Use uib-modal-animation-class instead."),d.modalAnimation&&c.addClass(d.modalAnimationClass)}}}]).directive("modalTransclude",["$log","$modalSuppressWarning",function(a,b){return{link:function(c,d,e,f,g){b||a.warn("modal-transclude is now deprecated. Use uib-modal-transclude instead."),g(c.$parent,function(a){d.empty(),d.append(a)})}}}]).service("$modalStack",["$animate","$timeout","$document","$compile","$rootScope","$q","$injector","$$multiMap","$$stackedMap","$uibModalStack","$log","$modalSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k,l){
9 l||k.warn("$modalStack is now deprecated. Use $uibModalStack instead."),angular.extend(this,j)}]).provider("$modal",["$uibModalProvider",function(a){angular.extend(this,a),this.$get=["$injector","$log","$modalSuppressWarning",function(b,c,d){return d||c.warn("$modal is now deprecated. Use $uibModal instead."),b.invoke(a.$get)}]}]),angular.module("ui.bootstrap.pagination",[]).controller("UibPaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(g,h){e=g,this.config=h,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=h.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b,c){c&&c.preventDefault();var d=!a.ngDisabled||!c;d&&a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).constant("uibPaginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("uibPagination",["$parse","uibPaginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["uibPagination","?ngModel"],controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pagination.html"},replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("uibPagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("uibPager",["uibPagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["uibPager","?ngModel"],controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pager.html"},replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.pagination").value("$paginationSuppressWarning",!1).controller("PaginationController",["$scope","$attrs","$parse","$log","$paginationSuppressWarning",function(a,b,c,d,e){e||d.warn("PaginationController is now deprecated. Use UibPaginationController instead.");var f=this,g={$setViewValue:angular.noop},h=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(d,e){g=d,this.config=e,g.$render=function(){f.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){f.itemsPerPage=parseInt(b,10),a.totalPages=f.calculateTotalPages()}):this.itemsPerPage=e.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=f.calculateTotalPages()}),a.$watch("totalPages",function(b){h(a.$parent,b),a.page>b?a.selectPage(b):g.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(g.$viewValue,10)||1},a.selectPage=function(b,c){c&&c.preventDefault();var d=!a.ngDisabled||!c;d&&a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),g.$setViewValue(b),g.$render())},a.getText=function(b){return a[b+"Text"]||f.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).directive("pagination",["$parse","uibPaginationConfig","$log","$paginationSuppressWarning",function(a,b,c,d){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["pagination","?ngModel"],controller:"PaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pagination.html"},replace:!0,link:function(e,f,g,h){function i(a,b,c){return{number:a,text:b,active:c}}function j(a,b){var c=[],d=1,e=b,f=angular.isDefined(m)&&b>m;f&&(n?(d=Math.max(a-Math.floor(m/2),1),e=d+m-1,e>b&&(e=b,d=e-m+1)):(d=(Math.ceil(a/m)-1)*m+1,e=Math.min(d+m-1,b)));for(var g=d;e>=g;g++){var h=i(g,g,g===a);c.push(h)}if(f&&!n){if(d>1){var j=i(d-1,"...",!1);c.unshift(j)}if(b>e){var k=i(e+1,"...",!1);c.push(k)}}return c}d||c.warn("pagination is now deprecated. Use uib-pagination instead.");var k=h[0],l=h[1];if(l){var m=angular.isDefined(g.maxSize)?e.$parent.$eval(g.maxSize):b.maxSize,n=angular.isDefined(g.rotate)?e.$parent.$eval(g.rotate):b.rotate;e.boundaryLinks=angular.isDefined(g.boundaryLinks)?e.$parent.$eval(g.boundaryLinks):b.boundaryLinks,e.directionLinks=angular.isDefined(g.directionLinks)?e.$parent.$eval(g.directionLinks):b.directionLinks,k.init(l,b),g.maxSize&&e.$parent.$watch(a(g.maxSize),function(a){m=parseInt(a,10),k.render()});var o=k.render;k.render=function(){o(),e.page>0&&e.page<=e.totalPages&&(e.pages=j(e.page,e.totalPages))}}}}}]).directive("pager",["uibPagerConfig","$log","$paginationSuppressWarning",function(a,b,c){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["pager","?ngModel"],controller:"PaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pager.html"},replace:!0,link:function(d,e,f,g){c||b.warn("pager is now deprecated. Use uib-pager instead.");var h=g[0],i=g[1];i&&(d.align=angular.isDefined(f.align)?d.$parent.$eval(f.align):a.align,h.init(i,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.stackedMap"]).provider("$uibTooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0,popupCloseDelay:500,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",focus:"blur",none:""},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$uibPosition","$interpolate","$rootScope","$parse","$$stackedMap",function(e,f,g,h,i,j,k,l,m){var n=m.createNew();return h.on("keypress",function(a){if(27===a.which){var b=n.top();b&&(b.value.close(),n.removeTop(),b=null)}}),function(e,k,m,o){function p(a){var b=(a||o.trigger||m).split(" "),d=b.map(function(a){return c[a]||a});return{show:b,hide:d}}o=angular.extend({},b,d,o);var q=a(e),r=j.startSymbol(),s=j.endSymbol(),t="<div "+q+'-popup title="'+r+"title"+s+'" '+(o.useContentExp?'content-exp="contentExp()" ':'content="'+r+"content"+s+'" ')+'placement="'+r+"placement"+s+'" popup-class="'+r+"popupClass"+s+'" animation="animation" is-open="isOpen"origin-scope="origScope" style="visibility: hidden; display: block;"></div>';return{compile:function(a,b){var c=f(t);return function(a,b,d,f){function j(){H.isOpen?q():m()}function m(){(!G||a.$eval(d[k+"Enable"]))&&(v(),H.popupDelay?C||(C=g(r,H.popupDelay,!1)):r())}function q(){s()}function r(){return C&&(g.cancel(C),C=null),B&&(g.cancel(B),B=null),H.content?(t(),void H.$evalAsync(function(){H.isOpen=!0,J&&angular.isFunction(J.assign)&&J.assign(H.origScope,H.isOpen),M()})):angular.noop}function s(){H&&(H.$evalAsync(function(){H.isOpen=!1,J&&angular.isFunction(J.assign)&&J.assign(H.origScope,H.isOpen)}),g.cancel(C),C=null,g.cancel(D),D=null,H.animation?B||(B=g(u,H.popupCloseDelay)):u())}function t(){z||(A=H.$new(),z=c(A,function(a){E?h.find("body").append(a):b.after(a)}),w())}function u(){x(),B=null,z&&(z.remove(),z=null),A&&(A.$destroy(),A=null)}function v(){H.title=d[k+"Title"],K?H.content=K(a):H.content=d[e],H.popupClass=d[k+"Class"],H.placement=angular.isDefined(d[k+"Placement"])?d[k+"Placement"]:o.placement;var b=parseInt(d[k+"PopupDelay"],10),c=parseInt(d[k+"PopupCloseDelay"],10);H.popupDelay=isNaN(b)?o.popupDelay:b,H.popupCloseDelay=isNaN(c)?o.popupCloseDelay:c}function w(){L.length=0,K?(L.push(a.$watch(K,function(a){H.content=a,!a&&H.isOpen&&s()})),L.push(A.$watch(function(){I||(I=!0,A.$$postDigest(function(){I=!1,H&&H.isOpen&&M()}))}))):L.push(d.$observe(e,function(a){H.content=a,!a&&H.isOpen?s():M()})),L.push(d.$observe(k+"Title",function(a){H.title=a,H.isOpen&&M()})),L.push(d.$observe(k+"Placement",function(a){H.placement=a?a:o.placement,H.isOpen&&M()}))}function x(){L.length&&(angular.forEach(L,function(a){a()}),L.length=0)}function y(){var a=d[k+"Trigger"];N(),F=p(a),"none"!==F.show&&F.show.forEach(function(a,c){a===F.hide[c]?b[0].addEventListener(a,j):a&&(b[0].addEventListener(a,m),F.hide[c].split(" ").forEach(function(a){b[0].addEventListener(a,q)})),b.on("keypress",function(a){27===a.which&&q()})})}var z,A,B,C,D,E=angular.isDefined(o.appendToBody)?o.appendToBody:!1,F=p(void 0),G=angular.isDefined(d[k+"Enable"]),H=a.$new(!0),I=!1,J=angular.isDefined(d[k+"IsOpen"])?l(d[k+"IsOpen"]):!1,K=o.useContentExp?l(d[e]):!1,L=[],M=function(){z&&z.html()&&(D||(D=g(function(){z.css({top:0,left:0});var a=i.positionElements(b,z,H.placement,E);a.top+="px",a.left+="px",a.visibility="visible",z.css(a),D=null},0,!1)))};H.origScope=a,H.isOpen=!1,n.add(H,{close:s}),H.contentExp=function(){return H.content},d.$observe("disabled",function(a){C&&a&&(g.cancel(C),C=null),a&&H.isOpen&&s()}),J&&a.$watch(J,function(a){!a===H.isOpen&&j()});var N=function(){F.show.forEach(function(a){b.unbind(a,m)}),F.hide.forEach(function(a){a.split(" ").forEach(function(a){b[0].removeEventListener(a,q)})})};y();var O=a.$eval(d[k+"Animation"]);H.animation=angular.isDefined(O)?!!O:o.animation;var P=a.$eval(d[k+"AppendToBody"]);E=angular.isDefined(P)?P:E,E&&a.$on("$locationChangeSuccess",function(){H.isOpen&&s()}),a.$on("$destroy",function(){g.cancel(B),g.cancel(C),g.cancel(D),N(),u(),H=null})}}}}}]}).directive("uibTooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.uibTooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("uibTooltipClasses",function(){return{restrict:"A",link:function(a,b,c){a.placement&&b.addClass(a.placement),a.popupClass&&b.addClass(a.popupClass),a.animation()&&b.addClass(c.tooltipAnimationClass)}}}).directive("uibTooltipPopup",function(){return{replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltip",["$uibTooltip",function(a){return a("uibTooltip","tooltip","mouseenter")}]).directive("uibTooltipTemplatePopup",function(){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltipTemplate",["$uibTooltip",function(a){return a("uibTooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("uibTooltipHtmlPopup",function(){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltipHtml",["$uibTooltip",function(a){return a("uibTooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.tooltip").value("$tooltipSuppressWarning",!1).provider("$tooltip",["$uibTooltipProvider",function(a){angular.extend(this,a),this.$get=["$log","$tooltipSuppressWarning","$injector",function(b,c,d){return c||b.warn("$tooltip is now deprecated. Use $uibTooltip instead."),d.invoke(a.$get)}]}]).directive("tooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest","$log","$tooltipSuppressWarning",function(a,b,c,d,e,f){return{link:function(g,h,i){f||e.warn("tooltip-template-transclude is now deprecated. Use uib-tooltip-template-transclude instead.");var j,k,l,m=g.$eval(i.tooltipTemplateTranscludeScope),n=0,o=function(){k&&(k.remove(),k=null),j&&(j.$destroy(),j=null),l&&(a.leave(l).then(function(){k=null}),k=l,l=null)};g.$watch(b.parseAsResourceUrl(i.tooltipTemplateTransclude),function(b){var e=++n;b?(d(b,!0).then(function(d){if(e===n){var f=m.$new(),g=d,i=c(g)(f,function(b){o(),a.enter(b,h)});j=f,l=i,j.$emit("$includeContentLoaded",b)}},function(){e===n&&(o(),g.$emit("$includeContentError",b))}),g.$emit("$includeContentRequested",b)):o()}),g.$on("$destroy",o)}}}]).directive("tooltipClasses",["$log","$tooltipSuppressWarning",function(a,b){return{restrict:"A",link:function(c,d,e){b||a.warn("tooltip-classes is now deprecated. Use uib-tooltip-classes instead."),c.placement&&d.addClass(c.placement),c.popupClass&&d.addClass(c.popupClass),c.animation()&&d.addClass(e.tooltipAnimationClass)}}}]).directive("tooltipPopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html",link:function(c,d){b||a.warn("tooltip-popup is now deprecated. Use uib-tooltip-popup instead."),d.addClass("tooltip")}}}]).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipTemplatePopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html",link:function(c,d){b||a.warn("tooltip-template-popup is now deprecated. Use uib-tooltip-template-popup instead."),d.addClass("tooltip")}}}]).directive("tooltipTemplate",["$tooltip",function(a){return a("tooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlPopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html",link:function(c,d){b||a.warn("tooltip-html-popup is now deprecated. Use uib-tooltip-html-popup instead."),d.addClass("tooltip")}}}]).directive("tooltipHtml",["$tooltip",function(a){return a("tooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("uibPopoverTemplatePopup",function(){return{replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopoverTemplate",["$uibTooltip",function(a){return a("uibPopoverTemplate","popover","click",{useContentExp:!0})}]).directive("uibPopoverHtmlPopup",function(){return{replace:!0,scope:{contentExp:"&",title:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover-html.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopoverHtml",["$uibTooltip",function(a){return a("uibPopoverHtml","popover","click",{useContentExp:!0})}]).directive("uibPopoverPopup",function(){return{replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopover",["$uibTooltip",function(a){return a("uibPopover","popover","click")}]),angular.module("ui.bootstrap.popover").value("$popoverSuppressWarning",!1).directive("popoverTemplatePopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html",link:function(c,d){b||a.warn("popover-template-popup is now deprecated. Use uib-popover-template-popup instead."),d.addClass("popover")}}}]).directive("popoverTemplate",["$tooltip",function(a){return a("popoverTemplate","popover","click",{useContentExp:!0})}]).directive("popoverHtmlPopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",title:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover-html.html",link:function(c,d){b||a.warn("popover-html-popup is now deprecated. Use uib-popover-html-popup instead."),d.addClass("popover")}}}]).directive("popoverHtml",["$tooltip",function(a){return a("popoverHtml","popover","click",{useContentExp:!0})}]).directive("popoverPopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html",link:function(c,d){b||a.warn("popover-popup is now deprecated. Use uib-popover-popup instead."),d.addClass("popover")}}}]).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("uibProgressConfig",{animate:!0,max:100}).controller("UibProgressController",["$scope","$attrs","uibProgressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c,f){e||c.css({transition:"none"}),this.bars.push(b),b.max=a.max,b.title=f&&angular.isDefined(f.title)?f.title:"progressbar",b.$watch("value",function(a){b.recalculatePercentage()}),b.recalculatePercentage=function(){b.percent=+(100*b.value/b.max).toFixed(2);var a=d.bars.reduce(function(a,b){return a+b.percent},0);a>100&&(b.percent-=a-100)},b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)},a.$watch("max",function(b){d.bars.forEach(function(b){b.max=a.max,b.recalculatePercentage()})})}]).directive("uibProgress",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",require:"uibProgress",scope:{max:"=?"},templateUrl:"template/progressbar/progress.html"}}).directive("uibBar",function(){return{replace:!0,transclude:!0,require:"^uibProgress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b,c)}}}).directive("uibProgressbar",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]),{title:c.title})}}}),angular.module("ui.bootstrap.progressbar").value("$progressSuppressWarning",!1).controller("ProgressController",["$scope","$attrs","uibProgressConfig","$log","$progressSuppressWarning",function(a,b,c,d,e){e||d.warn("ProgressController is now deprecated. Use UibProgressController instead.");var f=this,g=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c,d){g||c.css({transition:"none"}),this.bars.push(b),b.max=a.max,b.title=d&&angular.isDefined(d.title)?d.title:"progressbar",b.$watch("value",function(a){b.recalculatePercentage()}),b.recalculatePercentage=function(){b.percent=+(100*b.value/b.max).toFixed(2);var a=f.bars.reduce(function(a,b){return a+b.percent},0);a>100&&(b.percent-=a-100)},b.$on("$destroy",function(){c=null,f.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)},a.$watch("max",function(b){f.bars.forEach(function(b){b.max=a.max,b.recalculatePercentage()})})}]).directive("progress",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{max:"=?",title:"@?"},templateUrl:"template/progressbar/progress.html",link:function(){b||a.warn("progress is now deprecated. Use uib-progress instead.")}}}]).directive("bar",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(c,d,e,f){b||a.warn("bar is now deprecated. Use uib-bar instead."),f.addBar(c,d)}}}]).directive("progressbar",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(c,d,e,f){b||a.warn("progressbar is now deprecated. Use uib-progressbar instead."),f.addBar(c,angular.element(d.children()[0]),{title:e.title})}}}]),angular.module("ui.bootstrap.rating",[]).constant("uibRatingConfig",{max:5,stateOn:null,stateOff:null,titles:["one","two","three","four","five"]}).controller("UibRatingController",["$scope","$attrs","uibRatingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.titles)?a.$parent.$eval(b.titles):c.titles;this.titles=angular.isArray(f)&&f.length>0?f:c.titles;var g=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(g)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff,title:this.getTitle(b)},a[b]);return a},this.getTitle=function(a){return a>=this.titles.length?a+1:this.titles[a]},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(d.$viewValue===b?0:b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("uibRating",function(){return{require:["uibRating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"UibRatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.rating").value("$ratingSuppressWarning",!1).controller("RatingController",["$scope","$attrs","$controller","$log","$ratingSuppressWarning",function(a,b,c,d,e){e||d.warn("RatingController is now deprecated. Use UibRatingController instead."),angular.extend(this,c("UibRatingController",{$scope:a,$attrs:b}))}]).directive("rating",["$log","$ratingSuppressWarning",function(a,b){return{require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(c,d,e,f){b||a.warn("rating is now deprecated. Use uib-rating instead.");var g=f[0],h=f[1];g.init(h)}}}]),angular.module("ui.bootstrap.tabs",[]).controller("UibTabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect(),a.selectCalled=!1)}),a.active=!0,a.selectCalled||(a.onSelect(),a.selectCalled=!0)},b.addTab=function(a){c.push(a),1===c.length&&a.active!==!1?a.active=!0:a.active?b.select(a):a.active=!1},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("uibTabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"UibTabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("uibTab",["$parse",function(a){return{require:"^uibTabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},link:function(b,c,d,e,f){b.$watch("active",function(a){a&&e.select(b)}),b.disabled=!1,d.disable&&b.$parent.$watch(a(d.disable),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},e.addTab(b),b.$on("$destroy",function(){e.removeTab(b)}),b.$transcludeFn=f}}}]).directive("uibTabHeadingTransclude",function(){return{restrict:"A",require:["?^uibTab","?^tab"],link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}).directive("uibTabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||a.hasAttribute("x-tab-heading")||a.hasAttribute("uib-tab-heading")||a.hasAttribute("data-uib-tab-heading")||a.hasAttribute("x-uib-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase()||"x-tab-heading"===a.tagName.toLowerCase()||"uib-tab-heading"===a.tagName.toLowerCase()||"data-uib-tab-heading"===a.tagName.toLowerCase()||"x-uib-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:["?^uibTabset","?^tabset"],link:function(b,c,d){var e=b.$eval(d.uibTabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.tabs").value("$tabsSuppressWarning",!1).controller("TabsetController",["$scope","$controller","$log","$tabsSuppressWarning",function(a,b,c,d){d||c.warn("TabsetController is now deprecated. Use UibTabsetController instead."),angular.extend(this,b("UibTabsetController",{$scope:a}))}]).directive("tabset",["$log","$tabsSuppressWarning",function(a,b){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(c,d,e){b||a.warn("tabset is now deprecated. Use uib-tabset instead."),c.vertical=angular.isDefined(e.vertical)?c.$parent.$eval(e.vertical):!1,c.justified=angular.isDefined(e.justified)?c.$parent.$eval(e.justified):!1}}}]).directive("tab",["$parse","$log","$tabsSuppressWarning",function(a,b,c){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},link:function(d,e,f,g,h){c||b.warn("tab is now deprecated. Use uib-tab instead."),d.$watch("active",function(a){a&&g.select(d)}),d.disabled=!1,f.disable&&d.$parent.$watch(a(f.disable),function(a){d.disabled=!!a}),d.select=function(){d.disabled||(d.active=!0)},g.addTab(d),d.$on("$destroy",function(){g.removeTab(d)}),d.$transcludeFn=h}}}]).directive("tabHeadingTransclude",["$log","$tabsSuppressWarning",function(a,b){return{restrict:"A",require:"^tab",link:function(c,d){b||a.warn("tab-heading-transclude is now deprecated. Use uib-tab-heading-transclude instead."),c.$watch("headingElement",function(a){a&&(d.html(""),d.append(a))})}}}]).directive("tabContentTransclude",["$log","$tabsSuppressWarning",function(a,b){function c(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||a.hasAttribute("x-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase()||"x-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(d,e,f){b||a.warn("tab-content-transclude is now deprecated. Use uib-tab-content-transclude instead.");var g=d.$eval(f.tabContentTransclude);g.$transcludeFn(g.$parent,function(a){angular.forEach(a,function(a){c(a)?g.headingElement=a:e.append(a)})})}}}]),angular.module("ui.bootstrap.timepicker",[]).constant("uibTimepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0,showSpinners:!0}).controller("UibTimepickerController",["$scope","$element","$attrs","$parse","$log","$locale","uibTimepickerConfig",function(a,b,c,d,e,f,g){function h(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===r[1]&&(b+=12)),b):void 0}function i(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function j(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a.toString()}function k(a){l(),q.$setViewValue(new Date(p)),m(a)}function l(){q.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function m(b){var c=p.getHours(),d=p.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:j(c),"m"!==b&&(a.minutes=j(d)),a.meridian=p.getHours()<12?r[0]:r[1]}function n(a,b){var c=new Date(a.getTime()+6e4*b),d=new Date(a);return d.setHours(c.getHours(),c.getMinutes()),d}function o(a){p=n(p,a),k()}var p=new Date,q={$setViewValue:angular.noop},r=angular.isDefined(c.meridians)?a.$parent.$eval(c.meridians):g.meridians||f.DATETIME_FORMATS.AMPMS;a.tabindex=angular.isDefined(c.tabindex)?c.tabindex:0,b.removeAttr("tabindex"),this.init=function(b,d){q=b,q.$render=this.render,q.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),f=d.eq(1),h=angular.isDefined(c.mousewheel)?a.$parent.$eval(c.mousewheel):g.mousewheel;h&&this.setupMousewheelEvents(e,f);var i=angular.isDefined(c.arrowkeys)?a.$parent.$eval(c.arrowkeys):g.arrowkeys;i&&this.setupArrowkeyEvents(e,f),a.readonlyInput=angular.isDefined(c.readonlyInput)?a.$parent.$eval(c.readonlyInput):g.readonlyInput,this.setupInputEvents(e,f)};var s=g.hourStep;c.hourStep&&a.$parent.$watch(d(c.hourStep),function(a){s=parseInt(a,10)});var t=g.minuteStep;c.minuteStep&&a.$parent.$watch(d(c.minuteStep),function(a){t=parseInt(a,10)});var u;a.$parent.$watch(d(c.min),function(a){var b=new Date(a);u=isNaN(b)?void 0:b});var v;a.$parent.$watch(d(c.max),function(a){var b=new Date(a);v=isNaN(b)?void 0:b}),a.noIncrementHours=function(){var a=n(p,60*s);return a>v||p>a&&u>a},a.noDecrementHours=function(){var a=n(p,60*-s);return u>a||a>p&&a>v},a.noIncrementMinutes=function(){var a=n(p,t);return a>v||p>a&&u>a},a.noDecrementMinutes=function(){var a=n(p,-t);return u>a||a>p&&a>v},a.noToggleMeridian=function(){return p.getHours()<13?n(p,720)>v:n(p,-720)<u},a.showMeridian=g.showMeridian,c.showMeridian&&a.$parent.$watch(d(c.showMeridian),function(b){if(a.showMeridian=!!b,q.$error.time){
10 var c=h(),d=i();angular.isDefined(c)&&angular.isDefined(d)&&(p.setHours(c),k())}else m()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c){b.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply())}),c.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply())})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){q.$setViewValue(null),q.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=h(),b=i();angular.isDefined(a)&&angular.isDefined(b)?(p.setHours(a),u>p||p>v?d(!0):k("h")):d(!0)},b.bind("blur",function(b){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=j(a.hours)})}),a.updateMinutes=function(){var a=i(),b=h();angular.isDefined(a)&&angular.isDefined(b)?(p.setMinutes(a),u>p||p>v?d(void 0,!0):k("m")):d(void 0,!0)},c.bind("blur",function(b){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=j(a.minutes)})})},this.render=function(){var b=q.$viewValue;isNaN(b)?(q.$setValidity("time",!1),e.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(b&&(p=b),u>p||p>v?(q.$setValidity("time",!1),a.invalidHours=!0,a.invalidMinutes=!0):l(),m())},a.showSpinners=angular.isDefined(c.showSpinners)?a.$parent.$eval(c.showSpinners):g.showSpinners,a.incrementHours=function(){a.noIncrementHours()||o(60*s)},a.decrementHours=function(){a.noDecrementHours()||o(60*-s)},a.incrementMinutes=function(){a.noIncrementMinutes()||o(t)},a.decrementMinutes=function(){a.noDecrementMinutes()||o(-t)},a.toggleMeridian=function(){a.noToggleMeridian()||o(720*(p.getHours()<12?1:-1))}}]).directive("uibTimepicker",function(){return{restrict:"EA",require:["uibTimepicker","?^ngModel"],controller:"UibTimepickerController",controllerAs:"timepicker",replace:!0,scope:{},templateUrl:function(a,b){return b.templateUrl||"template/timepicker/timepicker.html"},link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.timepicker").value("$timepickerSuppressWarning",!1).controller("TimepickerController",["$scope","$element","$attrs","$controller","$log","$timepickerSuppressWarning",function(a,b,c,d,e,f){f||e.warn("TimepickerController is now deprecated. Use UibTimepickerController instead."),angular.extend(this,d("UibTimepickerController",{$scope:a,$element:b,$attrs:c}))}]).directive("timepicker",["$log","$timepickerSuppressWarning",function(a,b){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",controllerAs:"timepicker",replace:!0,scope:{},templateUrl:function(a,b){return b.templateUrl||"template/timepicker/timepicker.html"},link:function(c,d,e,f){b||a.warn("timepicker is now deprecated. Use uib-timepicker instead.");var g=f[0],h=f[1];h&&g.init(h,d.find("input"))}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position"]).factory("uibTypeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("uibTypeahead",["$compile","$parse","$q","$timeout","$document","$window","$rootScope","$uibPosition","uibTypeaheadParser",function(a,b,c,d,e,f,g,h,i){var j=[9,13,27,38,40],k=200;return{require:["ngModel","^?ngModelOptions"],link:function(l,m,n,o){function p(){L.moveInProgress||(L.moveInProgress=!0,L.$digest()),T&&d.cancel(T),T=d(function(){L.matches.length&&q(),L.moveInProgress=!1},k)}function q(){L.position=D?h.offset(m):h.position(m),L.position.top+=m.prop("offsetHeight")}var r=o[0],s=o[1],t=l.$eval(n.typeaheadMinLength);t||0===t||(t=1);var u,v,w=l.$eval(n.typeaheadWaitMs)||0,x=l.$eval(n.typeaheadEditable)!==!1,y=b(n.typeaheadLoading).assign||angular.noop,z=b(n.typeaheadOnSelect),A=angular.isDefined(n.typeaheadSelectOnBlur)?l.$eval(n.typeaheadSelectOnBlur):!1,B=b(n.typeaheadNoResults).assign||angular.noop,C=n.typeaheadInputFormatter?b(n.typeaheadInputFormatter):void 0,D=n.typeaheadAppendToBody?l.$eval(n.typeaheadAppendToBody):!1,E=n.typeaheadAppendToElementId||!1,F=l.$eval(n.typeaheadFocusFirst)!==!1,G=n.typeaheadSelectOnExact?l.$eval(n.typeaheadSelectOnExact):!1,H=b(n.ngModel),I=b(n.ngModel+"($$$p)"),J=function(a,b){return angular.isFunction(H(l))&&s&&s.$options&&s.$options.getterSetter?I(a,{$$$p:b}):H.assign(a,b)},K=i.parse(n.uibTypeahead),L=l.$new(),M=l.$on("$destroy",function(){L.$destroy()});L.$on("$destroy",M);var N="typeahead-"+L.$id+"-"+Math.floor(1e4*Math.random());m.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":N});var O=angular.element("<div uib-typeahead-popup></div>");O.attr({id:N,matches:"matches",active:"activeIdx",select:"select(activeIdx)","move-in-progress":"moveInProgress",query:"query",position:"position"}),angular.isDefined(n.typeaheadTemplateUrl)&&O.attr("template-url",n.typeaheadTemplateUrl),angular.isDefined(n.typeaheadPopupTemplateUrl)&&O.attr("popup-template-url",n.typeaheadPopupTemplateUrl);var P=function(){L.matches=[],L.activeIdx=-1,m.attr("aria-expanded",!1)},Q=function(a){return N+"-option-"+a};L.$watch("activeIdx",function(a){0>a?m.removeAttr("aria-activedescendant"):m.attr("aria-activedescendant",Q(a))});var R=function(a,b){return L.matches.length>b&&a?a.toUpperCase()===L.matches[b].label.toUpperCase():!1},S=function(a){var b={$viewValue:a};y(l,!0),B(l,!1),c.when(K.source(l,b)).then(function(c){var d=a===r.$viewValue;if(d&&u)if(c&&c.length>0){L.activeIdx=F?0:-1,B(l,!1),L.matches.length=0;for(var e=0;e<c.length;e++)b[K.itemName]=c[e],L.matches.push({id:Q(e),label:K.viewMapper(L,b),model:c[e]});L.query=a,q(),m.attr("aria-expanded",!0),G&&1===L.matches.length&&R(a,0)&&L.select(0)}else P(),B(l,!0);d&&y(l,!1)},function(){P(),y(l,!1),B(l,!0)})};D&&(angular.element(f).bind("resize",p),e.find("body").bind("scroll",p));var T;L.moveInProgress=!1,P(),L.query=void 0;var U,V=function(a){U=d(function(){S(a)},w)},W=function(){U&&d.cancel(U)};r.$parsers.unshift(function(a){return u=!0,0===t||a&&a.length>=t?w>0?(W(),V(a)):S(a):(y(l,!1),W(),P()),x?a:a?void r.$setValidity("editable",!1):(r.$setValidity("editable",!0),null)}),r.$formatters.push(function(a){var b,c,d={};return x||r.$setValidity("editable",!0),C?(d.$model=a,C(l,d)):(d[K.itemName]=a,b=K.viewMapper(l,d),d[K.itemName]=void 0,c=K.viewMapper(l,d),b!==c?b:a)}),L.select=function(a){var b,c,e={};v=!0,e[K.itemName]=c=L.matches[a].model,b=K.modelMapper(l,e),J(l,b),r.$setValidity("editable",!0),r.$setValidity("parse",!0),z(l,{$item:c,$model:b,$label:K.viewMapper(l,e)}),P(),L.$eval(n.typeaheadFocusOnSelect)!==!1&&d(function(){m[0].focus()},0,!1)},m.bind("keydown",function(a){if(0!==L.matches.length&&-1!==j.indexOf(a.which)){if(-1===L.activeIdx&&(9===a.which||13===a.which))return P(),void L.$digest();a.preventDefault(),40===a.which?(L.activeIdx=(L.activeIdx+1)%L.matches.length,L.$digest()):38===a.which?(L.activeIdx=(L.activeIdx>0?L.activeIdx:L.matches.length)-1,L.$digest()):13===a.which||9===a.which?L.$apply(function(){L.select(L.activeIdx)}):27===a.which&&(a.stopPropagation(),P(),L.$digest())}}),m.bind("blur",function(){A&&L.matches.length&&-1!==L.activeIdx&&!v&&(v=!0,L.$apply(function(){L.select(L.activeIdx)})),u=!1,v=!1});var X=function(a){m[0]!==a.target&&3!==a.which&&0!==L.matches.length&&(P(),g.$$phase||L.$digest())};e.bind("click",X),l.$on("$destroy",function(){e.unbind("click",X),(D||E)&&Y.remove(),O.remove()});var Y=a(O)(L);D?e.find("body").append(Y):E!==!1?angular.element(e[0].getElementById(E)).append(Y):m.after(Y)}}}]).directive("uibTypeaheadPopup",function(){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"template/typeahead/typeahead-popup.html"},link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("uibTypeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"template/typeahead/typeahead-match.html";a(g).then(function(a){b(a.trim())(d,function(a){e.replaceWith(a)})})}}}]).filter("uibTypeaheadHighlight",["$sce","$injector","$log",function(a,b,c){function d(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function e(a){return/<.*>/g.test(a)}var f;return f=b.has("$sanitize"),function(b,g){return!f&&e(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=g?(""+b).replace(new RegExp(d(g),"gi"),"<strong>$&</strong>"):b,f||(b=a.trustAsHtml(b)),b}}]),angular.module("ui.bootstrap.typeahead").value("$typeaheadSuppressWarning",!1).service("typeaheadParser",["$parse","uibTypeaheadParser","$log","$typeaheadSuppressWarning",function(a,b,c,d){return d||c.warn("typeaheadParser is now deprecated. Use uibTypeaheadParser instead."),b}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$window","$rootScope","$uibPosition","typeaheadParser","$log","$typeaheadSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k){var l=[9,13,27,38,40],m=200;return{require:["ngModel","^?ngModelOptions"],link:function(n,o,p,q){function r(){N.moveInProgress||(N.moveInProgress=!0,N.$digest()),V&&d.cancel(V),V=d(function(){N.matches.length&&s(),N.moveInProgress=!1},m)}function s(){N.position=F?h.offset(o):h.position(o),N.position.top+=o.prop("offsetHeight")}k||j.warn("typeahead is now deprecated. Use uib-typeahead instead.");var t=q[0],u=q[1],v=n.$eval(p.typeaheadMinLength);v||0===v||(v=1);var w,x,y=n.$eval(p.typeaheadWaitMs)||0,z=n.$eval(p.typeaheadEditable)!==!1,A=b(p.typeaheadLoading).assign||angular.noop,B=b(p.typeaheadOnSelect),C=angular.isDefined(p.typeaheadSelectOnBlur)?n.$eval(p.typeaheadSelectOnBlur):!1,D=b(p.typeaheadNoResults).assign||angular.noop,E=p.typeaheadInputFormatter?b(p.typeaheadInputFormatter):void 0,F=p.typeaheadAppendToBody?n.$eval(p.typeaheadAppendToBody):!1,G=p.typeaheadAppendToElementId||!1,H=n.$eval(p.typeaheadFocusFirst)!==!1,I=p.typeaheadSelectOnExact?n.$eval(p.typeaheadSelectOnExact):!1,J=b(p.ngModel),K=b(p.ngModel+"($$$p)"),L=function(a,b){return angular.isFunction(J(n))&&u&&u.$options&&u.$options.getterSetter?K(a,{$$$p:b}):J.assign(a,b)},M=i.parse(p.typeahead),N=n.$new(),O=n.$on("$destroy",function(){N.$destroy()});N.$on("$destroy",O);var P="typeahead-"+N.$id+"-"+Math.floor(1e4*Math.random());o.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":P});var Q=angular.element("<div typeahead-popup></div>");Q.attr({id:P,matches:"matches",active:"activeIdx",select:"select(activeIdx)","move-in-progress":"moveInProgress",query:"query",position:"position"}),angular.isDefined(p.typeaheadTemplateUrl)&&Q.attr("template-url",p.typeaheadTemplateUrl),angular.isDefined(p.typeaheadPopupTemplateUrl)&&Q.attr("popup-template-url",p.typeaheadPopupTemplateUrl);var R=function(){N.matches=[],N.activeIdx=-1,o.attr("aria-expanded",!1)},S=function(a){return P+"-option-"+a};N.$watch("activeIdx",function(a){0>a?o.removeAttr("aria-activedescendant"):o.attr("aria-activedescendant",S(a))});var T=function(a,b){return N.matches.length>b&&a?a.toUpperCase()===N.matches[b].label.toUpperCase():!1},U=function(a){var b={$viewValue:a};A(n,!0),D(n,!1),c.when(M.source(n,b)).then(function(c){var d=a===t.$viewValue;if(d&&w)if(c&&c.length>0){N.activeIdx=H?0:-1,D(n,!1),N.matches.length=0;for(var e=0;e<c.length;e++)b[M.itemName]=c[e],N.matches.push({id:S(e),label:M.viewMapper(N,b),model:c[e]});N.query=a,s(),o.attr("aria-expanded",!0),I&&1===N.matches.length&&T(a,0)&&N.select(0)}else R(),D(n,!0);d&&A(n,!1)},function(){R(),A(n,!1),D(n,!0)})};F&&(angular.element(f).bind("resize",r),e.find("body").bind("scroll",r));var V;N.moveInProgress=!1,R(),N.query=void 0;var W,X=function(a){W=d(function(){U(a)},y)},Y=function(){W&&d.cancel(W)};t.$parsers.unshift(function(a){return w=!0,0===v||a&&a.length>=v?y>0?(Y(),X(a)):U(a):(A(n,!1),Y(),R()),z?a:a?void t.$setValidity("editable",!1):(t.$setValidity("editable",!0),null)}),t.$formatters.push(function(a){var b,c,d={};return z||t.$setValidity("editable",!0),E?(d.$model=a,E(n,d)):(d[M.itemName]=a,b=M.viewMapper(n,d),d[M.itemName]=void 0,c=M.viewMapper(n,d),b!==c?b:a)}),N.select=function(a){var b,c,e={};x=!0,e[M.itemName]=c=N.matches[a].model,b=M.modelMapper(n,e),L(n,b),t.$setValidity("editable",!0),t.$setValidity("parse",!0),B(n,{$item:c,$model:b,$label:M.viewMapper(n,e)}),R(),N.$eval(p.typeaheadFocusOnSelect)!==!1&&d(function(){o[0].focus()},0,!1)},o.bind("keydown",function(a){if(0!==N.matches.length&&-1!==l.indexOf(a.which)){if(-1===N.activeIdx&&(9===a.which||13===a.which))return R(),void N.$digest();a.preventDefault(),40===a.which?(N.activeIdx=(N.activeIdx+1)%N.matches.length,N.$digest()):38===a.which?(N.activeIdx=(N.activeIdx>0?N.activeIdx:N.matches.length)-1,N.$digest()):13===a.which||9===a.which?N.$apply(function(){N.select(N.activeIdx)}):27===a.which&&(a.stopPropagation(),R(),N.$digest())}}),o.bind("blur",function(){C&&N.matches.length&&-1!==N.activeIdx&&!x&&(x=!0,N.$apply(function(){N.select(N.activeIdx)})),w=!1,x=!1});var Z=function(a){o[0]!==a.target&&3!==a.which&&0!==N.matches.length&&(R(),g.$$phase||N.$digest())};e.bind("click",Z),n.$on("$destroy",function(){e.unbind("click",Z),(F||G)&&$.remove(),Q.remove()});var $=a(Q)(N);F?e.find("body").append($):G!==!1?angular.element(e[0].getElementById(G)).append($):o.after($)}}}]).directive("typeaheadPopup",["$typeaheadSuppressWarning","$log",function(a,b){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"template/typeahead/typeahead-popup.html"},link:function(c,d,e){a||b.warn("typeahead-popup is now deprecated. Use uib-typeahead-popup instead."),c.templateUrl=e.templateUrl,c.isOpen=function(){return c.matches.length>0},c.isActive=function(a){return c.active==a},c.selectActive=function(a){c.active=a},c.selectMatch=function(a){c.select({activeIdx:a})}}}}]).directive("typeaheadMatch",["$templateRequest","$compile","$parse","$typeaheadSuppressWarning","$log",function(a,b,c,d,e){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(f,g,h){d||e.warn("typeahead-match is now deprecated. Use uib-typeahead-match instead.");var i=c(h.templateUrl)(f.$parent)||"template/typeahead/typeahead-match.html";a(i).then(function(a){b(a.trim())(f,function(a){g.replaceWith(a)})})}}}]).filter("typeaheadHighlight",["$sce","$injector","$log","$typeaheadSuppressWarning",function(a,b,c,d){function e(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function f(a){return/<.*>/g.test(a)}var g;return g=b.has("$sanitize"),function(b,h){return d||c.warn("typeaheadHighlight is now deprecated. Use uibTypeaheadHighlight instead."),!g&&f(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=h?(""+b).replace(new RegExp(e(h),"gi"),"<strong>$&</strong>"):b,g||(b=a.trustAsHtml(b)),b}}]),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'<div class="panel {{panelClass || \'panel-default\'}}">\n <div class="panel-heading" ng-keypress="toggleOpen($event)">\n <h4 class="panel-title">\n <a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n </h4>\n </div>\n <div class="panel-collapse collapse" uib-collapse="!isOpen">\n <div class="panel-body" ng-transclude></div>\n </div>\n</div>\n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'<div class="panel-group" ng-transclude></div>')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'<div class="alert" ng-class="[\'alert-\' + (type || \'warning\'), closeable ? \'alert-dismissible\' : null]" role="alert">\n <button ng-show="closeable" type="button" class="close" ng-click="close({$event: $event})">\n <span aria-hidden="true">&times;</span>\n <span class="sr-only">Close</span>\n </button>\n <div ng-transclude></div>\n</div>\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()" ng-swipe-left="next()">\n <div class="carousel-inner" ng-transclude></div>\n <a role="button" href class="left carousel-control" ng-click="prev()" ng-show="slides.length > 1">\n <span aria-hidden="true" class="glyphicon glyphicon-chevron-left"></span>\n <span class="sr-only">previous</span>\n </a>\n <a role="button" href class="right carousel-control" ng-click="next()" ng-show="slides.length > 1">\n <span aria-hidden="true" class="glyphicon glyphicon-chevron-right"></span>\n <span class="sr-only">next</span>\n </a>\n <ol class="carousel-indicators" ng-show="slides.length > 1">\n <li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index" ng-class="{ active: isActive(slide) }" ng-click="select(slide)">\n <span class="sr-only">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if="isActive(slide)">, currently active</span></span>\n </li>\n </ol>\n</div>')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html",'<div ng-class="{\n \'active\': active\n }" class="item text-center" ng-transclude></div>\n')}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'<div ng-switch="datepickerMode" role="application" ng-keydown="keydown($event)">\n <uib-daypicker ng-switch-when="day" tabindex="0"></uib-daypicker>\n <uib-monthpicker ng-switch-when="month" tabindex="0"></uib-monthpicker>\n <uib-yearpicker ng-switch-when="year" tabindex="0"></uib-yearpicker>\n</div>')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th colspan="{{::5 + showWeeks}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n <tr>\n <th ng-if="showWeeks" class="text-center"></th>\n <th ng-repeat="label in ::labels track by $index" class="text-center"><small aria-label="{{::label.full}}">{{::label.abbr}}</small></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-if="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}" ng-class="::dt.customClass">\n <button type="button" style="min-width:100%;" class="btn btn-default btn-sm" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{\'text-muted\': dt.secondary, \'text-info\': dt.current}">{{::dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}" ng-class="::dt.customClass">\n <button type="button" style="min-width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{\'text-info\': dt.current}">{{::dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'<ul class="dropdown-menu" dropdown-nested ng-if="isOpen" style="display: block" ng-style="{top: position.top+\'px\', left: position.left+\'px\'}" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">\n <li ng-transclude></li>\n <li ng-if="showButtonBar" style="padding:10px 9px 2px">\n <span class="btn-group pull-left">\n <button type="button" class="btn btn-sm btn-info" ng-click="select(\'today\')" ng-disabled="isDisabled(\'today\')">{{ getText(\'current\') }}</button>\n <button type="button" class="btn btn-sm btn-danger" ng-click="select(null)">{{ getText(\'clear\') }}</button>\n </span>\n <button type="button" class="btn btn-sm btn-success pull-right" ng-click="close()">{{ getText(\'close\') }}</button>\n </li>\n</ul>\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n <thead>\n <tr>\n <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n <th colspan="3"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat="row in rows track by $index">\n <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}" ng-class="::dt.customClass">\n <button type="button" style="min-width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{\'text-info\': dt.current}">{{::dt.label}}</span></button>\n </td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'<div uib-modal-animation-class="fade"\n modal-in-class="in"\n ng-style="{\'z-index\': 1040 + (index && 1 || 0) + index*10}"\n></div>\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'<div modal-render="{{$isRendered}}" tabindex="-1" role="dialog" class="modal"\n uib-modal-animation-class="fade"\n modal-in-class="in"\n ng-style="{\'z-index\': 1050 + index*10, display: \'block\'}">\n <div class="modal-dialog" ng-class="size ? \'modal-\' + size : \'\'"><div class="modal-content" uib-modal-transclude></div></div>\n</div>\n')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'<ul class="pager">\n <li ng-class="{disabled: noPrevious()||ngDisabled, previous: align}"><a href ng-click="selectPage(page - 1, $event)">{{::getText(\'previous\')}}</a></li>\n <li ng-class="{disabled: noNext()||ngDisabled, next: align}"><a href ng-click="selectPage(page + 1, $event)">{{::getText(\'next\')}}</a></li>\n</ul>\n')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'<ul class="pagination">\n <li ng-if="::boundaryLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-first"><a href ng-click="selectPage(1, $event)">{{::getText(\'first\')}}</a></li>\n <li ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev"><a href ng-click="selectPage(page - 1, $event)">{{::getText(\'previous\')}}</a></li>\n <li ng-repeat="page in pages track by $index" ng-class="{active: page.active,disabled: ngDisabled&&!page.active}" class="pagination-page"><a href ng-click="selectPage(page.number, $event)">{{page.text}}</a></li>\n <li ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next"><a href ng-click="selectPage(page + 1, $event)">{{::getText(\'next\')}}</a></li>\n <li ng-if="::boundaryLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-last"><a href ng-click="selectPage(totalPages, $event)">{{::getText(\'last\')}}</a></li>\n</ul>\n')}]),angular.module("template/tooltip/tooltip-html-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-popup.html",'<div\n tooltip-animation-class="fade"\n uib-tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner" ng-bind-html="contentExp()"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'<div class="tooltip"\n tooltip-animation-class="fade"\n tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner" bind-html-unsafe="content"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'<div\n tooltip-animation-class="fade"\n uib-tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner" ng-bind="content"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-template-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-template-popup.html",'<div\n tooltip-animation-class="fade"\n uib-tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="tooltip-arrow"></div>\n <div class="tooltip-inner"\n uib-tooltip-template-transclude="contentExp()"\n tooltip-template-transclude-scope="originScope()"></div>\n</div>\n')}]),angular.module("template/popover/popover-html.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-html.html",'<div tooltip-animation-class="fade"\n uib-tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="arrow"></div>\n\n <div class="popover-inner">\n <h3 class="popover-title" ng-bind="title" ng-if="title"></h3>\n <div class="popover-content" ng-bind-html="contentExp()"></div>\n </div>\n</div>\n')}]),angular.module("template/popover/popover-template.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-template.html",'<div tooltip-animation-class="fade"\n uib-tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="arrow"></div>\n\n <div class="popover-inner">\n <h3 class="popover-title" ng-bind="title" ng-if="title"></h3>\n <div class="popover-content"\n uib-tooltip-template-transclude="contentExp()"\n tooltip-template-transclude-scope="originScope()"></div>\n </div>\n</div>\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'<div tooltip-animation-class="fade"\n uib-tooltip-classes\n ng-class="{ in: isOpen() }">\n <div class="arrow"></div>\n\n <div class="popover-inner">\n <h3 class="popover-title" ng-bind="title" ng-if="title"></h3>\n <div class="popover-content" ng-bind="content"></div>\n </div>\n</div>\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'<div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" style="min-width: 0;" ng-transclude></div>\n')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'<div class="progress" ng-transclude aria-labelledby="{{::title}}"></div>')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'<div class="progress">\n <div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" style="min-width: 0;" ng-transclude></div>\n</div>\n')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}">\n <span ng-repeat-start="r in range track by $index" class="sr-only">({{ $index < value ? \'*\' : \' \' }})</span>\n <i ng-repeat-end ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || \'glyphicon-star\') || (r.stateOff || \'glyphicon-star-empty\')" ng-attr-title="{{r.title}}" aria-valuetext="{{r.title}}"></i>\n</span>\n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'<li ng-class="{active: active, disabled: disabled}">\n <a href ng-click="select()" uib-tab-heading-transclude>{{heading}}</a>\n</li>\n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){
11 a.put("template/tabs/tabset.html",'<div>\n <ul class="nav nav-{{type || \'tabs\'}}" ng-class="{\'nav-stacked\': vertical, \'nav-justified\': justified}" ng-transclude></ul>\n <div class="tab-content">\n <div class="tab-pane" \n ng-repeat="tab in tabs" \n ng-class="{active: tab.active}"\n uib-tab-content-transclude="tab">\n </div>\n </div>\n</div>\n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'<table>\n <tbody>\n <tr class="text-center" ng-show="::showSpinners">\n <td><a ng-click="incrementHours()" ng-class="{disabled: noIncrementHours()}" class="btn btn-link" ng-disabled="noIncrementHours()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td>&nbsp;</td>\n <td><a ng-click="incrementMinutes()" ng-class="{disabled: noIncrementMinutes()}" class="btn btn-link" ng-disabled="noIncrementMinutes()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n <td ng-show="showMeridian"></td>\n </tr>\n <tr>\n <td class="form-group" ng-class="{\'has-error\': invalidHours}">\n <input style="width:50px;" type="text" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}">\n </td>\n <td>:</td>\n <td class="form-group" ng-class="{\'has-error\': invalidMinutes}">\n <input style="width:50px;" type="text" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}">\n </td>\n <td ng-show="showMeridian"><button type="button" ng-class="{disabled: noToggleMeridian()}" class="btn btn-default text-center" ng-click="toggleMeridian()" ng-disabled="noToggleMeridian()" tabindex="{{::tabindex}}">{{meridian}}</button></td>\n </tr>\n <tr class="text-center" ng-show="::showSpinners">\n <td><a ng-click="decrementHours()" ng-class="{disabled: noDecrementHours()}" class="btn btn-link" ng-disabled="noDecrementHours()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td>&nbsp;</td>\n <td><a ng-click="decrementMinutes()" ng-class="{disabled: noDecrementMinutes()}" class="btn btn-link" ng-disabled="noDecrementMinutes()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n <td ng-show="showMeridian"></td>\n </tr>\n </tbody>\n</table>\n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'<a href tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query"></a>\n')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'<ul class="dropdown-menu" ng-show="isOpen() && !moveInProgress" ng-style="{top: position().top+\'px\', left: position().left+\'px\'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">\n <li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{::match.id}}">\n <div uib-typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>\n </li>\n</ul>\n')}]),!angular.$$csp()&&angular.element(document).find("head").prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>');
+0
-1974
faraday/server/www/script/ui-grid.css less more
0 /*!
1 * ui-grid - v3.0.7 - 2015-10-06
2 * Copyright (c) 2015 ; License: MIT
3 */
4 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,
5 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
6 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,
7 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
8 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,
9 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
10 content: " ";
11 display: table;
12 }
13 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
14 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
15 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
16 clear: both;
17 }
18 .ui-grid {
19 box-sizing: content-box;
20 -webkit-border-radius: 0px;
21 -moz-border-radius: 0px;
22 border-radius: 0px;
23 -webkit-transform: translateZ(0);
24 -moz-transform: translateZ(0);
25 -o-transform: translateZ(0);
26 -ms-transform: translateZ(0);
27 transform: translateZ(0);
28 }
29 .ui-grid-vertical-bar {
30 position: absolute;
31 right: 0;
32 width: 0;
33 }
34 .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,
35 .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
36 width: 1px;
37 }
38 .ui-grid-scrollbar-placeholder {
39 background-color: transparent;
40 }
41 .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {
42 background-color: #d4d4d4;
43 }
44 .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
45 background-color: #d4d4d4;
46 }
47 .ui-grid-header-cell:last-child .ui-grid-vertical-bar {
48 right: -1px;
49 width: 1px;
50 background-color: #d4d4d4;
51 }
52 .ui-grid-clearfix:before,
53 .ui-grid-clearfix:after {
54 content: "";
55 display: table;
56 }
57 .ui-grid-clearfix:after {
58 clear: both;
59 }
60 .ui-grid-invisible {
61 visibility: hidden;
62 }
63 .ui-grid-contents-wrapper {
64 position: relative;
65 height: 100%;
66 width: 100%;
67 }
68 .ui-grid-sr-only {
69 position: absolute;
70 width: 1px;
71 height: 1px;
72 margin: -1px;
73 padding: 0;
74 overflow: hidden;
75 clip: rect(0, 0, 0, 0);
76 border: 0;
77 }
78 .ui-grid-top-panel-background {
79 background: #f3f3f3;
80 background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
81 background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
82 background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
83 background: -o-linear-gradient(#ffffff, #eeeeee);
84 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
85 }
86 .ui-grid-header {
87 border-bottom: 1px solid #d4d4d4;
88 background-image: linear-gradient(to bottom,#E8EFF0 0,#DDDDDD 100%);
89 background-image: -webkit-linear-gradient(top,#E8EFF0 0,#DDDDDD 100%);
90 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#E8EFF0', endColorstr='#DDDDDD', GradientType=0);
91 filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
92 background-repeat: repeat-x;
93 border: none;
94 font-size: 14px;
95 padding: 10px 5px;
96 letter-spacing: -.05em;
97 font-weight: normal;
98 text-transform: uppercase;
99 }
100 .ui-grid-top-panel {
101 position: relative;
102 overflow: hidden;
103 font-weight: bold;
104 border-top-right-radius: -1px;
105 border-bottom-right-radius: 0;
106 border-bottom-left-radius: 0;
107 border-top-left-radius: -1px;
108 -moz-background-clip: padding-box;
109 -webkit-background-clip: padding-box;
110 background-clip: padding-box;
111 }
112 .ui-grid-header-viewport {
113 overflow: hidden;
114 }
115 .ui-grid-header-canvas:before,
116 .ui-grid-header-canvas:after {
117 content: "";
118 display: table;
119 line-height: 0;
120 }
121 .ui-grid-header-canvas:after {
122 clear: both;
123 }
124 .ui-grid-header-cell-wrapper {
125 position: relative;
126 display: table;
127 box-sizing: border-box;
128 height: 100%;
129 }
130 .ui-grid-header-cell-row {
131 display: table-row;
132 position: relative;
133 }
134 .ui-grid-header-cell {
135 position: relative;
136 box-sizing: border-box;
137 background-color: inherit;
138 border-color: #d4d4d4;
139 display: table-cell;
140 -webkit-user-select: none;
141 -moz-user-select: none;
142 -ms-user-select: none;
143 user-select: none;
144 width: 0;
145 }
146 .ui-grid-header-cell {
147 color: #3a3a3a;
148 text-shadow: 0 1px 0 #fff;
149 font-weight: normal;
150 }
151 .ui-grid-header-cell:last-child {
152 border-right: 0;
153 }
154 .ui-grid-header-cell .sortable {
155 cursor: pointer;
156 }
157 .ui-grid-header-cell .ui-grid-sort-priority-number {
158 margin-left: -8px;
159 }
160 .ui-grid-header .ui-grid-vertical-bar {
161 top: 0;
162 bottom: 0;
163 }
164 .ui-grid-column-menu-button {
165 position: absolute;
166 right: 1px;
167 top: 0;
168 }
169 .ui-grid-column-menu-button .ui-grid-icon-angle-down {
170 vertical-align: sub;
171 }
172 .ui-grid-column-menu-button-last-col {
173 margin-right: 25px;
174 }
175 .ui-grid-column-menu {
176 position: absolute;
177 }
178 /* Slide up/down animations */
179 .ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,
180 .ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {
181 -webkit-transition: all 0.05s linear;
182 -moz-transition: all 0.05s linear;
183 -o-transition: all 0.05s linear;
184 transition: all 0.05s linear;
185 display: block !important;
186 }
187 .ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,
188 .ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {
189 -webkit-transform: translateY(-100%);
190 -moz-transform: translateY(-100%);
191 -o-transform: translateY(-100%);
192 -ms-transform: translateY(-100%);
193 transform: translateY(-100%);
194 }
195 .ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,
196 .ui-grid-column-menu .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {
197 -webkit-transform: translateY(0);
198 -moz-transform: translateY(0);
199 -o-transform: translateY(0);
200 -ms-transform: translateY(0);
201 transform: translateY(0);
202 }
203 /* Slide up/down animations */
204 .ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,
205 .ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {
206 -webkit-transition: all 0.05s linear;
207 -moz-transition: all 0.05s linear;
208 -o-transition: all 0.05s linear;
209 transition: all 0.05s linear;
210 display: block !important;
211 }
212 .ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add.ng-hide-add-active,
213 .ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove {
214 -webkit-transform: translateY(-100%);
215 -moz-transform: translateY(-100%);
216 -o-transform: translateY(-100%);
217 -ms-transform: translateY(-100%);
218 transform: translateY(-100%);
219 }
220 .ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-add,
221 .ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid.ng-hide-remove.ng-hide-remove-active {
222 -webkit-transform: translateY(0);
223 -moz-transform: translateY(0);
224 -o-transform: translateY(0);
225 -ms-transform: translateY(0);
226 transform: translateY(0);
227 }
228 .ui-grid-filter-container {
229 padding: 4px 10px;
230 position: relative;
231 }
232 .ui-grid-filter-container .ui-grid-filter-button {
233 position: absolute;
234 top: 0;
235 bottom: 0;
236 right: 0;
237 }
238 .ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"] {
239 position: absolute;
240 top: 50%;
241 line-height: 32px;
242 margin-top: -16px;
243 right: 10px;
244 opacity: 0.66;
245 }
246 .ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"]:hover {
247 opacity: 1;
248 }
249 .ui-grid-filter-container .ui-grid-filter-button-select {
250 position: absolute;
251 top: 0;
252 bottom: 0;
253 right: 0;
254 }
255 .ui-grid-filter-container .ui-grid-filter-button-select [class^="ui-grid-icon"] {
256 position: absolute;
257 top: 50%;
258 line-height: 32px;
259 margin-top: -16px;
260 right: 0px;
261 opacity: 0.66;
262 }
263 .ui-grid-filter-container .ui-grid-filter-button-select [class^="ui-grid-icon"]:hover {
264 opacity: 1;
265 }
266 input[type="text"].ui-grid-filter-input {
267 padding: 0;
268 margin: 0;
269 border: 0;
270 width: 100%;
271 border: 1px solid #d4d4d4;
272 -webkit-border-top-right-radius: 0px;
273 -webkit-border-bottom-right-radius: 0;
274 -webkit-border-bottom-left-radius: 0;
275 -webkit-border-top-left-radius: 0;
276 -moz-border-radius-topright: 0px;
277 -moz-border-radius-bottomright: 0;
278 -moz-border-radius-bottomleft: 0;
279 -moz-border-radius-topleft: 0;
280 border-top-right-radius: 0px;
281 border-bottom-right-radius: 0;
282 border-bottom-left-radius: 0;
283 border-top-left-radius: 0;
284 -moz-background-clip: padding-box;
285 -webkit-background-clip: padding-box;
286 background-clip: padding-box;
287 }
288 input[type="text"].ui-grid-filter-input:hover {
289 border: 1px solid #d4d4d4;
290 }
291 select.ui-grid-filter-select {
292 padding: 0;
293 margin: 0;
294 border: 0;
295 width: 90%;
296 border: 1px solid #d4d4d4;
297 -webkit-border-top-right-radius: 0px;
298 -webkit-border-bottom-right-radius: 0;
299 -webkit-border-bottom-left-radius: 0;
300 -webkit-border-top-left-radius: 0;
301 -moz-border-radius-topright: 0px;
302 -moz-border-radius-bottomright: 0;
303 -moz-border-radius-bottomleft: 0;
304 -moz-border-radius-topleft: 0;
305 border-top-right-radius: 0px;
306 border-bottom-right-radius: 0;
307 border-bottom-left-radius: 0;
308 border-top-left-radius: 0;
309 -moz-background-clip: padding-box;
310 -webkit-background-clip: padding-box;
311 background-clip: padding-box;
312 }
313 select.ui-grid-filter-select:hover {
314 border: 1px solid #d4d4d4;
315 }
316 .ui-grid-filter-cancel-button-hidden select.ui-grid-filter-select {
317 width: 100%;
318 }
319 .ui-grid-render-container {
320 position: inherit;
321 -webkit-border-top-right-radius: 0;
322 -webkit-border-bottom-right-radius: 0px;
323 -webkit-border-bottom-left-radius: 0px;
324 -webkit-border-top-left-radius: 0;
325 -moz-border-radius-topright: 0;
326 -moz-border-radius-bottomright: 0px;
327 -moz-border-radius-bottomleft: 0px;
328 -moz-border-radius-topleft: 0;
329 border-top-right-radius: 0;
330 border-bottom-right-radius: 0px;
331 border-bottom-left-radius: 0px;
332 border-top-left-radius: 0;
333 -moz-background-clip: padding-box;
334 -webkit-background-clip: padding-box;
335 background-clip: padding-box;
336 }
337 .ui-grid-render-container:focus {
338 outline: none;
339 }
340 .ui-grid-viewport {
341 min-height: 20px;
342 position: relative;
343 overflow-y: scroll;
344 -webkit-overflow-scrolling: touch;
345 }
346 .ui-grid-viewport:focus {
347 outline: none !important;
348 }
349 .ui-grid-canvas {
350 position: relative;
351 padding-top: 1px;
352 }
353 .ui-grid-row:nth-child(odd) .ui-grid-cell {
354 background-color: #fdfdfd;
355 }
356 .ui-grid-row:nth-child(even) .ui-grid-cell {
357 background-color: #f1f1f1;
358 }
359 .ui-grid-row:last-child .ui-grid-cell {
360 border-bottom-color: #d4d4d4;
361 border-bottom-style: solid;
362 }
363 .ui-grid-no-row-overlay {
364 position: absolute;
365 top: 0;
366 bottom: 0;
367 left: 0;
368 right: 0;
369 margin: 10%;
370 background: #f3f3f3;
371 background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
372 background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
373 background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
374 background: -o-linear-gradient(#ffffff, #eeeeee);
375 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
376 -webkit-border-top-right-radius: 0px;
377 -webkit-border-bottom-right-radius: 0;
378 -webkit-border-bottom-left-radius: 0;
379 -webkit-border-top-left-radius: 0;
380 -moz-border-radius-topright: 0px;
381 -moz-border-radius-bottomright: 0;
382 -moz-border-radius-bottomleft: 0;
383 -moz-border-radius-topleft: 0;
384 border-top-right-radius: 0px;
385 border-bottom-right-radius: 0;
386 border-bottom-left-radius: 0;
387 border-top-left-radius: 0;
388 -moz-background-clip: padding-box;
389 -webkit-background-clip: padding-box;
390 background-clip: padding-box;
391 border: 1px solid #d4d4d4;
392 font-size: 2em;
393 text-align: center;
394 }
395 .ui-grid-no-row-overlay > * {
396 position: absolute;
397 display: table;
398 margin: auto 0;
399 width: 100%;
400 top: 0;
401 bottom: 0;
402 left: 0;
403 right: 0;
404 opacity: 0.66;
405 }
406 .ui-grid-cell {
407 overflow: hidden;
408 float: left;
409 background-color: inherit;
410 -webkit-box-sizing: border-box;
411 -moz-box-sizing: border-box;
412 box-sizing: border-box;
413 border-top: 1px solid #ddd;
414 }
415 .ui-grid-cell:last-child {
416 border-right: 0;
417 }
418 .ui-grid-cell-contents {
419 padding: 5px;
420 -moz-box-sizing: border-box;
421 -webkit-box-sizing: border-box;
422 box-sizing: border-box;
423 white-space: nowrap;
424 -ms-text-overflow: ellipsis;
425 -o-text-overflow: ellipsis;
426 text-overflow: ellipsis;
427 overflow: hidden;
428 height: 100%;
429 font-size: 12px;
430 }
431 .ui-grid-cell-contents-hidden {
432 visibility: hidden;
433 width: 0;
434 height: 0;
435 display: none;
436 }
437 .ui-grid-footer-panel-background {
438 background: #f3f3f3;
439 background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
440 background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
441 background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
442 background: -o-linear-gradient(#ffffff, #eeeeee);
443 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
444 }
445 .ui-grid-footer-panel {
446 position: relative;
447 border-bottom: 1px solid #d4d4d4;
448 border-top: 1px solid #d4d4d4;
449 overflow: hidden;
450 font-weight: bold;
451 background: #f3f3f3;
452 background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(1, #ffffff));
453 background: -ms-linear-gradient(bottom, #eeeeee, #ffffff);
454 background: -moz-linear-gradient(center bottom, #eeeeee 0%, #ffffff 100%);
455 background: -o-linear-gradient(#ffffff, #eeeeee);
456 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
457 -webkit-border-top-right-radius: -1px;
458 -webkit-border-bottom-right-radius: 0;
459 -webkit-border-bottom-left-radius: 0;
460 -webkit-border-top-left-radius: -1px;
461 -moz-border-radius-topright: -1px;
462 -moz-border-radius-bottomright: 0;
463 -moz-border-radius-bottomleft: 0;
464 -moz-border-radius-topleft: -1px;
465 border-top-right-radius: -1px;
466 border-bottom-right-radius: 0;
467 border-bottom-left-radius: 0;
468 border-top-left-radius: -1px;
469 -moz-background-clip: padding-box;
470 -webkit-background-clip: padding-box;
471 background-clip: padding-box;
472 }
473 .ui-grid-grid-footer {
474 float: left;
475 width: 100%;
476 }
477 .ui-grid-footer-viewport {
478 overflow: hidden;
479 }
480 .ui-grid-footer-canvas {
481 position: relative;
482 }
483 .ui-grid-footer-canvas:before,
484 .ui-grid-footer-canvas:after {
485 content: "";
486 display: table;
487 line-height: 0;
488 }
489 .ui-grid-footer-canvas:after {
490 clear: both;
491 }
492 .ui-grid-footer-cell-wrapper {
493 position: relative;
494 display: table;
495 box-sizing: border-box;
496 height: 100%;
497 }
498 .ui-grid-footer-cell-row {
499 display: table-row;
500 }
501 .ui-grid-footer-cell {
502 overflow: hidden;
503 background-color: inherit;
504 border-right: 1px solid;
505 border-color: #d4d4d4;
506 box-sizing: border-box;
507 display: table-cell;
508 }
509 .ui-grid-footer-cell:last-child {
510 border-right: 0;
511 }
512 input[type="text"].ui-grid-filter-input {
513 padding: 0;
514 margin: 0;
515 border: 0;
516 width: 100%;
517 border: 1px solid #d4d4d4;
518 -webkit-border-top-right-radius: 0px;
519 -webkit-border-bottom-right-radius: 0;
520 -webkit-border-bottom-left-radius: 0;
521 -webkit-border-top-left-radius: 0;
522 -moz-border-radius-topright: 0px;
523 -moz-border-radius-bottomright: 0;
524 -moz-border-radius-bottomleft: 0;
525 -moz-border-radius-topleft: 0;
526 border-top-right-radius: 0px;
527 border-bottom-right-radius: 0;
528 border-bottom-left-radius: 0;
529 border-top-left-radius: 0;
530 -moz-background-clip: padding-box;
531 -webkit-background-clip: padding-box;
532 background-clip: padding-box;
533 }
534 input[type="text"].ui-grid-filter-input:hover {
535 border: 1px solid #d4d4d4;
536 }
537 .ui-grid-menu-button {
538 z-index: 2;
539 position: absolute;
540 right: 0;
541 top: 0;
542 background: #f3f3f3;
543 border: 1px solid #d4d4d4;
544 cursor: pointer;
545 height: 31px;
546 font-weight: normal;
547 }
548 .ui-grid-menu-button .ui-grid-icon-container {
549 margin-top: 3px;
550 }
551 .ui-grid-menu-button .ui-grid-menu {
552 right: 0;
553 }
554 .ui-grid-menu-button .ui-grid-menu .ui-grid-menu-mid {
555 overflow: scroll;
556 max-height: 300px;
557 border: 1px solid #d4d4d4;
558 }
559 .ui-grid-menu {
560 z-index: 2;
561 position: absolute;
562 padding: 0 10px 20px 10px;
563 cursor: pointer;
564 box-sizing: border-box;
565 }
566 .ui-grid-menu .ui-grid-menu-inner {
567 background: #f3f3f3;
568 border: 1px solid #d4d4d4;
569 position: relative;
570 white-space: nowrap;
571 -webkit-border-radius: 0px;
572 -moz-border-radius: 0px;
573 border-radius: 0px;
574 -webkit-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);
575 -moz-box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);
576 box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2), inset 0 12px 12px -14px rgba(0, 0, 0, 0.2);
577 }
578 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
579 position: absolute;
580 right: 0px;
581 top: 0px;
582 display: inline-block;
583 margin-bottom: 0;
584 font-weight: normal;
585 text-align: center;
586 vertical-align: middle;
587 touch-action: manipulation;
588 cursor: pointer;
589 background-image: none;
590 border: 1px solid transparent;
591 white-space: nowrap;
592 padding: 6px 12px;
593 font-size: 14px;
594 line-height: 1.42857143;
595 border-radius: 4px;
596 -webkit-user-select: none;
597 -moz-user-select: none;
598 -ms-user-select: none;
599 user-select: none;
600 padding: 1px 1px;
601 font-size: 10px;
602 line-height: 1;
603 border-radius: 2px;
604 color: transparent;
605 background-color: transparent;
606 border-color: transparent;
607 }
608 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
609 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,
610 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,
611 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus,
612 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,
613 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus {
614 outline: thin dotted;
615 outline: 5px auto -webkit-focus-ring-color;
616 outline-offset: -2px;
617 }
618 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,
619 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
620 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {
621 color: #333333;
622 text-decoration: none;
623 }
624 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,
625 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active {
626 outline: 0;
627 background-image: none;
628 -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
629 box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
630 }
631 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,
632 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled],
633 fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
634 cursor: not-allowed;
635 opacity: 0.65;
636 filter: alpha(opacity=65);
637 -webkit-box-shadow: none;
638 box-shadow: none;
639 }
640 a.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,
641 fieldset[disabled] a.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
642 pointer-events: none;
643 }
644 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
645 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {
646 color: transparent;
647 background-color: rgba(0, 0, 0, 0);
648 border-color: rgba(0, 0, 0, 0);
649 }
650 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover {
651 color: transparent;
652 background-color: rgba(0, 0, 0, 0);
653 border-color: rgba(0, 0, 0, 0);
654 }
655 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,
656 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,
657 .open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
658 color: transparent;
659 background-color: rgba(0, 0, 0, 0);
660 border-color: rgba(0, 0, 0, 0);
661 }
662 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:hover,
663 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:hover,
664 .open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,
665 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active:focus,
666 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active:focus,
667 .open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
668 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active.focus,
669 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active.focus,
670 .open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus {
671 color: transparent;
672 background-color: rgba(0, 0, 0, 0);
673 border-color: rgba(0, 0, 0, 0);
674 }
675 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,
676 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active,
677 .open > .dropdown-toggle.ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button {
678 background-image: none;
679 }
680 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled,
681 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled],
682 fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button,
683 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:hover,
684 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:hover,
685 fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:hover,
686 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:focus,
687 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:focus,
688 fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:focus,
689 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled.focus,
690 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled].focus,
691 fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.focus,
692 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled:active,
693 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled]:active,
694 fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button:active,
695 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.disabled.active,
696 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button[disabled].active,
697 fieldset[disabled] .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button.active {
698 background-color: transparent;
699 border-color: transparent;
700 }
701 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button .badge {
702 color: transparent;
703 background-color: transparent;
704 }
705 .ui-grid-menu .ui-grid-menu-inner .ui-grid-menu-close-button > i {
706 opacity: 0.75;
707 color: black;
708 }
709 .ui-grid-menu .ui-grid-menu-inner ul {
710 margin: 0;
711 padding: 0;
712 list-style-type: none;
713 }
714 .ui-grid-menu .ui-grid-menu-inner ul li {
715 padding: 0px;
716 }
717 .ui-grid-menu .ui-grid-menu-inner ul li button {
718 min-width: 100%;
719 padding: 8px;
720 text-align: left;
721 background: transparent;
722 border: none;
723 }
724 .ui-grid-menu .ui-grid-menu-inner ul li button:hover,
725 .ui-grid-menu .ui-grid-menu-inner ul li button:focus {
726 -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
727 -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
728 box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
729 }
730 .ui-grid-menu .ui-grid-menu-inner ul li button.ui-grid-menu-item-active {
731 -webkit-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
732 -moz-box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
733 box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
734 background-color: #cecece;
735 }
736 .ui-grid-menu .ui-grid-menu-inner ul li:not(:last-child) > button {
737 border-bottom: 1px solid #d4d4d4;
738 }
739 .ui-grid-sortarrow {
740 right: 5px;
741 position: absolute;
742 width: 20px;
743 top: 0;
744 bottom: 0;
745 background-position: center;
746 }
747 .ui-grid-sortarrow.down {
748 -webkit-transform: rotate(180deg);
749 -moz-transform: rotate(180deg);
750 -o-transform: rotate(180deg);
751 -ms-transform: rotate(180deg);
752 transform: rotate(180deg);
753 }
754 @font-face {
755 font-family: 'ui-grid';
756 src: url('ui-grid.eot');
757 src: url('ui-grid.eot#iefix') format('embedded-opentype'), url('ui-grid.woff') format('woff'), url('ui-grid.ttf') format('truetype'), url('ui-grid.svg?#ui-grid') format('svg');
758 font-weight: normal;
759 font-style: normal;
760 }
761 /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
762 /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
763 /*
764 @media screen and (-webkit-min-device-pixel-ratio:0) {
765 @font-face {
766 font-family: 'ui-grid';
767 src: url('../font/ui-grid.svg?12312827#ui-grid') format('svg');
768 }
769 }
770 */
771 [class^="ui-grid-icon"]:before,
772 [class*=" ui-grid-icon"]:before {
773 font-family: 'ui-grid';
774 font-style: normal;
775 font-weight: normal;
776 speak: none;
777 display: inline-block;
778 text-decoration: inherit;
779 width: 1em;
780 margin-right: .2em;
781 text-align: center;
782 /* opacity: .8; */
783 /* For safety - reset parent styles, that can break glyph codes*/
784 font-variant: normal;
785 text-transform: none;
786 /* fix buttons height, for twitter bootstrap */
787 line-height: 1em;
788 /* Animation center compensation - margins should be symmetric */
789 /* remove if not needed */
790 margin-left: .2em;
791 /* you can be more comfortable with increased icons size */
792 /* font-size: 120%; */
793 /* Uncomment for 3D effect */
794 /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
795 }
796 .ui-grid-icon-blank::before {
797 width: 1em;
798 content: ' ';
799 }
800 /*
801 * RTL Styles
802 */
803 .ui-grid[dir=rtl] .ui-grid-header-cell,
804 .ui-grid[dir=rtl] .ui-grid-footer-cell,
805 .ui-grid[dir=rtl] .ui-grid-cell {
806 float: right !important;
807 }
808 .ui-grid[dir=rtl] .ui-grid-column-menu-button {
809 position: absolute;
810 left: 1px;
811 top: 0;
812 right: inherit;
813 }
814 .ui-grid[dir=rtl] .ui-grid-cell:first-child,
815 .ui-grid[dir=rtl] .ui-grid-header-cell:first-child,
816 .ui-grid[dir=rtl] .ui-grid-footer-cell:first-child {
817 border-right: 0;
818 }
819 .ui-grid[dir=rtl] .ui-grid-cell:last-child,
820 .ui-grid[dir=rtl] .ui-grid-header-cell:last-child {
821 border-right: 1px solid #d4d4d4;
822 border-left: 0;
823 }
824 .ui-grid[dir=rtl] .ui-grid-header-cell:first-child .ui-grid-vertical-bar,
825 .ui-grid[dir=rtl] .ui-grid-footer-cell:first-child .ui-grid-vertical-bar,
826 .ui-grid[dir=rtl] .ui-grid-cell:first-child .ui-grid-vertical-bar {
827 width: 0;
828 }
829 .ui-grid[dir=rtl] .ui-grid-menu-button {
830 z-index: 2;
831 position: absolute;
832 left: 0;
833 right: auto;
834 background: #f3f3f3;
835 border: 1px solid #d4d4d4;
836 cursor: pointer;
837 min-height: 27px;
838 font-weight: normal;
839 }
840 .ui-grid[dir=rtl] .ui-grid-menu-button .ui-grid-menu {
841 left: 0;
842 right: auto;
843 }
844 .ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button {
845 right: initial;
846 left: 0;
847 }
848 .ui-grid[dir=rtl] .ui-grid-filter-container .ui-grid-filter-button [class^="ui-grid-icon"] {
849 right: initial;
850 left: 10px;
851 }
852 /*
853 Animation example, for spinners
854 */
855 .ui-grid-animate-spin {
856 -moz-animation: ui-grid-spin 2s infinite linear;
857 -o-animation: ui-grid-spin 2s infinite linear;
858 -webkit-animation: ui-grid-spin 2s infinite linear;
859 animation: ui-grid-spin 2s infinite linear;
860 display: inline-block;
861 }
862 @-moz-keyframes ui-grid-spin {
863 0% {
864 -moz-transform: rotate(0deg);
865 -o-transform: rotate(0deg);
866 -webkit-transform: rotate(0deg);
867 transform: rotate(0deg);
868 }
869 100% {
870 -moz-transform: rotate(359deg);
871 -o-transform: rotate(359deg);
872 -webkit-transform: rotate(359deg);
873 transform: rotate(359deg);
874 }
875 }
876 @-webkit-keyframes ui-grid-spin {
877 0% {
878 -moz-transform: rotate(0deg);
879 -o-transform: rotate(0deg);
880 -webkit-transform: rotate(0deg);
881 transform: rotate(0deg);
882 }
883 100% {
884 -moz-transform: rotate(359deg);
885 -o-transform: rotate(359deg);
886 -webkit-transform: rotate(359deg);
887 transform: rotate(359deg);
888 }
889 }
890 @-o-keyframes ui-grid-spin {
891 0% {
892 -moz-transform: rotate(0deg);
893 -o-transform: rotate(0deg);
894 -webkit-transform: rotate(0deg);
895 transform: rotate(0deg);
896 }
897 100% {
898 -moz-transform: rotate(359deg);
899 -o-transform: rotate(359deg);
900 -webkit-transform: rotate(359deg);
901 transform: rotate(359deg);
902 }
903 }
904 @-ms-keyframes ui-grid-spin {
905 0% {
906 -moz-transform: rotate(0deg);
907 -o-transform: rotate(0deg);
908 -webkit-transform: rotate(0deg);
909 transform: rotate(0deg);
910 }
911 100% {
912 -moz-transform: rotate(359deg);
913 -o-transform: rotate(359deg);
914 -webkit-transform: rotate(359deg);
915 transform: rotate(359deg);
916 }
917 }
918 @keyframes ui-grid-spin {
919 0% {
920 -moz-transform: rotate(0deg);
921 -o-transform: rotate(0deg);
922 -webkit-transform: rotate(0deg);
923 transform: rotate(0deg);
924 }
925 100% {
926 -moz-transform: rotate(359deg);
927 -o-transform: rotate(359deg);
928 -webkit-transform: rotate(359deg);
929 transform: rotate(359deg);
930 }
931 }
932 /*---------------------------------------------------
933 LESS Elements 0.9
934 ---------------------------------------------------
935 A set of useful LESS mixins
936 More info at: http://lesselements.com
937 ---------------------------------------------------*/
938 /* This file contains variable declarations (do not remove this line) */
939 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
940 /**
941 * @section Grid styles
942 */
943 /**
944 * @section Header styles
945 */
946 /** @description Colors for header gradient */
947 /**
948 * @section Grid body styles
949 */
950 /** @description Colors used for row alternation */
951 /**
952 * @section Sort arrow colors
953 */
954 /**
955 * @section Scrollbar styles
956 */
957 /**
958 * @section font library path
959 */
960 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
961
962 /* This file contains variable declarations (do not remove this line) */
963 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
964 /**
965 * @section Grid styles
966 */
967 /**
968 * @section Header styles
969 */
970 /** @description Colors for header gradient */
971 /**
972 * @section Grid body styles
973 */
974 /** @description Colors used for row alternation */
975 /**
976 * @section Sort arrow colors
977 */
978 /**
979 * @section Scrollbar styles
980 */
981 /**
982 * @section font library path
983 */
984 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
985 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,
986 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
987 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,
988 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
989 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,
990 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
991 content: " ";
992 display: table;
993 }
994 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
995 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
996 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
997 clear: both;
998 }
999 .ui-grid-cell-focus {
1000 outline: 0;
1001 background-color: #b3c4c7;
1002 }
1003 .ui-grid-focuser {
1004 position: absolute;
1005 left: 0px;
1006 top: 0px;
1007 z-index: -1;
1008 width: 100%;
1009 height: 100%;
1010 }
1011 .ui-grid-focuser:focus {
1012 border-color: #66afe9;
1013 outline: 0;
1014 -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
1015 box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
1016 }
1017 .ui-grid-offscreen {
1018 display: block;
1019 position: absolute;
1020 left: -10000px;
1021 top: -10000px;
1022 clip: rect(0px, 0px, 0px, 0px);
1023 }
1024
1025 /* This file contains variable declarations (do not remove this line) */
1026 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1027 /**
1028 * @section Grid styles
1029 */
1030 /**
1031 * @section Header styles
1032 */
1033 /** @description Colors for header gradient */
1034 /**
1035 * @section Grid body styles
1036 */
1037 /** @description Colors used for row alternation */
1038 /**
1039 * @section Sort arrow colors
1040 */
1041 /**
1042 * @section Scrollbar styles
1043 */
1044 /**
1045 * @section font library path
1046 */
1047 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1048 div.ui-grid-cell input {
1049 border-radius: inherit;
1050 padding: 0;
1051 width: 100%;
1052 color: inherit;
1053 height: auto;
1054 font: inherit;
1055 outline: none;
1056 }
1057 div.ui-grid-cell input:focus {
1058 color: inherit;
1059 outline: none;
1060 }
1061 div.ui-grid-cell input[type="checkbox"] {
1062 margin: 9px 0 0 6px;
1063 width: auto;
1064 }
1065 div.ui-grid-cell input.ng-invalid {
1066 border: 1px solid #fc8f8f;
1067 }
1068 div.ui-grid-cell input.ng-valid {
1069 border: 1px solid #d4d4d4;
1070 }
1071
1072 /* This file contains variable declarations (do not remove this line) */
1073 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1074 /**
1075 * @section Grid styles
1076 */
1077 /**
1078 * @section Header styles
1079 */
1080 /** @description Colors for header gradient */
1081 /**
1082 * @section Grid body styles
1083 */
1084 /** @description Colors used for row alternation */
1085 /**
1086 * @section Sort arrow colors
1087 */
1088 /**
1089 * @section Scrollbar styles
1090 */
1091 /**
1092 * @section font library path
1093 */
1094 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1095 .expandableRow .ui-grid-row:nth-child(odd) .ui-grid-cell {
1096 background-color: #fdfdfd;
1097 }
1098 .expandableRow .ui-grid-row:nth-child(even) .ui-grid-cell {
1099 background-color: #f3f3f3;
1100 }
1101 .ui-grid-cell.ui-grid-disable-selection.ui-grid-row-header-cell {
1102 pointer-events: none;
1103 }
1104 .ui-grid-expandable-buttons-cell i {
1105 pointer-events: all;
1106 }
1107 .scrollFiller {
1108 float: left;
1109 border: 1px solid #d4d4d4;
1110 }
1111
1112 /* This file contains variable declarations (do not remove this line) */
1113 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1114 /**
1115 * @section Grid styles
1116 */
1117 /**
1118 * @section Header styles
1119 */
1120 /** @description Colors for header gradient */
1121 /**
1122 * @section Grid body styles
1123 */
1124 /** @description Colors used for row alternation */
1125 /**
1126 * @section Sort arrow colors
1127 */
1128 /**
1129 * @section Scrollbar styles
1130 */
1131 /**
1132 * @section font library path
1133 */
1134 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1135
1136 /* This file contains variable declarations (do not remove this line) */
1137 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1138 /**
1139 * @section Grid styles
1140 */
1141 /**
1142 * @section Header styles
1143 */
1144 /** @description Colors for header gradient */
1145 /**
1146 * @section Grid body styles
1147 */
1148 /** @description Colors used for row alternation */
1149 /**
1150 * @section Sort arrow colors
1151 */
1152 /**
1153 * @section Scrollbar styles
1154 */
1155 /**
1156 * @section font library path
1157 */
1158 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1159 .ui-grid-tree-header-row {
1160 font-weight: bold !important;
1161 }
1162
1163 /* This file contains variable declarations (do not remove this line) */
1164 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1165 /**
1166 * @section Grid styles
1167 */
1168 /**
1169 * @section Header styles
1170 */
1171 /** @description Colors for header gradient */
1172 /**
1173 * @section Grid body styles
1174 */
1175 /** @description Colors used for row alternation */
1176 /**
1177 * @section Sort arrow colors
1178 */
1179 /**
1180 * @section Scrollbar styles
1181 */
1182 /**
1183 * @section font library path
1184 */
1185 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1186
1187 /* This file contains variable declarations (do not remove this line) */
1188 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1189 /**
1190 * @section Grid styles
1191 */
1192 /**
1193 * @section Header styles
1194 */
1195 /** @description Colors for header gradient */
1196 /**
1197 * @section Grid body styles
1198 */
1199 /** @description Colors used for row alternation */
1200 /**
1201 * @section Sort arrow colors
1202 */
1203 /**
1204 * @section Scrollbar styles
1205 */
1206 /**
1207 * @section font library path
1208 */
1209 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1210 .movingColumn {
1211 position: absolute;
1212 top: 0;
1213 border: 1px solid #d4d4d4;
1214 box-shadow: inset 0 0 14px rgba(0, 0, 0, 0.2);
1215 }
1216 .movingColumn .ui-grid-icon-angle-down {
1217 display: none;
1218 }
1219
1220 /* This file contains variable declarations (do not remove this line) */
1221 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1222 /**
1223 * @section Grid styles
1224 */
1225 /**
1226 * @section Header styles
1227 */
1228 /** @description Colors for header gradient */
1229 /**
1230 * @section Grid body styles
1231 */
1232 /** @description Colors used for row alternation */
1233 /**
1234 * @section Sort arrow colors
1235 */
1236 /**
1237 * @section Scrollbar styles
1238 */
1239 /**
1240 * @section font library path
1241 */
1242 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1243 /*---------------------------------------------------
1244 LESS Elements 0.9
1245 ---------------------------------------------------
1246 A set of useful LESS mixins
1247 More info at: http://lesselements.com
1248 ---------------------------------------------------*/
1249 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:before,
1250 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
1251 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:before,
1252 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
1253 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:before,
1254 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
1255 content: " ";
1256 display: table;
1257 }
1258 #ui-grid-twbs #ui-grid-twbs .form-horizontal .form-group:after,
1259 #ui-grid-twbs #ui-grid-twbs .btn-toolbar:after,
1260 #ui-grid-twbs #ui-grid-twbs .btn-group-vertical > .btn-group:after {
1261 clear: both;
1262 }
1263 .ui-grid-pager-panel {
1264 position: absolute;
1265 left: 0;
1266 bottom: 0;
1267 width: 100%;
1268 padding-top: 3px;
1269 padding-bottom: 3px;
1270 }
1271 .ui-grid-pager-container {
1272 float: left;
1273 }
1274 .ui-grid-pager-control {
1275 margin-right: 10px;
1276 margin-left: 10px;
1277 min-width: 135px;
1278 float: left;
1279 }
1280 .ui-grid-pager-control button {
1281 height: 25px;
1282 min-width: 26px;
1283 display: inline-block;
1284 margin-bottom: 0;
1285 font-weight: normal;
1286 text-align: center;
1287 vertical-align: middle;
1288 touch-action: manipulation;
1289 cursor: pointer;
1290 background-image: none;
1291 border: 1px solid transparent;
1292 white-space: nowrap;
1293 padding: 6px 12px;
1294 font-size: 14px;
1295 line-height: 1.42857143;
1296 border-radius: 4px;
1297 -webkit-user-select: none;
1298 -moz-user-select: none;
1299 -ms-user-select: none;
1300 user-select: none;
1301 color: #eeeeee;
1302 background-color: #f3f3f3;
1303 border-color: #cccccc;
1304 }
1305 .ui-grid-pager-control button:focus,
1306 .ui-grid-pager-control button:active:focus,
1307 .ui-grid-pager-control button.active:focus,
1308 .ui-grid-pager-control button.focus,
1309 .ui-grid-pager-control button:active.focus,
1310 .ui-grid-pager-control button.active.focus {
1311 outline: thin dotted;
1312 outline: 5px auto -webkit-focus-ring-color;
1313 outline-offset: -2px;
1314 }
1315 .ui-grid-pager-control button:hover,
1316 .ui-grid-pager-control button:focus,
1317 .ui-grid-pager-control button.focus {
1318 color: #333333;
1319 text-decoration: none;
1320 }
1321 .ui-grid-pager-control button:active,
1322 .ui-grid-pager-control button.active {
1323 outline: 0;
1324 background-image: none;
1325 -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
1326 box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
1327 }
1328 .ui-grid-pager-control button.disabled,
1329 .ui-grid-pager-control button[disabled],
1330 fieldset[disabled] .ui-grid-pager-control button {
1331 cursor: not-allowed;
1332 opacity: 0.65;
1333 filter: alpha(opacity=65);
1334 -webkit-box-shadow: none;
1335 box-shadow: none;
1336 }
1337 a.ui-grid-pager-control button.disabled,
1338 fieldset[disabled] a.ui-grid-pager-control button {
1339 pointer-events: none;
1340 }
1341 .ui-grid-pager-control button:focus,
1342 .ui-grid-pager-control button.focus {
1343 color: #eeeeee;
1344 background-color: #dadada;
1345 border-color: #8c8c8c;
1346 }
1347 .ui-grid-pager-control button:hover {
1348 color: #eeeeee;
1349 background-color: #dadada;
1350 border-color: #adadad;
1351 }
1352 .ui-grid-pager-control button:active,
1353 .ui-grid-pager-control button.active,
1354 .open > .dropdown-toggle.ui-grid-pager-control button {
1355 color: #eeeeee;
1356 background-color: #dadada;
1357 border-color: #adadad;
1358 }
1359 .ui-grid-pager-control button:active:hover,
1360 .ui-grid-pager-control button.active:hover,
1361 .open > .dropdown-toggle.ui-grid-pager-control button:hover,
1362 .ui-grid-pager-control button:active:focus,
1363 .ui-grid-pager-control button.active:focus,
1364 .open > .dropdown-toggle.ui-grid-pager-control button:focus,
1365 .ui-grid-pager-control button:active.focus,
1366 .ui-grid-pager-control button.active.focus,
1367 .open > .dropdown-toggle.ui-grid-pager-control button.focus {
1368 color: #eeeeee;
1369 background-color: #c8c8c8;
1370 border-color: #8c8c8c;
1371 }
1372 .ui-grid-pager-control button:active,
1373 .ui-grid-pager-control button.active,
1374 .open > .dropdown-toggle.ui-grid-pager-control button {
1375 background-image: none;
1376 }
1377 .ui-grid-pager-control button.disabled,
1378 .ui-grid-pager-control button[disabled],
1379 fieldset[disabled] .ui-grid-pager-control button,
1380 .ui-grid-pager-control button.disabled:hover,
1381 .ui-grid-pager-control button[disabled]:hover,
1382 fieldset[disabled] .ui-grid-pager-control button:hover,
1383 .ui-grid-pager-control button.disabled:focus,
1384 .ui-grid-pager-control button[disabled]:focus,
1385 fieldset[disabled] .ui-grid-pager-control button:focus,
1386 .ui-grid-pager-control button.disabled.focus,
1387 .ui-grid-pager-control button[disabled].focus,
1388 fieldset[disabled] .ui-grid-pager-control button.focus,
1389 .ui-grid-pager-control button.disabled:active,
1390 .ui-grid-pager-control button[disabled]:active,
1391 fieldset[disabled] .ui-grid-pager-control button:active,
1392 .ui-grid-pager-control button.disabled.active,
1393 .ui-grid-pager-control button[disabled].active,
1394 fieldset[disabled] .ui-grid-pager-control button.active {
1395 background-color: #f3f3f3;
1396 border-color: #cccccc;
1397 }
1398 .ui-grid-pager-control button .badge {
1399 color: #f3f3f3;
1400 background-color: #eeeeee;
1401 }
1402 .ui-grid-pager-control input {
1403 display: block;
1404 width: 100%;
1405 height: 34px;
1406 padding: 6px 12px;
1407 font-size: 14px;
1408 line-height: 1.42857143;
1409 color: #555555;
1410 background-color: #ffffff;
1411 background-image: none;
1412 border: 1px solid #cccccc;
1413 border-radius: 4px;
1414 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1415 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1416 -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
1417 -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
1418 transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
1419 height: 30px;
1420 padding: 5px 10px;
1421 font-size: 12px;
1422 line-height: 1.5;
1423 border-radius: 3px;
1424 display: inline;
1425 height: 26px;
1426 width: 50px;
1427 vertical-align: top;
1428 }
1429 .ui-grid-pager-control input:focus {
1430 border-color: #66afe9;
1431 outline: 0;
1432 -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
1433 box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
1434 }
1435 .ui-grid-pager-control input::-moz-placeholder {
1436 color: #999999;
1437 opacity: 1;
1438 }
1439 .ui-grid-pager-control input:-ms-input-placeholder {
1440 color: #999999;
1441 }
1442 .ui-grid-pager-control input::-webkit-input-placeholder {
1443 color: #999999;
1444 }
1445 .ui-grid-pager-control input[disabled],
1446 .ui-grid-pager-control input[readonly],
1447 fieldset[disabled] .ui-grid-pager-control input {
1448 background-color: #eeeeee;
1449 opacity: 1;
1450 }
1451 .ui-grid-pager-control input[disabled],
1452 fieldset[disabled] .ui-grid-pager-control input {
1453 cursor: not-allowed;
1454 }
1455 textarea.ui-grid-pager-control input {
1456 height: auto;
1457 }
1458 select.ui-grid-pager-control input {
1459 height: 30px;
1460 line-height: 30px;
1461 }
1462 textarea.ui-grid-pager-control input,
1463 select[multiple].ui-grid-pager-control input {
1464 height: auto;
1465 }
1466 .ui-grid-pager-control .ui-grid-pager-max-pages-number {
1467 vertical-align: bottom;
1468 }
1469 .ui-grid-pager-control .ui-grid-pager-max-pages-number > * {
1470 vertical-align: middle;
1471 }
1472 .ui-grid-pager-control .first-bar {
1473 width: 10px;
1474 border-left: 2px solid #4d4d4d;
1475 margin-top: -6px;
1476 height: 12px;
1477 margin-left: -3px;
1478 }
1479 .ui-grid-pager-control .first-triangle {
1480 width: 0;
1481 height: 0;
1482 border-style: solid;
1483 border-width: 5px 8.7px 5px 0;
1484 border-color: transparent #4d4d4d transparent transparent;
1485 margin-left: 2px;
1486 }
1487 .ui-grid-pager-control .next-triangle {
1488 margin-left: 1px;
1489 }
1490 .ui-grid-pager-control .prev-triangle {
1491 margin-left: 0;
1492 }
1493 .ui-grid-pager-control .last-triangle {
1494 width: 0;
1495 height: 0;
1496 border-style: solid;
1497 border-width: 5px 0 5px 8.7px;
1498 border-color: transparent transparent transparent #4d4d4d;
1499 margin-left: -1px;
1500 }
1501 .ui-grid-pager-control .last-bar {
1502 width: 10px;
1503 border-left: 2px solid #4d4d4d;
1504 margin-top: -6px;
1505 height: 12px;
1506 margin-left: 1px;
1507 }
1508 .ui-grid-pager-row-count-picker {
1509 float: left;
1510 }
1511 .ui-grid-pager-row-count-picker select {
1512 display: block;
1513 width: 100%;
1514 height: 34px;
1515 padding: 6px 12px;
1516 font-size: 14px;
1517 line-height: 1.42857143;
1518 color: #555555;
1519 background-color: #ffffff;
1520 background-image: none;
1521 border: 1px solid #cccccc;
1522 border-radius: 4px;
1523 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1524 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1525 -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
1526 -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
1527 transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
1528 height: 30px;
1529 padding: 5px 10px;
1530 font-size: 12px;
1531 line-height: 1.5;
1532 border-radius: 3px;
1533 height: 26px;
1534 width: 67px;
1535 display: inline;
1536 }
1537 .ui-grid-pager-row-count-picker select:focus {
1538 border-color: #66afe9;
1539 outline: 0;
1540 -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
1541 box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
1542 }
1543 .ui-grid-pager-row-count-picker select::-moz-placeholder {
1544 color: #999999;
1545 opacity: 1;
1546 }
1547 .ui-grid-pager-row-count-picker select:-ms-input-placeholder {
1548 color: #999999;
1549 }
1550 .ui-grid-pager-row-count-picker select::-webkit-input-placeholder {
1551 color: #999999;
1552 }
1553 .ui-grid-pager-row-count-picker select[disabled],
1554 .ui-grid-pager-row-count-picker select[readonly],
1555 fieldset[disabled] .ui-grid-pager-row-count-picker select {
1556 background-color: #eeeeee;
1557 opacity: 1;
1558 }
1559 .ui-grid-pager-row-count-picker select[disabled],
1560 fieldset[disabled] .ui-grid-pager-row-count-picker select {
1561 cursor: not-allowed;
1562 }
1563 textarea.ui-grid-pager-row-count-picker select {
1564 height: auto;
1565 }
1566 select.ui-grid-pager-row-count-picker select {
1567 height: 30px;
1568 line-height: 30px;
1569 }
1570 textarea.ui-grid-pager-row-count-picker select,
1571 select[multiple].ui-grid-pager-row-count-picker select {
1572 height: auto;
1573 }
1574 .ui-grid-pager-row-count-picker .ui-grid-pager-row-count-label {
1575 margin-top: 3px;
1576 }
1577 .ui-grid-pager-count-container {
1578 float: right;
1579 margin-top: 4px;
1580 min-width: 50px;
1581 }
1582 .ui-grid-pager-count-container .ui-grid-pager-count {
1583 margin-right: 10px;
1584 margin-left: 10px;
1585 float: right;
1586 }
1587
1588 /* This file contains variable declarations (do not remove this line) */
1589 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1590 /**
1591 * @section Grid styles
1592 */
1593 /**
1594 * @section Header styles
1595 */
1596 /** @description Colors for header gradient */
1597 /**
1598 * @section Grid body styles
1599 */
1600 /** @description Colors used for row alternation */
1601 /**
1602 * @section Sort arrow colors
1603 */
1604 /**
1605 * @section Scrollbar styles
1606 */
1607 /**
1608 * @section font library path
1609 */
1610 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1611 .ui-grid-pinned-container {
1612 position: absolute;
1613 display: inline;
1614 top: 0;
1615 }
1616 .ui-grid-pinned-container.ui-grid-pinned-container-left {
1617 float: left;
1618 left: 0;
1619 }
1620 .ui-grid-pinned-container.ui-grid-pinned-container-right {
1621 float: right;
1622 right: 0;
1623 }
1624 .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child {
1625 box-sizing: border-box;
1626 /* border-right: 1px solid;*/
1627 border-width: 1px;
1628 /*border-right-color: #aeaeae;*/
1629 }
1630 .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:last-child {
1631 box-sizing: border-box;
1632 }
1633 .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar,
1634 .ui-grid-pinned-container .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
1635 width: 1px;
1636 }
1637 .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:not(:last-child) .ui-grid-vertical-bar {
1638 background-color: #d4d4d4;
1639 }
1640 .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
1641 background-color: #aeaeae;
1642 }
1643 .ui-grid-pinned-container.ui-grid-pinned-container-left .ui-grid-header-cell:last-child .ui-grid-vertical-bar {
1644 right: -1px;
1645 width: 1px;
1646 background-color: #aeaeae;
1647 }
1648 .ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:first-child {
1649 box-sizing: border-box;
1650 border-left: 1px solid;
1651 border-width: 1px;
1652 border-left-color: #aeaeae;
1653 }
1654 .ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:first-child {
1655 box-sizing: border-box;
1656 border-left: 1px solid;
1657 border-width: 1px;
1658 border-left-color: #aeaeae;
1659 }
1660 .ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar,
1661 .ui-grid-pinned-container .ui-grid-cell:not(:first-child) .ui-grid-vertical-bar {
1662 width: 1px;
1663 }
1664 .ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-header-cell:not(:first-child) .ui-grid-vertical-bar {
1665 background-color: #d4d4d4;
1666 }
1667 .ui-grid-pinned-container.ui-grid-pinned-container-right .ui-grid-cell:not(:last-child) .ui-grid-vertical-bar {
1668 background-color: #aeaeae;
1669 }
1670 .ui-grid-pinned-container.ui-grid-pinned-container-first .ui-grid-header-cell:first-child .ui-grid-vertical-bar {
1671 left: -1px;
1672 width: 1px;
1673 background-color: #aeaeae;
1674 }
1675
1676 /* This file contains variable declarations (do not remove this line) */
1677 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1678 /**
1679 * @section Grid styles
1680 */
1681 /**
1682 * @section Header styles
1683 */
1684 /** @description Colors for header gradient */
1685 /**
1686 * @section Grid body styles
1687 */
1688 /** @description Colors used for row alternation */
1689 /**
1690 * @section Sort arrow colors
1691 */
1692 /**
1693 * @section Scrollbar styles
1694 */
1695 /**
1696 * @section font library path
1697 */
1698 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1699 .ui-grid-column-resizer {
1700 top: 0;
1701 bottom: 0;
1702 width: 5px;
1703 position: absolute;
1704 cursor: col-resize;
1705 }
1706 .ui-grid-column-resizer.left {
1707 left: 0;
1708 }
1709 .ui-grid-column-resizer.right {
1710 right: 0;
1711 }
1712 .ui-grid-header-cell:last-child .ui-grid-column-resizer.right {
1713 border-right: 1px solid #d4d4d4;
1714 }
1715 .ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.right {
1716 border-right: 0;
1717 }
1718 .ui-grid[dir=rtl] .ui-grid-header-cell:last-child .ui-grid-column-resizer.left {
1719 border-left: 1px solid #d4d4d4;
1720 }
1721 .ui-grid.column-resizing {
1722 cursor: col-resize;
1723 }
1724 .ui-grid.column-resizing .ui-grid-resize-overlay {
1725 position: absolute;
1726 top: 0;
1727 height: 100%;
1728 width: 1px;
1729 background-color: #aeaeae;
1730 }
1731
1732 /* This file contains variable declarations (do not remove this line) */
1733 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1734 /**
1735 * @section Grid styles
1736 */
1737 /**
1738 * @section Header styles
1739 */
1740 /** @description Colors for header gradient */
1741 /**
1742 * @section Grid body styles
1743 */
1744 /** @description Colors used for row alternation */
1745 /**
1746 * @section Sort arrow colors
1747 */
1748 /**
1749 * @section Scrollbar styles
1750 */
1751 /**
1752 * @section font library path
1753 */
1754 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1755 .ui-grid-row-saving .ui-grid-cell {
1756 color: #848484 !important;
1757 }
1758 .ui-grid-row-dirty .ui-grid-cell {
1759 color: #610b38;
1760 }
1761 .ui-grid-row-error .ui-grid-cell {
1762 color: #ff0000 !important;
1763 }
1764
1765 /* This file contains variable declarations (do not remove this line) */
1766 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1767 /**
1768 * @section Grid styles
1769 */
1770 /**
1771 * @section Header styles
1772 */
1773 /** @description Colors for header gradient */
1774 /**
1775 * @section Grid body styles
1776 */
1777 /** @description Colors used for row alternation */
1778 /**
1779 * @section Sort arrow colors
1780 */
1781 /**
1782 * @section Scrollbar styles
1783 */
1784 /**
1785 * @section font library path
1786 */
1787 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1788 .ui-grid-row.ui-grid-row-selected > [ui-grid-row] > .ui-grid-cell {
1789 background-color: #f2dede;
1790 }
1791 .ui-grid-selection-row-header-buttons {
1792 cursor: pointer;
1793 opacity: 0.1;
1794 }
1795 .ui-grid-selection-row-header-buttons.ui-grid-row-selected {
1796 opacity: 1;
1797 }
1798 .ui-grid-selection-row-header-buttons.ui-grid-all-selected {
1799 opacity: 1;
1800 }
1801
1802 /* This file contains variable declarations (do not remove this line) */
1803 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1804 /**
1805 * @section Grid styles
1806 */
1807 /**
1808 * @section Header styles
1809 */
1810 /** @description Colors for header gradient */
1811 /**
1812 * @section Grid body styles
1813 */
1814 /** @description Colors used for row alternation */
1815 /**
1816 * @section Sort arrow colors
1817 */
1818 /**
1819 * @section Scrollbar styles
1820 */
1821 /**
1822 * @section font library path
1823 */
1824 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1825 .ui-grid-tree-row-header-buttons.ui-grid-tree-header {
1826 cursor: pointer;
1827 opacity: 1;
1828 }
1829
1830 /* This file contains variable declarations (do not remove this line) */
1831 /*-- VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1832 /**
1833 * @section Grid styles
1834 */
1835 /**
1836 * @section Header styles
1837 */
1838 /** @description Colors for header gradient */
1839 /**
1840 * @section Grid body styles
1841 */
1842 /** @description Colors used for row alternation */
1843 /**
1844 * @section Sort arrow colors
1845 */
1846 /**
1847 * @section Scrollbar styles
1848 */
1849 /**
1850 * @section font library path
1851 */
1852 /*-- END VARIABLES (DO NOT REMOVE THESE COMMENTS) --*/
1853 .ui-grid-tree-header-row {
1854 font-weight: bold !important;
1855 }
1856
1857 .ui-grid-icon-plus-squared:before {
1858 content: '\c350';
1859 }
1860 /* '썐' */
1861 .ui-grid-icon-minus-squared:before {
1862 content: '\c351';
1863 }
1864 /* '썑' */
1865 .ui-grid-icon-search:before {
1866 content: '\c352';
1867 }
1868 /* '썒' */
1869 .ui-grid-icon-cancel:before {
1870 content: '\c353';
1871 }
1872 /* '썓' */
1873 .ui-grid-icon-info-circled:before {
1874 content: '\c354';
1875 }
1876 /* '썔' */
1877 .ui-grid-icon-lock:before {
1878 content: '\c355';
1879 }
1880 /* '썕' */
1881 .ui-grid-icon-lock-open:before {
1882 content: '\c356';
1883 }
1884 /* '썖' */
1885 .ui-grid-icon-pencil:before {
1886 content: '\c357';
1887 }
1888 /* '썗' */
1889 .ui-grid-icon-down-dir:before {
1890 content: '\c358';
1891 }
1892 /* '썘' */
1893 .ui-grid-icon-up-dir:before {
1894 content: '\c359';
1895 }
1896 /* '썙' */
1897 .ui-grid-icon-left-dir:before {
1898 content: '\c35a';
1899 }
1900 /* '썚' */
1901 .ui-grid-icon-right-dir:before {
1902 content: '\c35b';
1903 }
1904 /* '썛' */
1905 .ui-grid-icon-left-open:before {
1906 content: '\c35c';
1907 }
1908 /* '썜' */
1909 .ui-grid-icon-right-open:before {
1910 content: '\c35d';
1911 }
1912 /* '썝' */
1913 .ui-grid-icon-angle-down:before {
1914 content: '\c35e';
1915 }
1916 /* '썞' */
1917 .ui-grid-icon-filter:before {
1918 content: '\c35f';
1919 }
1920 /* '썟' */
1921 .ui-grid-icon-sort-alt-up:before {
1922 content: '\c360';
1923 }
1924 /* 'ì ' */
1925 .ui-grid-icon-sort-alt-down:before {
1926 content: '\c361';
1927 }
1928 /* '썡' */
1929 .ui-grid-icon-ok:before {
1930 content: '\c362';
1931 }
1932 /* '썢' */
1933 .ui-grid-icon-menu:before {
1934 content: '\c363';
1935 }
1936 /* '썣' */
1937 .ui-grid-icon-indent-left:before {
1938 content: '\e800';
1939 }
1940 /* 'î €' */
1941 .ui-grid-icon-indent-right:before {
1942 content: '\e801';
1943 }
1944 /* 'î ' */
1945 .ui-grid-icon-spin5:before {
1946 content: '\ea61';
1947 }
1948 /* 'î©¡' */
1949 .crop-text {
1950 overflow: hidden;
1951 -o-text-overflow: ellipsis;
1952 -ms-text-overflow: ellipsis;
1953 text-overflow: ellipsis;
1954 white-space: nowrap;
1955 }
1956 .ui-grid .ui-grid-row:nth-child(odd) .ui-grid-cell .ui-grid-cell-contents .pos-middle,
1957 .ui-grid .ui-grid-row:nth-child(even) .ui-grid-cell .ui-grid-cell-contents .pos-middle {
1958 position: relative;
1959 top: 50%;
1960 -webkit-transform: translateY(-50%);
1961 -ms-transform: translateY(-50%);
1962 -moz-transform: translateY(-50%);
1963 -o-transform: translateY(-50%);
1964 transform: translateY(-50%);
1965 }
1966 .ui-grid .ui-grid-row:nth-child(odd) .ui-grid-cell .ui-grid-cell-contents .crop-text,
1967 .ui-grid .ui-grid-row:nth-child(even) .ui-grid-cell .ui-grid-cell-contents .crop-text {
1968 overflow: hidden;
1969 -o-text-overflow: ellipsis;
1970 -ms-text-overflow: ellipsis;
1971 text-overflow: ellipsis;
1972 white-space: nowrap;
1973 }
+0
-30396
faraday/server/www/script/ui-grid.js less more
0 /*!
1 * ui-grid - v4.6.3 - 2018-08-04
2 * Copyright (c) 2018 ; License: MIT
3 */
4
5 (function() {
6 'use strict';
7
8 angular.module('ui.grid.i18n', []);
9 angular.module('ui.grid', ['ui.grid.i18n']);
10 })();
11
12 (function () {
13 'use strict';
14
15 /**
16 * @ngdoc object
17 * @name ui.grid.service:uiGridConstants
18 * @description Constants for use across many grid features
19 *
20 */
21
22
23 angular.module('ui.grid').constant('uiGridConstants', {
24 LOG_DEBUG_MESSAGES: true,
25 LOG_WARN_MESSAGES: true,
26 LOG_ERROR_MESSAGES: true,
27 CUSTOM_FILTERS: /CUSTOM_FILTERS/g,
28 COL_FIELD: /COL_FIELD/g,
29 MODEL_COL_FIELD: /MODEL_COL_FIELD/g,
30 TOOLTIP: /title=\"TOOLTIP\"/g,
31 DISPLAY_CELL_TEMPLATE: /DISPLAY_CELL_TEMPLATE/g,
32 TEMPLATE_REGEXP: /<.+>/,
33 FUNC_REGEXP: /(\([^)]*\))?$/,
34 DOT_REGEXP: /\./g,
35 APOS_REGEXP: /'/g,
36 BRACKET_REGEXP: /^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/,
37 COL_CLASS_PREFIX: 'ui-grid-col',
38 ENTITY_BINDING: '$$this',
39 events: {
40 GRID_SCROLL: 'uiGridScroll',
41 COLUMN_MENU_SHOWN: 'uiGridColMenuShown',
42 ITEM_DRAGGING: 'uiGridItemDragStart', // For any item being dragged
43 COLUMN_HEADER_CLICK: 'uiGridColumnHeaderClick'
44 },
45 // copied from http://www.lsauer.com/2011/08/javascript-keymap-keycodes-in-json.html
46 keymap: {
47 TAB: 9,
48 STRG: 17,
49 CAPSLOCK: 20,
50 CTRL: 17,
51 CTRLRIGHT: 18,
52 CTRLR: 18,
53 SHIFT: 16,
54 RETURN: 13,
55 ENTER: 13,
56 BACKSPACE: 8,
57 BCKSP: 8,
58 ALT: 18,
59 ALTR: 17,
60 ALTRIGHT: 17,
61 SPACE: 32,
62 WIN: 91,
63 MAC: 91,
64 FN: null,
65 PG_UP: 33,
66 PG_DOWN: 34,
67 UP: 38,
68 DOWN: 40,
69 LEFT: 37,
70 RIGHT: 39,
71 ESC: 27,
72 DEL: 46,
73 F1: 112,
74 F2: 113,
75 F3: 114,
76 F4: 115,
77 F5: 116,
78 F6: 117,
79 F7: 118,
80 F8: 119,
81 F9: 120,
82 F10: 121,
83 F11: 122,
84 F12: 123
85 },
86 /**
87 * @ngdoc object
88 * @name ASC
89 * @propertyOf ui.grid.service:uiGridConstants
90 * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_sort columnDef.sort} and
91 * {@link ui.grid.class:GridOptions.columnDef#properties_sortDirectionCycle columnDef.sortDirectionCycle}
92 * to configure the sorting direction of the column
93 */
94 ASC: 'asc',
95 /**
96 * @ngdoc object
97 * @name DESC
98 * @propertyOf ui.grid.service:uiGridConstants
99 * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_sort columnDef.sort} and
100 * {@link ui.grid.class:GridOptions.columnDef#properties_sortDirectionCycle columnDef.sortDirectionCycle}
101 * to configure the sorting direction of the column
102 */
103 DESC: 'desc',
104
105
106 /**
107 * @ngdoc object
108 * @name filter
109 * @propertyOf ui.grid.service:uiGridConstants
110 * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_filter columnDef.filter}
111 * to configure filtering on the column
112 *
113 * `SELECT` and `INPUT` are used with the `type` property of the filter, the rest are used to specify
114 * one of the built-in conditions.
115 *
116 * Available `condition` options are:
117 * - `uiGridConstants.filter.STARTS_WITH`
118 * - `uiGridConstants.filter.ENDS_WITH`
119 * - `uiGridConstants.filter.CONTAINS`
120 * - `uiGridConstants.filter.GREATER_THAN`
121 * - `uiGridConstants.filter.GREATER_THAN_OR_EQUAL`
122 * - `uiGridConstants.filter.LESS_THAN`
123 * - `uiGridConstants.filter.LESS_THAN_OR_EQUAL`
124 * - `uiGridConstants.filter.NOT_EQUAL`
125 *
126 *
127 * Available `type` options are:
128 * - `uiGridConstants.filter.SELECT` - use a dropdown box for the cell header filter field
129 * - `uiGridConstants.filter.INPUT` - use a text box for the cell header filter field
130 */
131 filter: {
132 STARTS_WITH: 2,
133 ENDS_WITH: 4,
134 EXACT: 8,
135 CONTAINS: 16,
136 GREATER_THAN: 32,
137 GREATER_THAN_OR_EQUAL: 64,
138 LESS_THAN: 128,
139 LESS_THAN_OR_EQUAL: 256,
140 NOT_EQUAL: 512,
141 SELECT: 'select',
142 INPUT: 'input'
143 },
144
145 /**
146 * @ngdoc object
147 * @name aggregationTypes
148 * @propertyOf ui.grid.service:uiGridConstants
149 * @description Used in {@link ui.grid.class:GridOptions.columnDef#properties_aggregationType columnDef.aggregationType}
150 * to specify the type of built-in aggregation the column should use.
151 *
152 * Available options are:
153 * - `uiGridConstants.aggregationTypes.sum` - add the values in this column to produce the aggregated value
154 * - `uiGridConstants.aggregationTypes.count` - count the number of rows to produce the aggregated value
155 * - `uiGridConstants.aggregationTypes.avg` - average the values in this column to produce the aggregated value
156 * - `uiGridConstants.aggregationTypes.min` - use the minimum value in this column as the aggregated value
157 * - `uiGridConstants.aggregationTypes.max` - use the maximum value in this column as the aggregated value
158 */
159 aggregationTypes: {
160 sum: 2,
161 count: 4,
162 avg: 8,
163 min: 16,
164 max: 32
165 },
166
167 /**
168 * @ngdoc array
169 * @name CURRENCY_SYMBOLS
170 * @propertyOf ui.grid.service:uiGridConstants
171 * @description A list of all presently circulating currency symbols that was copied from
172 * https://en.wikipedia.org/wiki/Currency_symbol#List_of_presently-circulating_currency_symbols
173 *
174 * Can be used on {@link ui.grid.class:rowSorter} to create a number string regex that ignores currency symbols.
175 */
176 CURRENCY_SYMBOLS: ['¤', '؋', 'Ar', 'Ƀ', '฿', 'B/.', 'Br', 'Bs.', 'Bs.F.', 'GH₵', '¢', 'c', 'Ch.', '₡', 'C$', 'D', 'ден',
177 'دج', '.د.ب', 'د.ع', 'JD', 'د.ك', 'ل.د', 'дин', 'د.ت', 'د.م.', 'د.إ', 'Db', '$', '₫', 'Esc', '€', 'ƒ', 'Ft', 'FBu',
178 'FCFA', 'CFA', 'Fr', 'FRw', 'G', 'gr', '₲', 'h', '₴', '₭', 'Kč', 'kr', 'kn', 'MK', 'ZK', 'Kz', 'K', 'L', 'Le', 'лв',
179 'E', 'lp', 'M', 'KM', 'MT', '₥', 'Nfk', '₦', 'Nu.', 'UM', 'T$', 'MOP$', '₱', 'Pt.', '£', 'ج.م.', 'LL', 'LS', 'P', 'Q',
180 'q', 'R', 'R$', 'ر.ع.', 'ر.ق', 'ر.س', '៛', 'RM', 'p', 'Rf.', '₹', '₨', 'SRe', 'Rp', '₪', 'Ksh', 'Sh.So.', 'USh', 'S/',
181 'SDR', 'сом', '৳ ', 'WS$', '₮', 'VT', '₩', '¥', 'zł'],
182
183 /**
184 * @ngdoc object
185 * @name scrollDirection
186 * @propertyOf ui.grid.service:uiGridConstants
187 * @description Set on {@link ui.grid.class:Grid#properties_scrollDirection Grid.scrollDirection},
188 * to indicate the direction the grid is currently scrolling in
189 *
190 * Available options are:
191 * - `uiGridConstants.scrollDirection.UP` - set when the grid is scrolling up
192 * - `uiGridConstants.scrollDirection.DOWN` - set when the grid is scrolling down
193 * - `uiGridConstants.scrollDirection.LEFT` - set when the grid is scrolling left
194 * - `uiGridConstants.scrollDirection.RIGHT` - set when the grid is scrolling right
195 * - `uiGridConstants.scrollDirection.NONE` - set when the grid is not scrolling, this is the default
196 */
197 scrollDirection: {
198 UP: 'up',
199 DOWN: 'down',
200 LEFT: 'left',
201 RIGHT: 'right',
202 NONE: 'none'
203
204 },
205
206 /**
207 * @ngdoc object
208 * @name dataChange
209 * @propertyOf ui.grid.service:uiGridConstants
210 * @description Used with {@link ui.grid.api:PublicApi#methods_notifyDataChange PublicApi.notifyDataChange},
211 * {@link ui.grid.class:Grid#methods_callDataChangeCallbacks Grid.callDataChangeCallbacks},
212 * and {@link ui.grid.class:Grid#methods_registerDataChangeCallback Grid.registerDataChangeCallback}
213 * to specify the type of the event(s).
214 *
215 * Available options are:
216 * - `uiGridConstants.dataChange.ALL` - listeners fired on any of these events, fires listeners on all events.
217 * - `uiGridConstants.dataChange.EDIT` - fired when the data in a cell is edited
218 * - `uiGridConstants.dataChange.ROW` - fired when a row is added or removed
219 * - `uiGridConstants.dataChange.COLUMN` - fired when the column definitions are modified
220 * - `uiGridConstants.dataChange.OPTIONS` - fired when the grid options are modified
221 */
222 dataChange: {
223 ALL: 'all',
224 EDIT: 'edit',
225 ROW: 'row',
226 COLUMN: 'column',
227 OPTIONS: 'options'
228 },
229
230 /**
231 * @ngdoc object
232 * @name scrollbars
233 * @propertyOf ui.grid.service:uiGridConstants
234 * @description Used with {@link ui.grid.class:GridOptions#properties_enableHorizontalScrollbar GridOptions.enableHorizontalScrollbar}
235 * and {@link ui.grid.class:GridOptions#properties_enableVerticalScrollbar GridOptions.enableVerticalScrollbar}
236 * to specify the scrollbar policy for that direction.
237 *
238 * Available options are:
239 * - `uiGridConstants.scrollbars.NEVER` - never show scrollbars in this direction
240 * - `uiGridConstants.scrollbars.ALWAYS` - always show scrollbars in this direction
241 * - `uiGridConstants.scrollbars.WHEN_NEEDED` - shows scrollbars in this direction when needed
242 */
243
244 scrollbars: {
245 NEVER: 0,
246 ALWAYS: 1,
247 WHEN_NEEDED: 2
248 }
249 });
250
251 })();
252
253 angular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUtil', 'uiGridConstants', function ($compile, $parse, gridUtil, uiGridConstants) {
254 return {
255 priority: 0,
256 scope: false,
257 require: '?^uiGrid',
258 compile: function() {
259 return {
260 pre: function($scope, $elm, $attrs, uiGridCtrl) {
261 function compileTemplate() {
262 var compiledElementFn = $scope.col.compiledElementFn;
263
264 compiledElementFn($scope, function(clonedElement, scope) {
265 $elm.append(clonedElement);
266 });
267 }
268
269 // If the grid controller is present, use it to get the compiled cell template function
270 if (uiGridCtrl && $scope.col.compiledElementFn) {
271 compileTemplate();
272 }
273
274 // No controller, compile the element manually (for unit tests)
275 else {
276 if ( uiGridCtrl && !$scope.col.compiledElementFn ) {
277 $scope.col.getCompiledElementFn()
278 .then(function (compiledElementFn) {
279 compiledElementFn($scope, function(clonedElement, scope) {
280 $elm.append(clonedElement);
281 });
282 }).catch(angular.noop);
283 }
284 else {
285 var html = $scope.col.cellTemplate
286 .replace(uiGridConstants.MODEL_COL_FIELD, 'row.entity.' + gridUtil.preEval($scope.col.field))
287 .replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
288
289 var cellElement = $compile(html)($scope);
290 $elm.append(cellElement);
291 }
292 }
293 },
294 post: function($scope, $elm) {
295 var initColClass = $scope.col.getColClass(false),
296 classAdded;
297
298 $elm.addClass(initColClass);
299
300 function updateClass( grid ) {
301 var contents = $elm;
302
303 if ( classAdded ) {
304 contents.removeClass( classAdded );
305 classAdded = null;
306 }
307
308 if (angular.isFunction($scope.col.cellClass)) {
309 classAdded = $scope.col.cellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
310 }
311 else {
312 classAdded = $scope.col.cellClass;
313 }
314 contents.addClass(classAdded);
315 }
316
317 if ($scope.col.cellClass) {
318 updateClass();
319 }
320
321 // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
322 var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN, uiGridConstants.dataChange.EDIT]);
323
324 // watch the col and row to see if they change - which would indicate that we've scrolled or sorted or otherwise
325 // changed the row/col that this cell relates to, and we need to re-evaluate cell classes and maybe other things
326 function cellChangeFunction( n, o ) {
327 if ( n !== o ) {
328 if ( classAdded || $scope.col.cellClass ) {
329 updateClass();
330 }
331
332 // See if the column's internal class has changed
333 var newColClass = $scope.col.getColClass(false);
334
335 if (newColClass !== initColClass) {
336 $elm.removeClass(initColClass);
337 $elm.addClass(newColClass);
338 initColClass = newColClass;
339 }
340 }
341 }
342
343 // TODO(c0bra): Turn this into a deep array watch
344 var rowWatchDereg = $scope.$watch( 'row', cellChangeFunction );
345
346 function deregisterFunction() {
347 dataChangeDereg();
348 rowWatchDereg();
349 }
350
351 $scope.$on('$destroy', deregisterFunction);
352 $elm.on('$destroy', deregisterFunction);
353 }
354 };
355 }
356 };
357 }]);
358
359 (function() {
360
361 angular.module('ui.grid')
362 .service('uiGridColumnMenuService', [ 'i18nService', 'uiGridConstants', 'gridUtil',
363 function ( i18nService, uiGridConstants, gridUtil ) {
364 /**
365 * @ngdoc service
366 * @name ui.grid.service:uiGridColumnMenuService
367 *
368 * @description Services for working with column menus, factored out
369 * to make the code easier to understand
370 */
371
372 var service = {
373 /**
374 * @ngdoc method
375 * @methodOf ui.grid.service:uiGridColumnMenuService
376 * @name initialize
377 * @description Sets defaults, puts a reference to the $scope on
378 * the uiGridController
379 * @param {$scope} $scope the $scope from the uiGridColumnMenu
380 * @param {controller} uiGridCtrl the uiGridController for the grid
381 * we're on
382 *
383 */
384 initialize: function( $scope, uiGridCtrl ) {
385 $scope.grid = uiGridCtrl.grid;
386
387 // Store a reference to this link/controller in the main uiGrid controller
388 // to allow showMenu later
389 uiGridCtrl.columnMenuScope = $scope;
390
391 // Save whether we're shown or not so the columns can check
392 $scope.menuShown = false;
393 },
394
395
396 /**
397 * @ngdoc method
398 * @methodOf ui.grid.service:uiGridColumnMenuService
399 * @name setColMenuItemWatch
400 * @description Setup a watch on $scope.col.menuItems, and update
401 * menuItems based on this. $scope.col needs to be set by the column
402 * before calling the menu.
403 * @param {$scope} $scope the $scope from the uiGridColumnMenu
404 */
405 setColMenuItemWatch: function ( $scope ) {
406 var deregFunction = $scope.$watch('col.menuItems', function (n) {
407 if (typeof(n) !== 'undefined' && n && angular.isArray(n)) {
408 n.forEach(function (item) {
409 if (typeof(item.context) === 'undefined' || !item.context) {
410 item.context = {};
411 }
412 item.context.col = $scope.col;
413 });
414
415 $scope.menuItems = $scope.defaultMenuItems.concat(n);
416 }
417 else {
418 $scope.menuItems = $scope.defaultMenuItems;
419 }
420 });
421
422 $scope.$on( '$destroy', deregFunction );
423 },
424
425
426 /**
427 * @ngdoc boolean
428 * @name enableSorting
429 * @propertyOf ui.grid.class:GridOptions.columnDef
430 * @description (optional) True by default. When enabled, this setting adds sort
431 * widgets to the column header, allowing sorting of the data in the individual column.
432 */
433 /**
434 * @ngdoc method
435 * @methodOf ui.grid.service:uiGridColumnMenuService
436 * @name sortable
437 * @description determines whether this column is sortable
438 * @param {$scope} $scope the $scope from the uiGridColumnMenu
439 *
440 */
441 sortable: function( $scope ) {
442 return Boolean( $scope.grid.options.enableSorting && typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.enableSorting);
443 },
444
445 /**
446 * @ngdoc method
447 * @methodOf ui.grid.service:uiGridColumnMenuService
448 * @name isActiveSort
449 * @description determines whether the requested sort direction is current active, to
450 * allow highlighting in the menu
451 * @param {$scope} $scope the $scope from the uiGridColumnMenu
452 * @param {string} direction the direction that we'd have selected for us to be active
453 *
454 */
455 isActiveSort: function( $scope, direction ) {
456 return Boolean(typeof($scope.col) !== 'undefined' && typeof($scope.col.sort) !== 'undefined' &&
457 typeof($scope.col.sort.direction) !== 'undefined' && $scope.col.sort.direction === direction);
458 },
459
460 /**
461 * @ngdoc method
462 * @methodOf ui.grid.service:uiGridColumnMenuService
463 * @name suppressRemoveSort
464 * @description determines whether we should suppress the removeSort option
465 * @param {$scope} $scope the $scope from the uiGridColumnMenu
466 *
467 */
468 suppressRemoveSort: function( $scope ) {
469 return Boolean($scope.col && $scope.col.suppressRemoveSort);
470 },
471
472
473 /**
474 * @ngdoc boolean
475 * @name enableHiding
476 * @propertyOf ui.grid.class:GridOptions.columnDef
477 * @description (optional) True by default. When set to false, this setting prevents a user from hiding the column
478 * using the column menu or the grid menu.
479 */
480 /**
481 * @ngdoc method
482 * @methodOf ui.grid.service:uiGridColumnMenuService
483 * @name hideable
484 * @description determines whether a column can be hidden, by checking the enableHiding columnDef option
485 * @param {$scope} $scope the $scope from the uiGridColumnMenu
486 *
487 */
488 hideable: function( $scope ) {
489 return !(typeof($scope.col) !== 'undefined' && $scope.col && $scope.col.colDef && $scope.col.colDef.enableHiding === false );
490 },
491
492
493 /**
494 * @ngdoc method
495 * @methodOf ui.grid.service:uiGridColumnMenuService
496 * @name getDefaultMenuItems
497 * @description returns the default menu items for a column menu
498 * @param {$scope} $scope the $scope from the uiGridColumnMenu
499 *
500 */
501 getDefaultMenuItems: function( $scope ) {
502 return [
503 {
504 title: function() {return i18nService.getSafeText('sort.ascending');},
505 icon: 'ui-grid-icon-sort-alt-up',
506 action: function($event) {
507 $event.stopPropagation();
508 $scope.sortColumn($event, uiGridConstants.ASC);
509 },
510 shown: function () {
511 return service.sortable( $scope );
512 },
513 active: function() {
514 return service.isActiveSort( $scope, uiGridConstants.ASC);
515 }
516 },
517 {
518 title: function() {return i18nService.getSafeText('sort.descending');},
519 icon: 'ui-grid-icon-sort-alt-down',
520 action: function($event) {
521 $event.stopPropagation();
522 $scope.sortColumn($event, uiGridConstants.DESC);
523 },
524 shown: function() {
525 return service.sortable( $scope );
526 },
527 active: function() {
528 return service.isActiveSort( $scope, uiGridConstants.DESC);
529 }
530 },
531 {
532 title: function() {return i18nService.getSafeText('sort.remove');},
533 icon: 'ui-grid-icon-cancel',
534 action: function ($event) {
535 $event.stopPropagation();
536 $scope.unsortColumn();
537 },
538 shown: function() {
539 return service.sortable( $scope ) &&
540 typeof($scope.col) !== 'undefined' && (typeof($scope.col.sort) !== 'undefined' &&
541 typeof($scope.col.sort.direction) !== 'undefined') && $scope.col.sort.direction !== null &&
542 !service.suppressRemoveSort( $scope );
543 }
544 },
545 {
546 title: function() {return i18nService.getSafeText('column.hide');},
547 icon: 'ui-grid-icon-cancel',
548 shown: function() {
549 return service.hideable( $scope );
550 },
551 action: function ($event) {
552 $event.stopPropagation();
553 $scope.hideColumn();
554 }
555 }
556 ];
557 },
558
559
560 /**
561 * @ngdoc method
562 * @methodOf ui.grid.service:uiGridColumnMenuService
563 * @name getColumnElementPosition
564 * @description gets the position information needed to place the column
565 * menu below the column header
566 * @param {$scope} $scope the $scope from the uiGridColumnMenu
567 * @param {GridColumn} column the column we want to position below
568 * @param {element} $columnElement the column element we want to position below
569 * @returns {hash} containing left, top, offset, height, width
570 *
571 */
572 getColumnElementPosition: function( $scope, column, $columnElement ) {
573 var positionData = {};
574
575 positionData.left = $columnElement[0].offsetLeft;
576 positionData.top = $columnElement[0].offsetTop;
577 positionData.parentLeft = $columnElement[0].offsetParent.offsetLeft;
578
579 // Get the grid scrollLeft
580 positionData.offset = 0;
581 if (column.grid.options.offsetLeft) {
582 positionData.offset = column.grid.options.offsetLeft;
583 }
584
585 positionData.height = gridUtil.elementHeight($columnElement, true);
586 positionData.width = gridUtil.elementWidth($columnElement, true);
587
588 return positionData;
589 },
590
591
592 /**
593 * @ngdoc method
594 * @methodOf ui.grid.service:uiGridColumnMenuService
595 * @name repositionMenu
596 * @description Reposition the menu below the new column. If the menu has no child nodes
597 * (i.e. it's not currently visible) then we guess it's width at 100, we'll be called again
598 * later to fix it
599 * @param {$scope} $scope the $scope from the uiGridColumnMenu
600 * @param {GridColumn} column the column we want to position below
601 * @param {hash} positionData a hash containing left, top, offset, height, width
602 * @param {element} $elm the column menu element that we want to reposition
603 * @param {element} $columnElement the column element that we want to reposition underneath
604 *
605 */
606 repositionMenu: function( $scope, column, positionData, $elm, $columnElement ) {
607 var menu = $elm[0].querySelectorAll('.ui-grid-menu');
608
609 // It's possible that the render container of the column we're attaching to is
610 // offset from the grid (i.e. pinned containers), we need to get the difference in the offsetLeft
611 // between the render container and the grid
612 var renderContainerElm = gridUtil.closestElm($columnElement, '.ui-grid-render-container'),
613 renderContainerOffset = renderContainerElm.getBoundingClientRect().left - $scope.grid.element[0].getBoundingClientRect().left,
614 containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft;
615
616 // repositionMenu is now always called after it's visible in the DOM,
617 // allowing us to simply get the width every time the menu is opened
618 var myWidth = gridUtil.elementWidth(menu, true),
619 paddingRight = column.lastMenuPaddingRight ? column.lastMenuPaddingRight : ( $scope.lastMenuPaddingRight ? $scope.lastMenuPaddingRight : 10);
620
621 if ( menu.length !== 0 ) {
622 var mid = menu[0].querySelectorAll('.ui-grid-menu-mid');
623
624 if ( mid.length !== 0 ) {
625 // TODO(c0bra): use padding-left/padding-right based on document direction (ltr/rtl), place menu on proper side
626 // Get the column menu right padding
627 paddingRight = parseInt(gridUtil.getStyles(angular.element(menu)[0])['paddingRight'], 10);
628 $scope.lastMenuPaddingRight = paddingRight;
629 column.lastMenuPaddingRight = paddingRight;
630 }
631 }
632
633 var left = positionData.left + renderContainerOffset - containerScrollLeft + positionData.parentLeft + positionData.width + paddingRight;
634
635 if (left < positionData.offset + myWidth) {
636 left = Math.max(positionData.left - containerScrollLeft + positionData.parentLeft - paddingRight + myWidth, positionData.offset + myWidth);
637 }
638
639 $elm.css('left', left + 'px');
640 $elm.css('top', (positionData.top + positionData.height) + 'px');
641 }
642 };
643 return service;
644 }])
645
646
647 .directive('uiGridColumnMenu', ['$timeout', 'gridUtil', 'uiGridConstants', 'uiGridColumnMenuService', '$document',
648 function ($timeout, gridUtil, uiGridConstants, uiGridColumnMenuService, $document) {
649 /**
650 * @ngdoc directive
651 * @name ui.grid.directive:uiGridColumnMenu
652 * @description Provides the column menu framework, leverages uiGridMenu underneath
653 *
654 */
655
656 return {
657 priority: 0,
658 scope: true,
659 require: '^uiGrid',
660 templateUrl: 'ui-grid/uiGridColumnMenu',
661 replace: true,
662 link: function ($scope, $elm, $attrs, uiGridCtrl) {
663 uiGridColumnMenuService.initialize( $scope, uiGridCtrl );
664
665 $scope.defaultMenuItems = uiGridColumnMenuService.getDefaultMenuItems( $scope );
666
667 // Set the menu items for use with the column menu. The user can later add additional items via the watch
668 $scope.menuItems = $scope.defaultMenuItems;
669 uiGridColumnMenuService.setColMenuItemWatch( $scope );
670
671
672 /**
673 * @ngdoc method
674 * @methodOf ui.grid.directive:uiGridColumnMenu
675 * @name showMenu
676 * @description Shows the column menu. If the menu is already displayed it
677 * calls the menu to ask it to hide (it will animate), then it repositions the menu
678 * to the right place whilst hidden (it will make an assumption on menu width),
679 * then it asks the menu to show (it will animate), then it repositions the menu again
680 * once we can calculate it's size.
681 * @param {GridColumn} column the column we want to position below
682 * @param {element} $columnElement the column element we want to position below
683 */
684 $scope.showMenu = function(column, $columnElement, event) {
685 // Swap to this column
686 $scope.col = column;
687
688 // Get the position information for the column element
689 var colElementPosition = uiGridColumnMenuService.getColumnElementPosition( $scope, column, $columnElement );
690
691 if ($scope.menuShown) {
692 // we want to hide, then reposition, then show, but we want to wait for animations
693 // we set a variable, and then rely on the menu-hidden event to call the reposition and show
694 $scope.colElement = $columnElement;
695 $scope.colElementPosition = colElementPosition;
696 $scope.hideThenShow = true;
697
698 $scope.$broadcast('hide-menu', { originalEvent: event });
699 } else {
700 $scope.menuShown = true;
701
702 $scope.colElement = $columnElement;
703 $scope.colElementPosition = colElementPosition;
704 $scope.$broadcast('show-menu', { originalEvent: event });
705 }
706 };
707
708
709 /**
710 * @ngdoc method
711 * @methodOf ui.grid.directive:uiGridColumnMenu
712 * @name hideMenu
713 * @description Hides the column menu.
714 * @param {boolean} broadcastTrigger true if we were triggered by a broadcast
715 * from the menu itself - in which case don't broadcast again as we'll get
716 * an infinite loop
717 */
718 $scope.hideMenu = function( broadcastTrigger ) {
719 $scope.menuShown = false;
720 if ( !broadcastTrigger ) {
721 $scope.$broadcast('hide-menu');
722 }
723 };
724
725
726 $scope.$on('menu-hidden', function() {
727 var menuItems = angular.element($elm[0].querySelector('.ui-grid-menu-items'))[0];
728
729 $elm[0].removeAttribute('style');
730
731 if ( $scope.hideThenShow ) {
732 delete $scope.hideThenShow;
733
734 $scope.$broadcast('show-menu');
735
736 $scope.menuShown = true;
737 } else {
738 $scope.hideMenu( true );
739
740 if ($scope.col) {
741 // Focus on the menu button
742 gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + $scope.col.getColClass()+ ' .ui-grid-column-menu-button', $scope.col.grid, false);
743 }
744 }
745
746 if (menuItems) {
747 menuItems.onkeydown = null;
748 angular.forEach(menuItems.children, function removeHandlers(item) {
749 item.onkeydown = null;
750 });
751 }
752 });
753
754 $scope.$on('menu-shown', function() {
755 $timeout(function() {
756 uiGridColumnMenuService.repositionMenu( $scope, $scope.col, $scope.colElementPosition, $elm, $scope.colElement );
757
758 // automatically set the focus to the first button element in the now open menu.
759 gridUtil.focus.bySelector($document, '.ui-grid-menu-items .ui-grid-menu-item:not(.ng-hide)', true);
760 delete $scope.colElementPosition;
761 delete $scope.columnElement;
762 addKeydownHandlersToMenu();
763 });
764 });
765
766
767 /* Column methods */
768 $scope.sortColumn = function (event, dir) {
769 event.stopPropagation();
770
771 $scope.grid.sortColumn($scope.col, dir, true)
772 .then(function () {
773 $scope.grid.refresh();
774 $scope.hideMenu();
775 }).catch(angular.noop);
776 };
777
778 $scope.unsortColumn = function () {
779 $scope.col.unsort();
780
781 $scope.grid.refresh();
782 $scope.hideMenu();
783 };
784
785 function addKeydownHandlersToMenu() {
786 var menu = angular.element($elm[0].querySelector('.ui-grid-menu-items'))[0],
787 menuItems,
788 visibleMenuItems = [];
789
790 if (menu) {
791 menu.onkeydown = function closeMenu(event) {
792 if (event.keyCode === uiGridConstants.keymap.ESC) {
793 event.preventDefault();
794 $scope.hideMenu();
795 }
796 };
797
798 menuItems = menu.querySelectorAll('.ui-grid-menu-item:not(.ng-hide)');
799 angular.forEach(menuItems, function filterVisibleItems(item) {
800 if (item.offsetParent !== null) {
801 this.push(item);
802 }
803 }, visibleMenuItems);
804
805 if (visibleMenuItems.length) {
806 if (visibleMenuItems.length === 1) {
807 visibleMenuItems[0].onkeydown = function singleItemHandler(event) {
808 circularFocusHandler(event, true);
809 };
810 } else {
811 visibleMenuItems[0].onkeydown = function firstItemHandler(event) {
812 circularFocusHandler(event, false, event.shiftKey, visibleMenuItems.length - 1);
813 };
814 visibleMenuItems[visibleMenuItems.length - 1].onkeydown = function lastItemHandler(event) {
815 circularFocusHandler(event, false, !event.shiftKey, 0);
816 };
817 }
818 }
819 }
820
821 function circularFocusHandler(event, isSingleItem, shiftKeyStatus, index) {
822 if (event.keyCode === uiGridConstants.keymap.TAB) {
823 if (isSingleItem) {
824 event.preventDefault();
825 } else if (shiftKeyStatus) {
826 event.preventDefault();
827 visibleMenuItems[index].focus();
828 }
829 }
830 }
831 }
832
833 // Since we are hiding this column the default hide action will fail so we need to focus somewhere else.
834 var setFocusOnHideColumn = function() {
835 $timeout(function() {
836 // Get the UID of the first
837 var focusToGridMenu = function() {
838 return gridUtil.focus.byId('grid-menu', $scope.grid);
839 };
840
841 var thisIndex;
842 $scope.grid.columns.some(function(element, index) {
843 if (angular.equals(element, $scope.col)) {
844 thisIndex = index;
845 return true;
846 }
847 });
848
849 var previousVisibleCol;
850 // Try and find the next lower or nearest column to focus on
851 $scope.grid.columns.some(function(element, index) {
852 if (!element.visible) {
853 return false;
854 } // This columns index is below the current column index
855 else if ( index < thisIndex) {
856 previousVisibleCol = element;
857 } // This elements index is above this column index and we haven't found one that is lower
858 else if ( index > thisIndex && !previousVisibleCol) {
859 // This is the next best thing
860 previousVisibleCol = element;
861 // We've found one so use it.
862 return true;
863 } // We've reached an element with an index above this column and the previousVisibleCol variable has been set
864 else if (index > thisIndex && previousVisibleCol) {
865 // We are done.
866 return true;
867 }
868 });
869 // If found then focus on it
870 if (previousVisibleCol) {
871 var colClass = previousVisibleCol.getColClass();
872 gridUtil.focus.bySelector($document, '.ui-grid-header-cell.' + colClass+ ' .ui-grid-header-cell-primary-focus', true).then(angular.noop, function(reason) {
873 if (reason !== 'canceled') { // If this is canceled then don't perform the action
874 // The fallback action is to focus on the grid menu
875 return focusToGridMenu();
876 }
877 }).catch(angular.noop);
878 } else {
879 // Fallback action to focus on the grid menu
880 focusToGridMenu();
881 }
882 });
883 };
884
885 $scope.hideColumn = function () {
886 $scope.col.colDef.visible = false;
887 $scope.col.visible = false;
888
889 $scope.grid.queueGridRefresh();
890 $scope.hideMenu();
891 $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
892 $scope.grid.api.core.raise.columnVisibilityChanged( $scope.col );
893
894 // We are hiding so the default action of focusing on the button that opened this menu will fail.
895 setFocusOnHideColumn();
896 };
897 },
898
899 controller: ['$scope', function ($scope) {
900 var self = this;
901
902 $scope.$watch('menuItems', function (n) {
903 self.menuItems = n;
904 });
905 }]
906 };
907 }]);
908 })();
909
910 (function() {
911 'use strict';
912
913 angular.module('ui.grid').directive('uiGridFilter', ['$compile', '$templateCache', 'i18nService', 'gridUtil', function ($compile, $templateCache, i18nService, gridUtil) {
914
915 return {
916 compile: function() {
917 return {
918 pre: function ($scope, $elm) {
919 $scope.col.updateFilters = function( filterable ) {
920 $elm.children().remove();
921 if ( filterable ) {
922 var template = $scope.col.filterHeaderTemplate;
923 if (template === undefined && $scope.col.providedFilterHeaderTemplate !== '') {
924 if ($scope.col.filterHeaderTemplatePromise) {
925 $scope.col.filterHeaderTemplatePromise.then(function () {
926 template = $scope.col.filterHeaderTemplate;
927 $elm.append($compile(template)($scope));
928 });
929 }
930 }
931 else {
932 $elm.append($compile(template)($scope));
933 }
934 }
935 };
936
937 $scope.$on( '$destroy', function() {
938 delete $scope.col.updateFilters;
939 });
940 },
941 post: function ($scope, $elm) {
942 $scope.aria = i18nService.getSafeText('headerCell.aria');
943 $scope.removeFilter = function(colFilter, index) {
944 colFilter.term = null;
945 // Set the focus to the filter input after the action disables the button
946 gridUtil.focus.bySelector($elm, '.ui-grid-filter-input-' + index);
947 };
948 }
949 };
950 }
951 };
952 }]);
953 })();
954
955 (function () {
956 'use strict';
957
958 angular.module('ui.grid').directive('uiGridFooterCell', ['$timeout', 'gridUtil', 'uiGridConstants', '$compile',
959 function ($timeout, gridUtil, uiGridConstants, $compile) {
960 return {
961 priority: 0,
962 scope: {
963 col: '=',
964 row: '=',
965 renderIndex: '='
966 },
967 replace: true,
968 require: '^uiGrid',
969 compile: function compile() {
970 return {
971 pre: function ($scope, $elm) {
972 var template = $scope.col.footerCellTemplate;
973
974 if (template === undefined && $scope.col.providedFooterCellTemplate !== '') {
975 if ($scope.col.footerCellTemplatePromise) {
976 $scope.col.footerCellTemplatePromise.then(function () {
977 template = $scope.col.footerCellTemplate;
978 $elm.append($compile(template)($scope));
979 });
980 }
981 }
982 else {
983 $elm.append($compile(template)($scope));
984 }
985 },
986 post: function ($scope, $elm, $attrs, uiGridCtrl) {
987 // $elm.addClass($scope.col.getColClass(false));
988 $scope.grid = uiGridCtrl.grid;
989
990 var initColClass = $scope.col.getColClass(false);
991
992 $elm.addClass(initColClass);
993
994 // apply any footerCellClass
995 var classAdded;
996
997 var updateClass = function() {
998 var contents = $elm;
999
1000 if ( classAdded ) {
1001 contents.removeClass( classAdded );
1002 classAdded = null;
1003 }
1004
1005 if (angular.isFunction($scope.col.footerCellClass)) {
1006 classAdded = $scope.col.footerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
1007 }
1008 else {
1009 classAdded = $scope.col.footerCellClass;
1010 }
1011 contents.addClass(classAdded);
1012 };
1013
1014 if ($scope.col.footerCellClass) {
1015 updateClass();
1016 }
1017
1018 $scope.col.updateAggregationValue();
1019
1020 // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
1021 var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateClass, [uiGridConstants.dataChange.COLUMN]);
1022
1023 // listen for visible rows change and update aggregation values
1024 $scope.grid.api.core.on.rowsRendered( $scope, $scope.col.updateAggregationValue );
1025 $scope.grid.api.core.on.rowsRendered( $scope, updateClass );
1026 $scope.$on( '$destroy', dataChangeDereg );
1027 }
1028 };
1029 }
1030 };
1031 }]);
1032 })();
1033
1034 (function () {
1035 'use strict';
1036
1037 angular.module('ui.grid').directive('uiGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', function ($templateCache, $compile, uiGridConstants, gridUtil, $timeout) {
1038
1039 return {
1040 restrict: 'EA',
1041 replace: true,
1042 // priority: 1000,
1043 require: ['^uiGrid', '^uiGridRenderContainer'],
1044 scope: true,
1045 compile: function ($elm, $attrs) {
1046 return {
1047 pre: function ($scope, $elm, $attrs, controllers) {
1048 var uiGridCtrl = controllers[0];
1049 var containerCtrl = controllers[1];
1050
1051 $scope.grid = uiGridCtrl.grid;
1052 $scope.colContainer = containerCtrl.colContainer;
1053
1054 containerCtrl.footer = $elm;
1055
1056 var footerTemplate = $scope.grid.options.footerTemplate;
1057 gridUtil.getTemplate(footerTemplate)
1058 .then(function (contents) {
1059 var template = angular.element(contents);
1060
1061 var newElm = $compile(template)($scope);
1062 $elm.append(newElm);
1063
1064 if (containerCtrl) {
1065 // Inject a reference to the footer viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
1066 var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
1067
1068 if (footerViewport) {
1069 containerCtrl.footerViewport = footerViewport;
1070 }
1071 }
1072 }).catch(angular.noop);
1073 },
1074
1075 post: function ($scope, $elm, $attrs, controllers) {
1076 var uiGridCtrl = controllers[0];
1077 var containerCtrl = controllers[1];
1078
1079 // gridUtil.logDebug('ui-grid-footer link');
1080
1081 var grid = uiGridCtrl.grid;
1082
1083 // Don't animate footer cells
1084 gridUtil.disableAnimations($elm);
1085
1086 containerCtrl.footer = $elm;
1087
1088 var footerViewport = $elm[0].getElementsByClassName('ui-grid-footer-viewport')[0];
1089 if (footerViewport) {
1090 containerCtrl.footerViewport = footerViewport;
1091 }
1092 }
1093 };
1094 }
1095 };
1096 }]);
1097
1098 })();
1099
1100 (function() {
1101 'use strict';
1102
1103 angular.module('ui.grid').directive('uiGridGridFooter', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil',
1104 function($templateCache, $compile, uiGridConstants, gridUtil) {
1105 return {
1106 restrict: 'EA',
1107 replace: true,
1108 require: '^uiGrid',
1109 scope: true,
1110 compile: function() {
1111 return {
1112 pre: function($scope, $elm, $attrs, uiGridCtrl) {
1113 $scope.grid = uiGridCtrl.grid;
1114
1115 var footerTemplate = $scope.grid.options.gridFooterTemplate;
1116
1117 gridUtil.getTemplate(footerTemplate)
1118 .then(function(contents) {
1119 var template = angular.element(contents),
1120 newElm = $compile(template)($scope);
1121
1122 $elm.append(newElm);
1123 }).catch(angular.noop);
1124 }
1125 };
1126 }
1127 };
1128 }]);
1129 })();
1130
1131 (function() {
1132 'use strict';
1133
1134 angular.module('ui.grid').directive('uiGridHeaderCell', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'ScrollEvent', 'i18nService',
1135 function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, ScrollEvent, i18nService) {
1136 // Do stuff after mouse has been down this many ms on the header cell
1137 var mousedownTimeout = 500,
1138 changeModeTimeout = 500; // length of time between a touch event and a mouse event being recognised again, and vice versa
1139
1140 return {
1141 priority: 0,
1142 scope: {
1143 col: '=',
1144 row: '=',
1145 renderIndex: '='
1146 },
1147 require: ['^uiGrid', '^uiGridRenderContainer'],
1148 replace: true,
1149 compile: function() {
1150 return {
1151 pre: function ($scope, $elm) {
1152 var template = $scope.col.headerCellTemplate;
1153 if (template === undefined && $scope.col.providedHeaderCellTemplate !== '') {
1154 if ($scope.col.headerCellTemplatePromise) {
1155 $scope.col.headerCellTemplatePromise.then(function () {
1156 template = $scope.col.headerCellTemplate;
1157 $elm.append($compile(template)($scope));
1158 });
1159 }
1160 }
1161 else {
1162 $elm.append($compile(template)($scope));
1163 }
1164 },
1165
1166 post: function ($scope, $elm, $attrs, controllers) {
1167 var uiGridCtrl = controllers[0];
1168 var renderContainerCtrl = controllers[1];
1169
1170 $scope.i18n = {
1171 headerCell: i18nService.getSafeText('headerCell'),
1172 sort: i18nService.getSafeText('sort')
1173 };
1174 $scope.isSortPriorityVisible = function() {
1175 // show sort priority if column is sorted and there is at least one other sorted column
1176 return angular.isNumber($scope.col.sort.priority) && $scope.grid.columns.some(function(element, index) {
1177 return angular.isNumber(element.sort.priority) && element !== $scope.col;
1178 });
1179 };
1180 $scope.getSortDirectionAriaLabel = function() {
1181 var col = $scope.col;
1182 // Trying to recreate this sort of thing but it was getting messy having it in the template.
1183 // Sort direction {{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending': 'none')}}.
1184 // {{col.sort.priority ? {{columnPriorityText}} {{col.sort.priority}} : ''}
1185 var label = col.sort.direction === uiGridConstants.ASC ? $scope.i18n.sort.ascending : ( col.sort.direction === uiGridConstants.DESC ? $scope.i18n.sort.descending : $scope.i18n.sort.none);
1186
1187 if ($scope.isSortPriorityVisible()) {
1188 label = label + '. ' + $scope.i18n.headerCell.priority + ' ' + (col.sort.priority + 1);
1189 }
1190 return label;
1191 };
1192
1193 $scope.grid = uiGridCtrl.grid;
1194
1195 $scope.renderContainer = uiGridCtrl.grid.renderContainers[renderContainerCtrl.containerId];
1196
1197 var initColClass = $scope.col.getColClass(false);
1198 $elm.addClass(initColClass);
1199
1200 // Hide the menu by default
1201 $scope.menuShown = false;
1202
1203 // Put asc and desc sort directions in scope
1204 $scope.asc = uiGridConstants.ASC;
1205 $scope.desc = uiGridConstants.DESC;
1206
1207 // Store a reference to menu element
1208 var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
1209
1210
1211 // apply any headerCellClass
1212 var classAdded,
1213 previousMouseX;
1214
1215 // filter watchers
1216 var filterDeregisters = [];
1217
1218
1219 /*
1220 * Our basic approach here for event handlers is that we listen for a down event (mousedown or touchstart).
1221 * Once we have a down event, we need to work out whether we have a click, a drag, or a
1222 * hold. A click would sort the grid (if sortable). A drag would be used by moveable, so
1223 * we ignore it. A hold would open the menu.
1224 *
1225 * So, on down event, we put in place handlers for move and up events, and a timer. If the
1226 * timer expires before we see a move or up, then we have a long press and hence a column menu open.
1227 * If the up happens before the timer, then we have a click, and we sort if the column is sortable.
1228 * If a move happens before the timer, then we are doing column move, so we do nothing, the moveable feature
1229 * will handle it.
1230 *
1231 * To deal with touch enabled devices that also have mice, we only create our handlers when
1232 * we get the down event, and we create the corresponding handlers - if we're touchstart then
1233 * we get touchmove and touchend, if we're mousedown then we get mousemove and mouseup.
1234 *
1235 * We also suppress the click action whilst this is happening - otherwise after the mouseup there
1236 * will be a click event and that can cause the column menu to close
1237 *
1238 */
1239 $scope.downFn = function( event ) {
1240 event.stopPropagation();
1241
1242 if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
1243 event = event.originalEvent;
1244 }
1245
1246 // Don't show the menu if it's not the left button
1247 if (event.button && event.button !== 0) {
1248 return;
1249 }
1250 previousMouseX = event.pageX;
1251
1252 $scope.mousedownStartTime = (new Date()).getTime();
1253 $scope.mousedownTimeout = $timeout(function() { }, mousedownTimeout);
1254
1255 $scope.mousedownTimeout.then(function () {
1256 if ( $scope.colMenu ) {
1257 uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm, event);
1258 }
1259 }).catch(angular.noop);
1260
1261 uiGridCtrl.fireEvent(uiGridConstants.events.COLUMN_HEADER_CLICK, {event: event, columnName: $scope.col.colDef.name});
1262
1263 $scope.offAllEvents();
1264 if ( event.type === 'touchstart') {
1265 $document.on('touchend', $scope.upFn);
1266 $document.on('touchmove', $scope.moveFn);
1267 } else if ( event.type === 'mousedown' ) {
1268 $document.on('mouseup', $scope.upFn);
1269 $document.on('mousemove', $scope.moveFn);
1270 }
1271 };
1272
1273 $scope.upFn = function( event ) {
1274 event.stopPropagation();
1275 $timeout.cancel($scope.mousedownTimeout);
1276 $scope.offAllEvents();
1277 $scope.onDownEvents(event.type);
1278
1279 var mousedownEndTime = (new Date()).getTime();
1280 var mousedownTime = mousedownEndTime - $scope.mousedownStartTime;
1281
1282 if (mousedownTime > mousedownTimeout) {
1283 // long click, handled above with mousedown
1284 }
1285 else {
1286 // short click
1287 if ( $scope.sortable ) {
1288 $scope.handleClick(event);
1289 }
1290 }
1291 };
1292
1293 $scope.handleKeyDown = function(event) {
1294 if (event.keyCode === 32) {
1295 event.preventDefault();
1296 }
1297 };
1298
1299 $scope.moveFn = function( event ) {
1300 // Chrome is known to fire some bogus move events.
1301 var changeValue = event.pageX - previousMouseX;
1302 if ( changeValue === 0 ) { return; }
1303
1304 // we're a move, so do nothing and leave for column move (if enabled) to take over
1305 $timeout.cancel($scope.mousedownTimeout);
1306 $scope.offAllEvents();
1307 $scope.onDownEvents(event.type);
1308 };
1309
1310 $scope.clickFn = function ( event ) {
1311 event.stopPropagation();
1312 $contentsElm.off('click', $scope.clickFn);
1313 };
1314
1315
1316 $scope.offAllEvents = function() {
1317 $contentsElm.off('touchstart', $scope.downFn);
1318 $contentsElm.off('mousedown', $scope.downFn);
1319
1320 $document.off('touchend', $scope.upFn);
1321 $document.off('mouseup', $scope.upFn);
1322
1323 $document.off('touchmove', $scope.moveFn);
1324 $document.off('mousemove', $scope.moveFn);
1325
1326 $contentsElm.off('click', $scope.clickFn);
1327 };
1328
1329 $scope.onDownEvents = function( type ) {
1330 // If there is a previous event, then wait a while before
1331 // activating the other mode - i.e. if the last event was a touch event then
1332 // don't enable mouse events for a wee while (500ms or so)
1333 // Avoids problems with devices that emulate mouse events when you have touch events
1334
1335 switch (type) {
1336 case 'touchmove':
1337 case 'touchend':
1338 $contentsElm.on('click', $scope.clickFn);
1339 $contentsElm.on('touchstart', $scope.downFn);
1340 $timeout(function() {
1341 $contentsElm.on('mousedown', $scope.downFn);
1342 }, changeModeTimeout);
1343 break;
1344 case 'mousemove':
1345 case 'mouseup':
1346 $contentsElm.on('click', $scope.clickFn);
1347 $contentsElm.on('mousedown', $scope.downFn);
1348 $timeout(function() {
1349 $contentsElm.on('touchstart', $scope.downFn);
1350 }, changeModeTimeout);
1351 break;
1352 default:
1353 $contentsElm.on('click', $scope.clickFn);
1354 $contentsElm.on('touchstart', $scope.downFn);
1355 $contentsElm.on('mousedown', $scope.downFn);
1356 }
1357 };
1358
1359
1360 var updateHeaderOptions = function() {
1361 var contents = $elm;
1362
1363 if ( classAdded ) {
1364 contents.removeClass( classAdded );
1365 classAdded = null;
1366 }
1367
1368 if (angular.isFunction($scope.col.headerCellClass)) {
1369 classAdded = $scope.col.headerCellClass($scope.grid, $scope.row, $scope.col, $scope.rowRenderIndex, $scope.colRenderIndex);
1370 }
1371 else {
1372 classAdded = $scope.col.headerCellClass;
1373 }
1374 contents.addClass(classAdded);
1375
1376 $scope.$applyAsync(function() {
1377 var rightMostContainer = $scope.grid.renderContainers['right'] && $scope.grid.renderContainers['right'].visibleColumnCache.length ?
1378 $scope.grid.renderContainers['right'] : $scope.grid.renderContainers['body'];
1379 $scope.isLastCol = uiGridCtrl.grid.options && uiGridCtrl.grid.options.enableGridMenu &&
1380 $scope.col === rightMostContainer.visibleColumnCache[ rightMostContainer.visibleColumnCache.length - 1 ];
1381 });
1382
1383 // Figure out whether this column is sortable or not
1384 $scope.sortable = Boolean($scope.col.enableSorting);
1385
1386 // Figure out whether this column is filterable or not
1387 var oldFilterable = $scope.filterable;
1388 $scope.filterable = Boolean(uiGridCtrl.grid.options.enableFiltering && $scope.col.enableFiltering);
1389
1390 if ( oldFilterable !== $scope.filterable) {
1391 if ( typeof($scope.col.updateFilters) !== 'undefined' ) {
1392 $scope.col.updateFilters($scope.filterable);
1393 }
1394
1395 // if column is filterable add a filter watcher
1396 if ($scope.filterable) {
1397 $scope.col.filters.forEach( function(filter, i) {
1398 filterDeregisters.push($scope.$watch('col.filters[' + i + '].term', function(n, o) {
1399 if (n !== o) {
1400 uiGridCtrl.grid.api.core.raise.filterChanged();
1401 uiGridCtrl.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
1402 uiGridCtrl.grid.queueGridRefresh();
1403 }
1404 }));
1405 });
1406 $scope.$on('$destroy', function() {
1407 filterDeregisters.forEach( function(filterDeregister) {
1408 filterDeregister();
1409 });
1410 });
1411 } else {
1412 filterDeregisters.forEach( function(filterDeregister) {
1413 filterDeregister();
1414 });
1415 }
1416 }
1417
1418 // figure out whether we support column menus
1419 $scope.colMenu = ($scope.col.grid.options && $scope.col.grid.options.enableColumnMenus !== false &&
1420 $scope.col.colDef && $scope.col.colDef.enableColumnMenu !== false);
1421
1422 /**
1423 * @ngdoc property
1424 * @name enableColumnMenu
1425 * @propertyOf ui.grid.class:GridOptions.columnDef
1426 * @description if column menus are enabled, controls the column menus for this specific
1427 * column (i.e. if gridOptions.enableColumnMenus, then you can control column menus
1428 * using this option. If gridOptions.enableColumnMenus === false then you get no column
1429 * menus irrespective of the value of this option ). Defaults to true.
1430 *
1431 * By default column menu's trigger is hidden before mouse over, but you can always force it to be visible with CSS:
1432 *
1433 * <pre>
1434 * .ui-grid-column-menu-button {
1435 * display: block;
1436 * }
1437 * </pre>
1438 */
1439 /**
1440 * @ngdoc property
1441 * @name enableColumnMenus
1442 * @propertyOf ui.grid.class:GridOptions.columnDef
1443 * @description Override for column menus everywhere - if set to false then you get no
1444 * column menus. Defaults to true.
1445 *
1446 */
1447
1448 $scope.offAllEvents();
1449
1450 if ($scope.sortable || $scope.colMenu) {
1451 $scope.onDownEvents();
1452
1453 $scope.$on('$destroy', function () {
1454 $scope.offAllEvents();
1455 });
1456 }
1457 };
1458
1459 updateHeaderOptions();
1460
1461 // Register a data change watch that would get triggered whenever someone edits a cell or modifies column defs
1462 var dataChangeDereg = $scope.grid.registerDataChangeCallback( updateHeaderOptions, [uiGridConstants.dataChange.COLUMN]);
1463
1464 $scope.$on( '$destroy', dataChangeDereg );
1465
1466 $scope.handleClick = function(event) {
1467 // If the shift key is being held down, add this column to the sort
1468 var add = false;
1469 if (event.shiftKey) {
1470 add = true;
1471 }
1472
1473 // Sort this column then rebuild the grid's rows
1474 uiGridCtrl.grid.sortColumn($scope.col, add)
1475 .then(function () {
1476 if (uiGridCtrl.columnMenuScope) { uiGridCtrl.columnMenuScope.hideMenu(); }
1477 uiGridCtrl.grid.refresh();
1478 }).catch(angular.noop);
1479 };
1480
1481 $scope.headerCellArrowKeyDown = function(event) {
1482 if (event.keyCode === 32 || event.keyCode === 13) {
1483 event.preventDefault();
1484 $scope.toggleMenu(event);
1485 }
1486 };
1487
1488 $scope.toggleMenu = function(event) {
1489
1490 event.stopPropagation();
1491
1492 // If the menu is already showing...
1493 if (uiGridCtrl.columnMenuScope.menuShown) {
1494 // ... and we're the column the menu is on...
1495 if (uiGridCtrl.columnMenuScope.col === $scope.col) {
1496 // ... hide it
1497 uiGridCtrl.columnMenuScope.hideMenu();
1498 }
1499 // ... and we're NOT the column the menu is on
1500 else {
1501 // ... move the menu to our column
1502 uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
1503 }
1504 }
1505 // If the menu is NOT showing
1506 else {
1507 // ... show it on our column
1508 uiGridCtrl.columnMenuScope.showMenu($scope.col, $elm);
1509 }
1510 };
1511 }
1512 };
1513 }
1514 };
1515 }]);
1516 })();
1517
1518 (function() {
1519 'use strict';
1520
1521 angular.module('ui.grid').directive('uiGridHeader', ['$templateCache', '$compile', 'uiGridConstants', 'gridUtil', '$timeout', 'ScrollEvent',
1522 function($templateCache, $compile, uiGridConstants, gridUtil, $timeout, ScrollEvent) {
1523 var defaultTemplate = 'ui-grid/ui-grid-header',
1524 emptyTemplate = 'ui-grid/ui-grid-no-header';
1525
1526 return {
1527 restrict: 'EA',
1528 replace: true,
1529 require: ['^uiGrid', '^uiGridRenderContainer'],
1530 scope: true,
1531 compile: function() {
1532 return {
1533 pre: function ($scope, $elm, $attrs, controllers) {
1534 var uiGridCtrl = controllers[0],
1535 containerCtrl = controllers[1];
1536
1537 $scope.grid = uiGridCtrl.grid;
1538 $scope.colContainer = containerCtrl.colContainer;
1539
1540 updateHeaderReferences();
1541
1542 var headerTemplate;
1543 if (!$scope.grid.options.showHeader) {
1544 headerTemplate = emptyTemplate;
1545 }
1546 else {
1547 headerTemplate = ($scope.grid.options.headerTemplate) ? $scope.grid.options.headerTemplate : defaultTemplate;
1548 }
1549
1550 gridUtil.getTemplate(headerTemplate)
1551 .then(function (contents) {
1552 var template = angular.element(contents);
1553
1554 var newElm = $compile(template)($scope);
1555 $elm.replaceWith(newElm);
1556
1557 // And update $elm to be the new element
1558 $elm = newElm;
1559
1560 updateHeaderReferences();
1561
1562 if (containerCtrl) {
1563 // Inject a reference to the header viewport (if it exists) into the grid controller for use in the horizontal scroll handler below
1564 var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
1565
1566
1567 if (headerViewport) {
1568 containerCtrl.headerViewport = headerViewport;
1569 angular.element(headerViewport).on('scroll', scrollHandler);
1570 $scope.$on('$destroy', function () {
1571 angular.element(headerViewport).off('scroll', scrollHandler);
1572 });
1573 }
1574 }
1575
1576 $scope.grid.queueRefresh();
1577 }).catch(angular.noop);
1578
1579 function updateHeaderReferences() {
1580 containerCtrl.header = containerCtrl.colContainer.header = $elm;
1581
1582 var headerCanvases = $elm[0].getElementsByClassName('ui-grid-header-canvas');
1583
1584 if (headerCanvases.length > 0) {
1585 containerCtrl.headerCanvas = containerCtrl.colContainer.headerCanvas = headerCanvases[0];
1586 }
1587 else {
1588 containerCtrl.headerCanvas = null;
1589 }
1590 }
1591
1592 function scrollHandler() {
1593 if (uiGridCtrl.grid.isScrollingHorizontally) {
1594 return;
1595 }
1596 var newScrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.headerViewport, uiGridCtrl.grid);
1597 var horizScrollPercentage = containerCtrl.colContainer.scrollHorizontal(newScrollLeft);
1598
1599 var scrollEvent = new ScrollEvent(uiGridCtrl.grid, null, containerCtrl.colContainer, ScrollEvent.Sources.ViewPortScroll);
1600 scrollEvent.newScrollLeft = newScrollLeft;
1601 if ( horizScrollPercentage > -1 ) {
1602 scrollEvent.x = { percentage: horizScrollPercentage };
1603 }
1604
1605 uiGridCtrl.grid.scrollContainers(null, scrollEvent);
1606 }
1607 },
1608
1609 post: function ($scope, $elm, $attrs, controllers) {
1610 var uiGridCtrl = controllers[0];
1611 var containerCtrl = controllers[1];
1612
1613 // gridUtil.logDebug('ui-grid-header link');
1614
1615 var grid = uiGridCtrl.grid;
1616
1617 // Don't animate header cells
1618 gridUtil.disableAnimations($elm);
1619
1620 function updateColumnWidths() {
1621 // this styleBuilder always runs after the renderContainer, so we can rely on the column widths
1622 // already being populated correctly
1623
1624 var columnCache = containerCtrl.colContainer.visibleColumnCache;
1625
1626 // Build the CSS
1627 // uiGridCtrl.grid.columns.forEach(function (column) {
1628 var ret = '';
1629 var canvasWidth = 0;
1630 columnCache.forEach(function (column) {
1631 ret = ret + column.getColClassDefinition();
1632 canvasWidth += column.drawnWidth;
1633 });
1634
1635 containerCtrl.colContainer.canvasWidth = canvasWidth;
1636
1637 // Return the styles back to buildStyles which pops them into the `customStyles` scope variable
1638 return ret;
1639 }
1640
1641 containerCtrl.header = $elm;
1642
1643 var headerViewport = $elm[0].getElementsByClassName('ui-grid-header-viewport')[0];
1644 if (headerViewport) {
1645 containerCtrl.headerViewport = headerViewport;
1646 }
1647
1648 // todo: remove this if by injecting gridCtrl into unit tests
1649 if (uiGridCtrl) {
1650 uiGridCtrl.grid.registerStyleComputation({
1651 priority: 15,
1652 func: updateColumnWidths
1653 });
1654 }
1655 }
1656 };
1657 }
1658 };
1659 }]);
1660 })();
1661
1662 (function() {
1663
1664 angular.module('ui.grid')
1665 .service('uiGridGridMenuService', [ 'gridUtil', 'i18nService', 'uiGridConstants', function( gridUtil, i18nService, uiGridConstants ) {
1666 /**
1667 * @ngdoc service
1668 * @name ui.grid.uiGridGridMenuService
1669 *
1670 * @description Methods for working with the grid menu
1671 */
1672
1673 var service = {
1674 /**
1675 * @ngdoc method
1676 * @methodOf ui.grid.uiGridGridMenuService
1677 * @name initialize
1678 * @description Sets up the gridMenu. Most importantly, sets our
1679 * scope onto the grid object as grid.gridMenuScope, allowing us
1680 * to operate when passed only the grid. Second most importantly,
1681 * we register the 'addToGridMenu' and 'removeFromGridMenu' methods
1682 * on the core api.
1683 * @param {$scope} $scope the scope of this gridMenu
1684 * @param {Grid} grid the grid to which this gridMenu is associated
1685 */
1686 initialize: function( $scope, grid ) {
1687 grid.gridMenuScope = $scope;
1688 $scope.grid = grid;
1689 $scope.registeredMenuItems = [];
1690
1691 // not certain this is needed, but would be bad to create a memory leak
1692 $scope.$on('$destroy', function() {
1693 if ( $scope.grid && $scope.grid.gridMenuScope ) {
1694 $scope.grid.gridMenuScope = null;
1695 }
1696 if ( $scope.grid ) {
1697 $scope.grid = null;
1698 }
1699 if ( $scope.registeredMenuItems ) {
1700 $scope.registeredMenuItems = null;
1701 }
1702 });
1703
1704 $scope.registeredMenuItems = [];
1705
1706 /**
1707 * @ngdoc function
1708 * @name addToGridMenu
1709 * @methodOf ui.grid.api:PublicApi
1710 * @description add items to the grid menu. Used by features
1711 * to add their menu items if they are enabled, can also be used by
1712 * end users to add menu items. This method has the advantage of allowing
1713 * remove again, which can simplify management of which items are included
1714 * in the menu when. (Noting that in most cases the shown and active functions
1715 * provide a better way to handle visibility of menu items)
1716 * @param {Grid} grid the grid on which we are acting
1717 * @param {array} items menu items in the format as described in the tutorial, with
1718 * the added note that if you want to use remove you must also specify an `id` field,
1719 * which is provided when you want to remove an item. The id should be unique.
1720 *
1721 */
1722 grid.api.registerMethod( 'core', 'addToGridMenu', service.addToGridMenu );
1723
1724 /**
1725 * @ngdoc function
1726 * @name removeFromGridMenu
1727 * @methodOf ui.grid.api:PublicApi
1728 * @description Remove an item from the grid menu based on a provided id. Assumes
1729 * that the id is unique, removes only the last instance of that id. Does nothing if
1730 * the specified id is not found
1731 * @param {Grid} grid the grid on which we are acting
1732 * @param {string} id the id we'd like to remove from the menu
1733 *
1734 */
1735 grid.api.registerMethod( 'core', 'removeFromGridMenu', service.removeFromGridMenu );
1736 },
1737
1738
1739 /**
1740 * @ngdoc function
1741 * @name addToGridMenu
1742 * @propertyOf ui.grid.uiGridGridMenuService
1743 * @description add items to the grid menu. Used by features
1744 * to add their menu items if they are enabled, can also be used by
1745 * end users to add menu items. This method has the advantage of allowing
1746 * remove again, which can simplify management of which items are included
1747 * in the menu when. (Noting that in most cases the shown and active functions
1748 * provide a better way to handle visibility of menu items)
1749 * @param {Grid} grid the grid on which we are acting
1750 * @param {array} menuItems menu items in the format as described in the tutorial, with
1751 * the added note that if you want to use remove you must also specify an `id` field,
1752 * which is provided when you want to remove an item. The id should be unique.
1753 *
1754 */
1755 addToGridMenu: function( grid, menuItems ) {
1756 if ( !angular.isArray( menuItems ) ) {
1757 gridUtil.logError( 'addToGridMenu: menuItems must be an array, and is not, not adding any items');
1758 } else {
1759 if ( grid.gridMenuScope ) {
1760 grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems ? grid.gridMenuScope.registeredMenuItems : [];
1761 grid.gridMenuScope.registeredMenuItems = grid.gridMenuScope.registeredMenuItems.concat( menuItems );
1762 } else {
1763 gridUtil.logError( 'Asked to addToGridMenu, but gridMenuScope not present. Timing issue? Please log issue with ui-grid');
1764 }
1765 }
1766 },
1767
1768
1769 /**
1770 * @ngdoc function
1771 * @name removeFromGridMenu
1772 * @methodOf ui.grid.uiGridGridMenuService
1773 * @description Remove an item from the grid menu based on a provided id. Assumes
1774 * that the id is unique, removes only the last instance of that id. Does nothing if
1775 * the specified id is not found. If there is no gridMenuScope or registeredMenuItems
1776 * then do nothing silently - the desired result is those menu items not be present and they
1777 * aren't.
1778 * @param {Grid} grid the grid on which we are acting
1779 * @param {string} id the id we'd like to remove from the menu
1780 *
1781 */
1782 removeFromGridMenu: function( grid, id ) {
1783 var foundIndex = -1;
1784
1785 if ( grid && grid.gridMenuScope ) {
1786 grid.gridMenuScope.registeredMenuItems.forEach( function( value, index ) {
1787 if ( value.id === id ) {
1788 if (foundIndex > -1) {
1789 gridUtil.logError( 'removeFromGridMenu: found multiple items with the same id, removing only the last' );
1790 } else {
1791
1792 foundIndex = index;
1793 }
1794 }
1795 });
1796 }
1797
1798 if ( foundIndex > -1 ) {
1799 grid.gridMenuScope.registeredMenuItems.splice( foundIndex, 1 );
1800 }
1801 },
1802
1803
1804 /**
1805 * @ngdoc array
1806 * @name gridMenuCustomItems
1807 * @propertyOf ui.grid.class:GridOptions
1808 * @description (optional) An array of menu items that should be added to
1809 * the gridMenu. Follow the format documented in the tutorial for column
1810 * menu customisation. The context provided to the action function will
1811 * include context.grid. An alternative if working with dynamic menus is to use the
1812 * provided api - core.addToGridMenu and core.removeFromGridMenu, which handles
1813 * some of the management of items for you.
1814 *
1815 */
1816 /**
1817 * @ngdoc boolean
1818 * @name gridMenuShowHideColumns
1819 * @propertyOf ui.grid.class:GridOptions
1820 * @description true by default, whether the grid menu should allow hide/show
1821 * of columns
1822 *
1823 */
1824 /**
1825 * @ngdoc method
1826 * @methodOf ui.grid.uiGridGridMenuService
1827 * @name getMenuItems
1828 * @description Decides the menu items to show in the menu. This is a
1829 * combination of:
1830 *
1831 * - the default menu items that are always included,
1832 * - any menu items that have been provided through the addMenuItem api. These
1833 * are typically added by features within the grid
1834 * - any menu items included in grid.options.gridMenuCustomItems. These can be
1835 * changed dynamically, as they're always recalculated whenever we show the
1836 * menu
1837 * @param {$scope} $scope the scope of this gridMenu, from which we can find all
1838 * the information that we need
1839 * @returns {Array} an array of menu items that can be shown
1840 */
1841 getMenuItems: function( $scope ) {
1842 var menuItems = [
1843 // this is where we add any menu items we want to always include
1844 ];
1845
1846 if ( $scope.grid.options.gridMenuCustomItems ) {
1847 if ( !angular.isArray( $scope.grid.options.gridMenuCustomItems ) ) {
1848 gridUtil.logError( 'gridOptions.gridMenuCustomItems must be an array, and is not');
1849 } else {
1850 menuItems = menuItems.concat( $scope.grid.options.gridMenuCustomItems );
1851 }
1852 }
1853
1854 var clearFilters = [{
1855 title: i18nService.getSafeText('gridMenu.clearAllFilters'),
1856 action: function ($event) {
1857 $scope.grid.clearAllFilters();
1858 },
1859 shown: function() {
1860 return $scope.grid.options.enableFiltering;
1861 },
1862 order: 100
1863 }];
1864 menuItems = menuItems.concat( clearFilters );
1865
1866 menuItems = menuItems.concat( $scope.registeredMenuItems );
1867
1868 if ( $scope.grid.options.gridMenuShowHideColumns !== false ) {
1869 menuItems = menuItems.concat( service.showHideColumns( $scope ) );
1870 }
1871
1872 menuItems.sort(function(a, b) {
1873 return a.order - b.order;
1874 });
1875
1876 return menuItems;
1877 },
1878
1879
1880 /**
1881 * @ngdoc array
1882 * @name gridMenuTitleFilter
1883 * @propertyOf ui.grid.class:GridOptions
1884 * @description (optional) A function that takes a title string
1885 * (usually the col.displayName), and converts it into a display value. The function
1886 * must return either a string or a promise.
1887 *
1888 * Used for internationalization of the grid menu column names - for angular-translate
1889 * you can pass $translate as the function, for i18nService you can pass getSafeText as the
1890 * function
1891 * @example
1892 * <pre>
1893 * gridOptions = {
1894 * gridMenuTitleFilter: $translate
1895 * }
1896 * </pre>
1897 */
1898 /**
1899 * @ngdoc method
1900 * @methodOf ui.grid.uiGridGridMenuService
1901 * @name showHideColumns
1902 * @description Adds two menu items for each of the columns in columnDefs. One
1903 * menu item for hide, one menu item for show. Each is visible when appropriate
1904 * (show when column is not visible, hide when column is visible). Each toggles
1905 * the visible property on the columnDef using toggleColumnVisibility
1906 * @param {$scope} $scope of a gridMenu, which contains a reference to the grid
1907 */
1908 showHideColumns: function( $scope ) {
1909 var showHideColumns = [];
1910 if ( !$scope.grid.options.columnDefs || $scope.grid.options.columnDefs.length === 0 || $scope.grid.columns.length === 0 ) {
1911 return showHideColumns;
1912 }
1913
1914 function isColumnVisible(colDef) {
1915 return colDef.visible === true || colDef.visible === undefined;
1916 }
1917
1918 function getColumnIcon(colDef) {
1919 return isColumnVisible(colDef) ? 'ui-grid-icon-ok' : 'ui-grid-icon-cancel';
1920 }
1921
1922 // add header for columns
1923 showHideColumns.push({
1924 title: i18nService.getSafeText('gridMenu.columns'),
1925 order: 300,
1926 templateUrl: 'ui-grid/ui-grid-menu-header-item'
1927 });
1928
1929 $scope.grid.options.gridMenuTitleFilter = $scope.grid.options.gridMenuTitleFilter ? $scope.grid.options.gridMenuTitleFilter : function( title ) { return title; };
1930
1931 $scope.grid.options.columnDefs.forEach( function( colDef, index ) {
1932 if ( colDef.enableHiding !== false ) {
1933 // add hide menu item - shows an OK icon as we only show when column is already visible
1934 var menuItem = {
1935 icon: getColumnIcon(colDef),
1936 action: function($event) {
1937 $event.stopPropagation();
1938
1939 service.toggleColumnVisibility( this.context.gridCol );
1940
1941 if ($event.target && $event.target.firstChild) {
1942 if (angular.element($event.target)[0].nodeName === 'I') {
1943 $event.target.className = getColumnIcon(this.context.gridCol.colDef);
1944 }
1945 else {
1946 $event.target.firstChild.className = getColumnIcon(this.context.gridCol.colDef);
1947 }
1948 }
1949 },
1950 shown: function() {
1951 return this.context.gridCol.colDef.enableHiding !== false;
1952 },
1953 context: { gridCol: $scope.grid.getColumn(colDef.name || colDef.field) },
1954 leaveOpen: true,
1955 order: 301 + index
1956 };
1957 service.setMenuItemTitle( menuItem, colDef, $scope.grid );
1958 showHideColumns.push( menuItem );
1959 }
1960 });
1961 return showHideColumns;
1962 },
1963
1964
1965 /**
1966 * @ngdoc method
1967 * @methodOf ui.grid.uiGridGridMenuService
1968 * @name setMenuItemTitle
1969 * @description Handles the response from gridMenuTitleFilter, adding it directly to the menu
1970 * item if it returns a string, otherwise waiting for the promise to resolve or reject then
1971 * putting the result into the title
1972 * @param {object} menuItem the menuItem we want to put the title on
1973 * @param {object} colDef the colDef from which we can get displayName, name or field
1974 * @param {Grid} grid the grid, from which we can get the options.gridMenuTitleFilter
1975 *
1976 */
1977 setMenuItemTitle: function( menuItem, colDef, grid ) {
1978 var title = grid.options.gridMenuTitleFilter( colDef.displayName || gridUtil.readableColumnName(colDef.name) || colDef.field );
1979
1980 if ( typeof(title) === 'string' ) {
1981 menuItem.title = title;
1982 } else if ( title.then ) {
1983 // must be a promise
1984 menuItem.title = "";
1985 title.then( function( successValue ) {
1986 menuItem.title = successValue;
1987 }, function( errorValue ) {
1988 menuItem.title = errorValue;
1989 }).catch(angular.noop);
1990 } else {
1991 gridUtil.logError('Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config');
1992 menuItem.title = 'badconfig';
1993 }
1994 },
1995
1996 /**
1997 * @ngdoc method
1998 * @methodOf ui.grid.uiGridGridMenuService
1999 * @name toggleColumnVisibility
2000 * @description Toggles the visibility of an individual column. Expects to be
2001 * provided a context that has on it a gridColumn, which is the column that
2002 * we'll operate upon. We change the visibility, and refresh the grid as appropriate
2003 * @param {GridColumn} gridCol the column that we want to toggle
2004 *
2005 */
2006 toggleColumnVisibility: function( gridCol ) {
2007 gridCol.colDef.visible = !( gridCol.colDef.visible === true || gridCol.colDef.visible === undefined );
2008
2009 gridCol.grid.refresh();
2010 gridCol.grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
2011 gridCol.grid.api.core.raise.columnVisibilityChanged( gridCol );
2012 }
2013 };
2014
2015 return service;
2016 }])
2017
2018 .directive('uiGridMenuButton', ['gridUtil', 'uiGridConstants', 'uiGridGridMenuService', 'i18nService',
2019 function (gridUtil, uiGridConstants, uiGridGridMenuService, i18nService) {
2020
2021 return {
2022 priority: 0,
2023 scope: true,
2024 require: ['^uiGrid'],
2025 templateUrl: 'ui-grid/ui-grid-menu-button',
2026 replace: true,
2027
2028 link: function ($scope, $elm, $attrs, controllers) {
2029 var uiGridCtrl = controllers[0];
2030
2031 // For the aria label
2032 $scope.i18n = {
2033 aria: i18nService.getSafeText('gridMenu.aria')
2034 };
2035
2036 uiGridGridMenuService.initialize($scope, uiGridCtrl.grid);
2037
2038 $scope.shown = false;
2039
2040 $scope.toggleMenu = function () {
2041 if ( $scope.shown ) {
2042 $scope.$broadcast('hide-menu');
2043 $scope.shown = false;
2044 } else {
2045 $scope.menuItems = uiGridGridMenuService.getMenuItems( $scope );
2046 $scope.$broadcast('show-menu');
2047 $scope.shown = true;
2048 }
2049 };
2050
2051 $scope.$on('menu-hidden', function() {
2052 $scope.shown = false;
2053 gridUtil.focus.bySelector($elm, '.ui-grid-icon-container');
2054 });
2055 }
2056 };
2057 }]);
2058 })();
2059
2060 (function() {
2061
2062 /**
2063 * @ngdoc directive
2064 * @name ui.grid.directive:uiGridMenu
2065 * @element style
2066 * @restrict A
2067 *
2068 * @description
2069 * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.
2070 *
2071 * @example
2072 <doc:example module="app">
2073 <doc:source>
2074 <script>
2075 var app = angular.module('app', ['ui.grid']);
2076
2077 app.controller('MainCtrl', ['$scope', function ($scope) {
2078
2079 }]);
2080 </script>
2081
2082 <div ng-controller="MainCtrl">
2083 <div ui-grid-menu shown="true" ></div>
2084 </div>
2085 </doc:source>
2086 <doc:scenario>
2087 </doc:scenario>
2088 </doc:example>
2089 */
2090 angular.module('ui.grid')
2091
2092 .directive('uiGridMenu', ['$compile', '$timeout', '$window', '$document', 'gridUtil', 'uiGridConstants', 'i18nService',
2093 function ($compile, $timeout, $window, $document, gridUtil, uiGridConstants, i18nService) {
2094 return {
2095 priority: 0,
2096 scope: {
2097 // shown: '&',
2098 menuItems: '=',
2099 autoHide: '=?'
2100 },
2101 require: '?^uiGrid',
2102 templateUrl: 'ui-grid/uiGridMenu',
2103 replace: false,
2104 link: function ($scope, $elm, $attrs, uiGridCtrl) {
2105 $scope.dynamicStyles = '';
2106 if (uiGridCtrl && uiGridCtrl.grid && uiGridCtrl.grid.options && uiGridCtrl.grid.options.gridMenuTemplate) {
2107 var gridMenuTemplate = uiGridCtrl.grid.options.gridMenuTemplate;
2108 gridUtil.getTemplate(gridMenuTemplate).then(function (contents) {
2109 var template = angular.element(contents);
2110 var newElm = $compile(template)($scope);
2111 $elm.replaceWith(newElm);
2112 }).catch(angular.noop);
2113 }
2114
2115 var setupHeightStyle = function(gridHeight) {
2116 // menu appears under header row, so substract that height from it's total
2117 // additional 20px for general padding
2118 var gridMenuMaxHeight = gridHeight - uiGridCtrl.grid.headerHeight - 20;
2119 $scope.dynamicStyles = [
2120 '.grid' + uiGridCtrl.grid.id + ' .ui-grid-menu-mid {',
2121 'max-height: ' + gridMenuMaxHeight + 'px;',
2122 '}'
2123 ].join(' ');
2124 };
2125
2126 if (uiGridCtrl) {
2127 setupHeightStyle(uiGridCtrl.grid.gridHeight);
2128 uiGridCtrl.grid.api.core.on.gridDimensionChanged($scope, function(oldGridHeight, oldGridWidth, newGridHeight, newGridWidth) {
2129 setupHeightStyle(newGridHeight);
2130 });
2131 }
2132
2133 $scope.i18n = {
2134 close: i18nService.getSafeText('columnMenu.close')
2135 };
2136
2137 // *** Show/Hide functions ******
2138 $scope.showMenu = function(event, args) {
2139 if ( !$scope.shown ) {
2140
2141 /*
2142 * In order to animate cleanly we remove the ng-if, wait a digest cycle, then
2143 * animate the removal of the ng-hide. We can't successfully (so far as I can tell)
2144 * animate removal of the ng-if, as the menu items aren't there yet. And we don't want
2145 * to rely on ng-show only, as that leaves elements in the DOM that are needlessly evaluated
2146 * on scroll events.
2147 *
2148 * Note when testing animation that animations don't run on the tutorials. When debugging it looks
2149 * like they do, but angular has a default $animate provider that is just a stub, and that's what's
2150 * being called. ALso don't be fooled by the fact that your browser has actually loaded the
2151 * angular-translate.js, it's not using it. You need to test animations in an external application.
2152 */
2153 $scope.shown = true;
2154
2155 // Must be a timeout in order to work properly in Firefox. Issue #6533
2156 $timeout(function() {
2157 $scope.shownMid = true;
2158 $scope.$emit('menu-shown');
2159 });
2160 } else if ( !$scope.shownMid ) {
2161 // we're probably doing a hide then show, so we don't need to wait for ng-if
2162 $scope.shownMid = true;
2163 $scope.$emit('menu-shown');
2164 }
2165
2166 var docEventType = 'click';
2167 if (args && args.originalEvent && args.originalEvent.type && args.originalEvent.type === 'touchstart') {
2168 docEventType = args.originalEvent.type;
2169 }
2170
2171 // Turn off an existing document click handler
2172 angular.element(document).off('click touchstart', applyHideMenu);
2173 $elm.off('keyup', checkKeyUp);
2174 $elm.off('keydown', checkKeyDown);
2175
2176 // Turn on the document click handler, but in a timeout so it doesn't apply to THIS click if there is one
2177 $timeout(function() {
2178 angular.element(document).on(docEventType, applyHideMenu);
2179 $elm.on('keyup', checkKeyUp);
2180 $elm.on('keydown', checkKeyDown);
2181 });
2182 };
2183
2184
2185 $scope.hideMenu = function(event) {
2186 if ( $scope.shown ) {
2187 /*
2188 * In order to animate cleanly we animate the addition of ng-hide, then use a $timeout to
2189 * set the ng-if (shown = false) after the animation runs. In theory we can cascade off the
2190 * callback on the addClass method, but it is very unreliable with unit tests for no discernable reason.
2191 *
2192 * The user may have clicked on the menu again whilst
2193 * we're waiting, so we check that the mid isn't shown before applying the ng-if.
2194 */
2195 $scope.shownMid = false;
2196 $timeout( function() {
2197 if ( !$scope.shownMid ) {
2198 $scope.shown = false;
2199 $scope.$emit('menu-hidden');
2200 }
2201 }, 40);
2202 }
2203
2204 angular.element(document).off('click touchstart', applyHideMenu);
2205 $elm.off('keyup', checkKeyUp);
2206 $elm.off('keydown', checkKeyDown);
2207 };
2208
2209 $scope.$on('hide-menu', function (event, args) {
2210 $scope.hideMenu(event, args);
2211 });
2212
2213 $scope.$on('show-menu', function (event, args) {
2214 $scope.showMenu(event, args);
2215 });
2216
2217
2218 // *** Auto hide when click elsewhere ******
2219 var applyHideMenu = function() {
2220 if ($scope.shown) {
2221 $scope.$apply(function () {
2222 $scope.hideMenu();
2223 });
2224 }
2225 };
2226
2227 // close menu on ESC and keep tab cyclical
2228 var checkKeyUp = function(event) {
2229 if (event.keyCode === 27) {
2230 $scope.hideMenu();
2231 }
2232 };
2233
2234 var checkKeyDown = function(event) {
2235 var setFocus = function(elm) {
2236 elm.focus();
2237 event.preventDefault();
2238 return false;
2239 };
2240 if (event.keyCode === 9) {
2241 var firstMenuItem, lastMenuItem;
2242 var menuItemButtons = $elm[0].querySelectorAll('button:not(.ng-hide)');
2243 if (menuItemButtons.length > 0) {
2244 firstMenuItem = menuItemButtons[0];
2245 lastMenuItem = menuItemButtons[menuItemButtons.length - 1];
2246 if (event.target === lastMenuItem && !event.shiftKey) {
2247 setFocus(firstMenuItem);
2248 } else if (event.target === firstMenuItem && event.shiftKey) {
2249 setFocus(lastMenuItem);
2250 }
2251 }
2252 }
2253 };
2254
2255 if (typeof($scope.autoHide) === 'undefined' || $scope.autoHide === undefined) {
2256 $scope.autoHide = true;
2257 }
2258
2259 if ($scope.autoHide) {
2260 angular.element($window).on('resize', applyHideMenu);
2261 }
2262
2263 $scope.$on('$destroy', function unbindEvents() {
2264 angular.element($window).off('resize', applyHideMenu);
2265 angular.element(document).off('click touchstart', applyHideMenu);
2266 $elm.off('keyup', checkKeyUp);
2267 $elm.off('keydown', checkKeyDown);
2268 });
2269
2270 if (uiGridCtrl) {
2271 $scope.$on('$destroy', uiGridCtrl.grid.api.core.on.scrollBegin($scope, applyHideMenu ));
2272 }
2273
2274 $scope.$on('$destroy', $scope.$on(uiGridConstants.events.ITEM_DRAGGING, applyHideMenu ));
2275 }
2276 };
2277 }])
2278
2279 .directive('uiGridMenuItem', ['gridUtil', '$compile', 'i18nService', function (gridUtil, $compile, i18nService) {
2280 return {
2281 priority: 0,
2282 scope: {
2283 name: '=',
2284 active: '=',
2285 action: '=',
2286 icon: '=',
2287 shown: '=',
2288 context: '=',
2289 templateUrl: '=',
2290 leaveOpen: '=',
2291 screenReaderOnly: '='
2292 },
2293 require: ['?^uiGrid'],
2294 templateUrl: 'ui-grid/uiGridMenuItem',
2295 replace: false,
2296 compile: function() {
2297 return {
2298 pre: function ($scope, $elm) {
2299 if ($scope.templateUrl) {
2300 gridUtil.getTemplate($scope.templateUrl)
2301 .then(function (contents) {
2302 var template = angular.element(contents);
2303
2304 var newElm = $compile(template)($scope);
2305 $elm.replaceWith(newElm);
2306 }).catch(angular.noop);
2307 }
2308 },
2309 post: function ($scope, $elm, $attrs, controllers) {
2310 var uiGridCtrl = controllers[0];
2311
2312 // TODO(c0bra): validate that shown and active are functions if they're defined. An exception is already thrown above this though
2313 // if (typeof($scope.shown) !== 'undefined' && $scope.shown && typeof($scope.shown) !== 'function') {
2314 // throw new TypeError("$scope.shown is defined but not a function");
2315 // }
2316 if (typeof($scope.shown) === 'undefined' || $scope.shown === null) {
2317 $scope.shown = function() { return true; };
2318 }
2319
2320 $scope.itemShown = function () {
2321 var context = {};
2322 if ($scope.context) {
2323 context.context = $scope.context;
2324 }
2325
2326 if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
2327 context.grid = uiGridCtrl.grid;
2328 }
2329
2330 return $scope.shown.call(context);
2331 };
2332
2333 $scope.itemAction = function($event, title) {
2334 $event.stopPropagation();
2335
2336 if (typeof($scope.action) === 'function') {
2337 var context = {};
2338
2339 if ($scope.context) {
2340 context.context = $scope.context;
2341 }
2342
2343 // Add the grid to the function call context if the uiGrid controller is present
2344 if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
2345 context.grid = uiGridCtrl.grid;
2346 }
2347
2348 $scope.action.call(context, $event, title);
2349
2350 if ( !$scope.leaveOpen ) {
2351 $scope.$emit('hide-menu');
2352 } else {
2353 // Maintain focus on the selected item
2354 var correctParent = $event.target.parentElement;
2355
2356 // nodeName of 'I' means target is i element, need the next parent
2357 if (angular.element($event.target)[0].nodeName === 'I') {
2358 correctParent = correctParent.parentElement;
2359 }
2360
2361 gridUtil.focus.bySelector(correctParent, 'button[type=button]', true);
2362 }
2363 }
2364 };
2365
2366 $scope.label = function() {
2367 var toBeDisplayed = $scope.name;
2368
2369 if (typeof($scope.name) === 'function') {
2370 toBeDisplayed = $scope.name.call();
2371 }
2372
2373 return toBeDisplayed;
2374 };
2375
2376 $scope.i18n = i18nService.get();
2377 }
2378 };
2379 }
2380 };
2381 }]);
2382
2383 })();
2384
2385 (function() {
2386 'use strict';
2387 /**
2388 * @ngdoc overview
2389 * @name ui.grid.directive:uiGridOneBind
2390 * @summary A group of directives that provide a one time bind to a dom element.
2391 * @description A group of directives that provide a one time bind to a dom element.
2392 * As one time bindings are not supported in Angular 1.2.* this directive provdes this capability.
2393 * This is done to reduce the number of watchers on the dom.
2394 * <br/>
2395 * <h2>Short Example ({@link ui.grid.directive:uiGridOneBindSrc ui-grid-one-bind-src})</h2>
2396 * <pre>
2397 <div ng-init="imageName = 'myImageDir.jpg'">
2398 <img ui-grid-one-bind-src="imageName"></img>
2399 </div>
2400 </pre>
2401 * Will become:
2402 * <pre>
2403 <div ng-init="imageName = 'myImageDir.jpg'">
2404 <img ui-grid-one-bind-src="imageName" src="myImageDir.jpg"></img>
2405 </div>
2406 </pre>
2407 </br>
2408 <h2>Short Example ({@link ui.grid.directive:uiGridOneBindText ui-grid-one-bind-text})</h2>
2409 * <pre>
2410 <div ng-init="text='Add this text'" ui-grid-one-bind-text="text"></div>
2411 </pre>
2412 * Will become:
2413 * <pre>
2414 <div ng-init="text='Add this text'" ui-grid-one-bind-text="text">Add this text</div>
2415 </pre>
2416 </br>
2417 * <b>Note:</b> This behavior is slightly different for the {@link ui.grid.directive:uiGridOneBindIdGrid uiGridOneBindIdGrid}
2418 * and {@link ui.grid.directive:uiGridOneBindAriaLabelledbyGrid uiGridOneBindAriaLabelledbyGrid} directives.
2419 *
2420 */
2421 // https://github.com/joshkurz/Black-Belt-AngularJS-Directives/blob/master/directives/Optimization/oneBind.js
2422 var oneBinders = angular.module('ui.grid');
2423 angular.forEach([
2424 /**
2425 * @ngdoc directive
2426 * @name ui.grid.directive:uiGridOneBindSrc
2427 * @memberof ui.grid.directive:uiGridOneBind
2428 * @element img
2429 * @restrict A
2430 * @param {String} uiGridOneBindSrc The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2431 * @description One time binding for the src dom tag.
2432 *
2433 */
2434 {tag: 'Src', method: 'attr'},
2435 /**
2436 * @ngdoc directive
2437 * @name ui.grid.directive:uiGridOneBindText
2438 * @element div
2439 * @restrict A
2440 * @param {String} uiGridOneBindText The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2441 * @description One time binding for the text dom tag.
2442 */
2443 {tag: 'Text', method: 'text'},
2444 /**
2445 * @ngdoc directive
2446 * @name ui.grid.directive:uiGridOneBindHref
2447 * @element div
2448 * @restrict A
2449 * @param {String} uiGridOneBindHref The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2450 * @description One time binding for the href dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2451 */
2452 {tag: 'Href', method: 'attr'},
2453 /**
2454 * @ngdoc directive
2455 * @name ui.grid.directive:uiGridOneBindClass
2456 * @element div
2457 * @restrict A
2458 * @param {String} uiGridOneBindClass The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2459 * @param {Object} uiGridOneBindClass The object that you want to bind. At least one of the values in the object must be something other than null or undefined for the watcher to be removed.
2460 * this is to prevent the watcher from being removed before the scope is initialized.
2461 * @param {Array} uiGridOneBindClass An array of classes to bind to this element.
2462 * @description One time binding for the class dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2463 */
2464 {tag: 'Class', method: 'addClass'},
2465 /**
2466 * @ngdoc directive
2467 * @name ui.grid.directive:uiGridOneBindHtml
2468 * @element div
2469 * @restrict A
2470 * @param {String} uiGridOneBindHtml The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2471 * @description One time binding for the html method on a dom element. For more information see {@link ui.grid.directive:uiGridOneBind}.
2472 */
2473 {tag: 'Html', method: 'html'},
2474 /**
2475 * @ngdoc directive
2476 * @name ui.grid.directive:uiGridOneBindAlt
2477 * @element div
2478 * @restrict A
2479 * @param {String} uiGridOneBindAlt The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2480 * @description One time binding for the alt dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2481 */
2482 {tag: 'Alt', method: 'attr'},
2483 /**
2484 * @ngdoc directive
2485 * @name ui.grid.directive:uiGridOneBindStyle
2486 * @element div
2487 * @restrict A
2488 * @param {String} uiGridOneBindStyle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2489 * @description One time binding for the style dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2490 */
2491 {tag: 'Style', method: 'css'},
2492 /**
2493 * @ngdoc directive
2494 * @name ui.grid.directive:uiGridOneBindValue
2495 * @element div
2496 * @restrict A
2497 * @param {String} uiGridOneBindValue The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2498 * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2499 */
2500 {tag: 'Value', method: 'attr'},
2501 /**
2502 * @ngdoc directive
2503 * @name ui.grid.directive:uiGridOneBindId
2504 * @element div
2505 * @restrict A
2506 * @param {String} uiGridOneBindId The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2507 * @description One time binding for the value dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2508 */
2509 {tag: 'Id', method: 'attr'},
2510 /**
2511 * @ngdoc directive
2512 * @name ui.grid.directive:uiGridOneBindIdGrid
2513 * @element div
2514 * @restrict A
2515 * @param {String} uiGridOneBindIdGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2516 * @description One time binding for the id dom tag.
2517 * <h1>Important Note!</h1>
2518 * If the id tag passed as a parameter does <b>not</b> contain the grid id as a substring
2519 * then the directive will search the scope and the parent controller (if it is a uiGridController) for the grid.id value.
2520 * If this value is found then it is appended to the begining of the id tag. If the grid is not found then the directive throws an error.
2521 * This is done in order to ensure uniqueness of id tags across the grid.
2522 * This is to prevent two grids in the same document having duplicate id tags.
2523 */
2524 {tag: 'Id', directiveName: 'IdGrid', method: 'attr', appendGridId: true},
2525 /**
2526 * @ngdoc directive
2527 * @name ui.grid.directive:uiGridOneBindTitle
2528 * @element div
2529 * @restrict A
2530 * @param {String} uiGridOneBindTitle The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2531 * @description One time binding for the title dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2532 */
2533 {tag: 'Title', method: 'attr'},
2534 /**
2535 * @ngdoc directive
2536 * @name ui.grid.directive:uiGridOneBindAriaLabel
2537 * @element div
2538 * @restrict A
2539 * @param {String} uiGridOneBindAriaLabel The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2540 * @description One time binding for the aria-label dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2541 *<br/>
2542 * <pre>
2543 <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text"></div>
2544 </pre>
2545 * Will become:
2546 * <pre>
2547 <div ng-init="text='Add this text'" ui-grid-one-bind-aria-label="text" aria-label="Add this text"></div>
2548 </pre>
2549 */
2550 {tag: 'Label', method: 'attr', aria: true},
2551 /**
2552 * @ngdoc directive
2553 * @name ui.grid.directive:uiGridOneBindAriaLabelledby
2554 * @element div
2555 * @restrict A
2556 * @param {String} uiGridOneBindAriaLabelledby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2557 * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2558 *<br/>
2559 * <pre>
2560 <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId"></div>
2561 </pre>
2562 * Will become:
2563 * <pre>
2564 <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby="anId" aria-labelledby="gridID32"></div>
2565 </pre>
2566 */
2567 {tag: 'Labelledby', method: 'attr', aria: true},
2568 /**
2569 * @ngdoc directive
2570 * @name ui.grid.directive:uiGridOneBindAriaLabelledbyGrid
2571 * @element div
2572 * @restrict A
2573 * @param {String} uiGridOneBindAriaLabelledbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2574 * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2575 * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the
2576 * grid id to each one.
2577 *<br/>
2578 * <pre>
2579 <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId"></div>
2580 </pre>
2581 * Will become ([grid.id] will be replaced by the actual grid id):
2582 * <pre>
2583 <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-labelledby-grid="anId" aria-labelledby-Grid="[grid.id]-gridID32"></div>
2584 </pre>
2585 */
2586 {tag: 'Labelledby', directiveName: 'LabelledbyGrid', appendGridId: true, method: 'attr', aria: true},
2587 /**
2588 * @ngdoc directive
2589 * @name ui.grid.directive:uiGridOneBindAriaDescribedby
2590 * @element ANY
2591 * @restrict A
2592 * @param {String} uiGridOneBindAriaDescribedby The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2593 * @description One time binding for the aria-describedby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2594 *<br/>
2595 * <pre>
2596 <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby="anId"></div>
2597 </pre>
2598 * Will become:
2599 * <pre>
2600 <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby="anId" aria-describedby="gridID32"></div>
2601 </pre>
2602 */
2603 {tag: 'Describedby', method: 'attr', aria: true},
2604 /**
2605 * @ngdoc directive
2606 * @name ui.grid.directive:uiGridOneBindAriaDescribedbyGrid
2607 * @element ANY
2608 * @restrict A
2609 * @param {String} uiGridOneBindAriaDescribedbyGrid The angular string you want to bind. Does not support interpolation. Don't use <code>{{scopeElt}}</code> instead use <code>scopeElt</code>.
2610 * @description One time binding for the aria-labelledby dom tag. For more information see {@link ui.grid.directive:uiGridOneBind}.
2611 * Works somewhat like {@link ui.grid.directive:uiGridOneBindIdGrid} however this one supports a list of ids (seperated by a space) and will dynamically add the
2612 * grid id to each one.
2613 *<br/>
2614 * <pre>
2615 <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby-grid="anId"></div>
2616 </pre>
2617 * Will become ([grid.id] will be replaced by the actual grid id):
2618 * <pre>
2619 <div ng-init="anId = 'gridID32'" ui-grid-one-bind-aria-describedby-grid="anId" aria-describedby="[grid.id]-gridID32"></div>
2620 </pre>
2621 */
2622 {tag: 'Describedby', directiveName: 'DescribedbyGrid', appendGridId: true, method: 'attr', aria: true}],
2623 function(v) {
2624
2625 var baseDirectiveName = 'uiGridOneBind';
2626 // If it is an aria tag then append the aria label seperately
2627 // This is done because the aria tags are formatted aria-* and the directive name can't have a '-' character in it.
2628 // If the diretiveName has to be overridden then it does so here. This is because the tag being modified and the directive sometimes don't
2629 // match up.
2630 var directiveName = (v.aria ? baseDirectiveName + 'Aria' : baseDirectiveName) + (v.directiveName ? v.directiveName : v.tag);
2631 oneBinders.directive(directiveName, ['gridUtil', function(gridUtil) {
2632 return {
2633 restrict: 'A',
2634 require: ['?uiGrid','?^uiGrid'],
2635 link: function(scope, iElement, iAttrs, controllers) {
2636 /* Appends the grid id to the beginning of the value. */
2637 var appendGridId = function(val) {
2638 var grid; // Get an instance of the grid if its available
2639
2640 // If its available in the scope then we don't need to try to find it elsewhere
2641 if (scope.grid) {
2642 grid = scope.grid;
2643 }
2644
2645 // Another possible location to try to find the grid
2646 else if (scope.col && scope.col.grid) {
2647 grid = scope.col.grid;
2648 }
2649
2650 // Last ditch effort: Search through the provided controllers.
2651 else if (!controllers.some( // Go through the controllers till one has the element we need
2652 function(controller) {
2653 if (controller && controller.grid) {
2654 grid = controller.grid;
2655 return true; // We've found the grid
2656 }
2657 })) {
2658 // We tried our best to find it for you
2659 gridUtil.logError("["+directiveName+"] A valid grid could not be found to bind id. Are you using this directive " +
2660 "within the correct scope? Trying to generate id: [gridID]-" + val);
2661 throw new Error("No valid grid could be found");
2662 }
2663
2664 if (grid) {
2665 var idRegex = new RegExp(grid.id.toString());
2666
2667 // If the grid id hasn't been appended already in the template declaration
2668 if (!idRegex.test(val)) {
2669 val = grid.id.toString() + '-' + val;
2670 }
2671 }
2672 return val;
2673 };
2674
2675 // The watch returns a function to remove itself.
2676 var rmWatcher = scope.$watch(iAttrs[directiveName], function(newV) {
2677 if (newV) {
2678 // If we are trying to add an id element then we also apply the grid id if it isn't already there
2679 if (v.appendGridId) {
2680 var newIdString = null;
2681
2682 // Append the id to all of the new ids.
2683 angular.forEach( newV.split(' '), function(s) {
2684 newIdString = (newIdString ? (newIdString + ' ') : '') + appendGridId(s);
2685 });
2686 newV = newIdString;
2687 }
2688
2689 // Append this newValue to the dom element.
2690 switch (v.method) {
2691 case 'attr': // The attr method takes two paraams the tag and the value
2692 if (v.aria) {
2693 // If it is an aria element then append the aria prefix
2694 iElement[v.method]('aria-' + v.tag.toLowerCase(),newV);
2695 } else {
2696 iElement[v.method](v.tag.toLowerCase(),newV);
2697 }
2698 break;
2699 case 'addClass':
2700 // Pulled from https://github.com/Pasvaz/bindonce/blob/master/bindonce.js
2701 if (angular.isObject(newV) && !angular.isArray(newV)) {
2702 var results = [],
2703 nonNullFound = false; // We don't want to remove the binding unless the key is actually defined
2704
2705 angular.forEach(newV, function (value, index) {
2706 if (value !== null && typeof(value) !== "undefined") {
2707 nonNullFound = true; // A non null value for a key was found so the object must have been initialized
2708 if (value) {results.push(index);}
2709 }
2710 });
2711 // A non null value for a key wasn't found so assume that the scope values haven't been fully initialized
2712 if (!nonNullFound) {
2713 return; // If not initialized then the watcher should not be removed yet.
2714 }
2715 newV = results;
2716 }
2717
2718 if (newV) {
2719 iElement.addClass(angular.isArray(newV) ? newV.join(' ') : newV);
2720 } else {
2721 return;
2722 }
2723 break;
2724 default:
2725 iElement[v.method](newV);
2726 break;
2727 }
2728
2729 // Removes the watcher on itself after the bind
2730 rmWatcher();
2731 }
2732 // True ensures that equality is determined using angular.equals instead of ===
2733 }, true); // End rm watchers
2734 } // End compile function
2735 }; // End directive return
2736 } // End directive function
2737 ]); // End directive
2738 }); // End angular foreach
2739 })();
2740
2741 (function() {
2742 'use strict';
2743
2744 var module = angular.module('ui.grid');
2745
2746 module.directive('uiGridRenderContainer', ['$timeout', '$document', 'uiGridConstants', 'gridUtil', 'ScrollEvent',
2747 function($timeout, $document, uiGridConstants, gridUtil, ScrollEvent) {
2748 return {
2749 replace: true,
2750 transclude: true,
2751 templateUrl: 'ui-grid/uiGridRenderContainer',
2752 require: ['^uiGrid', 'uiGridRenderContainer'],
2753 scope: {
2754 containerId: '=',
2755 rowContainerName: '=',
2756 colContainerName: '=',
2757 bindScrollHorizontal: '=',
2758 bindScrollVertical: '=',
2759 enableVerticalScrollbar: '=',
2760 enableHorizontalScrollbar: '='
2761 },
2762 controller: 'uiGridRenderContainer as RenderContainer',
2763 compile: function() {
2764 return {
2765 pre: function prelink($scope, $elm, $attrs, controllers) {
2766 var rowContainer, colContainer,
2767 uiGridCtrl = controllers[0],
2768 containerCtrl = controllers[1],
2769 grid = $scope.grid = uiGridCtrl.grid;
2770
2771 // Verify that the render container for this element exists
2772 if (!$scope.rowContainerName) {
2773 throw new Error('No row render container name specified');
2774 }
2775 if (!$scope.colContainerName) {
2776 throw new Error('No column render container name specified');
2777 }
2778
2779 if (!grid.renderContainers[$scope.rowContainerName]) {
2780 throw new Error('Row render container "' + $scope.rowContainerName + '" is not registered.');
2781 }
2782 if (!grid.renderContainers[$scope.colContainerName]) {
2783 throw new Error('Column render container "' + $scope.colContainerName + '" is not registered.');
2784 }
2785
2786 rowContainer = $scope.rowContainer = grid.renderContainers[$scope.rowContainerName];
2787 colContainer = $scope.colContainer = grid.renderContainers[$scope.colContainerName];
2788
2789 containerCtrl.containerId = $scope.containerId;
2790 containerCtrl.rowContainer = rowContainer;
2791 containerCtrl.colContainer = colContainer;
2792 },
2793 post: function postlink($scope, $elm, $attrs, controllers) {
2794 var uiGridCtrl = controllers[0],
2795 containerCtrl = controllers[1],
2796 grid = uiGridCtrl.grid,
2797 rowContainer = containerCtrl.rowContainer,
2798 colContainer = containerCtrl.colContainer,
2799 scrollTop = null,
2800 scrollLeft = null,
2801 renderContainer = grid.renderContainers[$scope.containerId];
2802
2803 // Put the container name on this element as a class
2804 $elm.addClass('ui-grid-render-container-' + $scope.containerId);
2805
2806 // Scroll the render container viewport when the mousewheel is used
2807 gridUtil.on.mousewheel($elm, function(event) {
2808 var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.RenderContainerMouseWheel);
2809
2810 if (event.deltaY !== 0) {
2811 var scrollYAmount = event.deltaY * -1 * event.deltaFactor;
2812
2813 scrollTop = containerCtrl.viewport[0].scrollTop;
2814
2815 // Get the scroll percentage
2816 scrollEvent.verticalScrollLength = rowContainer.getVerticalScrollLength();
2817 var scrollYPercentage = (scrollTop + scrollYAmount) / scrollEvent.verticalScrollLength;
2818
2819 // If we should be scrolled 100%, make sure the scrollTop matches the maximum scroll length
2820 // Viewports that have "overflow: hidden" don't let the mousewheel scroll all the way to the bottom without this check
2821 if (scrollYPercentage >= 1 && scrollTop < scrollEvent.verticalScrollLength) {
2822 containerCtrl.viewport[0].scrollTop = scrollEvent.verticalScrollLength;
2823 }
2824
2825 // Keep scrollPercentage within the range 0-1.
2826 if (scrollYPercentage < 0) { scrollYPercentage = 0; }
2827 else if (scrollYPercentage > 1) { scrollYPercentage = 1; }
2828
2829 scrollEvent.y = {percentage: scrollYPercentage, pixels: scrollYAmount};
2830 }
2831 if (event.deltaX !== 0) {
2832 var scrollXAmount = event.deltaX * event.deltaFactor;
2833
2834 // Get the scroll percentage
2835 scrollLeft = gridUtil.normalizeScrollLeft(containerCtrl.viewport, grid);
2836 scrollEvent.horizontalScrollLength = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
2837 var scrollXPercentage = (scrollLeft + scrollXAmount) / scrollEvent.horizontalScrollLength;
2838
2839 // Keep scrollPercentage within the range 0-1.
2840 if (scrollXPercentage < 0) { scrollXPercentage = 0; }
2841 else if (scrollXPercentage > 1) { scrollXPercentage = 1; }
2842
2843 scrollEvent.x = {percentage: scrollXPercentage, pixels: scrollXAmount};
2844 }
2845
2846 // Let the parent container scroll if the grid is already at the top/bottom
2847 if (!((event.deltaY !== 0 && (scrollEvent.atTop(scrollTop) || scrollEvent.atBottom(scrollTop))) ||
2848 (event.deltaX !== 0 && (scrollEvent.atLeft(scrollLeft) || scrollEvent.atRight(scrollLeft))))) {
2849 event.preventDefault();
2850 event.stopPropagation();
2851 scrollEvent.fireThrottledScrollingEvent('', scrollEvent);
2852 }
2853 });
2854
2855 $elm.bind('$destroy', function() {
2856 $elm.unbind('keydown');
2857
2858 ['touchstart', 'touchmove', 'touchend', 'keydown', 'wheel', 'mousewheel',
2859 'DomMouseScroll', 'MozMousePixelScroll'].forEach(function(eventName) {
2860 $elm.unbind(eventName);
2861 });
2862 });
2863
2864 // TODO(c0bra): Handle resizing the inner canvas based on the number of elements
2865 function update() {
2866 var ret = '';
2867
2868 var canvasWidth = colContainer.canvasWidth;
2869 var viewportWidth = colContainer.getViewportWidth();
2870
2871 var canvasHeight = rowContainer.getCanvasHeight();
2872
2873 var viewportHeight = rowContainer.getViewportHeight();
2874 // shorten the height to make room for a scrollbar placeholder
2875 if (colContainer.needsHScrollbarPlaceholder()) {
2876 viewportHeight -= grid.scrollbarHeight;
2877 }
2878
2879 var headerViewportWidth,
2880 footerViewportWidth;
2881 headerViewportWidth = footerViewportWidth = colContainer.getHeaderViewportWidth();
2882
2883 // Set canvas dimensions
2884 ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId
2885 + ' .ui-grid-canvas { width: ' + canvasWidth + 'px; height: ' + canvasHeight + 'px; }';
2886
2887 ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId
2888 + ' .ui-grid-header-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';
2889
2890 if (renderContainer.explicitHeaderCanvasHeight) {
2891 // get height from body container
2892 var reHCHeight = document.querySelector(
2893 '.grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-body .ui-grid-header-canvas');
2894
2895 if (reHCHeight) {
2896 renderContainer.explicitHeaderCanvasHeight = reHCHeight.offsetHeight;
2897 }
2898
2899 ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId
2900 + ' .ui-grid-header-canvas { height: ' + renderContainer.explicitHeaderCanvasHeight + 'px; }';
2901 }
2902 else {
2903 ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId
2904 + ' .ui-grid-header-canvas { height: inherit; }';
2905 }
2906
2907 ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId
2908 + ' .ui-grid-viewport { width: ' + viewportWidth + 'px; height: ' + viewportHeight + 'px; }';
2909 ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId
2910 + ' .ui-grid-header-viewport { width: ' + headerViewportWidth + 'px; }';
2911
2912 ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId
2913 + ' .ui-grid-footer-canvas { width: ' + (canvasWidth + grid.scrollbarWidth) + 'px; }';
2914 ret += '\n .grid' + uiGridCtrl.grid.id + ' .ui-grid-render-container-' + $scope.containerId
2915 + ' .ui-grid-footer-viewport { width: ' + footerViewportWidth + 'px; }';
2916
2917 return ret;
2918 }
2919
2920 uiGridCtrl.grid.registerStyleComputation({
2921 priority: 6,
2922 func: update
2923 });
2924 }
2925 };
2926 }
2927 };
2928 }]);
2929
2930 module.controller('uiGridRenderContainer', ['$scope', 'gridUtil', function($scope, gridUtil) {
2931 }]);
2932 })();
2933
2934 (function() {
2935 'use strict';
2936
2937 angular.module('ui.grid').directive('uiGridRow', function() {
2938 return {
2939 replace: true,
2940 require: ['^uiGrid', '^uiGridRenderContainer'],
2941 scope: {
2942 row: '=uiGridRow',
2943 // rowRenderIndex is added to scope to give the true visual index of the row to any directives that need it
2944 rowRenderIndex: '='
2945 },
2946 compile: function() {
2947 return {
2948 pre: function($scope, $elm, $attrs, controllers) {
2949 var uiGridCtrl = controllers[0];
2950 var containerCtrl = controllers[1];
2951
2952 $scope.grid = uiGridCtrl.grid;
2953 $scope.colContainer = containerCtrl.colContainer;
2954
2955 // Function for attaching the template to this scope
2956 var clonedElement, cloneScope;
2957 function compileTemplate() {
2958 $scope.row.getRowTemplateFn.then(function (compiledElementFn) {
2959 // var compiledElementFn = $scope.row.compiledElementFn;
2960
2961 // Create a new scope for the contents of this row, so we can destroy it later if need be
2962 var newScope = $scope.$new();
2963
2964 compiledElementFn(newScope, function (newElm, scope) {
2965 // If we already have a cloned element, we need to remove it and destroy its scope
2966 if (clonedElement) {
2967 clonedElement.remove();
2968 cloneScope.$destroy();
2969 }
2970
2971 // Empty the row and append the new element
2972 $elm.empty().append(newElm);
2973
2974 // Save the new cloned element and scope
2975 clonedElement = newElm;
2976 cloneScope = newScope;
2977 });
2978 }).catch(angular.noop);
2979 }
2980
2981 // Initially attach the compiled template to this scope
2982 compileTemplate();
2983
2984 // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template
2985 $scope.$watch('row.getRowTemplateFn', function (newFunc, oldFunc) {
2986 if (newFunc !== oldFunc) {
2987 compileTemplate();
2988 }
2989 });
2990 },
2991 post: function($scope, $elm) {
2992 $scope.row.element = $elm;
2993 }
2994 };
2995 }
2996 };
2997 });
2998 })();
2999
3000 (function() {
3001 // 'use strict';
3002
3003 /**
3004 * @ngdoc directive
3005 * @name ui.grid.directive:uiGridStyle
3006 * @element style
3007 * @restrict A
3008 *
3009 * @description
3010 * Allows us to interpolate expressions in `<style>` elements. Angular doesn't do this by default as it can/will/might? break in IE8.
3011 *
3012 * @example
3013 <doc:example module="app">
3014 <doc:source>
3015 <script>
3016 var app = angular.module('app', ['ui.grid']);
3017
3018 app.controller('MainCtrl', ['$scope', function ($scope) {
3019 $scope.myStyle = '.blah { border: 1px solid }';
3020 }]);
3021 </script>
3022
3023 <div ng-controller="MainCtrl">
3024 <style ui-grid-style>{{ myStyle }}</style>
3025 <span class="blah">I am in a box.</span>
3026 </div>
3027 </doc:source>
3028 <doc:scenario>
3029 it('should apply the right class to the element', function () {
3030 element(by.css('.blah')).getCssValue('border-top-width')
3031 .then(function(c) {
3032 expect(c).toContain('1px');
3033 });
3034 });
3035 </doc:scenario>
3036 </doc:example>
3037 */
3038
3039
3040 angular.module('ui.grid').directive('uiGridStyle', ['gridUtil', '$interpolate', function(gridUtil, $interpolate) {
3041 return {
3042 link: function($scope, $elm) {
3043 var interpolateFn = $interpolate($elm.text(), true);
3044
3045 if (interpolateFn) {
3046 $scope.$watch(interpolateFn, function(value) {
3047 $elm.text(value);
3048 });
3049 }
3050 }
3051 };
3052 }]);
3053 })();
3054
3055 (function() {
3056 'use strict';
3057
3058 angular.module('ui.grid').directive('uiGridViewport', ['gridUtil', 'ScrollEvent',
3059 function(gridUtil, ScrollEvent) {
3060 return {
3061 replace: true,
3062 scope: {},
3063 controllerAs: 'Viewport',
3064 templateUrl: 'ui-grid/uiGridViewport',
3065 require: ['^uiGrid', '^uiGridRenderContainer'],
3066 link: function($scope, $elm, $attrs, controllers) {
3067 // gridUtil.logDebug('viewport post-link');
3068
3069 var uiGridCtrl = controllers[0];
3070 var containerCtrl = controllers[1];
3071
3072 $scope.containerCtrl = containerCtrl;
3073
3074 var rowContainer = containerCtrl.rowContainer;
3075 var colContainer = containerCtrl.colContainer;
3076
3077 var grid = uiGridCtrl.grid;
3078
3079 $scope.grid = uiGridCtrl.grid;
3080
3081 // Put the containers in scope so we can get rows and columns from them
3082 $scope.rowContainer = containerCtrl.rowContainer;
3083 $scope.colContainer = containerCtrl.colContainer;
3084
3085 // Register this viewport with its container
3086 containerCtrl.viewport = $elm;
3087
3088 /**
3089 * @ngdoc function
3090 * @name customScroller
3091 * @methodOf ui.grid.class:GridOptions
3092 * @description (optional) uiGridViewport.on('scroll', scrollHandler) by default.
3093 * A function that allows you to provide your own scroller function. It is particularly helpful if you want to use third party scrollers
3094 * as this allows you to do that.
3095 *
3096 * <div class="alert alert-info" role="alert"> <strong>NOTE:</strong> It is important to remember to always pass in an event object to
3097 * the scrollHandler as the grid scrolling behavior will break without it.</div>
3098 * <h5>Example</h5>
3099 * <pre>
3100 * $scope.gridOptions = {
3101 * customScroller: function myScrolling(uiGridViewport, scrollHandler) {
3102 * uiGridViewport.on('scroll', function myScrollingOverride(event) {
3103 * // Do something here
3104 *
3105 * scrollHandler(event);
3106 * });
3107 * }
3108 * };
3109 * </pre>
3110 * @param {object} uiGridViewport Element being scrolled. (this gets passed in by the grid).
3111 * @param {function} scrollHandler Function that needs to be called when scrolling happens. (this gets passed in by the grid).
3112 */
3113 if (grid && grid.options && grid.options.customScroller) {
3114 grid.options.customScroller($elm, scrollHandler);
3115 } else {
3116 $elm.on('scroll', scrollHandler);
3117 }
3118
3119 var ignoreScroll = false;
3120
3121 function scrollHandler() {
3122 var newScrollTop = $elm[0].scrollTop;
3123 var newScrollLeft = gridUtil.normalizeScrollLeft($elm, grid);
3124
3125 var vertScrollPercentage = rowContainer.scrollVertical(newScrollTop);
3126 var horizScrollPercentage = colContainer.scrollHorizontal(newScrollLeft);
3127
3128 var scrollEvent = new ScrollEvent(grid, rowContainer, colContainer, ScrollEvent.Sources.ViewPortScroll);
3129 scrollEvent.newScrollLeft = newScrollLeft;
3130 scrollEvent.newScrollTop = newScrollTop;
3131 if ( horizScrollPercentage > -1 ) {
3132 scrollEvent.x = { percentage: horizScrollPercentage };
3133 }
3134
3135 if ( vertScrollPercentage > -1 ) {
3136 scrollEvent.y = { percentage: vertScrollPercentage };
3137 }
3138
3139 grid.scrollContainers($scope.$parent.containerId, scrollEvent);
3140 }
3141
3142 if ($scope.$parent.bindScrollVertical) {
3143 grid.addVerticalScrollSync($scope.$parent.containerId, syncVerticalScroll);
3144 }
3145
3146 if ($scope.$parent.bindScrollHorizontal) {
3147 grid.addHorizontalScrollSync($scope.$parent.containerId, syncHorizontalScroll);
3148 grid.addHorizontalScrollSync($scope.$parent.containerId + 'header', syncHorizontalHeader);
3149 grid.addHorizontalScrollSync($scope.$parent.containerId + 'footer', syncHorizontalFooter);
3150 }
3151
3152 function syncVerticalScroll(scrollEvent) {
3153 containerCtrl.prevScrollArgs = scrollEvent;
3154 $elm[0].scrollTop = scrollEvent.getNewScrollTop(rowContainer,containerCtrl.viewport);
3155 }
3156
3157 function syncHorizontalScroll(scrollEvent) {
3158 containerCtrl.prevScrollArgs = scrollEvent;
3159 var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
3160
3161 $elm[0].scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
3162 }
3163
3164 function syncHorizontalHeader(scrollEvent) {
3165 var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
3166
3167 if (containerCtrl.headerViewport) {
3168 containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
3169 }
3170 }
3171
3172 function syncHorizontalFooter(scrollEvent) {
3173 var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
3174
3175 if (containerCtrl.footerViewport) {
3176 containerCtrl.footerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
3177 }
3178 }
3179
3180 $scope.$on('$destroy', function unbindEvents() {
3181 $elm.off();
3182 });
3183 },
3184 controller: ['$scope', function ($scope) {
3185 this.rowStyle = function () {
3186 var rowContainer = $scope.rowContainer;
3187 var colContainer = $scope.colContainer;
3188
3189 var styles = {};
3190
3191 if (rowContainer.currentTopRow !== 0) {
3192 // top offset based on hidden rows count
3193 var translateY = "translateY("+ (rowContainer.currentTopRow * rowContainer.grid.options.rowHeight) +"px)";
3194
3195 styles['transform'] = translateY;
3196 styles['-webkit-transform'] = translateY;
3197 styles['-ms-transform'] = translateY;
3198 }
3199
3200 if (colContainer.currentFirstColumn !== 0) {
3201 if (colContainer.grid.isRTL()) {
3202 styles['margin-right'] = colContainer.columnOffset + 'px';
3203 }
3204 else {
3205 styles['margin-left'] = colContainer.columnOffset + 'px';
3206 }
3207 }
3208
3209 return styles;
3210 };
3211 }]
3212 };
3213 }
3214 ]);
3215
3216 })();
3217
3218 (function() {
3219 angular.module('ui.grid')
3220 .directive('uiGridVisible', function uiGridVisibleAction() {
3221 return function($scope, $elm, $attr) {
3222 $scope.$watch($attr.uiGridVisible, function(visible) {
3223 $elm[visible ? 'removeClass' : 'addClass']('ui-grid-invisible');
3224 });
3225 };
3226 });
3227 })();
3228
3229 (function () {
3230 'use strict';
3231
3232 angular.module('ui.grid').controller('uiGridController', ['$scope', '$element', '$attrs', 'gridUtil', '$q', 'uiGridConstants',
3233 'gridClassFactory', '$parse', '$compile',
3234 function ($scope, $elm, $attrs, gridUtil, $q, uiGridConstants,
3235 gridClassFactory, $parse, $compile) {
3236 // gridUtil.logDebug('ui-grid controller');
3237 var self = this;
3238 var deregFunctions = [];
3239
3240 self.grid = gridClassFactory.createGrid($scope.uiGrid);
3241
3242 // assign $scope.$parent if appScope not already assigned
3243 self.grid.appScope = self.grid.appScope || $scope.$parent;
3244
3245 $elm.addClass('grid' + self.grid.id);
3246 self.grid.rtl = gridUtil.getStyles($elm[0])['direction'] === 'rtl';
3247
3248
3249 // angular.extend(self.grid.options, );
3250
3251 // all properties of grid are available on scope
3252 $scope.grid = self.grid;
3253
3254 if ($attrs.uiGridColumns) {
3255 deregFunctions.push( $attrs.$observe('uiGridColumns', function(value) {
3256 self.grid.options.columnDefs = angular.isString(value) ? angular.fromJson(value) : value;
3257 self.grid.buildColumns()
3258 .then(function() {
3259 self.grid.preCompileCellTemplates();
3260
3261 self.grid.refreshCanvas(true);
3262 }).catch(angular.noop);
3263 }) );
3264 }
3265
3266 // prevents an error from being thrown when the array is not defined yet and fastWatch is on
3267 function getSize(array) {
3268 return array ? array.length : 0;
3269 }
3270
3271 // if fastWatch is set we watch only the length and the reference, not every individual object
3272 if (self.grid.options.fastWatch) {
3273 self.uiGrid = $scope.uiGrid;
3274 if (angular.isString($scope.uiGrid.data)) {
3275 deregFunctions.push( $scope.$parent.$watch($scope.uiGrid.data, dataWatchFunction) );
3276 deregFunctions.push( $scope.$parent.$watch(function() {
3277 if ( self.grid.appScope[$scope.uiGrid.data] ) {
3278 return self.grid.appScope[$scope.uiGrid.data].length;
3279 } else {
3280 return undefined;
3281 }
3282 }, dataWatchFunction) );
3283 } else {
3284 deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.data; }, dataWatchFunction) );
3285 deregFunctions.push( $scope.$parent.$watch(function() { return getSize($scope.uiGrid.data); }, function() { dataWatchFunction($scope.uiGrid.data); }) );
3286 }
3287 deregFunctions.push( $scope.$parent.$watch(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );
3288 deregFunctions.push( $scope.$parent.$watch(function() { return getSize($scope.uiGrid.columnDefs); }, function() { columnDefsWatchFunction($scope.uiGrid.columnDefs); }) );
3289 } else {
3290 if (angular.isString($scope.uiGrid.data)) {
3291 deregFunctions.push( $scope.$parent.$watchCollection($scope.uiGrid.data, dataWatchFunction) );
3292 } else {
3293 deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.data; }, dataWatchFunction) );
3294 }
3295 deregFunctions.push( $scope.$parent.$watchCollection(function() { return $scope.uiGrid.columnDefs; }, columnDefsWatchFunction) );
3296 }
3297
3298
3299 function columnDefsWatchFunction(n, o) {
3300 if (n && n !== o) {
3301 self.grid.options.columnDefs = $scope.uiGrid.columnDefs;
3302 self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.COLUMN, {
3303 orderByColumnDefs: true,
3304 preCompileCellTemplates: true
3305 });
3306 }
3307 }
3308
3309 var mostRecentData;
3310
3311 function dataWatchFunction(newData) {
3312 // gridUtil.logDebug('dataWatch fired');
3313 var promises = [];
3314
3315 if ( self.grid.options.fastWatch ) {
3316 if (angular.isString($scope.uiGrid.data)) {
3317 newData = self.grid.appScope.$eval($scope.uiGrid.data);
3318 } else {
3319 newData = $scope.uiGrid.data;
3320 }
3321 }
3322
3323 mostRecentData = newData;
3324
3325 if (newData) {
3326 // columns length is greater than the number of row header columns, which don't count because they're created automatically
3327 var hasColumns = self.grid.columns.length > (self.grid.rowHeaderColumns ? self.grid.rowHeaderColumns.length : 0);
3328
3329 if (
3330 // If we have no columns
3331 !hasColumns &&
3332 // ... and we don't have a ui-grid-columns attribute, which would define columns for us
3333 !$attrs.uiGridColumns &&
3334 // ... and we have no pre-defined columns
3335 self.grid.options.columnDefs.length === 0 &&
3336 // ... but we DO have data
3337 newData.length > 0
3338 ) {
3339 // ... then build the column definitions from the data that we have
3340 self.grid.buildColumnDefsFromData(newData);
3341 }
3342
3343 // If we haven't built columns before and either have some columns defined or some data defined
3344 if (!hasColumns && (self.grid.options.columnDefs.length > 0 || newData.length > 0)) {
3345 // Build the column set, then pre-compile the column cell templates
3346 promises.push(self.grid.buildColumns()
3347 .then(function() {
3348 self.grid.preCompileCellTemplates();
3349 }).catch(angular.noop));
3350 }
3351
3352 $q.all(promises).then(function() {
3353 // use most recent data, rather than the potentially outdated data passed into watcher handler
3354 self.grid.modifyRows(mostRecentData)
3355 .then(function () {
3356 // if (self.viewport) {
3357 self.grid.redrawInPlace(true);
3358 // }
3359
3360 $scope.$evalAsync(function() {
3361 self.grid.refreshCanvas(true);
3362 self.grid.callDataChangeCallbacks(uiGridConstants.dataChange.ROW);
3363 });
3364 }).catch(angular.noop);
3365 }).catch(angular.noop);
3366 }
3367 }
3368
3369 var styleWatchDereg = $scope.$watch(function () { return self.grid.styleComputations; }, function() {
3370 self.grid.refreshCanvas(true);
3371 });
3372
3373 $scope.$on('$destroy', function() {
3374 deregFunctions.forEach( function( deregFn ) { deregFn(); });
3375 styleWatchDereg();
3376 });
3377
3378 self.fireEvent = function(eventName, args) {
3379 args = args || {};
3380
3381 // Add the grid to the event arguments if it's not there
3382 if (angular.isUndefined(args.grid)) {
3383 args.grid = self.grid;
3384 }
3385
3386 $scope.$broadcast(eventName, args);
3387 };
3388
3389 self.innerCompile = function innerCompile(elm) {
3390 $compile(elm)($scope);
3391 };
3392 }]);
3393
3394 /**
3395 * @ngdoc directive
3396 * @name ui.grid.directive:uiGrid
3397 * @element div
3398 * @restrict EA
3399 * @param {Object} uiGrid Options for the grid to use
3400 *
3401 * @description Create a very basic grid.
3402 *
3403 * @example
3404 <example module="app">
3405 <file name="app.js">
3406 var app = angular.module('app', ['ui.grid']);
3407
3408 app.controller('MainCtrl', ['$scope', function ($scope) {
3409 $scope.data = [
3410 { name: 'Bob', title: 'CEO' },
3411 { name: 'Frank', title: 'Lowly Developer' }
3412 ];
3413 }]);
3414 </file>
3415 <file name="index.html">
3416 <div ng-controller="MainCtrl">
3417 <div ui-grid="{ data: data }"></div>
3418 </div>
3419 </file>
3420 </example>
3421 */
3422 angular.module('ui.grid').directive('uiGrid', uiGridDirective);
3423
3424 uiGridDirective.$inject = ['$window', 'gridUtil', 'uiGridConstants'];
3425 function uiGridDirective($window, gridUtil, uiGridConstants) {
3426 return {
3427 templateUrl: 'ui-grid/ui-grid',
3428 scope: {
3429 uiGrid: '='
3430 },
3431 replace: true,
3432 transclude: true,
3433 controller: 'uiGridController',
3434 compile: function () {
3435 return {
3436 post: function ($scope, $elm, $attrs, uiGridCtrl) {
3437 var grid = uiGridCtrl.grid;
3438 // Initialize scrollbars (TODO: move to controller??)
3439 uiGridCtrl.scrollbars = [];
3440 grid.element = $elm;
3441
3442
3443 // See if the grid has a rendered width, if not, wait a bit and try again
3444 var sizeCheckInterval = 100; // ms
3445 var maxSizeChecks = 20; // 2 seconds total
3446 var sizeChecks = 0;
3447
3448 // Setup (event listeners) the grid
3449 setup();
3450
3451 // And initialize it
3452 init();
3453
3454 // Mark rendering complete so API events can happen
3455 grid.renderingComplete();
3456
3457 // If the grid doesn't have size currently, wait for a bit to see if it gets size
3458 checkSize();
3459
3460 /*-- Methods --*/
3461
3462 function checkSize() {
3463 // If the grid has no width and we haven't checked more than <maxSizeChecks> times, check again in <sizeCheckInterval> milliseconds
3464 if ($elm[0].offsetWidth <= 0 && sizeChecks < maxSizeChecks) {
3465 setTimeout(checkSize, sizeCheckInterval);
3466 sizeChecks++;
3467 } else {
3468 $scope.$applyAsync(init);
3469 }
3470 }
3471
3472 // Setup event listeners and watchers
3473 function setup() {
3474 var deregisterLeftWatcher, deregisterRightWatcher;
3475
3476 // Bind to window resize events
3477 angular.element($window).on('resize', gridResize);
3478
3479 // Unbind from window resize events when the grid is destroyed
3480 $elm.on('$destroy', function () {
3481 angular.element($window).off('resize', gridResize);
3482 deregisterLeftWatcher();
3483 deregisterRightWatcher();
3484 });
3485
3486 // If we add a left container after render, we need to watch and react
3487 deregisterLeftWatcher = $scope.$watch(function () { return grid.hasLeftContainer();}, function (newValue, oldValue) {
3488 if (newValue === oldValue) {
3489 return;
3490 }
3491 grid.refreshCanvas(true);
3492 });
3493
3494 // If we add a right container after render, we need to watch and react
3495 deregisterRightWatcher = $scope.$watch(function () { return grid.hasRightContainer();}, function (newValue, oldValue) {
3496 if (newValue === oldValue) {
3497 return;
3498 }
3499 grid.refreshCanvas(true);
3500 });
3501 }
3502
3503 // Initialize the directive
3504 function init() {
3505 grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);
3506
3507 // Default canvasWidth to the grid width, in case we don't get any column definitions to calculate it from
3508 grid.canvasWidth = uiGridCtrl.grid.gridWidth;
3509
3510 grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
3511
3512 // If the grid isn't tall enough to fit a single row, it's kind of useless. Resize it to fit a minimum number of rows
3513 if (grid.gridHeight - grid.scrollbarHeight <= grid.options.rowHeight && grid.options.enableMinHeightCheck) {
3514 autoAdjustHeight();
3515 }
3516
3517 // Run initial canvas refresh
3518 grid.refreshCanvas(true);
3519 }
3520
3521 // Set the grid's height ourselves in the case that its height would be unusably small
3522 function autoAdjustHeight() {
3523 // Figure out the new height
3524 var contentHeight = grid.options.minRowsToShow * grid.options.rowHeight;
3525 var headerHeight = grid.options.showHeader ? grid.options.headerRowHeight : 0;
3526 var footerHeight = grid.calcFooterHeight();
3527
3528 var scrollbarHeight = 0;
3529 if (grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
3530 scrollbarHeight = gridUtil.getScrollbarWidth();
3531 }
3532
3533 var maxNumberOfFilters = 0;
3534 // Calculates the maximum number of filters in the columns
3535 angular.forEach(grid.options.columnDefs, function(col) {
3536 if (col.hasOwnProperty('filter')) {
3537 if (maxNumberOfFilters < 1) {
3538 maxNumberOfFilters = 1;
3539 }
3540 }
3541 else if (col.hasOwnProperty('filters')) {
3542 if (maxNumberOfFilters < col.filters.length) {
3543 maxNumberOfFilters = col.filters.length;
3544 }
3545 }
3546 });
3547
3548 if (grid.options.enableFiltering && !maxNumberOfFilters) {
3549 var allColumnsHaveFilteringTurnedOff = grid.options.columnDefs.length && grid.options.columnDefs.every(function(col) {
3550 return col.enableFiltering === false;
3551 });
3552
3553 if (!allColumnsHaveFilteringTurnedOff) {
3554 maxNumberOfFilters = 1;
3555 }
3556 }
3557
3558 var filterHeight = maxNumberOfFilters * headerHeight;
3559
3560 var newHeight = headerHeight + contentHeight + footerHeight + scrollbarHeight + filterHeight;
3561
3562 $elm.css('height', newHeight + 'px');
3563
3564 grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
3565 }
3566
3567 // Resize the grid on window resize events
3568 function gridResize() {
3569 grid.gridWidth = $scope.gridWidth = gridUtil.elementWidth($elm);
3570 grid.gridHeight = $scope.gridHeight = gridUtil.elementHeight($elm);
3571
3572 grid.refreshCanvas(true);
3573 }
3574 }
3575 };
3576 }
3577 };
3578 }
3579 })();
3580
3581 (function() {
3582 'use strict';
3583
3584 angular.module('ui.grid').directive('uiGridPinnedContainer', ['gridUtil', function (gridUtil) {
3585 return {
3586 restrict: 'EA',
3587 replace: true,
3588 template: '<div class="ui-grid-pinned-container">'
3589 + '<div ui-grid-render-container container-id="side"'
3590 + ' row-container-name="\'body\'" col-container-name="side"'
3591 + ' bind-scroll-vertical="true"'
3592 + ' class="{{ side }} ui-grid-render-container-{{ side }}"></div>'
3593 + '</div>',
3594 scope: {
3595 side: '=uiGridPinnedContainer'
3596 },
3597 require: '^uiGrid',
3598 compile: function compile() {
3599 return {
3600 post: function ($scope, $elm, $attrs, uiGridCtrl) {
3601 // gridUtil.logDebug('ui-grid-pinned-container ' + $scope.side + ' link');
3602
3603 var grid = uiGridCtrl.grid;
3604
3605 var myWidth = 0;
3606
3607 $elm.addClass('ui-grid-pinned-container-' + $scope.side);
3608
3609 // Monkey-patch the viewport width function
3610 if ($scope.side === 'left' || $scope.side === 'right') {
3611 grid.renderContainers[$scope.side].getViewportWidth = monkeyPatchedGetViewportWidth;
3612 }
3613
3614 function monkeyPatchedGetViewportWidth() {
3615 /*jshint validthis: true */
3616 var self = this;
3617
3618 var viewportWidth = 0;
3619 self.visibleColumnCache.forEach(function (column) {
3620 viewportWidth += column.drawnWidth;
3621 });
3622
3623 var adjustment = self.getViewportAdjustment();
3624
3625 viewportWidth = viewportWidth + adjustment.width;
3626
3627 return viewportWidth;
3628 }
3629
3630 function updateContainerWidth() {
3631 if ($scope.side === 'left' || $scope.side === 'right') {
3632 var cols = grid.renderContainers[$scope.side].visibleColumnCache;
3633 var width = 0;
3634 for (var i = 0; i < cols.length; i++) {
3635 var col = cols[i];
3636 width += col.drawnWidth || col.width || 0;
3637 }
3638
3639 return width;
3640 }
3641 }
3642
3643 function updateContainerDimensions() {
3644 var ret = '';
3645
3646 // Column containers
3647 if ($scope.side === 'left' || $scope.side === 'right') {
3648 myWidth = updateContainerWidth();
3649
3650 // gridUtil.logDebug('myWidth', myWidth);
3651
3652 // TODO(c0bra): Subtract sum of col widths from grid viewport width and update it
3653 $elm.attr('style', null);
3654
3655 // var myHeight = grid.renderContainers.body.getViewportHeight(); // + grid.horizontalScrollbarHeight;
3656
3657 ret += '.grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ', .grid' + grid.id + ' .ui-grid-pinned-container-' + $scope.side + ' .ui-grid-render-container-' + $scope.side + ' .ui-grid-viewport { width: ' + myWidth + 'px; } ';
3658 }
3659
3660 return ret;
3661 }
3662
3663 grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
3664 myWidth = updateContainerWidth();
3665
3666 // Subtract our own width
3667 adjustment.width -= myWidth;
3668 adjustment.side = $scope.side;
3669
3670 return adjustment;
3671 });
3672
3673 // Register style computation to adjust for columns in `side`'s render container
3674 grid.registerStyleComputation({
3675 priority: 15,
3676 func: updateContainerDimensions
3677 });
3678 }
3679 };
3680 }
3681 };
3682 }]);
3683 })();
3684
3685 (function() {
3686
3687 angular.module('ui.grid')
3688 .factory('Grid', ['$q', '$compile', '$parse', 'gridUtil', 'uiGridConstants', 'GridOptions', 'GridColumn', 'GridRow', 'GridApi', 'rowSorter', 'rowSearcher', 'GridRenderContainer', '$timeout','ScrollEvent',
3689 function($q, $compile, $parse, gridUtil, uiGridConstants, GridOptions, GridColumn, GridRow, GridApi, rowSorter, rowSearcher, GridRenderContainer, $timeout, ScrollEvent) {
3690
3691 /**
3692 * @ngdoc object
3693 * @name ui.grid.api:PublicApi
3694 * @description Public Api for the core grid features
3695 *
3696 */
3697
3698 /**
3699 * @ngdoc function
3700 * @name ui.grid.class:Grid
3701 * @description Grid is the main viewModel. Any properties or methods needed to maintain state are defined in
3702 * this prototype. One instance of Grid is created per Grid directive instance.
3703 * @param {object} options Object map of options to pass into the grid. An 'id' property is expected.
3704 */
3705 var Grid = function Grid(options) {
3706 var self = this;
3707 // Get the id out of the options, then remove it
3708 if (options !== undefined && typeof(options.id) !== 'undefined' && options.id) {
3709 if (!/^[_a-zA-Z0-9-]+$/.test(options.id)) {
3710 throw new Error("Grid id '" + options.id + '" is invalid. It must follow CSS selector syntax rules.');
3711 }
3712 }
3713 else {
3714 throw new Error('No ID provided. An ID must be given when creating a grid.');
3715 }
3716
3717 self.id = options.id;
3718 delete options.id;
3719
3720 // Get default options
3721 self.options = GridOptions.initialize( options );
3722
3723 /**
3724 * @ngdoc object
3725 * @name appScope
3726 * @propertyOf ui.grid.class:Grid
3727 * @description reference to the application scope (the parent scope of the ui-grid element). Assigned in ui-grid controller
3728 * <br/>
3729 * use gridOptions.appScopeProvider to override the default assignment of $scope.$parent with any reference
3730 */
3731 self.appScope = self.options.appScopeProvider;
3732
3733 self.headerHeight = self.options.headerRowHeight;
3734
3735
3736 /**
3737 * @ngdoc object
3738 * @name footerHeight
3739 * @propertyOf ui.grid.class:Grid
3740 * @description returns the total footer height gridFooter + columnFooter
3741 */
3742 self.footerHeight = self.calcFooterHeight();
3743
3744
3745 /**
3746 * @ngdoc object
3747 * @name columnFooterHeight
3748 * @propertyOf ui.grid.class:Grid
3749 * @description returns the total column footer height
3750 */
3751 self.columnFooterHeight = self.calcColumnFooterHeight();
3752
3753 self.rtl = false;
3754 self.gridHeight = 0;
3755 self.gridWidth = 0;
3756 self.columnBuilders = [];
3757 self.rowBuilders = [];
3758 self.rowsProcessors = [];
3759 self.columnsProcessors = [];
3760 self.styleComputations = [];
3761 self.viewportAdjusters = [];
3762 self.rowHeaderColumns = [];
3763 self.dataChangeCallbacks = {};
3764 self.verticalScrollSyncCallBackFns = {};
3765 self.horizontalScrollSyncCallBackFns = {};
3766
3767 // self.visibleRowCache = [];
3768
3769 // Set of 'render' containers for self grid, which can render sets of rows
3770 self.renderContainers = {};
3771
3772 // Create a
3773 self.renderContainers.body = new GridRenderContainer('body', self);
3774
3775 self.cellValueGetterCache = {};
3776
3777 // Cached function to use with custom row templates
3778 self.getRowTemplateFn = null;
3779
3780
3781 // representation of the rows on the grid.
3782 // these are wrapped references to the actual data rows (options.data)
3783 self.rows = [];
3784
3785 // represents the columns on the grid
3786 self.columns = [];
3787
3788 /**
3789 * @ngdoc boolean
3790 * @name isScrollingVertically
3791 * @propertyOf ui.grid.class:Grid
3792 * @description set to true when Grid is scrolling vertically. Set to false via debounced method
3793 */
3794 self.isScrollingVertically = false;
3795
3796 /**
3797 * @ngdoc boolean
3798 * @name isScrollingHorizontally
3799 * @propertyOf ui.grid.class:Grid
3800 * @description set to true when Grid is scrolling horizontally. Set to false via debounced method
3801 */
3802 self.isScrollingHorizontally = false;
3803
3804 /**
3805 * @ngdoc property
3806 * @name scrollDirection
3807 * @propertyOf ui.grid.class:Grid
3808 * @description set one of the {@link ui.grid.service:uiGridConstants#properties_scrollDirection uiGridConstants.scrollDirection}
3809 * values (UP, DOWN, LEFT, RIGHT, NONE), which tells us which direction we are scrolling.
3810 * Set to NONE via debounced method
3811 */
3812 self.scrollDirection = uiGridConstants.scrollDirection.NONE;
3813
3814 // if true, grid will not respond to any scroll events
3815 self.disableScrolling = false;
3816
3817
3818 function vertical (scrollEvent) {
3819 self.isScrollingVertically = false;
3820 self.api.core.raise.scrollEnd(scrollEvent);
3821 self.scrollDirection = uiGridConstants.scrollDirection.NONE;
3822 }
3823
3824 var debouncedVertical = gridUtil.debounce(vertical, self.options.scrollDebounce);
3825 var debouncedVerticalMinDelay = gridUtil.debounce(vertical, 0);
3826
3827 function horizontal (scrollEvent) {
3828 self.isScrollingHorizontally = false;
3829 self.api.core.raise.scrollEnd(scrollEvent);
3830 self.scrollDirection = uiGridConstants.scrollDirection.NONE;
3831 }
3832
3833 var debouncedHorizontal = gridUtil.debounce(horizontal, self.options.scrollDebounce);
3834 var debouncedHorizontalMinDelay = gridUtil.debounce(horizontal, 0);
3835
3836
3837 /**
3838 * @ngdoc function
3839 * @name flagScrollingVertically
3840 * @methodOf ui.grid.class:Grid
3841 * @description sets isScrollingVertically to true and sets it to false in a debounced function
3842 */
3843 self.flagScrollingVertically = function(scrollEvent) {
3844 if (!self.isScrollingVertically && !self.isScrollingHorizontally) {
3845 self.api.core.raise.scrollBegin(scrollEvent);
3846 }
3847 self.isScrollingVertically = true;
3848 if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {
3849 debouncedVerticalMinDelay(scrollEvent);
3850 }
3851 else {
3852 debouncedVertical(scrollEvent);
3853 }
3854 };
3855
3856 /**
3857 * @ngdoc function
3858 * @name flagScrollingHorizontally
3859 * @methodOf ui.grid.class:Grid
3860 * @description sets isScrollingHorizontally to true and sets it to false in a debounced function
3861 */
3862 self.flagScrollingHorizontally = function(scrollEvent) {
3863 if (!self.isScrollingVertically && !self.isScrollingHorizontally) {
3864 self.api.core.raise.scrollBegin(scrollEvent);
3865 }
3866 self.isScrollingHorizontally = true;
3867 if (self.options.scrollDebounce === 0 || !scrollEvent.withDelay) {
3868 debouncedHorizontalMinDelay(scrollEvent);
3869 }
3870 else {
3871 debouncedHorizontal(scrollEvent);
3872 }
3873 };
3874
3875 self.scrollbarHeight = 0;
3876 self.scrollbarWidth = 0;
3877 if (self.options.enableHorizontalScrollbar !== uiGridConstants.scrollbars.NEVER) {
3878 self.scrollbarHeight = gridUtil.getScrollbarWidth();
3879 }
3880
3881 if (self.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER) {
3882 self.scrollbarWidth = gridUtil.getScrollbarWidth();
3883 }
3884
3885 self.api = new GridApi(self);
3886
3887 /**
3888 * @ngdoc function
3889 * @name refresh
3890 * @methodOf ui.grid.api:PublicApi
3891 * @description Refresh the rendered grid on screen.
3892 * The refresh method re-runs both the columnProcessors and the
3893 * rowProcessors, as well as calling refreshCanvas to update all
3894 * the grid sizing. In general you should prefer to use queueGridRefresh
3895 * instead, which is basically a debounced version of refresh.
3896 *
3897 * If you only want to resize the grid, not regenerate all the rows
3898 * and columns, you should consider directly calling refreshCanvas instead.
3899 *
3900 * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed
3901 */
3902 self.api.registerMethod( 'core', 'refresh', this.refresh );
3903
3904 /**
3905 * @ngdoc function
3906 * @name queueGridRefresh
3907 * @methodOf ui.grid.api:PublicApi
3908 * @description Request a refresh of the rendered grid on screen, if multiple
3909 * calls to queueGridRefresh are made within a digest cycle only one will execute.
3910 * The refresh method re-runs both the columnProcessors and the
3911 * rowProcessors, as well as calling refreshCanvas to update all
3912 * the grid sizing. In general you should prefer to use queueGridRefresh
3913 * instead, which is basically a debounced version of refresh.
3914 *
3915 */
3916 self.api.registerMethod( 'core', 'queueGridRefresh', this.queueGridRefresh );
3917
3918 /**
3919 * @ngdoc function
3920 * @name refreshRows
3921 * @methodOf ui.grid.api:PublicApi
3922 * @description Runs only the rowProcessors, columns remain as they were.
3923 * It then calls redrawInPlace and refreshCanvas, which adjust the grid sizing.
3924 * @returns {promise} promise that is resolved when render completes?
3925 *
3926 */
3927 self.api.registerMethod( 'core', 'refreshRows', this.refreshRows );
3928
3929 /**
3930 * @ngdoc function
3931 * @name queueRefresh
3932 * @methodOf ui.grid.api:PublicApi
3933 * @description Requests execution of refreshCanvas, if multiple requests are made
3934 * during a digest cycle only one will run. RefreshCanvas updates the grid sizing.
3935 * @returns {promise} promise that is resolved when render completes?
3936 *
3937 */
3938 self.api.registerMethod( 'core', 'queueRefresh', this.queueRefresh );
3939
3940 /**
3941 * @ngdoc function
3942 * @name handleWindowResize
3943 * @methodOf ui.grid.api:PublicApi
3944 * @description Trigger a grid resize, normally this would be picked
3945 * up by a watch on window size, but in some circumstances it is necessary
3946 * to call this manually
3947 * @returns {promise} promise that is resolved when render completes?
3948 *
3949 */
3950 self.api.registerMethod( 'core', 'handleWindowResize', this.handleWindowResize );
3951
3952
3953 /**
3954 * @ngdoc function
3955 * @name addRowHeaderColumn
3956 * @methodOf ui.grid.api:PublicApi
3957 * @description adds a row header column to the grid
3958 * @param {object} column def
3959 * @param {number} order Determines order of header column on grid. Lower order means header
3960 * is positioned to the left of higher order headers
3961 *
3962 */
3963 self.api.registerMethod( 'core', 'addRowHeaderColumn', this.addRowHeaderColumn );
3964
3965 /**
3966 * @ngdoc function
3967 * @name scrollToIfNecessary
3968 * @methodOf ui.grid.api:PublicApi
3969 * @description Scrolls the grid to make a certain row and column combo visible,
3970 * in the case that it is not completely visible on the screen already.
3971 * @param {GridRow} gridRow row to make visible
3972 * @param {GridColumn} gridCol column to make visible
3973 * @returns {promise} a promise that is resolved when scrolling is complete
3974 *
3975 */
3976 self.api.registerMethod( 'core', 'scrollToIfNecessary', function(gridRow, gridCol) { return self.scrollToIfNecessary(gridRow, gridCol);} );
3977
3978 /**
3979 * @ngdoc function
3980 * @name scrollTo
3981 * @methodOf ui.grid.api:PublicApi
3982 * @description Scroll the grid such that the specified
3983 * row and column is in view
3984 * @param {object} rowEntity gridOptions.data[] array instance to make visible
3985 * @param {object} colDef to make visible
3986 * @returns {promise} a promise that is resolved after any scrolling is finished
3987 */
3988 self.api.registerMethod( 'core', 'scrollTo', function (rowEntity, colDef) { return self.scrollTo(rowEntity, colDef);} );
3989
3990 /**
3991 * @ngdoc function
3992 * @name registerRowsProcessor
3993 * @methodOf ui.grid.api:PublicApi
3994 * @description
3995 * Register a "rows processor" function. When the rows are updated,
3996 * the grid calls each registered "rows processor", which has a chance
3997 * to alter the set of rows (sorting, etc) as long as the count is not
3998 * modified.
3999 *
4000 * @param {function(renderedRowsToProcess, columns )} processorFunction rows processor function, which
4001 * is run in the context of the grid (i.e. this for the function will be the grid), and must
4002 * return the updated rows list, which is passed to the next processor in the chain
4003 * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
4004 * for other people to inject rows processors at intermediate priorities. Lower priority rowsProcessors run earlier.
4005 *
4006 * At present allRowsVisible is running at 50, sort manipulations running at 60-65, filter is running at 100,
4007 * sort is at 200, grouping and treeview at 400-410, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
4008 */
4009 self.api.registerMethod( 'core', 'registerRowsProcessor', this.registerRowsProcessor );
4010
4011 /**
4012 * @ngdoc function
4013 * @name registerColumnsProcessor
4014 * @methodOf ui.grid.api:PublicApi
4015 * @description
4016 * Register a "columns processor" function. When the columns are updated,
4017 * the grid calls each registered "columns processor", which has a chance
4018 * to alter the set of columns as long as the count is not
4019 * modified.
4020 *
4021 * @param {function(renderedColumnsToProcess, rows )} processorFunction columns processor function, which
4022 * is run in the context of the grid (i.e. this for the function will be the grid), and must
4023 * return the updated columns list, which is passed to the next processor in the chain
4024 * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
4025 * for other people to inject columns processors at intermediate priorities. Lower priority columnsProcessors run earlier.
4026 *
4027 * At present allRowsVisible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
4028 */
4029 self.api.registerMethod( 'core', 'registerColumnsProcessor', this.registerColumnsProcessor );
4030
4031 /**
4032 * @ngdoc function
4033 * @name sortHandleNulls
4034 * @methodOf ui.grid.api:PublicApi
4035 * @description A null handling method that can be used when building custom sort
4036 * functions
4037 * @example
4038 * <pre>
4039 * mySortFn = function(a, b) {
4040 * var nulls = $scope.gridApi.core.sortHandleNulls(a, b);
4041 * if ( nulls !== null ) {
4042 * return nulls;
4043 * } else {
4044 * // your code for sorting here
4045 * };
4046 * </pre>
4047 * @param {object} a sort value a
4048 * @param {object} b sort value b
4049 * @returns {number} null if there were no nulls/undefineds, otherwise returns
4050 * a sort value that should be passed back from the sort function
4051 *
4052 */
4053 self.api.registerMethod( 'core', 'sortHandleNulls', rowSorter.handleNulls );
4054
4055 /**
4056 * @ngdoc function
4057 * @name sortChanged
4058 * @methodOf ui.grid.api:PublicApi
4059 * @description The sort criteria on one or more columns has
4060 * changed. Provides as parameters the grid and the output of
4061 * getColumnSorting, which is an array of gridColumns
4062 * that have sorting on them, sorted in priority order.
4063 *
4064 * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.
4065 * @param {Function} callBack Will be called when the event is emited. The function passes back the grid and an array of
4066 * columns with sorts on them, in priority order.
4067 *
4068 * @example
4069 * <pre>
4070 * gridApi.core.on.sortChanged( $scope, function(grid, sortColumns) {
4071 * // do something
4072 * });
4073 * </pre>
4074 */
4075 self.api.registerEvent( 'core', 'sortChanged' );
4076
4077 /**
4078 * @ngdoc function
4079 * @name columnVisibilityChanged
4080 * @methodOf ui.grid.api:PublicApi
4081 * @description The visibility of a column has changed,
4082 * the column itself is passed out as a parameter of the event.
4083 *
4084 * @param {$scope} scope The scope of the controller. This is used to deregister this event when the scope is destroyed.
4085 * @param {Function} callBack Will be called when the event is emited. The function passes back the GridCol that has changed.
4086 *
4087 * @example
4088 * <pre>
4089 * gridApi.core.on.columnVisibilityChanged( $scope, function (column) {
4090 * // do something
4091 * } );
4092 * </pre>
4093 */
4094 self.api.registerEvent( 'core', 'columnVisibilityChanged' );
4095
4096 /**
4097 * @ngdoc method
4098 * @name notifyDataChange
4099 * @methodOf ui.grid.api:PublicApi
4100 * @description Notify the grid that a data or config change has occurred,
4101 * where that change isn't something the grid was otherwise noticing. This
4102 * might be particularly relevant where you've changed values within the data
4103 * and you'd like cell classes to be re-evaluated, or changed config within
4104 * the columnDef and you'd like headerCellClasses to be re-evaluated.
4105 * @param {string} type one of the
4106 * {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}
4107 * values (ALL, ROW, EDIT, COLUMN, OPTIONS), which tells us which refreshes to fire.
4108 *
4109 * - ALL: listeners fired on any of these events, fires listeners on all events.
4110 * - ROW: fired when a row is added or removed.
4111 * - EDIT: fired when the data in a cell is edited.
4112 * - COLUMN: fired when the column definitions are modified.
4113 * - OPTIONS: fired when the grid options are modified.
4114 */
4115 self.api.registerMethod( 'core', 'notifyDataChange', this.notifyDataChange );
4116
4117 /**
4118 * @ngdoc method
4119 * @name clearAllFilters
4120 * @methodOf ui.grid.api:PublicApi
4121 * @description Clears all filters and optionally refreshes the visible rows.
4122 * @param {object} refreshRows Defaults to true.
4123 * @param {object} clearConditions Defaults to false.
4124 * @param {object} clearFlags Defaults to false.
4125 * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.
4126 */
4127 self.api.registerMethod('core', 'clearAllFilters', this.clearAllFilters);
4128
4129 self.registerDataChangeCallback( self.columnRefreshCallback, [uiGridConstants.dataChange.COLUMN]);
4130 self.registerDataChangeCallback( self.processRowsCallback, [uiGridConstants.dataChange.EDIT]);
4131 self.registerDataChangeCallback( self.updateFooterHeightCallback, [uiGridConstants.dataChange.OPTIONS]);
4132
4133 self.registerStyleComputation({
4134 priority: 10,
4135 func: self.getFooterStyles
4136 });
4137 };
4138
4139 Grid.prototype.calcFooterHeight = function () {
4140 if (!this.hasFooter()) {
4141 return 0;
4142 }
4143
4144 var height = 0;
4145 if (this.options.showGridFooter) {
4146 height += this.options.gridFooterHeight;
4147 }
4148
4149 height += this.calcColumnFooterHeight();
4150
4151 return height;
4152 };
4153
4154 Grid.prototype.calcColumnFooterHeight = function () {
4155 var height = 0;
4156
4157 if (this.options.showColumnFooter) {
4158 height += this.options.columnFooterHeight;
4159 }
4160
4161 return height;
4162 };
4163
4164 Grid.prototype.getFooterStyles = function () {
4165 var style = '.grid' + this.id + ' .ui-grid-footer-aggregates-row { height: ' + this.options.columnFooterHeight + 'px; }';
4166 style += ' .grid' + this.id + ' .ui-grid-footer-info { height: ' + this.options.gridFooterHeight + 'px; }';
4167 return style;
4168 };
4169
4170 Grid.prototype.hasFooter = function () {
4171 return this.options.showGridFooter || this.options.showColumnFooter;
4172 };
4173
4174 /**
4175 * @ngdoc function
4176 * @name isRTL
4177 * @methodOf ui.grid.class:Grid
4178 * @description Returns true if grid is RightToLeft
4179 */
4180 Grid.prototype.isRTL = function () {
4181 return this.rtl;
4182 };
4183
4184
4185 /**
4186 * @ngdoc function
4187 * @name registerColumnBuilder
4188 * @methodOf ui.grid.class:Grid
4189 * @description When the build creates columns from column definitions, the columnbuilders will be called to add
4190 * additional properties to the column.
4191 * @param {function(colDef, col, gridOptions)} columnBuilder function to be called
4192 */
4193 Grid.prototype.registerColumnBuilder = function registerColumnBuilder(columnBuilder) {
4194 this.columnBuilders.push(columnBuilder);
4195 };
4196
4197 /**
4198 * @ngdoc function
4199 * @name buildColumnDefsFromData
4200 * @methodOf ui.grid.class:Grid
4201 * @description Populates columnDefs from the provided data
4202 * @param {function(colDef, col, gridOptions)} rowBuilder function to be called
4203 */
4204 Grid.prototype.buildColumnDefsFromData = function (dataRows) {
4205 this.options.columnDefs = gridUtil.getColumnsFromData(dataRows, this.options.excludeProperties);
4206 };
4207
4208 /**
4209 * @ngdoc function
4210 * @name registerRowBuilder
4211 * @methodOf ui.grid.class:Grid
4212 * @description When the build creates rows from gridOptions.data, the rowBuilders will be called to add
4213 * additional properties to the row.
4214 * @param {function(row, gridOptions)} rowBuilder function to be called
4215 */
4216 Grid.prototype.registerRowBuilder = function registerRowBuilder(rowBuilder) {
4217 this.rowBuilders.push(rowBuilder);
4218 };
4219
4220 /**
4221 * @ngdoc function
4222 * @name registerDataChangeCallback
4223 * @methodOf ui.grid.class:Grid
4224 * @description When a data change occurs, the data change callbacks of the specified type
4225 * will be called. The rules are:
4226 *
4227 * - when the data watch fires, that is considered a ROW change (the data watch only notices
4228 * added or removed rows)
4229 * - when the api is called to inform us of a change, the declared type of that change is used
4230 * - when a cell edit completes, the EDIT callbacks are triggered
4231 * - when the columnDef watch fires, the COLUMN callbacks are triggered
4232 * - when the options watch fires, the OPTIONS callbacks are triggered
4233 *
4234 * For a given event:
4235 * - ALL calls ROW, EDIT, COLUMN, OPTIONS and ALL callbacks
4236 * - ROW calls ROW and ALL callbacks
4237 * - EDIT calls EDIT and ALL callbacks
4238 * - COLUMN calls COLUMN and ALL callbacks
4239 * - OPTIONS calls OPTIONS and ALL callbacks
4240 *
4241 * @param {function(grid)} callback function to be called
4242 * @param {array} types the types of data change you want to be informed of. Values from
4243 * the {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}
4244 * values ( ALL, EDIT, ROW, COLUMN, OPTIONS ). Optional and defaults to ALL
4245 * @returns {function} deregister function - a function that can be called to deregister this callback
4246 */
4247 Grid.prototype.registerDataChangeCallback = function registerDataChangeCallback(callback, types, _this) {
4248 var self = this,
4249 uid = gridUtil.nextUid();
4250
4251 if ( !types ) {
4252 types = [uiGridConstants.dataChange.ALL];
4253 }
4254 if ( !Array.isArray(types)) {
4255 gridUtil.logError("Expected types to be an array or null in registerDataChangeCallback, value passed was: " + types );
4256 }
4257 this.dataChangeCallbacks[uid] = { callback: callback, types: types, _this: _this };
4258
4259 return function() {
4260 delete self.dataChangeCallbacks[uid];
4261 };
4262 };
4263
4264 /**
4265 * @ngdoc function
4266 * @name callDataChangeCallbacks
4267 * @methodOf ui.grid.class:Grid
4268 * @description Calls the callbacks based on the type of data change that
4269 * has occurred. Always calls the ALL callbacks, calls the ROW, EDIT, COLUMN and OPTIONS callbacks if the
4270 * event type is matching, or if the type is ALL.
4271 * @param {string} type the type of event that occurred - one of the
4272 * {@link ui.grid.service:uiGridConstants#properties_dataChange uiGridConstants.dataChange}
4273 * values (ALL, ROW, EDIT, COLUMN, OPTIONS)
4274 */
4275 Grid.prototype.callDataChangeCallbacks = function callDataChangeCallbacks(type, options) {
4276 angular.forEach( this.dataChangeCallbacks, function( callback, uid ) {
4277 if ( callback.types.indexOf( uiGridConstants.dataChange.ALL ) !== -1 ||
4278 callback.types.indexOf( type ) !== -1 ||
4279 type === uiGridConstants.dataChange.ALL ) {
4280 if (callback._this) {
4281 callback.callback.apply(callback._this, this, options);
4282 }
4283 else {
4284 callback.callback(this, options);
4285 }
4286 }
4287 }, this);
4288 };
4289
4290 /**
4291 * @ngdoc function
4292 * @name notifyDataChange
4293 * @methodOf ui.grid.class:Grid
4294 * @description Notifies us that a data change has occurred, used in the public
4295 * api for users to tell us when they've changed data or some other event that
4296 * our watches cannot pick up
4297 * @param {string} type the type of event that occurred - one of the
4298 * uiGridConstants.dataChange values (ALL, ROW, EDIT, COLUMN, OPTIONS)
4299 *
4300 * - ALL: listeners fired on any of these events, fires listeners on all events.
4301 * - ROW: fired when a row is added or removed.
4302 * - EDIT: fired when the data in a cell is edited.
4303 * - COLUMN: fired when the column definitions are modified.
4304 * - OPTIONS: fired when the grid options are modified.
4305 */
4306 Grid.prototype.notifyDataChange = function notifyDataChange(type) {
4307 var constants = uiGridConstants.dataChange;
4308
4309 if ( type === constants.ALL ||
4310 type === constants.COLUMN ||
4311 type === constants.EDIT ||
4312 type === constants.ROW ||
4313 type === constants.OPTIONS ) {
4314 this.callDataChangeCallbacks( type );
4315 }
4316 else {
4317 gridUtil.logError("Notified of a data change, but the type was not recognised, so no action taken, type was: " + type);
4318 }
4319 };
4320
4321 /**
4322 * @ngdoc function
4323 * @name columnRefreshCallback
4324 * @methodOf ui.grid.class:Grid
4325 * @description refreshes the grid when a column refresh
4326 * is notified, which triggers handling of the visible flag.
4327 * This is called on uiGridConstants.dataChange.COLUMN, and is
4328 * registered as a dataChangeCallback in grid.js
4329 * @param {object} grid The grid object.
4330 * @param {object} options Any options passed into the callback.
4331 */
4332 Grid.prototype.columnRefreshCallback = function columnRefreshCallback(grid, options) {
4333 grid.buildColumns(options);
4334 grid.queueGridRefresh();
4335 };
4336
4337 /**
4338 * @ngdoc function
4339 * @name processRowsCallback
4340 * @methodOf ui.grid.class:Grid
4341 * @description calls the row processors, specifically
4342 * intended to reset the sorting when an edit is called,
4343 * registered as a dataChangeCallback on uiGridConstants.dataChange.EDIT
4344 * @param {object} grid The grid object.
4345 */
4346 Grid.prototype.processRowsCallback = function processRowsCallback( grid ) {
4347 grid.queueGridRefresh();
4348 };
4349
4350
4351 /**
4352 * @ngdoc function
4353 * @name updateFooterHeightCallback
4354 * @methodOf ui.grid.class:Grid
4355 * @description recalculates the footer height,
4356 * registered as a dataChangeCallback on uiGridConstants.dataChange.OPTIONS
4357 * @param {object} grid The grid object.
4358 */
4359 Grid.prototype.updateFooterHeightCallback = function updateFooterHeightCallback( grid ) {
4360 grid.footerHeight = grid.calcFooterHeight();
4361 grid.columnFooterHeight = grid.calcColumnFooterHeight();
4362 };
4363
4364
4365 /**
4366 * @ngdoc function
4367 * @name getColumn
4368 * @methodOf ui.grid.class:Grid
4369 * @description returns a grid column for the column name
4370 * @param {string} name column name
4371 */
4372 Grid.prototype.getColumn = function getColumn(name) {
4373 var columns = this.columns.filter(function (column) {
4374 return column.colDef.name === name;
4375 });
4376
4377 return columns.length > 0 ? columns[0] : null;
4378 };
4379
4380 /**
4381 * @ngdoc function
4382 * @name getColDef
4383 * @methodOf ui.grid.class:Grid
4384 * @description returns a grid colDef for the column name
4385 * @param {string} name column.field
4386 */
4387 Grid.prototype.getColDef = function getColDef(name) {
4388 var colDefs = this.options.columnDefs.filter(function (colDef) {
4389 return colDef.name === name;
4390 });
4391 return colDefs.length > 0 ? colDefs[0] : null;
4392 };
4393
4394 /**
4395 * @ngdoc function
4396 * @name assignTypes
4397 * @methodOf ui.grid.class:Grid
4398 * @description uses the first row of data to assign colDef.type for any types not defined.
4399 */
4400 /**
4401 * @ngdoc property
4402 * @name type
4403 * @propertyOf ui.grid.class:GridOptions.columnDef
4404 * @description the type of the column, used in sorting. If not provided then the
4405 * grid will guess the type. Add this only if the grid guessing is not to your
4406 * satisfaction. One of:
4407 * - 'string'
4408 * - 'boolean'
4409 * - 'number'
4410 * - 'date'
4411 * - 'object'
4412 * - 'numberStr'
4413 * Note that if you choose date, your dates should be in a javascript date type
4414 *
4415 */
4416 Grid.prototype.assignTypes = function() {
4417 var self = this;
4418
4419 self.options.columnDefs.forEach(function (colDef, index) {
4420 // Assign colDef type if not specified
4421 if (!colDef.type) {
4422 var col = new GridColumn(colDef, index, self);
4423 var firstRow = self.rows.length > 0 ? self.rows[0] : null;
4424 if (firstRow) {
4425 colDef.type = gridUtil.guessType(self.getCellValue(firstRow, col));
4426 }
4427 else {
4428 colDef.type = 'string';
4429 }
4430 }
4431 });
4432 };
4433
4434
4435 /**
4436 * @ngdoc function
4437 * @name isRowHeaderColumn
4438 * @methodOf ui.grid.class:Grid
4439 * @description returns true if the column is a row Header
4440 * @param {object} column column
4441 */
4442 Grid.prototype.isRowHeaderColumn = function isRowHeaderColumn(column) {
4443 return this.rowHeaderColumns.indexOf(column) !== -1;
4444 };
4445
4446 /**
4447 * @ngdoc function
4448 * @name addRowHeaderColumn
4449 * @methodOf ui.grid.class:Grid
4450 * @description adds a row header column to the grid
4451 * @param {object} colDef Column definition object.
4452 * @param {float} order Number that indicates where the column should be placed in the grid.
4453 * @param {boolean} stopColumnBuild Prevents the buildColumn callback from being triggered. This is useful to improve
4454 * performance of the grid during initial load.
4455 */
4456 Grid.prototype.addRowHeaderColumn = function addRowHeaderColumn(colDef, order, stopColumnBuild) {
4457 var self = this;
4458
4459 // default order
4460 if (order === undefined) {
4461 order = 0;
4462 }
4463
4464 var rowHeaderCol = new GridColumn(colDef, gridUtil.nextUid(), self);
4465 rowHeaderCol.isRowHeader = true;
4466 if (self.isRTL()) {
4467 self.createRightContainer();
4468 rowHeaderCol.renderContainer = 'right';
4469 }
4470 else {
4471 self.createLeftContainer();
4472 rowHeaderCol.renderContainer = 'left';
4473 }
4474
4475 // relies on the default column builder being first in array, as it is instantiated
4476 // as part of grid creation
4477 self.columnBuilders[0](colDef,rowHeaderCol,self.options)
4478 .then(function() {
4479 rowHeaderCol.enableFiltering = false;
4480 rowHeaderCol.enableSorting = false;
4481 rowHeaderCol.enableHiding = false;
4482 rowHeaderCol.headerPriority = order;
4483 self.rowHeaderColumns.push(rowHeaderCol);
4484 self.rowHeaderColumns = self.rowHeaderColumns.sort(function (a, b) {
4485 return a.headerPriority - b.headerPriority;
4486 });
4487
4488 if (!stopColumnBuild) {
4489 self.buildColumns()
4490 .then(function() {
4491 self.preCompileCellTemplates();
4492 self.queueGridRefresh();
4493 }).catch(angular.noop);
4494 }
4495 }).catch(angular.noop);
4496 };
4497
4498 /**
4499 * @ngdoc function
4500 * @name getOnlyDataColumns
4501 * @methodOf ui.grid.class:Grid
4502 * @description returns all columns except for rowHeader columns
4503 */
4504 Grid.prototype.getOnlyDataColumns = function getOnlyDataColumns() {
4505 var self = this,
4506 cols = [];
4507
4508 self.columns.forEach(function (col) {
4509 if (self.rowHeaderColumns.indexOf(col) === -1) {
4510 cols.push(col);
4511 }
4512 });
4513 return cols;
4514 };
4515
4516 /**
4517 * @ngdoc function
4518 * @name buildColumns
4519 * @methodOf ui.grid.class:Grid
4520 * @description creates GridColumn objects from the columnDefinition. Calls each registered
4521 * columnBuilder to further process the column
4522 * @param {object} opts An object contains options to use when building columns
4523 *
4524 * * **orderByColumnDefs**: defaults to **false**. When true, `buildColumns` will reorder existing columns according to the order within the column definitions.
4525 *
4526 * @returns {Promise} a promise to load any needed column resources
4527 */
4528 Grid.prototype.buildColumns = function buildColumns(opts) {
4529 var options = {
4530 orderByColumnDefs: false
4531 };
4532
4533 angular.extend(options, opts);
4534
4535 // gridUtil.logDebug('buildColumns');
4536 var self = this;
4537 var builderPromises = [];
4538 var headerOffset = self.rowHeaderColumns.length;
4539 var i;
4540
4541 // Remove any columns for which a columnDef cannot be found
4542 // Deliberately don't use forEach, as it doesn't like splice being called in the middle
4543 // Also don't cache columns.length, as it will change during this operation
4544 for (i = 0; i < self.columns.length; i++) {
4545 if (!self.getColDef(self.columns[i].name)) {
4546 self.columns.splice(i, 1);
4547 i--;
4548 }
4549 }
4550
4551 // add row header columns to the grid columns array _after_ columns without columnDefs have been removed
4552 // rowHeaderColumns is ordered by priority so insert in reverse
4553 for (var j = self.rowHeaderColumns.length - 1; j >= 0; j--) {
4554 self.columns.unshift(self.rowHeaderColumns[j]);
4555 }
4556
4557 // look at each column def, and update column properties to match. If the column def
4558 // doesn't have a column, then splice in a new gridCol
4559 self.options.columnDefs.forEach(function (colDef, index) {
4560 self.preprocessColDef(colDef);
4561 var col = self.getColumn(colDef.name);
4562
4563 if (!col) {
4564 col = new GridColumn(colDef, gridUtil.nextUid(), self);
4565 self.columns.splice(index + headerOffset, 0, col);
4566 }
4567 else {
4568 // tell updateColumnDef that the column was pre-existing
4569 col.updateColumnDef(colDef, false);
4570 }
4571
4572 self.columnBuilders.forEach(function (builder) {
4573 builderPromises.push(builder.call(self, colDef, col, self.options));
4574 });
4575 });
4576
4577 /*** Reorder columns if necessary ***/
4578 if (!!options.orderByColumnDefs) {
4579 // Create a shallow copy of the columns as a cache
4580 var columnCache = self.columns.slice(0);
4581
4582 // We need to allow for the "row headers" when mapping from the column defs array to the columns array
4583 // If we have a row header in columns[0] and don't account for it we'll overwrite it with the column in columnDefs[0]
4584
4585 // Go through all the column defs, use the shorter of columns length and colDefs.length because if a user has given two columns the same name then
4586 // columns will be shorter than columnDefs. In this situation we'll avoid an error, but the user will still get an unexpected result
4587 var len = Math.min(self.options.columnDefs.length, self.columns.length);
4588 for (i = 0; i < len; i++) {
4589 // If the column at this index has a different name than the column at the same index in the column defs...
4590 if (self.columns[i + headerOffset].name !== self.options.columnDefs[i].name) {
4591 // Replace the one in the cache with the appropriate column
4592 columnCache[i + headerOffset] = self.getColumn(self.options.columnDefs[i].name);
4593 }
4594 else {
4595 // Otherwise just copy over the one from the initial columns
4596 columnCache[i + headerOffset] = self.columns[i + headerOffset];
4597 }
4598 }
4599
4600 // Empty out the columns array, non-destructively
4601 self.columns.length = 0;
4602
4603 // And splice in the updated, ordered columns from the cache
4604 Array.prototype.splice.apply(self.columns, [0, 0].concat(columnCache));
4605 }
4606
4607 return $q.all(builderPromises).then(function() {
4608 if (self.rows.length > 0) {
4609 self.assignTypes();
4610 }
4611 if (options.preCompileCellTemplates) {
4612 self.preCompileCellTemplates();
4613 }
4614 }).catch(angular.noop);
4615 };
4616
4617 Grid.prototype.preCompileCellTemplate = function(col) {
4618 var self = this;
4619 var html = col.cellTemplate.replace(uiGridConstants.MODEL_COL_FIELD, self.getQualifiedColField(col));
4620 html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
4621
4622 col.compiledElementFn = $compile(html);
4623
4624 if (col.compiledElementFnDefer) {
4625 col.compiledElementFnDefer.resolve(col.compiledElementFn);
4626 }
4627 };
4628
4629 /**
4630 * @ngdoc function
4631 * @name preCompileCellTemplates
4632 * @methodOf ui.grid.class:Grid
4633 * @description precompiles all cell templates
4634 */
4635 Grid.prototype.preCompileCellTemplates = function() {
4636 var self = this;
4637 self.columns.forEach(function (col) {
4638 if ( col.cellTemplate ) {
4639 self.preCompileCellTemplate( col );
4640 } else if ( col.cellTemplatePromise ) {
4641 col.cellTemplatePromise.then( function() {
4642 self.preCompileCellTemplate( col );
4643 }).catch(angular.noop);
4644 }
4645 });
4646 };
4647
4648 /**
4649 * @ngdoc function
4650 * @name getGridQualifiedColField
4651 * @methodOf ui.grid.class:Grid
4652 * @description Returns the $parse-able accessor for a column within its $scope
4653 * @param {GridColumn} col col object
4654 */
4655 Grid.prototype.getQualifiedColField = function (col) {
4656 var base = 'row.entity';
4657 if ( col.field === uiGridConstants.ENTITY_BINDING ) {
4658 return base;
4659 }
4660 return gridUtil.preEval(base + '.' + col.field);
4661 };
4662
4663 /**
4664 * @ngdoc function
4665 * @name createLeftContainer
4666 * @methodOf ui.grid.class:Grid
4667 * @description creates the left render container if it doesn't already exist
4668 */
4669 Grid.prototype.createLeftContainer = function() {
4670 if (!this.hasLeftContainer()) {
4671 this.renderContainers.left = new GridRenderContainer('left', this, { disableColumnOffset: true });
4672 }
4673 };
4674
4675 /**
4676 * @ngdoc function
4677 * @name createRightContainer
4678 * @methodOf ui.grid.class:Grid
4679 * @description creates the right render container if it doesn't already exist
4680 */
4681 Grid.prototype.createRightContainer = function() {
4682 if (!this.hasRightContainer()) {
4683 this.renderContainers.right = new GridRenderContainer('right', this, { disableColumnOffset: true });
4684 }
4685 };
4686
4687 /**
4688 * @ngdoc function
4689 * @name hasLeftContainer
4690 * @methodOf ui.grid.class:Grid
4691 * @description returns true if leftContainer exists
4692 */
4693 Grid.prototype.hasLeftContainer = function() {
4694 return this.renderContainers.left !== undefined;
4695 };
4696
4697 /**
4698 * @ngdoc function
4699 * @name hasRightContainer
4700 * @methodOf ui.grid.class:Grid
4701 * @description returns true if rightContainer exists
4702 */
4703 Grid.prototype.hasRightContainer = function() {
4704 return this.renderContainers.right !== undefined;
4705 };
4706
4707
4708 /**
4709 * undocumented function
4710 * @name preprocessColDef
4711 * @methodOf ui.grid.class:Grid
4712 * @description defaults the name property from field to maintain backwards compatibility with 2.x
4713 * validates that name or field is present
4714 */
4715 Grid.prototype.preprocessColDef = function preprocessColDef(colDef) {
4716 var self = this;
4717
4718 if (!colDef.field && !colDef.name) {
4719 throw new Error('colDef.name or colDef.field property is required');
4720 }
4721
4722 // maintain backwards compatibility with 2.x
4723 // field was required in 2.x. now name is required
4724 if (colDef.name === undefined && colDef.field !== undefined) {
4725 // See if the column name already exists:
4726 var newName = colDef.field,
4727 counter = 2;
4728 while (self.getColumn(newName)) {
4729 newName = colDef.field + counter.toString();
4730 counter++;
4731 }
4732 colDef.name = newName;
4733 }
4734 };
4735
4736 // Return a list of items that exist in the `n` array but not the `o` array. Uses optional property accessors passed as third & fourth parameters
4737 Grid.prototype.newInN = function newInN(o, n, oAccessor, nAccessor) {
4738 var self = this;
4739
4740 var t = [];
4741 for (var i = 0; i < n.length; i++) {
4742 var nV = nAccessor ? n[i][nAccessor] : n[i];
4743
4744 var found = false;
4745 for (var j = 0; j < o.length; j++) {
4746 var oV = oAccessor ? o[j][oAccessor] : o[j];
4747 if (self.options.rowEquality(nV, oV)) {
4748 found = true;
4749 break;
4750 }
4751 }
4752 if (!found) {
4753 t.push(nV);
4754 }
4755 }
4756
4757 return t;
4758 };
4759
4760 /**
4761 * @ngdoc function
4762 * @name getRow
4763 * @methodOf ui.grid.class:Grid
4764 * @description returns the GridRow that contains the rowEntity
4765 * @param {object} rowEntity the gridOptions.data array element instance
4766 * @param {array} lookInRows [optional] the rows to look in - if not provided then
4767 * looks in grid.rows
4768 */
4769 Grid.prototype.getRow = function getRow(rowEntity, lookInRows) {
4770 var self = this;
4771
4772 lookInRows = typeof(lookInRows) === 'undefined' ? self.rows : lookInRows;
4773
4774 var rows = lookInRows.filter(function (row) {
4775 return self.options.rowEquality(row.entity, rowEntity);
4776 });
4777 return rows.length > 0 ? rows[0] : null;
4778 };
4779
4780
4781 /**
4782 * @ngdoc function
4783 * @name modifyRows
4784 * @methodOf ui.grid.class:Grid
4785 * @description creates or removes GridRow objects from the newRawData array. Calls each registered
4786 * rowBuilder to further process the row
4787 * @param {array} newRawData Modified set of data
4788 *
4789 * This method aims to achieve three things:
4790 * 1. the resulting rows array is in the same order as the newRawData, we'll call
4791 * rowsProcessors immediately after to sort the data anyway
4792 * 2. if we have row hashing available, we try to use the rowHash to find the row
4793 * 3. no memory leaks - rows that are no longer in newRawData need to be garbage collected
4794 *
4795 * The basic logic flow makes use of the newRawData, oldRows and oldHash, and creates
4796 * the newRows and newHash
4797 *
4798 * ```
4799 * newRawData.forEach newEntity
4800 * if (hashing enabled)
4801 * check oldHash for newEntity
4802 * else
4803 * look for old row directly in oldRows
4804 * if !oldRowFound // must be a new row
4805 * create newRow
4806 * append to the newRows and add to newHash
4807 * run the processors
4808 * ```
4809 *
4810 * Rows are identified using the hashKey if configured. If not configured, then rows
4811 * are identified using the gridOptions.rowEquality function
4812 *
4813 * This method is useful when trying to select rows immediately after loading data without
4814 * using a $timeout/$interval, e.g.:
4815 *
4816 * $scope.gridOptions.data = someData;
4817 * $scope.gridApi.grid.modifyRows($scope.gridOptions.data);
4818 * $scope.gridApi.selection.selectRow($scope.gridOptions.data[0]);
4819 *
4820 * OR to persist row selection after data update (e.g. rows selected, new data loaded, want
4821 * originally selected rows to be re-selected))
4822 */
4823 Grid.prototype.modifyRows = function modifyRows(newRawData) {
4824 var self = this;
4825 var oldRows = self.rows.slice(0);
4826 var oldRowHash = self.rowHashMap || self.createRowHashMap();
4827 var allRowsSelected = true;
4828 self.rowHashMap = self.createRowHashMap();
4829 self.rows.length = 0;
4830
4831 newRawData.forEach( function( newEntity, i ) {
4832 var newRow, oldRow;
4833
4834 if ( self.options.enableRowHashing ) {
4835 // if hashing is enabled, then this row will be in the hash if we already know about it
4836 oldRow = oldRowHash.get( newEntity );
4837 } else {
4838 // otherwise, manually search the oldRows to see if we can find this row
4839 oldRow = self.getRow(newEntity, oldRows);
4840 }
4841
4842 // update newRow to have an entity
4843 if ( oldRow ) {
4844 newRow = oldRow;
4845 newRow.entity = newEntity;
4846 }
4847
4848 // if we didn't find the row, it must be new, so create it
4849 if ( !newRow ) {
4850 newRow = self.processRowBuilders(new GridRow(newEntity, i, self));
4851 }
4852
4853 self.rows.push( newRow );
4854 self.rowHashMap.put( newEntity, newRow );
4855 if (!newRow.isSelected) {
4856 allRowsSelected = false;
4857 }
4858 });
4859
4860 if (self.selection && self.rows.length) {
4861 self.selection.selectAll = allRowsSelected;
4862 }
4863
4864 self.assignTypes();
4865
4866 var p1 = $q.when(self.processRowsProcessors(self.rows))
4867 .then(function (renderableRows) {
4868 return self.setVisibleRows(renderableRows);
4869 }).catch(angular.noop);
4870
4871 var p2 = $q.when(self.processColumnsProcessors(self.columns))
4872 .then(function (renderableColumns) {
4873 return self.setVisibleColumns(renderableColumns);
4874 }).catch(angular.noop);
4875
4876 return $q.all([p1, p2]);
4877 };
4878
4879
4880 /**
4881 * Private Undocumented Method
4882 * @name addRows
4883 * @methodOf ui.grid.class:Grid
4884 * @description adds the newRawData array of rows to the grid and calls all registered
4885 * rowBuilders. this keyword will reference the grid
4886 */
4887 Grid.prototype.addRows = function addRows(newRawData) {
4888 var self = this,
4889 existingRowCount = self.rows.length;
4890
4891 for (var i = 0; i < newRawData.length; i++) {
4892 var newRow = self.processRowBuilders(new GridRow(newRawData[i], i + existingRowCount, self));
4893
4894 if (self.options.enableRowHashing) {
4895 var found = self.rowHashMap.get(newRow.entity);
4896 if (found) {
4897 found.row = newRow;
4898 }
4899 }
4900
4901 self.rows.push(newRow);
4902 }
4903 };
4904
4905 /**
4906 * @ngdoc function
4907 * @name processRowBuilders
4908 * @methodOf ui.grid.class:Grid
4909 * @description processes all RowBuilders for the gridRow
4910 * @param {GridRow} gridRow reference to gridRow
4911 * @returns {GridRow} the gridRow with all additional behavior added
4912 */
4913 Grid.prototype.processRowBuilders = function processRowBuilders(gridRow) {
4914 var self = this;
4915
4916 self.rowBuilders.forEach(function (builder) {
4917 builder.call(self, gridRow, self.options);
4918 });
4919
4920 return gridRow;
4921 };
4922
4923 /**
4924 * @ngdoc function
4925 * @name registerStyleComputation
4926 * @methodOf ui.grid.class:Grid
4927 * @description registered a styleComputation function
4928 *
4929 * If the function returns a value it will be appended into the grid's `<style>` block
4930 * @param {function($scope)} styleComputationInfo function
4931 */
4932 Grid.prototype.registerStyleComputation = function registerStyleComputation(styleComputationInfo) {
4933 this.styleComputations.push(styleComputationInfo);
4934 };
4935
4936 /**
4937 * @ngdoc function
4938 * @name registerRowsProcessor
4939 * @methodOf ui.grid.class:Grid
4940 * @description
4941 *
4942 * Register a "rows processor" function. When the rows are updated,
4943 * the grid calls each registered "rows processor", which has a chance
4944 * to alter the set of rows (sorting, etc) as long as the count is not
4945 * modified.
4946 *
4947 * @param {function(renderedRowsToProcess, columns )} processor rows processor function, which
4948 * is run in the context of the grid (i.e. this for the function will be the grid), and must
4949 * return the updated rows list, which is passed to the next processor in the chain
4950 * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
4951 * for other people to inject rows processors at intermediate priorities. Lower priority rowsProcessors run earlier.
4952 *
4953 * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
4954 *
4955 */
4956 Grid.prototype.registerRowsProcessor = function registerRowsProcessor(processor, priority) {
4957 if (!angular.isFunction(processor)) {
4958 throw 'Attempt to register non-function rows processor: ' + processor;
4959 }
4960
4961 this.rowsProcessors.push({processor: processor, priority: priority});
4962 this.rowsProcessors.sort(function sortByPriority( a, b ) {
4963 return a.priority - b.priority;
4964 });
4965 };
4966
4967 /**
4968 * @ngdoc function
4969 * @name removeRowsProcessor
4970 * @methodOf ui.grid.class:Grid
4971 * @param {function(renderableRows)} processor processor function
4972 * @description Remove a registered rows processor
4973 */
4974 Grid.prototype.removeRowsProcessor = function removeRowsProcessor(processor) {
4975 var idx = -1;
4976 this.rowsProcessors.forEach(function(rowsProcessor, index) {
4977 if ( rowsProcessor.processor === processor ) {
4978 idx = index;
4979 }
4980 });
4981
4982 if ( idx !== -1 ) {
4983 this.rowsProcessors.splice(idx, 1);
4984 }
4985 };
4986
4987 /**
4988 * Private Undocumented Method
4989 * @name processRowsProcessors
4990 * @methodOf ui.grid.class:Grid
4991 * @param {Array[GridRow]} renderableRows The array of "renderable" rows
4992 * @description Run all the registered rows processors on the array of renderable rows
4993 */
4994 Grid.prototype.processRowsProcessors = function processRowsProcessors(renderableRows) {
4995 var self = this;
4996
4997 // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order
4998 var myRenderableRows = renderableRows.slice(0);
4999
5000 // Return myRenderableRows with no processing if we have no rows processors
5001 if (self.rowsProcessors.length === 0) {
5002 return $q.when(myRenderableRows);
5003 }
5004
5005 // Counter for iterating through rows processors
5006 var i = 0;
5007
5008 // Promise for when we're done with all the processors
5009 var finished = $q.defer();
5010
5011 // This function will call the processor in self.rowsProcessors at index 'i', and then
5012 // when done will call the next processor in the list, using the output from the processor
5013 // at i as the argument for 'renderedRowsToProcess' on the next iteration.
5014 //
5015 // If we're at the end of the list of processors, we resolve our 'finished' callback with
5016 // the result.
5017 function startProcessor(i, renderedRowsToProcess) {
5018 // Get the processor at 'i'
5019 var processor = self.rowsProcessors[i].processor;
5020
5021 // Call the processor, passing in the rows to process and the current columns
5022 // (note: it's wrapped in $q.when() in case the processor does not return a promise)
5023 return $q.when( processor.call(self, renderedRowsToProcess, self.columns) )
5024 .then(function handleProcessedRows(processedRows) {
5025 // Check for errors
5026 if (!processedRows) {
5027 throw "Processor at index " + i + " did not return a set of renderable rows";
5028 }
5029
5030 if (!angular.isArray(processedRows)) {
5031 throw "Processor at index " + i + " did not return an array";
5032 }
5033
5034 // Processor is done, increment the counter
5035 i++;
5036
5037 // If we're not done with the processors, call the next one
5038 if (i <= self.rowsProcessors.length - 1) {
5039 return startProcessor(i, processedRows);
5040 }
5041 // We're done! Resolve the 'finished' promise
5042 else {
5043 finished.resolve(processedRows);
5044 }
5045 }).catch(function(error) {
5046 throw error;
5047 });
5048 }
5049
5050 // Start on the first processor
5051 startProcessor(0, myRenderableRows);
5052
5053 return finished.promise;
5054 };
5055
5056 Grid.prototype.setVisibleRows = function setVisibleRows(rows) {
5057 var self = this;
5058
5059 // Reset all the render container row caches
5060 for (var i in self.renderContainers) {
5061 var container = self.renderContainers[i];
5062
5063 container.canvasHeightShouldUpdate = true;
5064
5065 if ( typeof(container.visibleRowCache) === 'undefined' ) {
5066 container.visibleRowCache = [];
5067 } else {
5068 container.visibleRowCache.length = 0;
5069 }
5070 }
5071
5072 // rows.forEach(function (row) {
5073 for (var ri = 0; ri < rows.length; ri++) {
5074 var row = rows[ri];
5075
5076 var targetContainer = (typeof(row.renderContainer) !== 'undefined' && row.renderContainer) ? row.renderContainer : 'body';
5077
5078 // If the row is visible
5079 if (row.visible) {
5080 self.renderContainers[targetContainer].visibleRowCache.push(row);
5081 }
5082 }
5083 self.api.core.raise.rowsVisibleChanged(this.api);
5084 self.api.core.raise.rowsRendered(this.api);
5085 };
5086
5087 /**
5088 * @ngdoc function
5089 * @name registerColumnsProcessor
5090 * @methodOf ui.grid.class:Grid
5091 * @param {function(renderedColumnsToProcess, rows)} processor column processor function, which
5092 * is run in the context of the grid (i.e. this for the function will be the grid), and
5093 * which must return an updated renderedColumnsToProcess which can be passed to the next processor
5094 * in the chain
5095 * @param {number} priority the priority of this processor. In general we try to do them in 100s to leave room
5096 * for other people to inject columns processors at intermediate priorities. Lower priority columnsProcessors run earlier.
5097 *
5098 * At present all rows visible is running at 50, filter is running at 100, sort is at 200, grouping at 400, selectable rows at 500, pagination at 900 (pagination will generally want to be last)
5099 * @description
5100
5101 Register a "columns processor" function. When the columns are updated,
5102 the grid calls each registered "columns processor", which has a chance
5103 to alter the set of columns, as long as the count is not modified.
5104 */
5105 Grid.prototype.registerColumnsProcessor = function registerColumnsProcessor(processor, priority) {
5106 if (!angular.isFunction(processor)) {
5107 throw 'Attempt to register non-function rows processor: ' + processor;
5108 }
5109
5110 this.columnsProcessors.push({processor: processor, priority: priority});
5111 this.columnsProcessors.sort(function sortByPriority( a, b ) {
5112 return a.priority - b.priority;
5113 });
5114 };
5115
5116 Grid.prototype.removeColumnsProcessor = function removeColumnsProcessor(processor) {
5117 var idx = this.columnsProcessors.indexOf(processor);
5118
5119 if (typeof(idx) !== 'undefined' && idx !== undefined) {
5120 this.columnsProcessors.splice(idx, 1);
5121 }
5122 };
5123
5124 Grid.prototype.processColumnsProcessors = function processColumnsProcessors(renderableColumns) {
5125 var self = this;
5126
5127 // Create a shallow copy of the rows so that we can safely sort them without altering the original grid.rows sort order
5128 var myRenderableColumns = renderableColumns.slice(0);
5129
5130 // Return myRenderableRows with no processing if we have no rows processors
5131 if (self.columnsProcessors.length === 0) {
5132 return $q.when(myRenderableColumns);
5133 }
5134
5135 // Promise for when we're done with all the processors
5136 var finished = $q.defer();
5137
5138 // This function will call the processor in self.rowsProcessors at index 'i', and then
5139 // when done will call the next processor in the list, using the output from the processor
5140 // at i as the argument for 'renderedRowsToProcess' on the next iteration.
5141 //
5142 // If we're at the end of the list of processors, we resolve our 'finished' callback with
5143 // the result.
5144 function startProcessor(i, renderedColumnsToProcess) {
5145 // Get the processor at 'i'
5146 var processor = self.columnsProcessors[i].processor;
5147
5148 // Call the processor, passing in the rows to process and the current columns
5149 // (note: it's wrapped in $q.when() in case the processor does not return a promise)
5150 return $q.when( processor.call(self, renderedColumnsToProcess, self.rows) )
5151 .then(function handleProcessedRows(processedColumns) {
5152 // Check for errors
5153 if (!processedColumns) {
5154 throw "Processor at index " + i + " did not return a set of renderable rows";
5155 }
5156
5157 if (!angular.isArray(processedColumns)) {
5158 throw "Processor at index " + i + " did not return an array";
5159 }
5160
5161 // Processor is done, increment the counter
5162 i++;
5163
5164 // If we're not done with the processors, call the next one
5165 if (i <= self.columnsProcessors.length - 1) {
5166 return startProcessor(i, myRenderableColumns);
5167 }
5168 // We're done! Resolve the 'finished' promise
5169 else {
5170 finished.resolve(myRenderableColumns);
5171 }
5172 }).catch(angular.noop);
5173 }
5174
5175 // Start on the first processor
5176 startProcessor(0, myRenderableColumns);
5177
5178 return finished.promise;
5179 };
5180
5181 Grid.prototype.setVisibleColumns = function setVisibleColumns(columns) {
5182 // gridUtil.logDebug('setVisibleColumns');
5183
5184 var self = this;
5185
5186 // Reset all the render container row caches
5187 for (var i in self.renderContainers) {
5188 var container = self.renderContainers[i];
5189
5190 container.visibleColumnCache.length = 0;
5191 }
5192
5193 for (var ci = 0; ci < columns.length; ci++) {
5194 var column = columns[ci];
5195
5196 // If the column is visible
5197 if (column.visible) {
5198 // If the column has a container specified
5199 if (typeof(column.renderContainer) !== 'undefined' && column.renderContainer) {
5200 self.renderContainers[column.renderContainer].visibleColumnCache.push(column);
5201 }
5202 // If not, put it into the body container
5203 else {
5204 self.renderContainers.body.visibleColumnCache.push(column);
5205 }
5206 }
5207 }
5208 };
5209
5210 /**
5211 * @ngdoc function
5212 * @name handleWindowResize
5213 * @methodOf ui.grid.class:Grid
5214 * @description Triggered when the browser window resizes; automatically resizes the grid
5215 * @returns {Promise} A resolved promise once the window resize has completed.
5216 */
5217 Grid.prototype.handleWindowResize = function handleWindowResize($event) {
5218 var self = this;
5219
5220 self.gridWidth = gridUtil.elementWidth(self.element);
5221 self.gridHeight = gridUtil.elementHeight(self.element);
5222
5223 return self.queueRefresh();
5224 };
5225
5226 /**
5227 * @ngdoc function
5228 * @name queueRefresh
5229 * @methodOf ui.grid.class:Grid
5230 * @description queues a grid refreshCanvas, a way of debouncing all the refreshes we might otherwise issue
5231 */
5232 Grid.prototype.queueRefresh = function queueRefresh() {
5233 var self = this;
5234
5235 if (self.refreshCanceller) {
5236 $timeout.cancel(self.refreshCanceller);
5237 }
5238
5239 self.refreshCanceller = $timeout(function () {
5240 self.refreshCanvas(true);
5241 });
5242
5243 self.refreshCanceller.then(function () {
5244 self.refreshCanceller = null;
5245 }).catch(angular.noop);
5246
5247 return self.refreshCanceller;
5248 };
5249
5250
5251 /**
5252 * @ngdoc function
5253 * @name queueGridRefresh
5254 * @methodOf ui.grid.class:Grid
5255 * @description queues a grid refresh, a way of debouncing all the refreshes we might otherwise issue
5256 */
5257 Grid.prototype.queueGridRefresh = function queueGridRefresh() {
5258 var self = this;
5259
5260 if (self.gridRefreshCanceller) {
5261 $timeout.cancel(self.gridRefreshCanceller);
5262 }
5263
5264 self.gridRefreshCanceller = $timeout(function () {
5265 self.refresh(true);
5266 });
5267
5268 self.gridRefreshCanceller.then(function () {
5269 self.gridRefreshCanceller = null;
5270 }).catch(angular.noop);
5271
5272 return self.gridRefreshCanceller;
5273 };
5274
5275
5276 /**
5277 * @ngdoc function
5278 * @name updateCanvasHeight
5279 * @methodOf ui.grid.class:Grid
5280 * @description flags all render containers to update their canvas height
5281 */
5282 Grid.prototype.updateCanvasHeight = function updateCanvasHeight() {
5283 var self = this;
5284
5285 for (var containerId in self.renderContainers) {
5286 if (self.renderContainers.hasOwnProperty(containerId)) {
5287 var container = self.renderContainers[containerId];
5288 container.canvasHeightShouldUpdate = true;
5289 }
5290 }
5291 };
5292
5293 /**
5294 * @ngdoc function
5295 * @name buildStyles
5296 * @methodOf ui.grid.class:Grid
5297 * @description calls each styleComputation function
5298 */
5299 Grid.prototype.buildStyles = function buildStyles() {
5300 var self = this;
5301
5302 // gridUtil.logDebug('buildStyles');
5303
5304 self.customStyles = '';
5305
5306 self.styleComputations
5307 .sort(function(a, b) {
5308 if (a.priority === null) { return 1; }
5309 if (b.priority === null) { return -1; }
5310 if (a.priority === null && b.priority === null) { return 0; }
5311 return a.priority - b.priority;
5312 })
5313 .forEach(function (compInfo) {
5314 // this used to provide $scope as a second parameter, but I couldn't find any
5315 // style builders that used it, so removed it as part of moving to grid from controller
5316 var ret = compInfo.func.call(self);
5317
5318 if (angular.isString(ret)) {
5319 self.customStyles += '\n' + ret;
5320 }
5321 });
5322 };
5323
5324
5325 Grid.prototype.minColumnsToRender = function minColumnsToRender() {
5326 var self = this;
5327 var viewport = this.getViewportWidth();
5328
5329 var min = 0;
5330 var totalWidth = 0;
5331 self.columns.forEach(function(col, i) {
5332 if (totalWidth < viewport) {
5333 totalWidth += col.drawnWidth;
5334 min++;
5335 }
5336 else {
5337 var currWidth = 0;
5338 for (var j = i; j >= i - min; j--) {
5339 currWidth += self.columns[j].drawnWidth;
5340 }
5341 if (currWidth < viewport) {
5342 min++;
5343 }
5344 }
5345 });
5346
5347 return min;
5348 };
5349
5350 Grid.prototype.getBodyHeight = function getBodyHeight() {
5351 return this.getViewportHeight();
5352 };
5353
5354 // NOTE: viewport drawable height is the height of the grid minus the header row height (including any border)
5355 // TODO(c0bra): account for footer height
5356 Grid.prototype.getViewportHeight = function getViewportHeight() {
5357 var self = this;
5358
5359 var viewPortHeight = this.gridHeight - this.headerHeight - this.footerHeight;
5360
5361 // Account for native horizontal scrollbar, if present
5362 // if (typeof(this.horizontalScrollbarHeight) !== 'undefined' && this.horizontalScrollbarHeight !== undefined && this.horizontalScrollbarHeight > 0) {
5363 // viewPortHeight = viewPortHeight - this.horizontalScrollbarHeight;
5364 // }
5365
5366 var adjustment = self.getViewportAdjustment();
5367
5368 viewPortHeight = viewPortHeight + adjustment.height;
5369
5370 // gridUtil.logDebug('viewPortHeight', viewPortHeight);
5371
5372 return viewPortHeight;
5373 };
5374
5375 Grid.prototype.getViewportWidth = function getViewportWidth() {
5376 var self = this;
5377
5378 var viewPortWidth = this.gridWidth;
5379
5380 // if (typeof(this.verticalScrollbarWidth) !== 'undefined' && this.verticalScrollbarWidth !== undefined && this.verticalScrollbarWidth > 0) {
5381 // viewPortWidth = viewPortWidth - this.verticalScrollbarWidth;
5382 // }
5383
5384 var adjustment = self.getViewportAdjustment();
5385
5386 viewPortWidth = viewPortWidth + adjustment.width;
5387
5388 // gridUtil.logDebug('getviewPortWidth', viewPortWidth);
5389
5390 return viewPortWidth;
5391 };
5392
5393 Grid.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {
5394 return this.getViewportWidth();
5395 };
5396
5397 Grid.prototype.addVerticalScrollSync = function (containerId, callBackFn) {
5398 this.verticalScrollSyncCallBackFns[containerId] = callBackFn;
5399 };
5400
5401 Grid.prototype.addHorizontalScrollSync = function (containerId, callBackFn) {
5402 this.horizontalScrollSyncCallBackFns[containerId] = callBackFn;
5403 };
5404
5405 /**
5406 * Scroll needed containers by calling their ScrollSyncs
5407 * @param sourceContainerId the containerId that has already set it's top/left.
5408 * can be empty string which means all containers need to set top/left
5409 * @param scrollEvent
5410 */
5411 Grid.prototype.scrollContainers = function (sourceContainerId, scrollEvent) {
5412 if (scrollEvent.y) {
5413 // default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)
5414 var verts = ['body','left', 'right'];
5415
5416 this.flagScrollingVertically(scrollEvent);
5417
5418 if (sourceContainerId === 'body') {
5419 verts = ['left', 'right'];
5420 }
5421 else if (sourceContainerId === 'left') {
5422 verts = ['body', 'right'];
5423 }
5424 else if (sourceContainerId === 'right') {
5425 verts = ['body', 'left'];
5426 }
5427
5428 for (var i = 0; i < verts.length; i++) {
5429 var id = verts[i];
5430 if (this.verticalScrollSyncCallBackFns[id]) {
5431 this.verticalScrollSyncCallBackFns[id](scrollEvent);
5432 }
5433 }
5434
5435 }
5436
5437 if (scrollEvent.x) {
5438 // default for no container Id (ex. mousewheel means that all containers must set scrollTop/Left)
5439 var horizs = ['body','bodyheader', 'bodyfooter'];
5440
5441 this.flagScrollingHorizontally(scrollEvent);
5442 if (sourceContainerId === 'body') {
5443 horizs = ['bodyheader', 'bodyfooter'];
5444 }
5445
5446 for (var j = 0; j < horizs.length; j++) {
5447 var idh = horizs[j];
5448 if (this.horizontalScrollSyncCallBackFns[idh]) {
5449 this.horizontalScrollSyncCallBackFns[idh](scrollEvent);
5450 }
5451 }
5452 }
5453 };
5454
5455 Grid.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {
5456 this.viewportAdjusters.push(func);
5457 };
5458
5459 Grid.prototype.removeViewportAdjuster = function registerViewportAdjuster(func) {
5460 var idx = this.viewportAdjusters.indexOf(func);
5461
5462 if (typeof(idx) !== 'undefined' && idx !== undefined) {
5463 this.viewportAdjusters.splice(idx, 1);
5464 }
5465 };
5466
5467 Grid.prototype.getViewportAdjustment = function getViewportAdjustment() {
5468 var self = this;
5469
5470 var adjustment = { height: 0, width: 0 };
5471
5472 self.viewportAdjusters.forEach(function (func) {
5473 adjustment = func.call(this, adjustment);
5474 });
5475
5476 return adjustment;
5477 };
5478
5479 Grid.prototype.getVisibleRowCount = function getVisibleRowCount() {
5480 // return this.visibleRowCache.length;
5481 return this.renderContainers.body.visibleRowCache.length;
5482 };
5483
5484 Grid.prototype.getVisibleRows = function getVisibleRows() {
5485 return this.renderContainers.body.visibleRowCache;
5486 };
5487
5488 Grid.prototype.getVisibleColumnCount = function getVisibleColumnCount() {
5489 // return this.visibleRowCache.length;
5490 return this.renderContainers.body.visibleColumnCache.length;
5491 };
5492
5493
5494 Grid.prototype.searchRows = function searchRows(renderableRows) {
5495 return rowSearcher.search(this, renderableRows, this.columns);
5496 };
5497
5498 Grid.prototype.sortByColumn = function sortByColumn(renderableRows) {
5499 return rowSorter.sort(this, renderableRows, this.columns);
5500 };
5501
5502 /**
5503 * @ngdoc function
5504 * @name getCellValue
5505 * @methodOf ui.grid.class:Grid
5506 * @description Gets the value of a cell for a particular row and column
5507 * @param {GridRow} row Row to access
5508 * @param {GridColumn} col Column to access
5509 */
5510 Grid.prototype.getCellValue = function getCellValue(row, col) {
5511 if ( typeof(row.entity[ '$$' + col.uid ]) !== 'undefined' ) {
5512 return row.entity[ '$$' + col.uid].rendered;
5513 }
5514 else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined' ) {
5515 return row.entity[col.field];
5516 }
5517 else {
5518 if (!col.cellValueGetterCache) {
5519 col.cellValueGetterCache = $parse(row.getEntityQualifiedColField(col));
5520 }
5521
5522 return col.cellValueGetterCache(row);
5523 }
5524 };
5525
5526 /**
5527 * @ngdoc function
5528 * @name getCellDisplayValue
5529 * @methodOf ui.grid.class:Grid
5530 * @description Gets the displayed value of a cell after applying any the `cellFilter`
5531 * @param {GridRow} row Row to access
5532 * @param {GridColumn} col Column to access
5533 */
5534 Grid.prototype.getCellDisplayValue = function getCellDisplayValue(row, col) {
5535 if ( !col.cellDisplayGetterCache ) {
5536 var custom_filter = col.cellFilter ? " | " + col.cellFilter : "";
5537
5538 if (typeof(row.entity['$$' + col.uid]) !== 'undefined') {
5539 col.cellDisplayGetterCache = $parse(row.entity['$$' + col.uid].rendered + custom_filter);
5540 }
5541 else if (this.options.flatEntityAccess && typeof(col.field) !== 'undefined') {
5542 var colField = col.field.replace(/(')|(\\)/g, "\\$&");
5543
5544 col.cellDisplayGetterCache = $parse('entity[\'' + colField + '\']' + custom_filter);
5545 }
5546 else {
5547 col.cellDisplayGetterCache = $parse(row.getEntityQualifiedColField(col) + custom_filter);
5548 }
5549 }
5550
5551 var rowWithCol = angular.extend({}, row, {col: col});
5552
5553 return col.cellDisplayGetterCache(rowWithCol);
5554 };
5555
5556
5557 Grid.prototype.getNextColumnSortPriority = function getNextColumnSortPriority() {
5558 var self = this,
5559 p = 0;
5560
5561 self.columns.forEach(function (col) {
5562 if (col.sort && col.sort.priority !== undefined && col.sort.priority >= p) {
5563 p = col.sort.priority + 1;
5564 }
5565 });
5566
5567 return p;
5568 };
5569
5570 /**
5571 * @ngdoc function
5572 * @name resetColumnSorting
5573 * @methodOf ui.grid.class:Grid
5574 * @description Return the columns that the grid is currently being sorted by
5575 * @param {GridColumn} [excludedColumn] Optional GridColumn to exclude from having its sorting reset
5576 */
5577 Grid.prototype.resetColumnSorting = function resetColumnSorting(excludeCol) {
5578 var self = this;
5579
5580 self.columns.forEach(function (col) {
5581 if (col !== excludeCol && !col.suppressRemoveSort) {
5582 col.sort = {};
5583 }
5584 });
5585 };
5586
5587 /**
5588 * @ngdoc function
5589 * @name getColumnSorting
5590 * @methodOf ui.grid.class:Grid
5591 * @description Return the columns that the grid is currently being sorted by
5592 * @returns {Array[GridColumn]} An array of GridColumn objects
5593 */
5594 Grid.prototype.getColumnSorting = function getColumnSorting() {
5595 var self = this;
5596
5597 var sortedCols = [], myCols;
5598
5599 // Iterate through all the columns, sorted by priority
5600 // Make local copy of column list, because sorting is in-place and we do not want to
5601 // change the original sequence of columns
5602 myCols = self.columns.slice(0);
5603 myCols.sort(rowSorter.prioritySort).forEach(function (col) {
5604 if (col.sort && typeof(col.sort.direction) !== 'undefined' && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {
5605 sortedCols.push(col);
5606 }
5607 });
5608
5609 return sortedCols;
5610 };
5611
5612 /**
5613 * @ngdoc function
5614 * @name sortColumn
5615 * @methodOf ui.grid.class:Grid
5616 * @description Set the sorting on a given column, optionally resetting any existing sorting on the Grid.
5617 * Emits the sortChanged event whenever the sort criteria are changed.
5618 * @param {GridColumn} column Column to set the sorting on
5619 * @param {uiGridConstants.ASC|uiGridConstants.DESC} [direction] Direction to sort by, either descending or ascending.
5620 * If not provided, the column will iterate through the sort directions
5621 * specified in the {@link ui.grid.class:GridOptions.columnDef#sortDirectionCycle sortDirectionCycle} attribute.
5622 * @param {boolean} [add] Add this column to the sorting. If not provided or set to `false`, the Grid will reset any existing sorting and sort
5623 * by this column only
5624 * @returns {Promise} A resolved promise that supplies the column.
5625 */
5626
5627 Grid.prototype.sortColumn = function sortColumn(column, directionOrAdd, add) {
5628 var self = this,
5629 direction = null;
5630
5631 if (typeof(column) === 'undefined' || !column) {
5632 throw new Error('No column parameter provided');
5633 }
5634
5635 // Second argument can either be a direction or whether to add this column to the existing sort.
5636 // If it's a boolean, it's an add, otherwise, it's a direction
5637 if (typeof(directionOrAdd) === 'boolean') {
5638 add = directionOrAdd;
5639 }
5640 else {
5641 direction = directionOrAdd;
5642 }
5643
5644 if (!add) {
5645 self.resetColumnSorting(column);
5646 column.sort.priority = undefined;
5647 // Get the actual priority since there may be columns which have suppressRemoveSort set
5648 column.sort.priority = self.getNextColumnSortPriority();
5649 }
5650 else if (column.sort.priority === undefined) {
5651 column.sort.priority = self.getNextColumnSortPriority();
5652 }
5653
5654 if (!direction) {
5655 // Find the current position in the cycle (or -1).
5656 var i = column.sortDirectionCycle.indexOf(column.sort.direction ? column.sort.direction : null);
5657 // Proceed to the next position in the cycle (or start at the beginning).
5658 i = (i+1) % column.sortDirectionCycle.length;
5659 // If suppressRemoveSort is set, and the next position in the cycle would
5660 // remove the sort, skip it.
5661 if (column.colDef && column.suppressRemoveSort && !column.sortDirectionCycle[i]) {
5662 i = (i+1) % column.sortDirectionCycle.length;
5663 }
5664
5665 if (column.sortDirectionCycle[i]) {
5666 column.sort.direction = column.sortDirectionCycle[i];
5667 } else {
5668 removeSortOfColumn(column, self);
5669 }
5670 }
5671 else {
5672 column.sort.direction = direction;
5673 }
5674
5675 self.api.core.raise.sortChanged( self, self.getColumnSorting() );
5676
5677 return $q.when(column);
5678 };
5679
5680 var removeSortOfColumn = function removeSortOfColumn(column, grid) {
5681 // Decrease priority for every col where priority is higher than the removed sort's priority.
5682 grid.columns.forEach(function (col) {
5683 if (col.sort && col.sort.priority !== undefined && col.sort.priority > column.sort.priority) {
5684 col.sort.priority -= 1;
5685 }
5686 });
5687
5688 // Remove sort
5689 column.sort = {};
5690 };
5691
5692 /**
5693 * communicate to outside world that we are done with initial rendering
5694 */
5695 Grid.prototype.renderingComplete = function() {
5696 if (angular.isFunction(this.options.onRegisterApi)) {
5697 this.options.onRegisterApi(this.api);
5698 }
5699 this.api.core.raise.renderingComplete( this.api );
5700 };
5701
5702 Grid.prototype.createRowHashMap = function createRowHashMap() {
5703 var self = this;
5704
5705 var hashMap = new RowHashMap();
5706 hashMap.grid = self;
5707
5708 return hashMap;
5709 };
5710
5711
5712 /**
5713 * @ngdoc function
5714 * @name refresh
5715 * @methodOf ui.grid.class:Grid
5716 * @description Refresh the rendered grid on screen.
5717 * @param {boolean} [rowsAltered] Optional flag for refreshing when the number of rows has changed.
5718 */
5719 Grid.prototype.refresh = function refresh(rowsAltered) {
5720 var self = this;
5721
5722 var p1 = self.processRowsProcessors(self.rows).then(function (renderableRows) {
5723 self.setVisibleRows(renderableRows);
5724 }).catch(angular.noop);
5725
5726 var p2 = self.processColumnsProcessors(self.columns).then(function (renderableColumns) {
5727 self.setVisibleColumns(renderableColumns);
5728 }).catch(angular.noop);
5729
5730 return $q.all([p1, p2]).then(function () {
5731 self.refreshCanvas(true);
5732 self.redrawInPlace(rowsAltered);
5733 }).catch(angular.noop);
5734 };
5735
5736 /**
5737 * @ngdoc function
5738 * @name refreshRows
5739 * @methodOf ui.grid.class:Grid
5740 * @description Refresh the rendered rows on screen? Note: not functional at present
5741 * @returns {promise} promise that is resolved when render completes?
5742 *
5743 */
5744 Grid.prototype.refreshRows = function refreshRows() {
5745 var self = this;
5746
5747 return self.processRowsProcessors(self.rows)
5748 .then(function (renderableRows) {
5749 self.setVisibleRows(renderableRows);
5750
5751 self.redrawInPlace();
5752
5753 self.refreshCanvas( true );
5754 }).catch(angular.noop);
5755 };
5756
5757 /**
5758 * @ngdoc function
5759 * @name refreshCanvas
5760 * @methodOf ui.grid.class:Grid
5761 * @description Builds all styles and recalculates much of the grid sizing
5762 * @param {object} buildStyles optional parameter. Use TBD
5763 * @returns {promise} promise that is resolved when the canvas
5764 * has been refreshed
5765 *
5766 */
5767 Grid.prototype.refreshCanvas = function(buildStyles) {
5768 var self = this;
5769
5770 // gridUtil.logDebug('refreshCanvas');
5771
5772 var p = $q.defer();
5773
5774 // Get all the header heights
5775 var containerHeadersToRecalc = [];
5776 for (var containerId in self.renderContainers) {
5777 if (self.renderContainers.hasOwnProperty(containerId)) {
5778 var container = self.renderContainers[containerId];
5779
5780 // Skip containers that have no canvasWidth set yet
5781 if (container.canvasWidth === null || isNaN(container.canvasWidth)) {
5782 continue;
5783 }
5784
5785 if (container.header || container.headerCanvas) {
5786 container.explicitHeaderHeight = container.explicitHeaderHeight || null;
5787 container.explicitHeaderCanvasHeight = container.explicitHeaderCanvasHeight || null;
5788
5789 containerHeadersToRecalc.push(container);
5790 }
5791 }
5792 }
5793
5794 // Build the styles without the explicit header heights
5795 if (buildStyles) {
5796 self.buildStyles();
5797 }
5798
5799 /*
5800 *
5801 * Here we loop through the headers, measuring each element as well as any header "canvas" it has within it.
5802 *
5803 * If any header is less than the largest header height, it will be resized to that so that we don't have headers
5804 * with different heights, which looks like a rendering problem
5805 *
5806 * We'll do the same thing with the header canvases, and give the header CELLS an explicit height if their canvas
5807 * is smaller than the largest canvas height. That was header cells without extra controls like filtering don't
5808 * appear shorter than other cells.
5809 *
5810 */
5811 if (containerHeadersToRecalc.length > 0) {
5812 // Putting in a timeout as it's not calculating after the grid element is rendered and filled out
5813 $timeout(function() {
5814 // var oldHeaderHeight = self.grid.headerHeight;
5815 // self.grid.headerHeight = gridUtil.outerElementHeight(self.header);
5816
5817 var rebuildStyles = false;
5818
5819 // Get all the header heights
5820 var maxHeaderHeight = 0;
5821 var maxHeaderCanvasHeight = 0;
5822 var i, container;
5823 var getHeight = function(oldVal, newVal) {
5824 if ( oldVal !== newVal) {
5825 rebuildStyles = true;
5826 }
5827 return newVal;
5828 };
5829 for (i = 0; i < containerHeadersToRecalc.length; i++) {
5830 container = containerHeadersToRecalc[i];
5831
5832 // Skip containers that have no canvasWidth set yet
5833 if (container.canvasWidth === null || isNaN(container.canvasWidth)) {
5834 continue;
5835 }
5836
5837 if (container.header) {
5838 var headerHeight = container.headerHeight = getHeight(container.headerHeight, gridUtil.outerElementHeight(container.header));
5839
5840 // Get the "inner" header height, that is the height minus the top and bottom borders, if present. We'll use it to make sure all the headers have a consistent height
5841 var topBorder = gridUtil.getBorderSize(container.header, 'top');
5842 var bottomBorder = gridUtil.getBorderSize(container.header, 'bottom');
5843 var innerHeaderHeight = parseInt(headerHeight - topBorder - bottomBorder, 10);
5844
5845 innerHeaderHeight = innerHeaderHeight < 0 ? 0 : innerHeaderHeight;
5846
5847 container.innerHeaderHeight = innerHeaderHeight;
5848
5849 // If the header doesn't have an explicit height set, save the largest header height for use later
5850 // Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly
5851 if (!container.explicitHeaderHeight && innerHeaderHeight > maxHeaderHeight) {
5852 maxHeaderHeight = innerHeaderHeight;
5853 }
5854 }
5855
5856 if (container.headerCanvas) {
5857 var headerCanvasHeight = container.headerCanvasHeight = getHeight(container.headerCanvasHeight, parseInt(gridUtil.outerElementHeight(container.headerCanvas), 10));
5858
5859
5860 // If the header doesn't have an explicit canvas height, save the largest header canvas height for use later
5861 // Explicit header heights are based off of the max we are calculating here. We never want to base the max on something we're setting explicitly
5862 if (!container.explicitHeaderCanvasHeight && headerCanvasHeight > maxHeaderCanvasHeight) {
5863 maxHeaderCanvasHeight = headerCanvasHeight;
5864 }
5865 }
5866 }
5867
5868 // Go through all the headers
5869 for (i = 0; i < containerHeadersToRecalc.length; i++) {
5870 container = containerHeadersToRecalc[i];
5871
5872 /* If:
5873 1. We have a max header height
5874 2. This container has a header height defined
5875 3. And either this container has an explicit header height set, OR its header height is less than the max
5876
5877 then:
5878
5879 Give this container's header an explicit height so it will line up with the tallest header
5880 */
5881 if (
5882 maxHeaderHeight > 0 && typeof(container.headerHeight) !== 'undefined' && container.headerHeight !== null &&
5883 (container.explicitHeaderHeight || container.headerHeight < maxHeaderHeight)
5884 ) {
5885 container.explicitHeaderHeight = getHeight(container.explicitHeaderHeight, maxHeaderHeight);
5886 }
5887
5888 // Do the same as above except for the header canvas
5889 if (
5890 maxHeaderCanvasHeight > 0 && typeof(container.headerCanvasHeight) !== 'undefined' && container.headerCanvasHeight !== null &&
5891 (container.explicitHeaderCanvasHeight || container.headerCanvasHeight < maxHeaderCanvasHeight)
5892 ) {
5893 container.explicitHeaderCanvasHeight = getHeight(container.explicitHeaderCanvasHeight, maxHeaderCanvasHeight);
5894 }
5895 }
5896
5897 // Rebuild styles if the header height has changed
5898 // The header height is used in body/viewport calculations and those are then used in other styles so we need it to be available
5899 if (buildStyles && rebuildStyles) {
5900 self.buildStyles();
5901 }
5902
5903 p.resolve();
5904 });
5905 }
5906 else {
5907 // Timeout still needs to be here to trigger digest after styles have been rebuilt
5908 $timeout(function() {
5909 p.resolve();
5910 });
5911 }
5912
5913 return p.promise;
5914 };
5915
5916 function getPrevScrollValue(rowsAdded, prevScrollVal) {
5917 return rowsAdded || prevScrollVal > 0 ? prevScrollVal : null;
5918 }
5919
5920 /**
5921 * @ngdoc function
5922 * @name redrawInPlace
5923 * @methodOf ui.grid.class:Grid
5924 * @description Redraw the rows and columns based on our current scroll position
5925 * @param {boolean} [rowsAdded] Optional to indicate rows are added and the scroll percentage must be recalculated
5926 *
5927 */
5928 Grid.prototype.redrawInPlace = function redrawInPlace(rowsAdded) {
5929 // gridUtil.logDebug('redrawInPlace');
5930
5931 var self = this;
5932
5933 for (var i in self.renderContainers) {
5934 var container = self.renderContainers[i],
5935 prevScrollTop = getPrevScrollValue(rowsAdded, container.prevScrollTop),
5936 prevScrollLeft = getPrevScrollValue(rowsAdded, container.prevScrollLeft),
5937 prevScrolltopPercentage = rowsAdded || prevScrollTop > 0 ? null : container.prevScrolltopPercentage,
5938 prevScrollleftPercentage = rowsAdded || prevScrollLeft > 0 ? null : container.prevScrollleftPercentage;
5939
5940 // gridUtil.logDebug('redrawing container', i);
5941
5942 container.adjustRows(prevScrollTop, prevScrolltopPercentage);
5943 container.adjustColumns(prevScrollLeft, prevScrollleftPercentage);
5944 }
5945 };
5946
5947 /**
5948 * @ngdoc function
5949 * @name hasLeftContainerColumns
5950 * @methodOf ui.grid.class:Grid
5951 * @description returns true if leftContainer has columns
5952 */
5953 Grid.prototype.hasLeftContainerColumns = function () {
5954 return this.hasLeftContainer() && this.renderContainers.left.renderedColumns.length > 0;
5955 };
5956
5957 /**
5958 * @ngdoc function
5959 * @name hasRightContainerColumns
5960 * @methodOf ui.grid.class:Grid
5961 * @description returns true if rightContainer has columns
5962 */
5963 Grid.prototype.hasRightContainerColumns = function () {
5964 return this.hasRightContainer() && this.renderContainers.right.renderedColumns.length > 0;
5965 };
5966
5967 // Turn the scroll position into a percentage and make it an argument for a scroll event
5968 function getScrollPercentage(scrollPixels, scrollLength) {
5969 var percentage = scrollPixels / scrollLength;
5970
5971 // if the percentage is greater than 1, set it to 1
5972 return percentage <= 1 ? percentage : 1;
5973 }
5974
5975 // Only returns the scroll Y position if the percentage is different from the previous
5976 function getScrollY(scrollPixels, scrollLength, prevScrolltopPercentage) {
5977 var scrollPercentage = getScrollPercentage(scrollPixels, scrollLength);
5978
5979 if (scrollPercentage !== prevScrolltopPercentage) {
5980 return { percentage: getScrollPercentage(scrollPixels, scrollLength) };
5981 }
5982
5983 return undefined;
5984 }
5985
5986 // Only returns the scroll X position if the percentage is different from the previous
5987 function getScrollX(horizScrollPixels, horizScrollLength, prevScrollleftPercentage) {
5988 var horizPercentage = horizScrollPixels / horizScrollLength;
5989 horizPercentage = (horizPercentage > 1) ? 1 : horizPercentage;
5990
5991 if (horizPercentage !== prevScrollleftPercentage) {
5992 return { percentage: horizPercentage };
5993 }
5994
5995 return undefined;
5996 }
5997
5998 /**
5999 * @ngdoc method
6000 * @methodOf ui.grid.class:Grid
6001 * @name scrollToIfNecessary
6002 * @description Scrolls the grid to make a certain row and column combo visible,
6003 * in the case that it is not completely visible on the screen already.
6004 * @param {GridRow} gridRow row to make visible
6005 * @param {GridColumn} gridCol column to make visible
6006 * @returns {promise} a promise that is resolved when scrolling is complete
6007 */
6008 Grid.prototype.scrollToIfNecessary = function (gridRow, gridCol) {
6009 var self = this;
6010
6011 var scrollEvent = new ScrollEvent(self, 'uiGrid.scrollToIfNecessary');
6012
6013 // Alias the visible row and column caches
6014 var visRowCache = self.renderContainers.body.visibleRowCache;
6015 var visColCache = self.renderContainers.body.visibleColumnCache;
6016
6017 /*-- Get the top, left, right, and bottom "scrolled" edges of the grid --*/
6018
6019 // The top boundary is the current Y scroll position PLUS the header height, because the header can obscure rows when the grid is scrolled downwards
6020 var topBound = self.renderContainers.body.prevScrollTop + self.headerHeight;
6021
6022 // Don't the let top boundary be less than 0
6023 topBound = (topBound < 0) ? 0 : topBound;
6024
6025 // The left boundary is the current X scroll position
6026 var leftBound = self.renderContainers.body.prevScrollLeft;
6027
6028 // The bottom boundary is the current Y scroll position, plus the height of the grid, but minus the header height.
6029 // Basically this is the viewport height added on to the scroll position
6030 var bottomBound = self.renderContainers.body.prevScrollTop + self.gridHeight - self.renderContainers.body.headerHeight - self.footerHeight - self.scrollbarHeight;
6031
6032 // If there's a horizontal scrollbar, remove its height from the bottom boundary, otherwise we'll be letting it obscure rows
6033 // if (self.horizontalScrollbarHeight) {
6034 // bottomBound = bottomBound - self.horizontalScrollbarHeight;
6035 // }
6036
6037 // The right position is the current X scroll position minus the grid width
6038 var rightBound = self.renderContainers.body.prevScrollLeft + Math.ceil(self.renderContainers.body.getViewportWidth());
6039
6040 // If there's a vertical scrollbar, subtract it from the right boundary or we'll allow it to obscure cells
6041 // if (self.verticalScrollbarWidth) {
6042 // rightBound = rightBound - self.verticalScrollbarWidth;
6043 // }
6044
6045 // We were given a row to scroll to
6046 if (gridRow !== null) {
6047 // This is the index of the row we want to scroll to, within the list of rows that can be visible
6048 var seekRowIndex = visRowCache.indexOf(gridRow);
6049
6050 // Total vertical scroll length of the grid
6051 var scrollLength = (self.renderContainers.body.getCanvasHeight() - self.renderContainers.body.getViewportHeight());
6052
6053 // Add the height of the native horizontal scrollbar to the scroll length, if it's there. Otherwise it will mask over the final row
6054 // if (self.horizontalScrollbarHeight && self.horizontalScrollbarHeight > 0) {
6055 // scrollLength = scrollLength + self.horizontalScrollbarHeight;
6056 // }
6057
6058 // This is the minimum amount of pixels we need to scroll vertical in order to see this row.
6059 var pixelsToSeeRow = (seekRowIndex * self.options.rowHeight + self.headerHeight);
6060
6061 // Don't let the pixels required to see the row be less than zero
6062 pixelsToSeeRow = (pixelsToSeeRow < 0) ? 0 : pixelsToSeeRow;
6063
6064 var scrollPixels;
6065
6066 // If the scroll position we need to see the row is LESS than the top boundary, i.e. obscured above the top of the self...
6067 if (pixelsToSeeRow < Math.floor(topBound)) {
6068 // Get the different between the top boundary and the required scroll position and subtract it from the current scroll position\
6069 // to get the full position we need
6070 scrollPixels = self.renderContainers.body.prevScrollTop - (topBound - pixelsToSeeRow);
6071
6072 // Since scrollIfNecessary is called multiple times when enableCellEditOnFocus is true we need to make sure the scrollbarWidth and
6073 // footerHeight is accounted for to not cause a loop.
6074 if (gridCol && gridCol.colDef && gridCol.colDef.enableCellEditOnFocus) {
6075 scrollPixels = scrollPixels - self.footerHeight - self.scrollbarHeight;
6076 }
6077
6078 scrollEvent.y = getScrollY(scrollPixels, scrollLength, self.renderContainers.body.prevScrolltopPercentage);
6079 }
6080 // Otherwise if the scroll position we need to see the row is MORE than the bottom boundary, i.e. obscured below the bottom of the self...
6081 else if (pixelsToSeeRow > Math.ceil(bottomBound)) {
6082 // Get the different between the bottom boundary and the required scroll position and add it to the current scroll position
6083 // to get the full position we need
6084 scrollPixels = pixelsToSeeRow - bottomBound + self.renderContainers.body.prevScrollTop;
6085
6086 scrollEvent.y = getScrollY(scrollPixels, scrollLength,self.renderContainers.body.prevScrolltopPercentage);
6087 }
6088 }
6089
6090 // We were given a column to scroll to
6091 if (gridCol !== null) {
6092 // This is the index of the column we want to scroll to, within the list of columns that can be visible
6093 var seekColumnIndex = visColCache.indexOf(gridCol);
6094
6095 // Total horizontal scroll length of the grid
6096 var horizScrollLength = (self.renderContainers.body.getCanvasWidth() - self.renderContainers.body.getViewportWidth());
6097
6098 // This is the minimum amount of pixels we need to scroll horizontal in order to see this column
6099 var columnLeftEdge = 0;
6100 for (var i = 0; i < seekColumnIndex; i++) {
6101 var col = visColCache[i];
6102 columnLeftEdge += col.drawnWidth;
6103 }
6104 columnLeftEdge = (columnLeftEdge < 0) ? 0 : columnLeftEdge;
6105
6106 var columnRightEdge = columnLeftEdge + gridCol.drawnWidth;
6107
6108 // Don't let the pixels required to see the column be less than zero
6109 columnRightEdge = (columnRightEdge < 0) ? 0 : columnRightEdge;
6110
6111 var horizScrollPixels;
6112
6113 // If the scroll position we need to see the column is LESS than the left boundary, i.e. obscured before the left of the self...
6114 if (columnLeftEdge < leftBound) {
6115 // Get the different between the left boundary and the required scroll position and subtract it from the current scroll position\
6116 // to get the full position we need
6117 horizScrollPixels = self.renderContainers.body.prevScrollLeft - (leftBound - columnLeftEdge);
6118
6119 // Turn the scroll position into a percentage and make it an argument for a scroll event
6120 scrollEvent.x = getScrollX(horizScrollPixels, horizScrollLength, self.renderContainers.body.prevScrollleftPercentage);
6121 }
6122 // Otherwise if the scroll position we need to see the column is MORE than the right boundary, i.e. obscured after the right of the self...
6123 else if (columnRightEdge > rightBound) {
6124 // Get the different between the right boundary and the required scroll position and add it to the current scroll position
6125 // to get the full position we need
6126 horizScrollPixels = columnRightEdge - rightBound + self.renderContainers.body.prevScrollLeft;
6127
6128 // Turn the scroll position into a percentage and make it an argument for a scroll event
6129 scrollEvent.x = getScrollX(horizScrollPixels, horizScrollLength, self.renderContainers.body.prevScrollleftPercentage);
6130 }
6131 }
6132
6133 var deferred = $q.defer();
6134
6135 // If we need to scroll on either the x or y axes, fire a scroll event
6136 if (scrollEvent.y || scrollEvent.x) {
6137 scrollEvent.withDelay = false;
6138 self.scrollContainers('',scrollEvent);
6139 var dereg = self.api.core.on.scrollEnd(null,function() {
6140 deferred.resolve(scrollEvent);
6141 dereg();
6142 });
6143 }
6144 else {
6145 deferred.resolve();
6146 }
6147
6148 return deferred.promise;
6149 };
6150
6151 /**
6152 * @ngdoc method
6153 * @methodOf ui.grid.class:Grid
6154 * @name scrollTo
6155 * @description Scroll the grid such that the specified
6156 * row and column is in view
6157 * @param {object} rowEntity gridOptions.data[] array instance to make visible
6158 * @param {object} colDef to make visible
6159 * @returns {promise} a promise that is resolved after any scrolling is finished
6160 */
6161 Grid.prototype.scrollTo = function (rowEntity, colDef) {
6162 var gridRow = null, gridCol = null;
6163
6164 if (rowEntity !== null && typeof(rowEntity) !== 'undefined' ) {
6165 gridRow = this.getRow(rowEntity);
6166 }
6167
6168 if (colDef !== null && typeof(colDef) !== 'undefined' ) {
6169 gridCol = this.getColumn(colDef.name ? colDef.name : colDef.field);
6170 }
6171 return this.scrollToIfNecessary(gridRow, gridCol);
6172 };
6173
6174 /**
6175 * @ngdoc function
6176 * @name clearAllFilters
6177 * @methodOf ui.grid.class:Grid
6178 * @description Clears all filters and optionally refreshes the visible rows.
6179 * @param {object} refreshRows Defaults to true.
6180 * @param {object} clearConditions Defaults to false.
6181 * @param {object} clearFlags Defaults to false.
6182 * @returns {promise} If `refreshRows` is true, returns a promise of the rows refreshing.
6183 */
6184 Grid.prototype.clearAllFilters = function clearAllFilters(refreshRows, clearConditions, clearFlags) {
6185 // Default `refreshRows` to true because it will be the most commonly desired behaviour.
6186 if (refreshRows === undefined) {
6187 refreshRows = true;
6188 }
6189 if (clearConditions === undefined) {
6190 clearConditions = false;
6191 }
6192 if (clearFlags === undefined) {
6193 clearFlags = false;
6194 }
6195
6196 this.columns.forEach(function(column) {
6197 column.filters.forEach(function(filter) {
6198 filter.term = undefined;
6199
6200 if (clearConditions) {
6201 filter.condition = undefined;
6202 }
6203
6204 if (clearFlags) {
6205 filter.flags = undefined;
6206 }
6207 });
6208 });
6209
6210 if (refreshRows) {
6211 return this.refreshRows();
6212 }
6213 };
6214
6215
6216 // Blatantly stolen from Angular as it isn't exposed (yet? 2.0?)
6217 function RowHashMap() {}
6218
6219 RowHashMap.prototype = {
6220 /**
6221 * Store key value pair
6222 * @param key key to store can be any type
6223 * @param value value to store can be any type
6224 */
6225 put: function(key, value) {
6226 this[this.grid.options.rowIdentity(key)] = value;
6227 },
6228
6229 /**
6230 * @param key
6231 * @returns {Object} the value for the key
6232 */
6233 get: function(key) {
6234 return this[this.grid.options.rowIdentity(key)];
6235 },
6236
6237 /**
6238 * Remove the key/value pair
6239 * @param key
6240 */
6241 remove: function(key) {
6242 var value = this[key = this.grid.options.rowIdentity(key)];
6243 delete this[key];
6244 return value;
6245 }
6246 };
6247
6248 return Grid;
6249 }]);
6250 })();
6251
6252 (function () {
6253
6254 angular.module('ui.grid')
6255 .factory('GridApi', ['$q', '$rootScope', 'gridUtil', 'uiGridConstants', 'GridRow',
6256 function ($q, $rootScope, gridUtil, uiGridConstants, GridRow) {
6257 /**
6258 * @ngdoc function
6259 * @name ui.grid.class:GridApi
6260 * @description GridApi provides the ability to register public methods events inside the grid and allow
6261 * for other components to use the api via featureName.raise.methodName and featureName.on.eventName(function(args) {}.
6262 * <br/>
6263 * To listen to events, you must add a callback to gridOptions.onRegisterApi
6264 * <pre>
6265 * $scope.gridOptions.onRegisterApi = function(gridApi) {
6266 * gridApi.cellNav.on.navigate($scope,function(newRowCol, oldRowCol) {
6267 * $log.log('navigation event');
6268 * });
6269 * };
6270 * </pre>
6271 * @param {object} grid grid that owns api
6272 */
6273 var GridApi = function GridApi(grid) {
6274 this.grid = grid;
6275 this.listeners = [];
6276
6277 /**
6278 * @ngdoc function
6279 * @name renderingComplete
6280 * @methodOf ui.grid.api:PublicApi
6281 * @description Rendering is complete, called at the same
6282 * time as `onRegisterApi`, but provides a way to obtain
6283 * that same event within features without stopping end
6284 * users from getting at the onRegisterApi method.
6285 *
6286 * Included in gridApi so that it's always there - otherwise
6287 * there is still a timing problem with when a feature can
6288 * call this.
6289 *
6290 * @param {GridApi} gridApi the grid api, as normally
6291 * returned in the onRegisterApi method
6292 *
6293 * @example
6294 * <pre>
6295 * gridApi.core.on.renderingComplete( grid );
6296 * </pre>
6297 */
6298 this.registerEvent( 'core', 'renderingComplete' );
6299
6300 /**
6301 * @ngdoc event
6302 * @name filterChanged
6303 * @eventOf ui.grid.api:PublicApi
6304 * @description is raised after the filter is changed. The nature
6305 * of the watch expression doesn't allow notification of what changed,
6306 * so the receiver of this event will need to re-extract the filter
6307 * conditions from the columns.
6308 *
6309 */
6310 this.registerEvent( 'core', 'filterChanged' );
6311
6312 /**
6313 * @ngdoc function
6314 * @name setRowInvisible
6315 * @methodOf ui.grid.api:PublicApi
6316 * @description Sets an override on the row to make it always invisible,
6317 * which will override any filtering or other visibility calculations.
6318 * If the row is currently visible then sets it to invisible and calls
6319 * both grid refresh and emits the rowsVisibleChanged event
6320 * @param {GridRow} row the row we want to make invisible
6321 */
6322 this.registerMethod( 'core', 'setRowInvisible', GridRow.prototype.setRowInvisible );
6323
6324 /**
6325 * @ngdoc function
6326 * @name clearRowInvisible
6327 * @methodOf ui.grid.api:PublicApi
6328 * @description Clears any override on visibility for the row so that it returns to
6329 * using normal filtering and other visibility calculations.
6330 * If the row is currently invisible then sets it to visible and calls
6331 * both grid refresh and emits the rowsVisibleChanged event
6332 * TODO: if a filter is active then we can't just set it to visible?
6333 * @param {GridRow} row the row we want to make visible
6334 */
6335 this.registerMethod( 'core', 'clearRowInvisible', GridRow.prototype.clearRowInvisible );
6336
6337 /**
6338 * @ngdoc function
6339 * @name getVisibleRows
6340 * @methodOf ui.grid.api:PublicApi
6341 * @description Returns all visible rows
6342 * @param {Grid} grid the grid you want to get visible rows from
6343 * @returns {array} an array of gridRow
6344 */
6345 this.registerMethod( 'core', 'getVisibleRows', this.grid.getVisibleRows );
6346
6347 /**
6348 * @ngdoc event
6349 * @name rowsVisibleChanged
6350 * @eventOf ui.grid.api:PublicApi
6351 * @description is raised after the rows that are visible
6352 * change. The filtering is zero-based, so it isn't possible
6353 * to say which rows changed (unlike in the selection feature).
6354 * We can plausibly know which row was changed when setRowInvisible
6355 * is called, but in that situation the user already knows which row
6356 * they changed. When a filter runs we don't know what changed,
6357 * and that is the one that would have been useful.
6358 *
6359 */
6360 this.registerEvent( 'core', 'rowsVisibleChanged' );
6361
6362 /**
6363 * @ngdoc event
6364 * @name rowsRendered
6365 * @eventOf ui.grid.api:PublicApi
6366 * @description is raised after the cache of visible rows is changed.
6367 */
6368 this.registerEvent( 'core', 'rowsRendered' );
6369
6370
6371 /**
6372 * @ngdoc event
6373 * @name scrollBegin
6374 * @eventOf ui.grid.api:PublicApi
6375 * @description is raised when scroll begins. Is throttled, so won't be raised too frequently
6376 */
6377 this.registerEvent( 'core', 'scrollBegin' );
6378
6379 /**
6380 * @ngdoc event
6381 * @name scrollEnd
6382 * @eventOf ui.grid.api:PublicApi
6383 * @description is raised when scroll has finished. Is throttled, so won't be raised too frequently
6384 */
6385 this.registerEvent( 'core', 'scrollEnd' );
6386
6387 /**
6388 * @ngdoc event
6389 * @name canvasHeightChanged
6390 * @eventOf ui.grid.api:PublicApi
6391 * @description is raised when the canvas height has changed
6392 * <br/>
6393 * arguments: oldHeight, newHeight
6394 */
6395 this.registerEvent( 'core', 'canvasHeightChanged');
6396
6397 /**
6398 * @ngdoc event
6399 * @name gridDimensionChanged
6400 * @eventOf ui.grid.api:PublicApi
6401 * @description is raised when the grid dimensions have changed (when autoResize is on)
6402 * <br/>
6403 * arguments: oldGridHeight, oldGridWidth, newGridHeight, newGridWidth
6404 */
6405 this.registerEvent( 'core', 'gridDimensionChanged');
6406 };
6407
6408 /**
6409 * @ngdoc function
6410 * @name ui.grid.class:suppressEvents
6411 * @methodOf ui.grid.class:GridApi
6412 * @description Used to execute a function while disabling the specified event listeners.
6413 * Disables the listenerFunctions, executes the callbackFn, and then enables
6414 * the listenerFunctions again
6415 * @param {object} listenerFuncs listenerFunc or array of listenerFuncs to suppress. These must be the same
6416 * functions that were used in the .on.eventName method
6417 * @param {object} callBackFn function to execute
6418 * @example
6419 * <pre>
6420 * var navigate = function (newRowCol, oldRowCol) {
6421 * //do something on navigate
6422 * }
6423 *
6424 * gridApi.cellNav.on.navigate(scope,navigate);
6425 *
6426 *
6427 * //call the scrollTo event and suppress our navigate listener
6428 * //scrollTo will still raise the event for other listeners
6429 * gridApi.suppressEvents(navigate, function() {
6430 * gridApi.cellNav.scrollTo(aRow, aCol);
6431 * });
6432 *
6433 * </pre>
6434 */
6435 GridApi.prototype.suppressEvents = function (listenerFuncs, callBackFn) {
6436 var self = this,
6437 listeners = angular.isArray(listenerFuncs) ? listenerFuncs : [listenerFuncs];
6438
6439 // find all registered listeners
6440 var foundListeners = self.listeners.filter(function(listener) {
6441 return listeners.some(function(l) {
6442 return listener.handler === l;
6443 });
6444 });
6445
6446 // deregister all the listeners
6447 foundListeners.forEach(function(l) {
6448 l.dereg();
6449 });
6450
6451 callBackFn();
6452
6453 // reregister all the listeners
6454 foundListeners.forEach(function(l) {
6455 l.dereg = registerEventWithAngular(l.eventId, l.handler, self.grid, l._this);
6456 });
6457 };
6458
6459 /**
6460 * @ngdoc function
6461 * @name registerEvent
6462 * @methodOf ui.grid.class:GridApi
6463 * @description Registers a new event for the given feature. The event will get a
6464 * .raise and .on prepended to it
6465 * <br>
6466 * .raise.eventName() - takes no arguments
6467 * <br/>
6468 * <br/>
6469 * .on.eventName(scope, callBackFn, _this)
6470 * <br/>
6471 * scope - a scope reference to add a deregister call to the scopes .$on('destroy'). Scope is optional and can be a null value,
6472 * but in this case you must deregister it yourself via the returned deregister function
6473 * <br/>
6474 * callBackFn - The function to call
6475 * <br/>
6476 * _this - optional this context variable for callbackFn. If omitted, grid.api will be used for the context
6477 * <br/>
6478 * .on.eventName returns a dereg funtion that will remove the listener. It's not necessary to use it as the listener
6479 * will be removed when the scope is destroyed.
6480 * @param {string} featureName name of the feature that raises the event
6481 * @param {string} eventName name of the event
6482 */
6483 GridApi.prototype.registerEvent = function (featureName, eventName) {
6484 var self = this;
6485 if (!self[featureName]) {
6486 self[featureName] = {};
6487 }
6488
6489 var feature = self[featureName];
6490 if (!feature.on) {
6491 feature.on = {};
6492 feature.raise = {};
6493 }
6494
6495 var eventId = self.grid.id + featureName + eventName;
6496
6497 // gridUtil.logDebug('Creating raise event method ' + featureName + '.raise.' + eventName);
6498 feature.raise[eventName] = function () {
6499 $rootScope.$emit.apply($rootScope, [eventId].concat(Array.prototype.slice.call(arguments)));
6500 };
6501
6502 // gridUtil.logDebug('Creating on event method ' + featureName + '.on.' + eventName);
6503 feature.on[eventName] = function (scope, handler, _this) {
6504 if ( scope !== null && typeof(scope.$on) === 'undefined' ) {
6505 gridUtil.logError('asked to listen on ' + featureName + '.on.' + eventName + ' but scope wasn\'t passed in the input parameters. It is legitimate to pass null, but you\'ve passed something else, so you probably forgot to provide scope rather than did it deliberately, not registering');
6506 return;
6507 }
6508 var deregAngularOn = registerEventWithAngular(eventId, handler, self.grid, _this);
6509
6510 // track our listener so we can turn off and on
6511 var listener = {handler: handler, dereg: deregAngularOn, eventId: eventId, scope: scope, _this: _this};
6512
6513 self.listeners.push(listener);
6514
6515 var removeListener = function() {
6516 listener.dereg();
6517 var index = self.listeners.indexOf(listener);
6518 self.listeners.splice(index,1);
6519 };
6520
6521 // destroy tracking when scope is destroyed
6522 if (scope) {
6523 scope.$on('$destroy', function() {
6524 removeListener();
6525 });
6526 }
6527
6528 return removeListener;
6529 };
6530 };
6531
6532 function registerEventWithAngular(eventId, handler, grid, _this) {
6533 return $rootScope.$on(eventId, function (event) {
6534 var args = Array.prototype.slice.call(arguments);
6535 args.splice(0, 1); // remove evt argument
6536 handler.apply(_this ? _this : grid.api, args);
6537 });
6538 }
6539
6540 /**
6541 * @ngdoc function
6542 * @name registerEventsFromObject
6543 * @methodOf ui.grid.class:GridApi
6544 * @description Registers features and events from a simple objectMap.
6545 * eventObjectMap must be in this format (multiple features allowed)
6546 * <pre>
6547 * {featureName:
6548 * {
6549 * eventNameOne:function(args) {},
6550 * eventNameTwo:function(args) {}
6551 * }
6552 * }
6553 * </pre>
6554 * @param {object} eventObjectMap map of feature/event names
6555 */
6556 GridApi.prototype.registerEventsFromObject = function (eventObjectMap) {
6557 var self = this,
6558 features = [];
6559
6560 angular.forEach(eventObjectMap, function (featProp, featPropName) {
6561 var feature = {name: featPropName, events: []};
6562 angular.forEach(featProp, function (prop, propName) {
6563 feature.events.push(propName);
6564 });
6565 features.push(feature);
6566 });
6567
6568 features.forEach(function (feature) {
6569 feature.events.forEach(function (event) {
6570 self.registerEvent(feature.name, event);
6571 });
6572 });
6573 };
6574
6575 /**
6576 * @ngdoc function
6577 * @name registerMethod
6578 * @methodOf ui.grid.class:GridApi
6579 * @description Registers a new event for the given feature
6580 * @param {string} featureName name of the feature
6581 * @param {string} methodName name of the method
6582 * @param {object} callBackFn function to execute
6583 * @param {object} _this binds callBackFn 'this' to _this. Defaults to gridApi.grid
6584 */
6585 GridApi.prototype.registerMethod = function (featureName, methodName, callBackFn, _this) {
6586 if (!this[featureName]) {
6587 this[featureName] = {};
6588 }
6589
6590 var feature = this[featureName];
6591
6592 feature[methodName] = gridUtil.createBoundedWrapper(_this || this.grid, callBackFn);
6593 };
6594
6595 /**
6596 * @ngdoc function
6597 * @name registerMethodsFromObject
6598 * @methodOf ui.grid.class:GridApi
6599 * @description Registers features and methods from a simple objectMap.
6600 * eventObjectMap must be in this format (multiple features allowed)
6601 * <br>
6602 * {featureName:
6603 * {
6604 * methodNameOne:function(args) {},
6605 * methodNameTwo:function(args) {}
6606 * }
6607 * @param {object} methodMap map of feature/event names
6608 * @param {object} _this binds this to _this for all functions. Defaults to gridApi.grid
6609 */
6610 GridApi.prototype.registerMethodsFromObject = function (methodMap, _this) {
6611 var self = this;
6612 var features = [];
6613 angular.forEach(methodMap, function (featProp, featPropName) {
6614 var feature = {name: featPropName, methods: []};
6615 angular.forEach(featProp, function (prop, propName) {
6616 feature.methods.push({name: propName, fn: prop});
6617 });
6618 features.push(feature);
6619 });
6620
6621 features.forEach(function (feature) {
6622 feature.methods.forEach(function (method) {
6623 self.registerMethod(feature.name, method.name, method.fn, _this);
6624 });
6625 });
6626
6627 };
6628
6629 return GridApi;
6630 }]);
6631 })();
6632
6633 (function() {
6634
6635 angular.module('ui.grid')
6636 .factory('GridColumn', ['gridUtil', 'uiGridConstants', 'i18nService', function(gridUtil, uiGridConstants, i18nService) {
6637
6638 /**
6639 * ******************************************************************************************
6640 * PaulL1: Ugly hack here in documentation. These properties are clearly properties of GridColumn,
6641 * and need to be noted as such for those extending and building ui-grid itself.
6642 * However, from an end-developer perspective, they interact with all these through columnDefs,
6643 * and they really need to be documented there. I feel like they're relatively static, and
6644 * I can't find an elegant way for ngDoc to reference to both....so I've duplicated each
6645 * comment block. Ugh.
6646 *
6647 */
6648
6649 /**
6650 * @ngdoc property
6651 * @name name
6652 * @propertyOf ui.grid.class:GridColumn
6653 * @description (mandatory) Each column should have a name, although for backward
6654 * compatibility with 2.x name can be omitted if field is present.
6655 *
6656 * Important - This must be unique to each column on a web page since it can
6657 * be used as a key for retrieving information such as custom sort algorithms.
6658 *
6659 */
6660
6661 /**
6662 * @ngdoc property
6663 * @name name
6664 * @propertyOf ui.grid.class:GridOptions.columnDef
6665 * @description (mandatory) Each column should have a name, although for backward
6666 * compatibility with 2.x name can be omitted if field is present.
6667 *
6668 * Important - This must be unique to each column on a web page since it can
6669 * be used as a key for retrieving information such as custom sort algorithms.
6670 *
6671 */
6672
6673 /**
6674 * @ngdoc property
6675 * @name displayName
6676 * @propertyOf ui.grid.class:GridColumn
6677 * @description Column name that will be shown in the header. If displayName is not
6678 * provided then one is generated using the name.
6679 *
6680 */
6681
6682 /**
6683 * @ngdoc property
6684 * @name displayName
6685 * @propertyOf ui.grid.class:GridOptions.columnDef
6686 * @description Column name that will be shown in the header. If displayName is not
6687 * provided then one is generated using the name.
6688 *
6689 */
6690
6691 /**
6692 * @ngdoc property
6693 * @name field
6694 * @propertyOf ui.grid.class:GridColumn
6695 * @description field must be provided if you wish to bind to a
6696 * property in the data source. Should be an angular expression that evaluates against grid.options.data
6697 * array element. Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>.
6698 * See the angular docs on binding expressions.
6699 *
6700 */
6701
6702 /**
6703 * @ngdoc property
6704 * @name field
6705 * @propertyOf ui.grid.class:GridOptions.columnDef
6706 * @description field must be provided if you wish to bind to a
6707 * property in the data source. Should be an angular expression that evaluates against grid.options.data
6708 * array element. Can be a complex expression: <code>employee.address.city</code>, or can be a function: <code>employee.getFullAddress()</code>. * See the angular docs on binding expressions. *
6709 */
6710
6711 /**
6712 * @ngdoc property
6713 * @name filter
6714 * @propertyOf ui.grid.class:GridColumn
6715 * @description Filter on this column.
6716 *
6717 * Available built-in conditions and types are listed under {@link jui.grid.service:uiGridConstants#properties_filter uiGridOptions.filter}
6718 * @example
6719 * <pre>{ term: 'text', condition: uiGridConstants.filter.STARTS_WITH, placeholder: 'type to filter...', ariaLabel: 'Filter for text', flags: { caseSensitive: false }, type: uiGridConstants.filter.SELECT, [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ] }</pre>
6720 *
6721 */
6722
6723 /**
6724 * @ngdoc property
6725 * @name extraStyle
6726 * @propertyOf ui.grid.class:GridColumn
6727 * @description additional on this column.
6728 * @example
6729 * <pre>{extraStyle: {display: 'table-cell'}}</pre>
6730 *
6731 */
6732
6733 /**
6734 * @ngdoc object
6735 * @name ui.grid.class:GridColumn
6736 * @description Represents the viewModel for each column. Any state or methods needed for a Grid Column
6737 * are defined on this prototype
6738 * @param {ColumnDef} colDef the column def to associate with this column
6739 * @param {number} uid the unique and immutable uid we'd like to allocate to this column
6740 * @param {Grid} grid the grid we'd like to create this column in
6741 */
6742 function GridColumn(colDef, uid, grid) {
6743 var self = this;
6744
6745 self.grid = grid;
6746 self.uid = uid;
6747
6748 self.updateColumnDef(colDef, true);
6749
6750 self.aggregationValue = undefined;
6751
6752 // The footer cell registers to listen for the rowsRendered event, and calls this. Needed to be
6753 // in something with a scope so that the dereg would get called
6754 self.updateAggregationValue = function() {
6755
6756 // gridUtil.logDebug('getAggregationValue for Column ' + self.colDef.name);
6757
6758 /**
6759 * @ngdoc property
6760 * @name aggregationType
6761 * @propertyOf ui.grid.class:GridOptions.columnDef
6762 * @description The aggregation that you'd like to show in the columnFooter for this
6763 * column. Valid values are in
6764 * {@link ui.grid.service:uiGridConstants#properties_aggregationTypes uiGridConstants.aggregationTypes},
6765 * and currently include `uiGridConstants.aggregationTypes.count`,
6766 * `uiGridConstants.aggregationTypes.sum`, `uiGridConstants.aggregationTypes.avg`, `uiGridConstants.aggregationTypes.min`,
6767 * `uiGridConstants.aggregationTypes.max`.
6768 *
6769 * You can also provide a function as the aggregation type, in this case your function needs to accept the full
6770 * set of visible rows, and return a value that should be shown
6771 */
6772 if (!self.aggregationType) {
6773 self.aggregationValue = undefined;
6774 return;
6775 }
6776
6777 var result = 0;
6778 var visibleRows = self.grid.getVisibleRows();
6779
6780 var cellValues = function() {
6781 var values = [];
6782 visibleRows.forEach(function (row) {
6783 var cellValue = self.grid.getCellValue(row, self);
6784 var cellNumber = Number(cellValue);
6785 if (!isNaN(cellNumber)) {
6786 values.push(cellNumber);
6787 }
6788 });
6789 return values;
6790 };
6791
6792 if (angular.isFunction(self.aggregationType)) {
6793 self.aggregationValue = self.aggregationType(visibleRows, self);
6794 }
6795 else if (self.aggregationType === uiGridConstants.aggregationTypes.count) {
6796 self.aggregationValue = self.grid.getVisibleRowCount();
6797 }
6798 else if (self.aggregationType === uiGridConstants.aggregationTypes.sum) {
6799 cellValues().forEach(function (value) {
6800 result += value;
6801 });
6802 self.aggregationValue = result;
6803 }
6804 else if (self.aggregationType === uiGridConstants.aggregationTypes.avg) {
6805 cellValues().forEach(function (value) {
6806 result += value;
6807 });
6808 result = result / cellValues().length;
6809 self.aggregationValue = result;
6810 }
6811 else if (self.aggregationType === uiGridConstants.aggregationTypes.min) {
6812 self.aggregationValue = Math.min.apply(null, cellValues());
6813 }
6814 else if (self.aggregationType === uiGridConstants.aggregationTypes.max) {
6815 self.aggregationValue = Math.max.apply(null, cellValues());
6816 }
6817 else {
6818 self.aggregationValue = '\u00A0';
6819 }
6820 };
6821
6822 // var throttledUpdateAggregationValue = gridUtil.throttle(updateAggregationValue, self.grid.options.aggregationCalcThrottle, { trailing: true, context: self.name });
6823
6824 /**
6825 * @ngdoc function
6826 * @name getAggregationValue
6827 * @methodOf ui.grid.class:GridColumn
6828 * @description gets the aggregation value based on the aggregation type for this column.
6829 * Debounced using scrollDebounce option setting
6830 */
6831 this.getAggregationValue = function() {
6832 // if (!self.grid.isScrollingVertically && !self.grid.isScrollingHorizontally) {
6833 // throttledUpdateAggregationValue();
6834 // }
6835
6836 return self.aggregationValue;
6837 };
6838 }
6839
6840 /**
6841 * @ngdoc function
6842 * @name hideColumn
6843 * @methodOf ui.grid.class:GridColumn
6844 * @description Hides the column by setting colDef.visible = false
6845 */
6846 GridColumn.prototype.hideColumn = function() {
6847 this.colDef.visible = false;
6848 };
6849
6850
6851 /**
6852 * @ngdoc method
6853 * @methodOf ui.grid.class:GridColumn
6854 * @name setPropertyOrDefault
6855 * @description Sets a property on the column using the passed in columnDef, and
6856 * setting the defaultValue if the value cannot be found on the colDef
6857 * @param {GridColumn} colDef the column def to look in for the property value
6858 * @param {string} propName the property name we'd like to set
6859 * @param {object} defaultValue the value to use if the colDef doesn't provide the setting
6860 */
6861 GridColumn.prototype.setPropertyOrDefault = function (colDef, propName, defaultValue) {
6862 var self = this;
6863
6864 // Use the column definition filter if we were passed it
6865 if (typeof(colDef[propName]) !== 'undefined' && colDef[propName]) {
6866 self[propName] = colDef[propName];
6867 }
6868 // Otherwise use our own if it's set
6869 else if (typeof(self[propName]) !== 'undefined') {
6870 self[propName] = self[propName];
6871 }
6872 // Default to empty object for the filter
6873 else {
6874 self[propName] = defaultValue ? defaultValue : {};
6875 }
6876 };
6877
6878
6879
6880 /**
6881 * @ngdoc property
6882 * @name width
6883 * @propertyOf ui.grid.class:GridOptions.columnDef
6884 * @description sets the column width. Can be either
6885 * a number or a percentage, or an * for auto.
6886 * @example
6887 * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', width: 100},
6888 * { field: 'field2', width: '20%'},
6889 * { field: 'field3', width: '*' }]; </pre>
6890 *
6891 */
6892
6893 /**
6894 * @ngdoc property
6895 * @name minWidth
6896 * @propertyOf ui.grid.class:GridOptions.columnDef
6897 * @description Sets the minimum column width. Should be a number.
6898 * Defaults to gridOptions.minimumColumnSize if minWidth is not provided.
6899 * @example
6900 * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', minWidth: 100}]; </pre>
6901 *
6902 */
6903
6904 /**
6905 * @ngdoc property
6906 * @name maxWidth
6907 * @propertyOf ui.grid.class:GridOptions.columnDef
6908 * @description sets the maximum column width. Should be a number.
6909 * @example
6910 * <pre> $scope.gridOptions.columnDefs = [ { field: 'field1', maxWidth: 100}]; </pre>
6911 *
6912 */
6913
6914 /**
6915 * @ngdoc property
6916 * @name visible
6917 * @propertyOf ui.grid.class:GridOptions.columnDef
6918 * @description sets whether or not the column is visible
6919 * </br>Default is true
6920 * @example
6921 * <pre> $scope.gridOptions.columnDefs = [
6922 * { field: 'field1', visible: true},
6923 * { field: 'field2', visible: false }
6924 * ]; </pre>
6925 *
6926 */
6927
6928 /**
6929 * @ngdoc property
6930 * @name sort
6931 * @propertyOf ui.grid.class:GridOptions.columnDef
6932 * @description An object of sort information, attributes are:
6933 *
6934 * - direction: values are {@link ui.grid.service:uiGridConstants#properties_ASC uiGridConstants.ASC}
6935 * or {@link ui.grid.service:uiGridConstants#properties_DESC uiGridConstants.DESC}
6936 * - ignoreSort: if set to true this sort is ignored (used by tree to manipulate the sort functionality)
6937 * - priority: says what order to sort the columns in (lower priority gets sorted first). Starts from 0.
6938 * @example
6939 * <pre>
6940 * $scope.gridOptions.columnDefs = [{
6941 * field: 'field1',
6942 * sort: {
6943 * direction: uiGridConstants.ASC,
6944 * ignoreSort: true,
6945 * priority: 0
6946 * }
6947 * }];
6948 * </pre>
6949 */
6950
6951
6952 /**
6953 * @ngdoc property
6954 * @name sortingAlgorithm
6955 * @propertyOf ui.grid.class:GridOptions.columnDef
6956 * @description Algorithm to use for sorting this column. Takes 'a' and 'b' parameters
6957 * like any normal sorting function with additional 'rowA', 'rowB', and 'direction' parameters
6958 * that are the row objects and the current direction of the sort respectively.
6959 *
6960 */
6961
6962 /**
6963 * @ngdoc property
6964 * @name defaultSort
6965 * @propertyOf ui.grid.class:GridOptions.columnDef
6966 * @description An object of sort information, provides a hidden default ordering of the data
6967 * when no user sorts are applied, or when a user-provided sort deems two rows to be equal.
6968 *
6969 * May be combined with a regular {@link ui.grid.class:GridOptions.columnDef#properties_sort columnDef.sort}
6970 * to explicitly sort by that column by default.
6971 *
6972 * Shares the same object format as {@link ui.grid.class:GridOptions.columnDef#properties_sort columnDef.sort}.
6973 *
6974 * Note that a defaultSort can never take priority over an explicit sort.
6975 * @example
6976 * <pre>
6977 * $scope.gridOptions.columnDefs = [{
6978 * field: 'field1',
6979 * defaultSort: {
6980 * direction: uiGridConstants.ASC,
6981 * priority: 0
6982 * }
6983 * }];
6984 * </pre>
6985 */
6986
6987 /**
6988 * @ngdoc array
6989 * @name filters
6990 * @propertyOf ui.grid.class:GridOptions.columnDef
6991 * @description Specify multiple filter fields.
6992 * @example
6993 * <pre>$scope.gridOptions.columnDefs = [
6994 * {
6995 * field: 'field1', filters: [
6996 * {
6997 * term: 'aa',
6998 * condition: uiGridConstants.filter.STARTS_WITH,
6999 * placeholder: 'starts with...',
7000 * ariaLabel: 'Filter for field1',
7001 * flags: { caseSensitive: false },
7002 * type: uiGridConstants.filter.SELECT,
7003 * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]
7004 * },
7005 * {
7006 * condition: uiGridConstants.filter.ENDS_WITH,
7007 * placeholder: 'ends with...'
7008 * }
7009 * ]
7010 * }
7011 * ]; </pre>
7012 *
7013 *
7014 */
7015
7016 /**
7017 * @ngdoc array
7018 * @name filters
7019 * @propertyOf ui.grid.class:GridColumn
7020 * @description Filters for this column. Includes 'term' property bound to filter input elements.
7021 * @example
7022 * <pre>[
7023 * {
7024 * term: 'foo', // ngModel for <input>
7025 * condition: uiGridConstants.filter.STARTS_WITH,
7026 * placeholder: 'starts with...',
7027 * ariaLabel: 'Filter for foo',
7028 * flags: { caseSensitive: false },
7029 * type: uiGridConstants.filter.SELECT,
7030 * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ]
7031 * },
7032 * {
7033 * term: 'baz',
7034 * condition: uiGridConstants.filter.ENDS_WITH,
7035 * placeholder: 'ends with...'
7036 * }
7037 * ] </pre>
7038 *
7039 *
7040 */
7041
7042 /**
7043 * @ngdoc array
7044 * @name menuItems
7045 * @propertyOf ui.grid.class:GridOptions.columnDef
7046 * @description used to add menu items to a column. Refer to the tutorial on this
7047 * functionality. A number of settings are supported:
7048 *
7049 * - title: controls the title that is displayed in the menu
7050 * - icon: the icon shown alongside that title
7051 * - action: the method to call when the menu is clicked
7052 * - shown: a function to evaluate to determine whether or not to show the item
7053 * - active: a function to evaluate to determine whether or not the item is currently selected
7054 * - context: context to pass to the action function, available in this.context in your handler
7055 * - leaveOpen: if set to true, the menu should stay open after the action, defaults to false
7056 * @example
7057 * <pre> $scope.gridOptions.columnDefs = [
7058 * { field: 'field1', menuItems: [
7059 * {
7060 * title: 'Outer Scope Alert',
7061 * icon: 'ui-grid-icon-info-circled',
7062 * action: function($event) {
7063 * this.context.blargh(); // $scope.blargh() would work too, this is just an example
7064 * },
7065 * shown: function() { return true; },
7066 * active: function() { return true; },
7067 * context: $scope
7068 * },
7069 * {
7070 * title: 'Grid ID',
7071 * action: function() {
7072 * alert('Grid ID: ' + this.grid.id);
7073 * }
7074 * }
7075 * ] }]; </pre>
7076 *
7077 */
7078
7079 // Use colDef.displayName as long as it's not undefined, otherwise default to the field name
7080 function getDisplayName(colDef) {
7081 return (colDef.displayName === undefined)
7082 ? gridUtil.readableColumnName(colDef.name)
7083 : colDef.displayName;
7084 }
7085
7086 /**
7087 * @ngdoc method
7088 * @methodOf ui.grid.class:GridColumn
7089 * @name updateColumnDef
7090 * @description Moves settings from the columnDef down onto the column,
7091 * and sets properties as appropriate
7092 * @param {GridColumn} colDef the column def to look in for the property value
7093 * @param {boolean} isNew whether the column is being newly created, if not
7094 * we're updating an existing column, and some items such as the sort shouldn't
7095 * be copied down
7096 */
7097 GridColumn.prototype.updateColumnDef = function(colDef, isNew) {
7098 var self = this;
7099
7100 self.colDef = colDef;
7101
7102 if (colDef.name === undefined) {
7103 throw new Error('colDef.name is required for column at index ' + self.grid.options.columnDefs.indexOf(colDef));
7104 }
7105
7106 self.displayName = getDisplayName(colDef);
7107
7108 if (!angular.isNumber(self.width) || !self.hasCustomWidth || colDef.allowCustomWidthOverride) {
7109 var colDefWidth = colDef.width;
7110 var parseErrorMsg = "Cannot parse column width '" + colDefWidth + "' for column named '" + colDef.name + "'";
7111 self.hasCustomWidth = false;
7112
7113 if (!angular.isString(colDefWidth) && !angular.isNumber(colDefWidth)) {
7114 self.width = '*';
7115 } else if (angular.isString(colDefWidth)) {
7116 // See if it ends with a percent
7117 if (gridUtil.endsWith(colDefWidth, '%')) {
7118 // If so we should be able to parse the non-percent-sign part to a number
7119 var percentStr = colDefWidth.replace(/%/g, '');
7120 var percent = parseInt(percentStr, 10);
7121 if (isNaN(percent)) {
7122 throw new Error(parseErrorMsg);
7123 }
7124 self.width = colDefWidth;
7125 }
7126 // And see if it's a number string
7127 else if (colDefWidth.match(/^(\d+)$/)) {
7128 self.width = parseInt(colDefWidth.match(/^(\d+)$/)[1], 10);
7129 }
7130 // Otherwise it should be a string of asterisks
7131 else if (colDefWidth.match(/^\*+$/)) {
7132 self.width = colDefWidth;
7133 }
7134 // No idea, throw an Error
7135 else {
7136 throw new Error(parseErrorMsg);
7137 }
7138 }
7139 // Is a number, use it as the width
7140 else {
7141 self.width = colDefWidth;
7142 }
7143 }
7144
7145 function isValidWidthValue(value) {
7146 return angular.isString(value) || angular.isNumber(value);
7147 }
7148
7149 ['minWidth', 'maxWidth'].forEach(function (name) {
7150 var minOrMaxWidth = colDef[name];
7151 var parseErrorMsg = "Cannot parse column " + name + " '" + minOrMaxWidth + "' for column named '" + colDef.name + "'";
7152
7153 // default minWidth to the minimumColumnSize
7154 if (name === 'minWidth' && !isValidWidthValue(minOrMaxWidth) && angular.isDefined(self.grid.options.minimumColumnSize)) {
7155 minOrMaxWidth = self.grid.options.minimumColumnSize;
7156 }
7157
7158 if (!isValidWidthValue(minOrMaxWidth)) {
7159 // Sets default minWidth and maxWidth values
7160 self[name] = ((name === 'minWidth') ? 30 : 9000);
7161 } else if (angular.isString(minOrMaxWidth)) {
7162 if (minOrMaxWidth.match(/^(\d+)$/)) {
7163 self[name] = parseInt(minOrMaxWidth.match(/^(\d+)$/)[1], 10);
7164 } else {
7165 throw new Error(parseErrorMsg);
7166 }
7167 } else {
7168 self[name] = minOrMaxWidth;
7169 }
7170 });
7171
7172 // use field if it is defined; name if it is not
7173 self.field = (colDef.field === undefined) ? colDef.name : colDef.field;
7174
7175 if ( typeof( self.field ) !== 'string' ) {
7176 gridUtil.logError( 'Field is not a string, this is likely to break the code, Field is: ' + self.field );
7177 }
7178
7179 self.name = colDef.name;
7180 self.displayName = getDisplayName(colDef);
7181
7182 // self.originalIndex = index;
7183
7184 self.aggregationType = angular.isDefined(colDef.aggregationType) ? colDef.aggregationType : null;
7185 self.footerCellTemplate = angular.isDefined(colDef.footerCellTemplate) ? colDef.footerCellTemplate : null;
7186
7187 /**
7188 * @ngdoc property
7189 * @name cellTooltip
7190 * @propertyOf ui.grid.class:GridOptions.columnDef
7191 * @description Whether or not to show a tooltip when a user hovers over the cell.
7192 * If set to false, no tooltip. If true, the cell value is shown in the tooltip (useful
7193 * if you have long values in your cells), if a function then that function is called
7194 * passing in the row and the col `cellTooltip( row, col )`, and the return value is shown in the tooltip,
7195 * if it is a static string then displays that static string.
7196 *
7197 * Defaults to false
7198 *
7199 */
7200 if ( typeof(colDef.cellTooltip) === 'undefined' || colDef.cellTooltip === false ) {
7201 self.cellTooltip = false;
7202 } else if ( colDef.cellTooltip === true ) {
7203 self.cellTooltip = function(row, col) {
7204 return self.grid.getCellValue( row, col );
7205 };
7206 } else if (typeof(colDef.cellTooltip) === 'function' ) {
7207 self.cellTooltip = colDef.cellTooltip;
7208 } else {
7209 self.cellTooltip = function ( row, col ) {
7210 return col.colDef.cellTooltip;
7211 };
7212 }
7213
7214 /**
7215 * @ngdoc property
7216 * @name headerTooltip
7217 * @propertyOf ui.grid.class:GridOptions.columnDef
7218 * @description Whether or not to show a tooltip when a user hovers over the header cell.
7219 * If set to false, no tooltip. If true, the displayName is shown in the tooltip (useful
7220 * if you have long values in your headers), if a function then that function is called
7221 * passing in the row and the col `headerTooltip( col )`, and the return value is shown in the tooltip,
7222 * if a static string then shows that static string.
7223 *
7224 * Defaults to false
7225 *
7226 */
7227 if ( typeof(colDef.headerTooltip) === 'undefined' || colDef.headerTooltip === false ) {
7228 self.headerTooltip = false;
7229 }
7230 else if ( colDef.headerTooltip === true ) {
7231 self.headerTooltip = function(col) {
7232 return col.displayName;
7233 };
7234 }
7235 else if (typeof(colDef.headerTooltip) === 'function' ) {
7236 self.headerTooltip = colDef.headerTooltip;
7237 }
7238 else {
7239 self.headerTooltip = function ( col ) {
7240 return col.colDef.headerTooltip;
7241 };
7242 }
7243
7244
7245 /**
7246 * @ngdoc property
7247 * @name footerCellClass
7248 * @propertyOf ui.grid.class:GridOptions.columnDef
7249 * @description footerCellClass can be a string specifying the class to append to a cell
7250 * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name
7251 *
7252 */
7253 self.footerCellClass = colDef.footerCellClass;
7254
7255 /**
7256 * @ngdoc property
7257 * @name cellClass
7258 * @propertyOf ui.grid.class:GridOptions.columnDef
7259 * @description cellClass can be a string specifying the class to append to a cell
7260 * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name
7261 *
7262 */
7263 self.cellClass = colDef.cellClass;
7264
7265 /**
7266 * @ngdoc property
7267 * @name headerCellClass
7268 * @propertyOf ui.grid.class:GridOptions.columnDef
7269 * @description headerCellClass can be a string specifying the class to append to a cell
7270 * or it can be a function(grid, row, col, rowRenderIndex, colRenderIndex) that returns a class name
7271 *
7272 */
7273 self.headerCellClass = colDef.headerCellClass;
7274
7275 /**
7276 * @ngdoc property
7277 * @name cellFilter
7278 * @propertyOf ui.grid.class:GridOptions.columnDef
7279 * @description cellFilter is a filter to apply to the content of each cell
7280 * @example
7281 * <pre>
7282 * gridOptions.columnDefs[0].cellFilter = 'date'
7283 *
7284 */
7285 self.cellFilter = colDef.cellFilter ? colDef.cellFilter : "";
7286
7287 /**
7288 * @ngdoc boolean
7289 * @name sortCellFiltered
7290 * @propertyOf ui.grid.class:GridOptions.columnDef
7291 * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before
7292 * sorting the data. Note that when using this option uiGrid will assume that the displayed value is
7293 * a string, and use the {@link ui.grid.class:RowSorter#sortAlpha sortAlpha} `sortFn`. It is possible
7294 * to return a non-string value from an angularjs filter, in which case you should define a {@link ui.grid.class:GridOptions.columnDef#sortingAlgorithm sortingAlgorithm}
7295 * for the column which hanldes the returned type. You may specify one of the `sortingAlgorithms`
7296 * found in the {@link ui.grid.RowSorter rowSorter} service.
7297 */
7298 self.sortCellFiltered = colDef.sortCellFiltered ? true : false;
7299
7300 /**
7301 * @ngdoc boolean
7302 * @name filterCellFiltered
7303 * @propertyOf ui.grid.class:GridOptions.columnDef
7304 * @description (optional) False by default. When `true` uiGrid will apply the cellFilter before
7305 * applying "search" `filters`.
7306 */
7307 self.filterCellFiltered = colDef.filterCellFiltered ? true : false;
7308
7309 /**
7310 * @ngdoc property
7311 * @name headerCellFilter
7312 * @propertyOf ui.grid.class:GridOptions.columnDef
7313 * @description headerCellFilter is a filter to apply to the content of the column header
7314 * @example
7315 * <pre>
7316 * gridOptions.columnDefs[0].headerCellFilter = 'translate'
7317 *
7318 */
7319 self.headerCellFilter = colDef.headerCellFilter ? colDef.headerCellFilter : "";
7320
7321 /**
7322 * @ngdoc property
7323 * @name footerCellFilter
7324 * @propertyOf ui.grid.class:GridOptions.columnDef
7325 * @description footerCellFilter is a filter to apply to the content of the column footer
7326 * @example
7327 * <pre>
7328 * gridOptions.columnDefs[0].footerCellFilter = 'date'
7329 *
7330 */
7331 self.footerCellFilter = colDef.footerCellFilter ? colDef.footerCellFilter : "";
7332
7333 self.visible = gridUtil.isNullOrUndefined(colDef.visible) || colDef.visible;
7334
7335 self.headerClass = colDef.headerClass;
7336 // self.cursor = self.sortable ? 'pointer' : 'default';
7337
7338 // Turn on sorting by default
7339 self.enableSorting = typeof(colDef.enableSorting) !== 'undefined' ? colDef.enableSorting : self.grid.options.enableSorting;
7340 self.sortingAlgorithm = colDef.sortingAlgorithm;
7341
7342 /**
7343 * @ngdoc property
7344 * @name sortDirectionCycle
7345 * @propertyOf ui.grid.class:GridOptions.columnDef
7346 * @description (optional) An array of {@link ui.grid.service:uiGridConstants#properties_ASC sort directions},
7347 * specifying the order that they should cycle through as the user repeatedly clicks on the column heading.
7348 * The default is `[null, uiGridConstants.ASC, uiGridConstants.DESC]`. Null
7349 * refers to the unsorted state. This does not affect the initial sort
7350 * direction; use the {@link ui.grid.class:GridOptions.columnDef#sort sort}
7351 * property for that. If
7352 * {@link ui.grid.class:GridOptions.columnDef#suppressRemoveSort suppressRemoveSort}
7353 * is also set, the unsorted state will be skipped even if it is listed here.
7354 * Each direction may not appear in the list more than once (e.g. `[ASC,
7355 * DESC, DESC]` is not allowed), and the list may not be empty.
7356 */
7357 self.sortDirectionCycle = typeof(colDef.sortDirectionCycle) !== 'undefined' ?
7358 colDef.sortDirectionCycle :
7359 [null, uiGridConstants.ASC, uiGridConstants.DESC];
7360
7361 /**
7362 * @ngdoc boolean
7363 * @name suppressRemoveSort
7364 * @propertyOf ui.grid.class:GridOptions.columnDef
7365 * @description (optional) False by default. When enabled, this setting hides the removeSort option
7366 * in the menu, and prevents users from manually removing the sort
7367 */
7368 if ( typeof(self.suppressRemoveSort) === 'undefined') {
7369 self.suppressRemoveSort = typeof(colDef.suppressRemoveSort) !== 'undefined' ? colDef.suppressRemoveSort : false;
7370 }
7371
7372 /**
7373 * @ngdoc property
7374 * @name enableFiltering
7375 * @propertyOf ui.grid.class:GridOptions.columnDef
7376 * @description turn off filtering for an individual column, where
7377 * you've turned on filtering for the overall grid
7378 * @example
7379 * <pre>
7380 * gridOptions.columnDefs[0].enableFiltering = false;
7381 *
7382 */
7383 // Turn on filtering by default (it's disabled by default at the Grid level)
7384 self.enableFiltering = typeof(colDef.enableFiltering) !== 'undefined' ? colDef.enableFiltering : true;
7385
7386 // self.menuItems = colDef.menuItems;
7387 self.setPropertyOrDefault(colDef, 'menuItems', []);
7388
7389 // Use the column definition sort if we were passed it, but only if this is a newly added column
7390 if ( isNew ) {
7391 self.setPropertyOrDefault(colDef, 'sort');
7392 }
7393
7394 // Use the column definition defaultSort always, unlike normal sort
7395 self.setPropertyOrDefault(colDef, 'defaultSort');
7396
7397 // Set up default filters array for when one is not provided.
7398 // In other words, this (in column def):
7399 //
7400 // filter: { term: 'something', flags: {}, condition: [CONDITION] }
7401 //
7402 // is just shorthand for this:
7403 //
7404 // filters: [{ term: 'something', flags: {}, condition: [CONDITION] }]
7405 //
7406 var defaultFilters = [];
7407 if (colDef.filter) {
7408 defaultFilters.push(colDef.filter);
7409 }
7410 else if ( colDef.filters ) {
7411 defaultFilters = colDef.filters;
7412 }
7413 else {
7414 // Add an empty filter definition object, which will
7415 // translate to a guessed condition and no pre-populated
7416 // value for the filter <input>.
7417 defaultFilters.push({});
7418 }
7419
7420 /**
7421 * @ngdoc property
7422 * @name filter
7423 * @propertyOf ui.grid.class:GridOptions.columnDef
7424 * @description Specify a single filter field on this column.
7425 *
7426 * A filter consists of a condition, a term, and a placeholder:
7427 *
7428 * - condition defines how rows are chosen as matching the filter term. This can be set to
7429 * one of the constants in {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter},
7430 * or you can supply a custom filter function
7431 * that gets passed the following arguments: [searchTerm, cellValue, row, column].
7432 * - term: If set, the filter field will be pre-populated
7433 * with this value.
7434 * - placeholder: String that will be set to the `<input>.placeholder` attribute.
7435 * - ariaLabel: String that will be set to the `<input>.ariaLabel` attribute. This is what is read as a label to screen reader users.
7436 * - noTerm: set this to true if you have defined a custom function in condition, and
7437 * your custom function doesn't require a term (so it can run even when the term is null)
7438 * - rawTerm: set this to true if you have defined a custom function in condition, and
7439 * your custom function requires access to the raw unmodified search term that was entered
7440 * - flags: only flag currently available is `caseSensitive`, set to false if you don't want
7441 * case sensitive matching
7442 * - type: defaults to {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter.INPUT},
7443 * which gives a text box. If set to {@link ui.grid.service:uiGridConstants#properties_filter uiGridConstants.filter.SELECT}
7444 * then a select box will be shown with options selectOptions
7445 * - selectOptions: options in the format `[ { value: 1, label: 'male' }]`. No i18n filter is provided, you need
7446 * to perform the i18n on the values before you provide them
7447 * - disableCancelFilterButton: defaults to false. If set to true then the 'x' button that cancels/clears the filter
7448 * will not be shown.
7449 * @example
7450 * <pre>$scope.gridOptions.columnDefs = [
7451 * {
7452 * field: 'field1',
7453 * filter: {
7454 * term: 'xx',
7455 * condition: uiGridConstants.filter.STARTS_WITH,
7456 * placeholder: 'starts with...',
7457 * ariaLabel: 'Starts with filter for field1',
7458 * flags: { caseSensitive: false },
7459 * type: uiGridConstants.filter.SELECT,
7460 * selectOptions: [ { value: 1, label: 'male' }, { value: 2, label: 'female' } ],
7461 * disableCancelFilterButton: true
7462 * }
7463 * }
7464 * ]; </pre>
7465 *
7466 */
7467
7468 // Only set filter if this is a newly added column, if we're updating an existing
7469 // column then we don't want to put the default filter back if the user may have already
7470 // removed it.
7471 // However, we do want to keep the settings if they change, just not the term
7472 if ( isNew ) {
7473 self.setPropertyOrDefault(colDef, 'filter');
7474 self.setPropertyOrDefault(colDef, 'extraStyle');
7475 self.setPropertyOrDefault(colDef, 'filters', defaultFilters);
7476 } else if ( self.filters.length === defaultFilters.length ) {
7477 self.filters.forEach( function( filter, index ) {
7478 if (typeof(defaultFilters[index].placeholder) !== 'undefined') {
7479 filter.placeholder = defaultFilters[index].placeholder;
7480 }
7481 if (typeof(defaultFilters[index].ariaLabel) !== 'undefined') {
7482 filter.ariaLabel = defaultFilters[index].ariaLabel;
7483 }
7484 if (typeof(defaultFilters[index].flags) !== 'undefined') {
7485 filter.flags = defaultFilters[index].flags;
7486 }
7487 if (typeof(defaultFilters[index].type) !== 'undefined') {
7488 filter.type = defaultFilters[index].type;
7489 }
7490 if (typeof(defaultFilters[index].selectOptions) !== 'undefined') {
7491 filter.selectOptions = defaultFilters[index].selectOptions;
7492 }
7493 });
7494 }
7495 };
7496
7497 /**
7498 * @ngdoc function
7499 * @name unsort
7500 * @methodOf ui.grid.class:GridColumn
7501 * @description Removes column from the grid sorting
7502 */
7503 GridColumn.prototype.unsort = function () {
7504 // Decrease priority for every col where priority is higher than the removed sort's priority.
7505 var thisPriority = this.sort.priority;
7506
7507 this.grid.columns.forEach(function (col) {
7508 if (col.sort && col.sort.priority !== undefined && col.sort.priority > thisPriority) {
7509 col.sort.priority -= 1;
7510 }
7511 });
7512
7513 this.sort = {};
7514 this.grid.api.core.raise.sortChanged( this.grid, this.grid.getColumnSorting() );
7515 };
7516
7517
7518 /**
7519 * @ngdoc function
7520 * @name getColClass
7521 * @methodOf ui.grid.class:GridColumn
7522 * @description Returns the class name for the column
7523 * @param {bool} prefixDot if true, will return .className instead of className
7524 */
7525 GridColumn.prototype.getColClass = function (prefixDot) {
7526 var cls = uiGridConstants.COL_CLASS_PREFIX + this.uid;
7527
7528 return prefixDot ? '.' + cls : cls;
7529 };
7530
7531 /**
7532 * @ngdoc function
7533 * @name isPinnedLeft
7534 * @methodOf ui.grid.class:GridColumn
7535 * @description Returns true if column is in the left render container
7536 */
7537 GridColumn.prototype.isPinnedLeft = function () {
7538 return this.renderContainer === 'left';
7539 };
7540
7541 /**
7542 * @ngdoc function
7543 * @name isPinnedRight
7544 * @methodOf ui.grid.class:GridColumn
7545 * @description Returns true if column is in the right render container
7546 */
7547 GridColumn.prototype.isPinnedRight = function () {
7548 return this.renderContainer === 'right';
7549 };
7550
7551
7552 /**
7553 * @ngdoc function
7554 * @name getColClassDefinition
7555 * @methodOf ui.grid.class:GridColumn
7556 * @description Returns the class definition for th column
7557 */
7558 GridColumn.prototype.getColClassDefinition = function () {
7559 return ' .grid' + this.grid.id + ' ' + this.getColClass(true) + ' { min-width: ' + this.drawnWidth + 'px; max-width: ' + this.drawnWidth + 'px; }';
7560 };
7561
7562 /**
7563 * @ngdoc function
7564 * @name getRenderContainer
7565 * @methodOf ui.grid.class:GridColumn
7566 * @description Returns the render container object that this column belongs to.
7567 *
7568 * Columns will be default be in the `body` render container if they aren't allocated to one specifically.
7569 */
7570 GridColumn.prototype.getRenderContainer = function getRenderContainer() {
7571 var self = this;
7572
7573 var containerId = self.renderContainer;
7574
7575 if (containerId === null || containerId === '' || containerId === undefined) {
7576 containerId = 'body';
7577 }
7578
7579 return self.grid.renderContainers[containerId];
7580 };
7581
7582 /**
7583 * @ngdoc function
7584 * @name showColumn
7585 * @methodOf ui.grid.class:GridColumn
7586 * @description Makes the column visible by setting colDef.visible = true
7587 */
7588 GridColumn.prototype.showColumn = function() {
7589 this.colDef.visible = true;
7590 };
7591
7592
7593 /**
7594 * @ngdoc property
7595 * @name aggregationHideLabel
7596 * @propertyOf ui.grid.class:GridOptions.columnDef
7597 * @description defaults to false, if set to true hides the label text
7598 * in the aggregation footer, so only the value is displayed.
7599 *
7600 */
7601 /**
7602 * @ngdoc function
7603 * @name getAggregationText
7604 * @methodOf ui.grid.class:GridColumn
7605 * @description Gets the aggregation label from colDef.aggregationLabel if
7606 * specified or by using i18n, including deciding whether or not to display
7607 * based on colDef.aggregationHideLabel.
7608 *
7609 * @param {string} label the i18n lookup value to use for the column label
7610 *
7611 */
7612 GridColumn.prototype.getAggregationText = function () {
7613 var self = this;
7614 if ( self.colDef.aggregationHideLabel ) {
7615 return '';
7616 }
7617 else if ( self.colDef.aggregationLabel ) {
7618 return self.colDef.aggregationLabel;
7619 }
7620 else {
7621 switch ( self.colDef.aggregationType ) {
7622 case uiGridConstants.aggregationTypes.count:
7623 return i18nService.getSafeText('aggregation.count');
7624 case uiGridConstants.aggregationTypes.sum:
7625 return i18nService.getSafeText('aggregation.sum');
7626 case uiGridConstants.aggregationTypes.avg:
7627 return i18nService.getSafeText('aggregation.avg');
7628 case uiGridConstants.aggregationTypes.min:
7629 return i18nService.getSafeText('aggregation.min');
7630 case uiGridConstants.aggregationTypes.max:
7631 return i18nService.getSafeText('aggregation.max');
7632 default:
7633 return '';
7634 }
7635 }
7636 };
7637
7638 GridColumn.prototype.getCellTemplate = function () {
7639 var self = this;
7640
7641 return self.cellTemplatePromise;
7642 };
7643
7644 GridColumn.prototype.getCompiledElementFn = function () {
7645 var self = this;
7646
7647 return self.compiledElementFnDefer.promise;
7648 };
7649
7650 return GridColumn;
7651 }]);
7652
7653 })();
7654
7655 (function() {
7656 angular.module('ui.grid')
7657 .factory('GridOptions', ['gridUtil','uiGridConstants', function(gridUtil, uiGridConstants) {
7658
7659 /**
7660 * @ngdoc function
7661 * @name ui.grid.class:GridOptions
7662 * @description Default GridOptions class. GridOptions are defined by the application developer and overlaid
7663 * over this object. Setting gridOptions within your controller is the most common method for an application
7664 * developer to configure the behaviour of their ui-grid
7665 *
7666 * @example To define your gridOptions within your controller:
7667 * <pre>$scope.gridOptions = {
7668 * data: $scope.myData,
7669 * columnDefs: [
7670 * { name: 'field1', displayName: 'pretty display name' },
7671 * { name: 'field2', visible: false }
7672 * ]
7673 * };</pre>
7674 *
7675 * You can then use this within your html template, when you define your grid:
7676 * <pre>&lt;div ui-grid="gridOptions"&gt;&lt;/div&gt;</pre>
7677 *
7678 * To provide default options for all of the grids within your application, use an angular
7679 * decorator to modify the GridOptions factory.
7680 * <pre>
7681 * app.config(function($provide) {
7682 * $provide.decorator('GridOptions',function($delegate) {
7683 * var gridOptions;
7684 * gridOptions = angular.copy($delegate);
7685 * gridOptions.initialize = function(options) {
7686 * var initOptions;
7687 * initOptions = $delegate.initialize(options);
7688 * initOptions.enableColumnMenus = false;
7689 * return initOptions;
7690 * };
7691 * return gridOptions;
7692 * });
7693 * });
7694 * </pre>
7695 */
7696 return {
7697 initialize: function( baseOptions ) {
7698 /**
7699 * @ngdoc function
7700 * @name onRegisterApi
7701 * @propertyOf ui.grid.class:GridOptions
7702 * @description A callback that returns the gridApi once the grid is instantiated, which is
7703 * then used to interact with the grid programatically.
7704 *
7705 * Note that the gridApi.core.renderingComplete event is identical to this
7706 * callback, but has the advantage that it can be called from multiple places
7707 * if needed
7708 *
7709 * @example
7710 * <pre>
7711 * $scope.gridOptions.onRegisterApi = function ( gridApi ) {
7712 * $scope.gridApi = gridApi;
7713 * $scope.gridApi.selection.selectAllRows( $scope.gridApi.grid );
7714 * };
7715 * </pre>
7716 *
7717 */
7718 baseOptions.onRegisterApi = baseOptions.onRegisterApi || angular.noop();
7719
7720 /**
7721 * @ngdoc object
7722 * @name data
7723 * @propertyOf ui.grid.class:GridOptions
7724 * @description (mandatory) Array of data to be rendered into the grid, providing the data source or data binding for
7725 * the grid.
7726 *
7727 * Most commonly the data is an array of objects, where each object has a number of attributes.
7728 * Each attribute automatically becomes a column in your grid. This array could, for example, be sourced from
7729 * an angularJS $resource query request. The array can also contain complex objects, refer the binding tutorial
7730 * for examples of that.
7731 *
7732 * The most flexible usage is to set your data on $scope:
7733 *
7734 * `$scope.data = data;`
7735 *
7736 * And then direct the grid to resolve whatever is in $scope.data:
7737 *
7738 * `$scope.gridOptions.data = 'data';`
7739 *
7740 * This is the most flexible approach as it allows you to replace $scope.data whenever you feel like it without
7741 * getting pointer issues.
7742 *
7743 * Alternatively you can directly set the data array:
7744 *
7745 * `$scope.gridOptions.data = [ ];`
7746 * or
7747 *
7748 * `$http.get('/data/100.json')
7749 * .success(function(data) {
7750 * $scope.myData = data;
7751 * $scope.gridOptions.data = $scope.myData;
7752 * });`
7753 *
7754 * Where you do this, you need to take care in updating the data - you can't just update `$scope.myData` to some other
7755 * array, you need to update $scope.gridOptions.data to point to that new array as well.
7756 *
7757 */
7758 baseOptions.data = baseOptions.data || [];
7759
7760 /**
7761 * @ngdoc array
7762 * @name columnDefs
7763 * @propertyOf ui.grid.class:GridOptions
7764 * @description Array of columnDef objects. Only required property is name.
7765 * The individual options available in columnDefs are documented in the
7766 * {@link ui.grid.class:GridOptions.columnDef columnDef} section
7767 * </br>_field property can be used in place of name for backwards compatibility with 2.x_
7768 * @example
7769 *
7770 * <pre>var columnDefs = [{name: 'field1'}, {name: 'field2'}];</pre>
7771 *
7772 */
7773 baseOptions.columnDefs = baseOptions.columnDefs || [];
7774
7775 /**
7776 * @ngdoc object
7777 * @name ui.grid.class:GridOptions.columnDef
7778 * @description Definition / configuration of an individual column, which would typically be
7779 * one of many column definitions within the gridOptions.columnDefs array
7780 * @example
7781 * <pre>{name: 'field1', field: 'field1', filter: { term: 'xxx' }}</pre>
7782 *
7783 */
7784
7785 /**
7786 * @ngdoc object
7787 * @name enableGridMenu
7788 * @propertyOf ui.grid.class:GridOptions
7789 * @description Takes a boolean that adds a settings icon in the top right of the grid, which floats above
7790 * the column header, when true. The menu by default gives access to show/hide columns, but can be
7791 * customised to show additional actions.
7792 *
7793 * See the {@link #!/tutorial/121_grid_menu Grid Menu tutorial} for more detailed information.
7794 */
7795
7796 /**
7797 * @ngdoc array
7798 * @name excludeProperties
7799 * @propertyOf ui.grid.class:GridOptions
7800 * @description Array of property names in data to ignore when auto-generating column names. Provides the
7801 * inverse of columnDefs - columnDefs is a list of columns to include, excludeProperties is a list of columns
7802 * to exclude.
7803 *
7804 * If columnDefs is defined, this will be ignored.
7805 *
7806 * Defaults to ['$$hashKey']
7807 */
7808
7809 baseOptions.excludeProperties = baseOptions.excludeProperties || ['$$hashKey'];
7810
7811 /**
7812 * @ngdoc boolean
7813 * @name enableRowHashing
7814 * @propertyOf ui.grid.class:GridOptions
7815 * @description True by default. When enabled, this setting allows uiGrid to add
7816 * `$$hashKey`-type properties (similar to Angular) to elements in the `data` array. This allows
7817 * the grid to maintain state while vastly speeding up the process of altering `data` by adding/moving/removing rows.
7818 *
7819 * Note that this DOES add properties to your data that you may not want, but they are stripped out when using `angular.toJson()`. IF
7820 * you do not want this at all you can disable this setting but you will take a performance hit if you are using large numbers of rows
7821 * and are altering the data set often.
7822 */
7823 baseOptions.enableRowHashing = baseOptions.enableRowHashing !== false;
7824
7825 /**
7826 * @ngdoc function
7827 * @name rowIdentity
7828 * @methodOf ui.grid.class:GridOptions
7829 * @description This function is used to get and, if necessary, set the value uniquely identifying this row (i.e. if an identity is not present it will set one).
7830 *
7831 * By default it returns the `$$hashKey` property if it exists. If it doesn't it uses gridUtil.nextUid() to generate one
7832 */
7833 baseOptions.rowIdentity = baseOptions.rowIdentity || function rowIdentity(row) {
7834 return gridUtil.hashKey(row);
7835 };
7836
7837 /**
7838 * @ngdoc function
7839 * @name getRowIdentity
7840 * @methodOf ui.grid.class:GridOptions
7841 * @description This function returns the identity value uniquely identifying this row, if one is not present it does not set it.
7842 *
7843 * By default it returns the `$$hashKey` property but can be overridden to use any property or set of properties you want.
7844 */
7845 baseOptions.getRowIdentity = baseOptions.getRowIdentity || function getRowIdentity(row) {
7846 return row.$$hashKey;
7847 };
7848
7849 /**
7850 * @ngdoc property
7851 * @name flatEntityAccess
7852 * @propertyOf ui.grid.class:GridOptions
7853 * @description Set to true if your columns are all related directly to fields in a flat object structure - i.e.
7854 * each of your columns associate directly with a property on each of the entities in your data array.
7855 *
7856 * In that situation we can avoid all the logic associated with complex binding to functions or to properties of sub-objects,
7857 * which can provide a significant speed improvement with large data sets when filtering or sorting.
7858 *
7859 * By default false
7860 */
7861 baseOptions.flatEntityAccess = baseOptions.flatEntityAccess === true;
7862
7863 /**
7864 * @ngdoc property
7865 * @name showHeader
7866 * @propertyOf ui.grid.class:GridOptions
7867 * @description True by default. When set to false, this setting will replace the
7868 * standard header template with '<div></div>', resulting in no header being shown.
7869 */
7870 baseOptions.showHeader = typeof(baseOptions.showHeader) !== "undefined" ? baseOptions.showHeader : true;
7871
7872 /**
7873 * @ngdoc property
7874 * @name headerRowHeight
7875 * @propertyOf ui.grid.class:GridOptions
7876 * @description The height of the header in pixels, defaults to 30.
7877 * Although, we recommend that you alter header height with CSS rather than using this option:
7878 *
7879 * <pre>
7880 * .grid .ui-grid-header-cell {
7881 * height: 60px;
7882 * }
7883 * </pre>
7884 **/
7885 if (!baseOptions.showHeader) {
7886 baseOptions.headerRowHeight = 0;
7887 }
7888 else {
7889 baseOptions.headerRowHeight = typeof(baseOptions.headerRowHeight) !== "undefined" ? baseOptions.headerRowHeight : 30;
7890 }
7891
7892 /**
7893 * @ngdoc property
7894 * @name rowHeight
7895 * @propertyOf ui.grid.class:GridOptions
7896 * @description The height of the row in pixels, Can be passed as integer or string. defaults to 30.
7897 *
7898 */
7899
7900 if (typeof baseOptions.rowHeight === "string") {
7901 baseOptions.rowHeight = parseInt(baseOptions.rowHeight) || 30;
7902 }
7903
7904 else {
7905 baseOptions.rowHeight = baseOptions.rowHeight || 30;
7906 }
7907
7908 /**
7909 * @ngdoc integer
7910 * @name minRowsToShow
7911 * @propertyOf ui.grid.class:GridOptions
7912 * @description Minimum number of rows to show when the grid doesn't have a defined height. Defaults to "10".
7913 */
7914 baseOptions.minRowsToShow = typeof(baseOptions.minRowsToShow) !== "undefined" ? baseOptions.minRowsToShow : 10;
7915
7916 /**
7917 * @ngdoc property
7918 * @name showGridFooter
7919 * @propertyOf ui.grid.class:GridOptions
7920 * @description Whether or not to show the footer, defaults to false
7921 * The footer display Total Rows and Visible Rows (filtered rows)
7922 */
7923 baseOptions.showGridFooter = baseOptions.showGridFooter === true;
7924
7925 /**
7926 * @ngdoc property
7927 * @name showColumnFooter
7928 * @propertyOf ui.grid.class:GridOptions
7929 * @description Whether or not to show the column footer, defaults to false
7930 * The column footer displays column aggregates
7931 */
7932 baseOptions.showColumnFooter = baseOptions.showColumnFooter === true;
7933
7934 /**
7935 * @ngdoc property
7936 * @name columnFooterHeight
7937 * @propertyOf ui.grid.class:GridOptions
7938 * @description The height of the footer rows (column footer and grid footer) in pixels
7939 *
7940 */
7941 baseOptions.columnFooterHeight = typeof(baseOptions.columnFooterHeight) !== "undefined" ? baseOptions.columnFooterHeight : 30;
7942 baseOptions.gridFooterHeight = typeof(baseOptions.gridFooterHeight) !== "undefined" ? baseOptions.gridFooterHeight : 30;
7943
7944 baseOptions.columnWidth = typeof(baseOptions.columnWidth) !== "undefined" ? baseOptions.columnWidth : 50;
7945
7946 /**
7947 * @ngdoc property
7948 * @name maxVisibleColumnCount
7949 * @propertyOf ui.grid.class:GridOptions
7950 * @description Defaults to 200
7951 *
7952 */
7953 baseOptions.maxVisibleColumnCount = typeof(baseOptions.maxVisibleColumnCount) !== "undefined" ? baseOptions.maxVisibleColumnCount : 200;
7954
7955 /**
7956 * @ngdoc property
7957 * @name virtualizationThreshold
7958 * @propertyOf ui.grid.class:GridOptions
7959 * @description Turn virtualization on when number of data elements goes over this number, defaults to 20
7960 */
7961 baseOptions.virtualizationThreshold = typeof(baseOptions.virtualizationThreshold) !== "undefined" ? baseOptions.virtualizationThreshold : 20;
7962
7963 /**
7964 * @ngdoc property
7965 * @name columnVirtualizationThreshold
7966 * @propertyOf ui.grid.class:GridOptions
7967 * @description Turn virtualization on when number of columns goes over this number, defaults to 10
7968 */
7969 baseOptions.columnVirtualizationThreshold = typeof(baseOptions.columnVirtualizationThreshold) !== "undefined" ? baseOptions.columnVirtualizationThreshold : 10;
7970
7971 /**
7972 * @ngdoc property
7973 * @name excessRows
7974 * @propertyOf ui.grid.class:GridOptions
7975 * @description Extra rows to to render outside of the viewport, which helps with smoothness of scrolling.
7976 * Defaults to 4
7977 */
7978 baseOptions.excessRows = typeof(baseOptions.excessRows) !== "undefined" ? baseOptions.excessRows : 4;
7979
7980 /**
7981 * @ngdoc property
7982 * @name scrollThreshold
7983 * @propertyOf ui.grid.class:GridOptions
7984 * @description Throttles the grid scrolling by the amount of rows set, which helps with smoothness of scrolling.
7985 * Defaults to 4.
7986 */
7987 baseOptions.scrollThreshold = typeof(baseOptions.scrollThreshold) !== "undefined" ? baseOptions.scrollThreshold : 4;
7988
7989 /**
7990 * @ngdoc property
7991 * @name excessColumns
7992 * @propertyOf ui.grid.class:GridOptions
7993 * @description Extra columns to to render outside of the viewport, which helps with smoothness of scrolling.
7994 * Defaults to 4
7995 */
7996 baseOptions.excessColumns = typeof(baseOptions.excessColumns) !== "undefined" ? baseOptions.excessColumns : 4;
7997
7998 /**
7999 * @ngdoc property
8000 * @name aggregationCalcThrottle
8001 * @propertyOf ui.grid.class:GridOptions
8002 * @description Default time in milliseconds to throttle aggregation calcuations, defaults to 500ms
8003 */
8004 baseOptions.aggregationCalcThrottle = typeof(baseOptions.aggregationCalcThrottle) !== "undefined" ? baseOptions.aggregationCalcThrottle : 500;
8005
8006 /**
8007 * @ngdoc property
8008 * @name wheelScrollThrottle
8009 * @propertyOf ui.grid.class:GridOptions
8010 * @description Default time in milliseconds to throttle scroll events to, defaults to 70ms
8011 */
8012 baseOptions.wheelScrollThrottle = typeof(baseOptions.wheelScrollThrottle) !== "undefined" ? baseOptions.wheelScrollThrottle : 70;
8013
8014
8015 /**
8016 * @ngdoc property
8017 * @name scrollDebounce
8018 * @propertyOf ui.grid.class:GridOptions
8019 * @description Default time in milliseconds to debounce scroll events, defaults to 300ms
8020 */
8021 baseOptions.scrollDebounce = typeof(baseOptions.scrollDebounce) !== "undefined" ? baseOptions.scrollDebounce : 300;
8022
8023 /**
8024 * @ngdoc boolean
8025 * @name enableSorting
8026 * @propertyOf ui.grid.class:GridOptions
8027 * @description True by default. When enabled, this setting adds sort
8028 * widgets to the column headers, allowing sorting of the data for the entire grid.
8029 * Sorting can then be disabled / enabled on individual columns using the columnDefs,
8030 * if it set, it will override GridOptions enableSorting setting.
8031 */
8032 baseOptions.enableSorting = baseOptions.enableSorting !== false;
8033
8034 /**
8035 * @ngdoc boolean
8036 * @name enableFiltering
8037 * @propertyOf ui.grid.class:GridOptions
8038 * @description False by default. When enabled, this setting adds filter
8039 * boxes to each column header, allowing filtering within the column for the entire grid.
8040 * Filtering can then be disabled on individual columns using the columnDefs.
8041 */
8042 baseOptions.enableFiltering = baseOptions.enableFiltering === true;
8043
8044 /**
8045 * @ngdoc boolean
8046 * @name enableColumnMenus
8047 * @propertyOf ui.grid.class:GridOptions
8048 * @description True by default. When enabled, this setting displays a column
8049 * menu within each column.
8050 * By default column menu's trigger is hidden before mouse over, but you can always force it to be visible with CSS:
8051 *
8052 * <pre>
8053 * .ui-grid-column-menu-button {
8054 * display: block;
8055 * }
8056 * </pre>
8057 */
8058 baseOptions.enableColumnMenus = baseOptions.enableColumnMenus !== false;
8059
8060 /**
8061 * @ngdoc boolean
8062 * @name enableVerticalScrollbar
8063 * @propertyOf ui.grid.class:GridOptions
8064 * @description {@link ui.grid.service:uiGridConstants#properties_scrollbars uiGridConstants.scrollbars.ALWAYS} by default.
8065 * This settings controls the vertical scrollbar for the grid.
8066 * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER, uiGridConstants.scrollbars.WHEN_NEEDED
8067 */
8068 baseOptions.enableVerticalScrollbar = typeof(baseOptions.enableVerticalScrollbar) !== "undefined" ? baseOptions.enableVerticalScrollbar : uiGridConstants.scrollbars.ALWAYS;
8069
8070 /**
8071 * @ngdoc boolean
8072 * @name enableHorizontalScrollbar
8073 * @propertyOf ui.grid.class:GridOptions
8074 * @description {@link ui.grid.service:uiGridConstants#properties_scrollbars uiGridConstants.scrollbars.ALWAYS} by default.
8075 * This settings controls the horizontal scrollbar for the grid.
8076 * Supported values: uiGridConstants.scrollbars.ALWAYS, uiGridConstants.scrollbars.NEVER, uiGridConstants.scrollbars.WHEN_NEEDED
8077 */
8078 baseOptions.enableHorizontalScrollbar = typeof(baseOptions.enableHorizontalScrollbar) !== "undefined" ? baseOptions.enableHorizontalScrollbar : uiGridConstants.scrollbars.ALWAYS;
8079
8080 /**
8081 * @ngdoc boolean
8082 * @name enableMinHeightCheck
8083 * @propertyOf ui.grid.class:GridOptions
8084 * @description True by default. When enabled, a newly initialized grid will check to see if it is tall enough to display
8085 * at least one row of data. If the grid is not tall enough, it will resize the DOM element to display minRowsToShow number
8086 * of rows.
8087 */
8088 baseOptions.enableMinHeightCheck = baseOptions.enableMinHeightCheck !== false;
8089
8090 /**
8091 * @ngdoc boolean
8092 * @name minimumColumnSize
8093 * @propertyOf ui.grid.class:GridOptions
8094 * @description Sets the default minimum column width, in other words,
8095 * it defines the default value for a column minWidth attribute if that is not otherwise specified.
8096 * Should be a number. Defaults to 30 pixels.
8097 */
8098 baseOptions.minimumColumnSize = typeof(baseOptions.minimumColumnSize) !== "undefined" ? baseOptions.minimumColumnSize : 30;
8099
8100 /**
8101 * @ngdoc function
8102 * @name rowEquality
8103 * @methodOf ui.grid.class:GridOptions
8104 * @description By default, rows are compared using object equality. This option can be overridden
8105 * to compare on any data item property or function
8106 * @param {object} entityA First Data Item to compare
8107 * @param {object} entityB Second Data Item to compare
8108 */
8109 baseOptions.rowEquality = baseOptions.rowEquality || function(entityA, entityB) {
8110 return entityA === entityB;
8111 };
8112
8113 /**
8114 * @ngdoc string
8115 * @name headerTemplate
8116 * @propertyOf ui.grid.class:GridOptions
8117 * @description Null by default. When provided, this setting uses a custom header
8118 * template, rather than the default template. Can be set to either the name of a template file:
8119 * <pre> $scope.gridOptions.headerTemplate = 'header_template.html';</pre>
8120 * inline html
8121 * <pre> $scope.gridOptions.headerTemplate = '<div class="ui-grid-top-panel" style="text-align: center">I am a Custom Grid Header</div>'</pre>
8122 * or the id of a precompiled template (TBD how to use this).
8123 * </br>Refer to the custom header tutorial for more information.
8124 * If you want no header at all, you can set to an empty div:
8125 * <pre> $scope.gridOptions.headerTemplate = '<div></div>';</pre>
8126 *
8127 * If you want to only have a static header, then you can set to static content. If
8128 * you want to tailor the existing column headers, then you should look at the
8129 * current 'ui-grid-header.html' template in github as your starting point.
8130 *
8131 */
8132 baseOptions.headerTemplate = baseOptions.headerTemplate || null;
8133
8134 /**
8135 * @ngdoc string
8136 * @name footerTemplate
8137 * @propertyOf ui.grid.class:GridOptions
8138 * @description (optional) ui-grid/ui-grid-footer by default. This footer shows the per-column
8139 * aggregation totals.
8140 * When provided, this setting uses a custom footer template. Can be set to either the name of a template file 'footer_template.html', inline html
8141 * <pre>'<div class="ui-grid-bottom-panel" style="text-align: center">I am a Custom Grid Footer</div>'</pre>, or the id
8142 * of a precompiled template (TBD how to use this). Refer to the custom footer tutorial for more information.
8143 */
8144 baseOptions.footerTemplate = baseOptions.footerTemplate || 'ui-grid/ui-grid-footer';
8145
8146 /**
8147 * @ngdoc string
8148 * @name gridFooterTemplate
8149 * @propertyOf ui.grid.class:GridOptions
8150 * @description (optional) ui-grid/ui-grid-grid-footer by default. This template by default shows the
8151 * total items at the bottom of the grid, and the selected items if selection is enabled.
8152 */
8153 baseOptions.gridFooterTemplate = baseOptions.gridFooterTemplate || 'ui-grid/ui-grid-grid-footer';
8154
8155 /**
8156 * @ngdoc string
8157 * @name rowTemplate
8158 * @propertyOf ui.grid.class:GridOptions
8159 * @description 'ui-grid/ui-grid-row' by default. When provided, this setting uses a
8160 * custom row template. Can be set to either the name of a template file:
8161 * <pre> $scope.gridOptions.rowTemplate = 'row_template.html';</pre>
8162 * inline html
8163 * <pre> $scope.gridOptions.rowTemplate = '<div style="background-color: aquamarine" ng-click="grid.appScope.fnOne(row)" ng-repeat="col in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell" ui-grid-cell></div>';</pre>
8164 * or the id of a precompiled template (TBD how to use this) can be provided.
8165 * </br>Refer to the custom row template tutorial for more information.
8166 */
8167 baseOptions.rowTemplate = baseOptions.rowTemplate || 'ui-grid/ui-grid-row';
8168
8169 /**
8170 * @ngdoc string
8171 * @name gridMenuTemplate
8172 * @propertyOf ui.grid.class:GridOptions
8173 * @description 'ui-grid/uiGridMenu' by default. When provided, this setting uses a
8174 * custom grid menu template.
8175 */
8176 baseOptions.gridMenuTemplate = baseOptions.gridMenuTemplate || 'ui-grid/uiGridMenu';
8177
8178 /**
8179 * @ngdoc object
8180 * @name appScopeProvider
8181 * @propertyOf ui.grid.class:GridOptions
8182 * @description by default, the parent scope of the ui-grid element will be assigned to grid.appScope
8183 * this property allows you to assign any reference you want to grid.appScope
8184 */
8185 baseOptions.appScopeProvider = baseOptions.appScopeProvider || null;
8186
8187 return baseOptions;
8188 }
8189 };
8190 }]);
8191 })();
8192
8193 (function() {
8194
8195 angular.module('ui.grid')
8196
8197 /**
8198 * @ngdoc function
8199 * @name ui.grid.class:GridRenderContainer
8200 * @description The grid has render containers, allowing the ability to have pinned columns. If the grid
8201 * is right-to-left then there may be a right render container, if left-to-right then there may
8202 * be a left render container. There is always a body render container.
8203 * @param {string} name The name of the render container ('body', 'left', or 'right')
8204 * @param {Grid} grid the grid the render container is in
8205 * @param {object} options the render container options
8206 */
8207 .factory('GridRenderContainer', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {
8208 function GridRenderContainer(name, grid, options) {
8209 var self = this;
8210
8211 // if (gridUtil.type(grid) !== 'Grid') {
8212 // throw new Error('Grid argument is not a Grid object');
8213 // }
8214
8215 self.name = name;
8216
8217 self.grid = grid;
8218
8219 // self.rowCache = [];
8220 // self.columnCache = [];
8221
8222 self.visibleRowCache = [];
8223 self.visibleColumnCache = [];
8224
8225 self.renderedRows = [];
8226 self.renderedColumns = [];
8227
8228 self.prevScrollTop = 0;
8229 self.prevScrolltopPercentage = 0;
8230 self.prevRowScrollIndex = 0;
8231
8232 self.prevScrollLeft = 0;
8233 self.prevScrollleftPercentage = 0;
8234 self.prevColumnScrollIndex = 0;
8235
8236 self.columnStyles = '';
8237
8238 self.viewportAdjusters = [];
8239
8240 /**
8241 * @ngdoc boolean
8242 * @name hasHScrollbar
8243 * @propertyOf ui.grid.class:GridRenderContainer
8244 * @description flag to signal that container has a horizontal scrollbar
8245 */
8246 self.hasHScrollbar = false;
8247
8248 /**
8249 * @ngdoc boolean
8250 * @name hasVScrollbar
8251 * @propertyOf ui.grid.class:GridRenderContainer
8252 * @description flag to signal that container has a vertical scrollbar
8253 */
8254 self.hasVScrollbar = false;
8255
8256 /**
8257 * @ngdoc boolean
8258 * @name canvasHeightShouldUpdate
8259 * @propertyOf ui.grid.class:GridRenderContainer
8260 * @description flag to signal that container should recalculate the canvas size
8261 */
8262 self.canvasHeightShouldUpdate = true;
8263
8264 /**
8265 * @ngdoc boolean
8266 * @name canvasHeight
8267 * @propertyOf ui.grid.class:GridRenderContainer
8268 * @description last calculated canvas height value
8269 */
8270 self.$$canvasHeight = 0;
8271
8272 if (options && angular.isObject(options)) {
8273 angular.extend(self, options);
8274 }
8275
8276 grid.registerStyleComputation({
8277 priority: 5,
8278 func: function () {
8279 self.updateColumnWidths();
8280 return self.columnStyles;
8281 }
8282 });
8283 }
8284
8285
8286 GridRenderContainer.prototype.reset = function reset() {
8287 // this.rowCache.length = 0;
8288 // this.columnCache.length = 0;
8289
8290 this.visibleColumnCache.length = 0;
8291 this.visibleRowCache.length = 0;
8292
8293 this.renderedRows.length = 0;
8294 this.renderedColumns.length = 0;
8295 };
8296
8297 // TODO(c0bra): calculate size?? Should this be in a stackable directive?
8298
8299
8300 GridRenderContainer.prototype.containsColumn = function (col) {
8301 return this.visibleColumnCache.indexOf(col) !== -1;
8302 };
8303
8304 GridRenderContainer.prototype.minRowsToRender = function minRowsToRender() {
8305 var self = this;
8306 var minRows = 0;
8307 var rowAddedHeight = 0;
8308 var viewPortHeight = self.getViewportHeight();
8309 for (var i = self.visibleRowCache.length - 1; rowAddedHeight < viewPortHeight && i >= 0; i--) {
8310 rowAddedHeight += self.visibleRowCache[i].height;
8311 minRows++;
8312 }
8313 return minRows;
8314 };
8315
8316 GridRenderContainer.prototype.minColumnsToRender = function minColumnsToRender() {
8317 var self = this;
8318 var viewportWidth = this.getViewportWidth();
8319
8320 var min = 0;
8321 var totalWidth = 0;
8322
8323 for (var i = 0; i < self.visibleColumnCache.length; i++) {
8324 var col = self.visibleColumnCache[i];
8325
8326 if (totalWidth < viewportWidth) {
8327 totalWidth += col.drawnWidth ? col.drawnWidth : 0;
8328 min++;
8329 }
8330 else {
8331 var currWidth = 0;
8332 for (var j = i; j >= i - min; j--) {
8333 currWidth += self.visibleColumnCache[j].drawnWidth ? self.visibleColumnCache[j].drawnWidth : 0;
8334 }
8335 if (currWidth < viewportWidth) {
8336 min++;
8337 }
8338 }
8339 }
8340
8341 return min;
8342 };
8343
8344 GridRenderContainer.prototype.getVisibleRowCount = function getVisibleRowCount() {
8345 return this.visibleRowCache.length;
8346 };
8347
8348 /**
8349 * @ngdoc function
8350 * @name registerViewportAdjuster
8351 * @methodOf ui.grid.class:GridRenderContainer
8352 * @description Registers an adjuster to the render container's available width or height. Adjusters are used
8353 * to tell the render container that there is something else consuming space, and to adjust it's size
8354 * appropriately.
8355 * @param {function} func the adjuster function we want to register
8356 */
8357
8358 GridRenderContainer.prototype.registerViewportAdjuster = function registerViewportAdjuster(func) {
8359 this.viewportAdjusters.push(func);
8360 };
8361
8362 /**
8363 * @ngdoc function
8364 * @name removeViewportAdjuster
8365 * @methodOf ui.grid.class:GridRenderContainer
8366 * @description Removes an adjuster, should be used when your element is destroyed
8367 * @param {function} func the adjuster function we want to remove
8368 */
8369 GridRenderContainer.prototype.removeViewportAdjuster = function removeViewportAdjuster(func) {
8370 var idx = this.viewportAdjusters.indexOf(func);
8371
8372 if (idx > -1) {
8373 this.viewportAdjusters.splice(idx, 1);
8374 }
8375 };
8376
8377 /**
8378 * @ngdoc function
8379 * @name getViewportAdjustment
8380 * @methodOf ui.grid.class:GridRenderContainer
8381 * @description Gets the adjustment based on the viewportAdjusters.
8382 * @returns {object} a hash of { height: x, width: y }. Usually the values will be negative
8383 */
8384 GridRenderContainer.prototype.getViewportAdjustment = function getViewportAdjustment() {
8385 var self = this;
8386
8387 var adjustment = { height: 0, width: 0 };
8388
8389 self.viewportAdjusters.forEach(function (func) {
8390 adjustment = func.call(this, adjustment);
8391 });
8392
8393 return adjustment;
8394 };
8395
8396 GridRenderContainer.prototype.getMargin = function getMargin(side) {
8397 var self = this;
8398
8399 var amount = 0;
8400
8401 self.viewportAdjusters.forEach(function (func) {
8402 var adjustment = func.call(this, { height: 0, width: 0 });
8403
8404 if (adjustment.side && adjustment.side === side) {
8405 amount += adjustment.width * -1;
8406 }
8407 });
8408
8409 return amount;
8410 };
8411
8412 GridRenderContainer.prototype.getViewportHeight = function getViewportHeight() {
8413 var self = this;
8414
8415 var headerHeight = (self.headerHeight) ? self.headerHeight : self.grid.headerHeight;
8416
8417 var viewPortHeight = self.grid.gridHeight - headerHeight - self.grid.footerHeight;
8418
8419
8420 var adjustment = self.getViewportAdjustment();
8421
8422 viewPortHeight = viewPortHeight + adjustment.height;
8423
8424 return viewPortHeight;
8425 };
8426
8427 GridRenderContainer.prototype.getViewportWidth = function getViewportWidth() {
8428 var self = this;
8429
8430 var viewportWidth = self.grid.gridWidth;
8431
8432 // if (typeof(self.grid.verticalScrollbarWidth) !== 'undefined' && self.grid.verticalScrollbarWidth !== undefined &&
8433 // self.grid.verticalScrollbarWidth > 0) {
8434 // viewPortWidth = viewPortWidth - self.grid.verticalScrollbarWidth;
8435 // }
8436
8437 // var viewportWidth = 0;\
8438 // self.visibleColumnCache.forEach(function (column) {
8439 // viewportWidth += column.drawnWidth;
8440 // });
8441
8442 var adjustment = self.getViewportAdjustment();
8443
8444 viewportWidth = viewportWidth + adjustment.width;
8445
8446 return viewportWidth;
8447 };
8448
8449 GridRenderContainer.prototype.getHeaderViewportWidth = function getHeaderViewportWidth() {
8450 return this.getViewportWidth();
8451 };
8452
8453
8454 /**
8455 * @ngdoc function
8456 * @name getCanvasHeight
8457 * @methodOf ui.grid.class:GridRenderContainer
8458 * @description Returns the total canvas height. Only recalculates if canvasHeightShouldUpdate = false
8459 * @returns {number} total height of all the visible rows in the container
8460 */
8461 GridRenderContainer.prototype.getCanvasHeight = function getCanvasHeight() {
8462 var self = this;
8463
8464 if (!self.canvasHeightShouldUpdate) {
8465 return self.$$canvasHeight;
8466 }
8467
8468 var oldCanvasHeight = self.$$canvasHeight;
8469
8470 self.$$canvasHeight = 0;
8471
8472 self.visibleRowCache.forEach(function(row) {
8473 self.$$canvasHeight += row.height;
8474 });
8475
8476
8477 self.canvasHeightShouldUpdate = false;
8478
8479 self.grid.api.core.raise.canvasHeightChanged(oldCanvasHeight, self.$$canvasHeight);
8480
8481 return self.$$canvasHeight;
8482 };
8483
8484 GridRenderContainer.prototype.getVerticalScrollLength = function getVerticalScrollLength() {
8485 return this.getCanvasHeight() - this.getViewportHeight() + this.grid.scrollbarHeight !== 0 ? this.getCanvasHeight() - this.getViewportHeight() + this.grid.scrollbarHeight : -1;
8486 };
8487
8488 GridRenderContainer.prototype.getHorizontalScrollLength = function getHorizontalScrollLength() {
8489 return this.getCanvasWidth() - this.getViewportWidth() + this.grid.scrollbarWidth !== 0 ? this.getCanvasWidth() - this.getViewportWidth() + this.grid.scrollbarWidth : -1;
8490 };
8491
8492 GridRenderContainer.prototype.getCanvasWidth = function getCanvasWidth() {
8493 var self = this;
8494
8495 return self.canvasWidth;
8496 };
8497
8498 GridRenderContainer.prototype.setRenderedRows = function setRenderedRows(newRows) {
8499 this.renderedRows.length = newRows.length;
8500 for (var i = 0; i < newRows.length; i++) {
8501 this.renderedRows[i] = newRows[i];
8502 }
8503 };
8504
8505 GridRenderContainer.prototype.setRenderedColumns = function setRenderedColumns(newColumns) {
8506 // OLD:
8507 this.renderedColumns.length = newColumns.length;
8508 for (var i = 0; i < newColumns.length; i++) {
8509 this.renderedColumns[i] = newColumns[i];
8510 }
8511
8512 this.updateColumnOffset();
8513 };
8514
8515 GridRenderContainer.prototype.updateColumnOffset = function updateColumnOffset() {
8516 // Calculate the width of the columns on the left side that are no longer rendered.
8517 // That will be the offset for the columns as we scroll horizontally.
8518 var hiddenColumnsWidth = 0;
8519 for (var i = 0; i < this.currentFirstColumn; i++) {
8520 hiddenColumnsWidth += this.visibleColumnCache[i].drawnWidth;
8521 }
8522
8523 this.columnOffset = hiddenColumnsWidth;
8524 };
8525
8526 GridRenderContainer.prototype.scrollVertical = function (newScrollTop) {
8527 var vertScrollPercentage = -1;
8528
8529 if (newScrollTop !== this.prevScrollTop) {
8530 var yDiff = newScrollTop - this.prevScrollTop;
8531
8532 if (yDiff > 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN; }
8533 if (yDiff < 0 ) { this.grid.scrollDirection = uiGridConstants.scrollDirection.UP; }
8534
8535 var vertScrollLength = this.getVerticalScrollLength();
8536
8537 vertScrollPercentage = newScrollTop / vertScrollLength;
8538
8539 if (vertScrollPercentage > 1) { vertScrollPercentage = 1; }
8540 if (vertScrollPercentage < 0) { vertScrollPercentage = 0; }
8541
8542 this.adjustScrollVertical(newScrollTop, vertScrollPercentage);
8543 return vertScrollPercentage;
8544 }
8545 };
8546
8547 GridRenderContainer.prototype.scrollHorizontal = function(newScrollLeft) {
8548 var horizScrollPercentage = -1;
8549
8550 // Handle RTL here
8551 if (newScrollLeft !== this.prevScrollLeft) {
8552 var xDiff = newScrollLeft - this.prevScrollLeft;
8553
8554 if (xDiff > 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.RIGHT; }
8555 if (xDiff < 0) { this.grid.scrollDirection = uiGridConstants.scrollDirection.LEFT; }
8556
8557 var horizScrollLength = this.getHorizontalScrollLength();
8558 if (horizScrollLength !== 0) {
8559 horizScrollPercentage = newScrollLeft / horizScrollLength;
8560 }
8561 else {
8562 horizScrollPercentage = 0;
8563 }
8564
8565 this.adjustScrollHorizontal(newScrollLeft, horizScrollPercentage);
8566 return horizScrollPercentage;
8567 }
8568 };
8569
8570 GridRenderContainer.prototype.adjustScrollVertical = function adjustScrollVertical(scrollTop, scrollPercentage, force) {
8571 if (this.prevScrollTop === scrollTop && !force) {
8572 return;
8573 }
8574
8575 if (typeof(scrollTop) === 'undefined' || scrollTop === undefined || scrollTop === null) {
8576 scrollTop = (this.getCanvasHeight() - this.getViewportHeight()) * scrollPercentage;
8577 }
8578
8579 this.adjustRows(scrollTop, scrollPercentage, false);
8580
8581 this.prevScrollTop = scrollTop;
8582 this.prevScrolltopPercentage = scrollPercentage;
8583
8584 this.grid.queueRefresh();
8585 };
8586
8587 GridRenderContainer.prototype.adjustScrollHorizontal = function adjustScrollHorizontal(scrollLeft, scrollPercentage, force) {
8588 if (this.prevScrollLeft === scrollLeft && !force) {
8589 return;
8590 }
8591
8592 if (typeof(scrollLeft) === 'undefined' || scrollLeft === undefined || scrollLeft === null) {
8593 scrollLeft = (this.getCanvasWidth() - this.getViewportWidth()) * scrollPercentage;
8594 }
8595
8596 this.adjustColumns(scrollLeft, scrollPercentage);
8597
8598 this.prevScrollLeft = scrollLeft;
8599 this.prevScrollleftPercentage = scrollPercentage;
8600
8601 this.grid.queueRefresh();
8602 };
8603
8604 GridRenderContainer.prototype.adjustRows = function adjustRows(scrollTop, scrollPercentage, postDataLoaded) {
8605 var self = this;
8606
8607 var minRows = self.minRowsToRender();
8608
8609 var rowCache = self.visibleRowCache;
8610
8611 var maxRowIndex = rowCache.length - minRows;
8612
8613 // Calculate the scroll percentage according to the scrollTop location, if no percentage was provided
8614 if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollTop) {
8615 scrollPercentage = scrollTop / self.getVerticalScrollLength();
8616 }
8617
8618 var rowIndex = Math.ceil(Math.min(maxRowIndex, maxRowIndex * scrollPercentage));
8619
8620 // Define a max row index that we can't scroll past
8621 if (rowIndex > maxRowIndex) {
8622 rowIndex = maxRowIndex;
8623 }
8624
8625 var newRange = [];
8626 if (rowCache.length > self.grid.options.virtualizationThreshold) {
8627 if (!(typeof(scrollTop) === 'undefined' || scrollTop === null)) {
8628 // Have we hit the threshold going down?
8629 if ( !self.grid.suppressParentScrollDown && self.prevScrollTop < scrollTop && rowIndex < self.prevRowScrollIndex + self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {
8630 return;
8631 }
8632 // Have we hit the threshold going up?
8633 if ( !self.grid.suppressParentScrollUp && self.prevScrollTop > scrollTop && rowIndex > self.prevRowScrollIndex - self.grid.options.scrollThreshold && rowIndex < maxRowIndex) {
8634 return;
8635 }
8636 }
8637
8638 var rangeStart = Math.max(0, rowIndex - self.grid.options.excessRows);
8639 var rangeEnd = Math.min(rowCache.length, rowIndex + minRows + self.grid.options.excessRows);
8640
8641 newRange = [rangeStart, rangeEnd];
8642 }
8643 else {
8644 var maxLen = self.visibleRowCache.length;
8645 newRange = [0, Math.max(maxLen, minRows + self.grid.options.excessRows)];
8646 }
8647
8648 self.updateViewableRowRange(newRange);
8649
8650 self.prevRowScrollIndex = rowIndex;
8651 };
8652
8653 GridRenderContainer.prototype.adjustColumns = function adjustColumns(scrollLeft, scrollPercentage) {
8654 var self = this;
8655
8656 var minCols = self.minColumnsToRender();
8657
8658 var columnCache = self.visibleColumnCache;
8659 var maxColumnIndex = columnCache.length - minCols;
8660
8661 // Calculate the scroll percentage according to the scrollLeft location, if no percentage was provided
8662 if ((typeof(scrollPercentage) === 'undefined' || scrollPercentage === null) && scrollLeft) {
8663 scrollPercentage = scrollLeft / self.getHorizontalScrollLength();
8664 }
8665
8666 var colIndex = Math.ceil(Math.min(maxColumnIndex, maxColumnIndex * scrollPercentage));
8667
8668 // Define a max row index that we can't scroll past
8669 if (colIndex > maxColumnIndex) {
8670 colIndex = maxColumnIndex;
8671 }
8672
8673 var newRange = [];
8674 if (columnCache.length > self.grid.options.columnVirtualizationThreshold && self.getCanvasWidth() > self.getViewportWidth()) {
8675 var rangeStart = Math.max(0, colIndex - self.grid.options.excessColumns);
8676 var rangeEnd = Math.min(columnCache.length, colIndex + minCols + self.grid.options.excessColumns);
8677
8678 newRange = [rangeStart, rangeEnd];
8679 }
8680 else {
8681 var maxLen = self.visibleColumnCache.length;
8682
8683 newRange = [0, Math.max(maxLen, minCols + self.grid.options.excessColumns)];
8684 }
8685
8686 self.updateViewableColumnRange(newRange);
8687
8688 self.prevColumnScrollIndex = colIndex;
8689 };
8690
8691 // Method for updating the visible rows
8692 GridRenderContainer.prototype.updateViewableRowRange = function updateViewableRowRange(renderedRange) {
8693 // Slice out the range of rows from the data
8694 // var rowArr = uiGridCtrl.grid.rows.slice(renderedRange[0], renderedRange[1]);
8695 var rowArr = this.visibleRowCache.slice(renderedRange[0], renderedRange[1]);
8696
8697 // Define the top-most rendered row
8698 this.currentTopRow = renderedRange[0];
8699
8700 this.setRenderedRows(rowArr);
8701 };
8702
8703 // Method for updating the visible columns
8704 GridRenderContainer.prototype.updateViewableColumnRange = function updateViewableColumnRange(renderedRange) {
8705 // Slice out the range of rows from the data
8706 // var columnArr = uiGridCtrl.grid.columns.slice(renderedRange[0], renderedRange[1]);
8707 var columnArr = this.visibleColumnCache.slice(renderedRange[0], renderedRange[1]);
8708
8709 // Define the left-most rendered columns
8710 this.currentFirstColumn = renderedRange[0];
8711
8712 this.setRenderedColumns(columnArr);
8713 };
8714
8715 GridRenderContainer.prototype.headerCellWrapperStyle = function () {
8716 var self = this;
8717
8718 if (self.currentFirstColumn !== 0) {
8719 var offset = self.columnOffset;
8720
8721 if (self.grid.isRTL()) {
8722 return { 'margin-right': offset + 'px' };
8723 }
8724 else {
8725 return { 'margin-left': offset + 'px' };
8726 }
8727 }
8728
8729 return null;
8730 };
8731
8732 /**
8733 * @ngdoc boolean
8734 * @name updateColumnWidths
8735 * @propertyOf ui.grid.class:GridRenderContainer
8736 * @description Determine the appropriate column width of each column across all render containers.
8737 *
8738 * Column width is easy when each column has a specified width. When columns are variable width (i.e.
8739 * have an * or % of the viewport) then we try to calculate so that things fit in. The problem is that
8740 * we have multiple render containers, and we don't want one render container to just take the whole viewport
8741 * when it doesn't need to - we want things to balance out across the render containers.
8742 *
8743 * To do this, we use this method to calculate all the renderContainers, recognising that in a given render
8744 * cycle it'll get called once per render container, so it needs to return the same values each time.
8745 *
8746 * The constraints on this method are therefore:
8747 * - must return the same value when called multiple times, to do this it needs to rely on properties of the
8748 * columns, but not properties that change when this is called (so it shouldn't rely on drawnWidth)
8749 *
8750 * The general logic of this method is:
8751 * - calculate our total available width
8752 * - look at all the columns across all render containers, and work out which have widths and which have
8753 * constraints such as % or * or something else
8754 * - for those with *, count the total number of * we see and add it onto a running total, add this column to an * array
8755 * - for those with a %, allocate the % as a percentage of the viewport, having consideration of min and max
8756 * - for those with manual width (in pixels) we set the drawnWidth to the specified width
8757 * - we end up with an asterisks array still to process
8758 * - we look at our remaining width. If it's greater than zero, we divide it up among the asterisk columns, then process
8759 * them for min and max width constraints
8760 * - if it's zero or less, we set the asterisk columns to their minimum widths
8761 * - we use parseInt quite a bit, as we try to make all our column widths integers
8762 */
8763 GridRenderContainer.prototype.updateColumnWidths = function () {
8764 var self = this;
8765
8766 var asterisksArray = [],
8767 asteriskNum = 0,
8768 usedWidthSum = 0,
8769 ret = '',
8770 pinRightColumn = false,
8771 fixedNumberArray = [],
8772 percentageArray = [],
8773 totalPercentage = 0;
8774
8775 // Get the width of the viewport
8776 var availableWidth = self.grid.getViewportWidth() - self.grid.scrollbarWidth;
8777
8778 // get all the columns across all render containers, we have to calculate them all or one render container
8779 // could consume the whole viewport
8780 var columnCache = [];
8781 angular.forEach(self.grid.renderContainers, function (container) {
8782 columnCache = columnCache.concat(container.visibleColumnCache);
8783 });
8784
8785 // look at each column, process any manual values or %, put the * into an array to look at later
8786 columnCache.forEach(function (column) {
8787 var width = 0;
8788 // Skip hidden columns
8789 if (!column.visible) { return; }
8790
8791 if (pinRightColumn) {
8792 availableWidth += self.grid.scrollbarWidth;
8793 }
8794
8795 if (!pinRightColumn && column.colDef.pinnedRight) {
8796 pinRightColumn = true;
8797 }
8798
8799 if (angular.isNumber(column.width)) {
8800 // pixel width, set to this value
8801 width = parseInt(column.width, 10);
8802 usedWidthSum = usedWidthSum + width;
8803 column.drawnWidth = width;
8804
8805 fixedNumberArray.push(column);
8806 } else if (gridUtil.endsWith(column.width, '%')) {
8807 // percentage width, set to percentage of the viewport
8808 // round down to int - some browsers don't play nice with float maxWidth
8809 var percentageIntegerValue = parseInt(column.width.replace(/%/g, ''), 10);
8810 width = parseInt(percentageIntegerValue / 100 * availableWidth);
8811
8812 if (width > column.maxWidth) {
8813 width = column.maxWidth;
8814 }
8815
8816 if (width < column.minWidth) {
8817 width = column.minWidth;
8818 }
8819
8820 usedWidthSum = usedWidthSum + width;
8821 column.drawnWidth = width;
8822
8823 totalPercentage = totalPercentage + percentageIntegerValue;
8824 percentageArray.push(column);
8825 } else if (angular.isString(column.width) && column.width.indexOf('*') !== -1) {
8826 // is an asterisk column, the gridColumn already checked the string consists only of '****'
8827 asteriskNum = asteriskNum + column.width.length;
8828 asterisksArray.push(column);
8829 }
8830 });
8831
8832 // Get the remaining width (available width subtracted by the used widths sum)
8833 var remainingWidth = availableWidth - usedWidthSum;
8834
8835 if (asterisksArray.length > 0) {
8836 // the width that each asterisk value would be assigned (this can be negative)
8837 var asteriskVal = remainingWidth / asteriskNum;
8838
8839 asterisksArray.forEach(function (column) {
8840 var width = parseInt(column.width.length * asteriskVal, 10);
8841
8842 if (width > column.maxWidth) {
8843 width = column.maxWidth;
8844 }
8845
8846 if (width < column.minWidth) {
8847 width = column.minWidth;
8848 }
8849
8850 usedWidthSum = usedWidthSum + width;
8851 column.drawnWidth = width;
8852 });
8853 }
8854
8855 // If there are no columns with asterisk widths then check if there are any with % widths and
8856 // use them as a fallback for adjusting column widths up or down if we have remaining grid width
8857 // or need to claw some width back
8858 var variableWidthColumnArray;
8859 if (asterisksArray.length > 0) {
8860 variableWidthColumnArray = asterisksArray;
8861 } else if (percentageArray.length > 0 && fixedNumberArray.length === 0 && totalPercentage === 100) {
8862 variableWidthColumnArray = percentageArray;
8863 }
8864
8865 if (!angular.isUndefined(variableWidthColumnArray)) {
8866 // If the grid width didn't divide evenly into the column widths and we have pixels left over, or our
8867 // calculated widths would have the grid narrower than the available space,
8868 // dole the remainder out one by one to make everything fit
8869 var processColumnUpwards = function (column) {
8870 if (column.drawnWidth < column.maxWidth && leftoverWidth > 0) {
8871 column.drawnWidth++;
8872 usedWidthSum++;
8873 leftoverWidth--;
8874 columnsToChange = true;
8875 }
8876 };
8877
8878 var leftoverWidth = availableWidth - usedWidthSum;
8879 var columnsToChange = true;
8880
8881 while (leftoverWidth > 0 && columnsToChange) {
8882 columnsToChange = false;
8883 variableWidthColumnArray.forEach(processColumnUpwards);
8884 }
8885
8886 // We can end up with too much width even though some columns aren't at their max width, in this situation
8887 // we can trim the columns a little
8888 var processColumnDownwards = function (column) {
8889 if (column.drawnWidth > column.minWidth && excessWidth > 0) {
8890 column.drawnWidth--;
8891 usedWidthSum--;
8892 excessWidth--;
8893 columnsToChange = true;
8894 }
8895 };
8896
8897 var excessWidth = usedWidthSum - availableWidth;
8898 columnsToChange = true;
8899
8900 while (excessWidth > 0 && columnsToChange) {
8901 columnsToChange = false;
8902 variableWidthColumnArray.forEach(processColumnDownwards);
8903 }
8904 }
8905
8906 // all that was across all the renderContainers, now we need to work out what that calculation decided for
8907 // our renderContainer
8908 var canvasWidth = 0;
8909 self.visibleColumnCache.forEach(function(column) {
8910 if ( column.visible ) {
8911 canvasWidth = canvasWidth + column.drawnWidth;
8912 }
8913 });
8914
8915 // Build the CSS
8916 columnCache.forEach(function (column) {
8917 ret = ret + column.getColClassDefinition();
8918 });
8919
8920 self.canvasWidth = canvasWidth;
8921
8922 // Return the styles back to buildStyles which pops them into the `customStyles` scope variable
8923 // return ret;
8924
8925 // Set this render container's column styles so they can be used in style computation
8926 this.columnStyles = ret;
8927 };
8928
8929 GridRenderContainer.prototype.needsHScrollbarPlaceholder = function () {
8930 var self = this,
8931 containerBody;
8932
8933 if (self.name === 'left' || self.name === 'right' && !this.hasHScrollbar && !this.grid.disableScrolling) {
8934 if (self.grid.options.enableHorizontalScrollbar === uiGridConstants.scrollbars.ALWAYS) {
8935 return true;
8936 }
8937 containerBody = this.grid.element[0].querySelector('.ui-grid-render-container-body .ui-grid-viewport');
8938 return containerBody.scrollWidth > containerBody.offsetWidth;
8939 }
8940 return false;
8941 };
8942
8943 GridRenderContainer.prototype.getViewportStyle = function () {
8944 var self = this;
8945 var styles = {};
8946 var scrollbarVisibility = {};
8947
8948 scrollbarVisibility[uiGridConstants.scrollbars.ALWAYS] = 'scroll';
8949 scrollbarVisibility[uiGridConstants.scrollbars.WHEN_NEEDED] = 'auto';
8950
8951 self.hasHScrollbar = false;
8952 self.hasVScrollbar = false;
8953
8954 if (self.grid.disableScrolling) {
8955 styles['overflow-x'] = 'hidden';
8956 styles['overflow-y'] = 'hidden';
8957 return styles;
8958 }
8959
8960 if (self.name === 'body') {
8961 self.hasHScrollbar = self.grid.options.enableHorizontalScrollbar !== uiGridConstants.scrollbars.NEVER;
8962 if (!self.grid.isRTL()) {
8963 if (!self.grid.hasRightContainerColumns()) {
8964 self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;
8965 }
8966 }
8967 else {
8968 if (!self.grid.hasLeftContainerColumns()) {
8969 self.hasVScrollbar = self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER;
8970 }
8971 }
8972 }
8973 else if (self.name === 'left') {
8974 self.hasVScrollbar = self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;
8975 }
8976 else {
8977 self.hasVScrollbar = !self.grid.isRTL() ? self.grid.options.enableVerticalScrollbar !== uiGridConstants.scrollbars.NEVER : false;
8978 }
8979
8980 styles['overflow-x'] = self.hasHScrollbar ? scrollbarVisibility[self.grid.options.enableHorizontalScrollbar] : 'hidden';
8981 styles['overflow-y'] = self.hasVScrollbar ? scrollbarVisibility[self.grid.options.enableVerticalScrollbar] : 'hidden';
8982
8983 return styles;
8984 };
8985
8986 return GridRenderContainer;
8987 }]);
8988
8989 })();
8990
8991 (function() {
8992
8993 angular.module('ui.grid')
8994 .factory('GridRow', ['gridUtil', 'uiGridConstants', function(gridUtil, uiGridConstants) {
8995
8996 /**
8997 * @class GridRow
8998 * @ngdoc function
8999 * @name ui.grid.class:GridRow
9000 * @description GridRow is the viewModel for one logical row on the grid. A grid Row is not necessarily a one-to-one
9001 * relation to gridOptions.data.
9002 * @param {object} entity the array item from GridOptions.data
9003 * @param {number} index the current position of the row in the array
9004 * @param {Grid} grid reference to the parent grid
9005 */
9006 function GridRow(entity, index, grid) {
9007
9008 /**
9009 * @ngdoc object
9010 * @name grid
9011 * @propertyOf ui.grid.class:GridRow
9012 * @description A reference back to the grid
9013 */
9014 this.grid = grid;
9015
9016 /**
9017 * @ngdoc object
9018 * @name entity
9019 * @propertyOf ui.grid.class:GridRow
9020 * @description A reference to an item in gridOptions.data[]
9021 */
9022 this.entity = entity;
9023
9024 /**
9025 * @ngdoc object
9026 * @name uid
9027 * @propertyOf ui.grid.class:GridRow
9028 * @description UniqueId of row
9029 */
9030 this.uid = gridUtil.nextUid();
9031
9032 /**
9033 * @ngdoc object
9034 * @name visible
9035 * @propertyOf ui.grid.class:GridRow
9036 * @description If true, the row will be rendered
9037 */
9038 // Default to true
9039 this.visible = true;
9040
9041 /**
9042 * @ngdoc object
9043 * @name isSelected
9044 * @propertyOf ui.grid.class:GridRow
9045 * @description Marks if the row has been selected
9046 */
9047 // Default to false
9048 this.isSelected = false;
9049
9050
9051 this.$$height = grid.options.rowHeight;
9052
9053 }
9054
9055 /**
9056 * @ngdoc object
9057 * @name height
9058 * @propertyOf ui.grid.class:GridRow
9059 * @description height of each individual row. changing the height will flag all
9060 * row renderContainers to recalculate their canvas height
9061 */
9062 Object.defineProperty(GridRow.prototype, 'height', {
9063 get: function() {
9064 return this.$$height;
9065 },
9066 set: function(height) {
9067 if (height !== this.$$height) {
9068 this.grid.updateCanvasHeight();
9069 this.$$height = height;
9070 }
9071 }
9072 });
9073
9074 /**
9075 * @ngdoc function
9076 * @name getQualifiedColField
9077 * @methodOf ui.grid.class:GridRow
9078 * @description returns the qualified field name as it exists on scope
9079 * ie: row.entity.fieldA
9080 * @param {GridColumn} col column instance
9081 * @returns {string} resulting name that can be evaluated on scope
9082 */
9083 GridRow.prototype.getQualifiedColField = function(col) {
9084 return 'row.' + this.getEntityQualifiedColField(col);
9085 };
9086
9087 /**
9088 * @ngdoc function
9089 * @name getEntityQualifiedColField
9090 * @methodOf ui.grid.class:GridRow
9091 * @description returns the qualified field name minus the row path
9092 * ie: entity.fieldA
9093 * @param {GridColumn} col column instance
9094 * @returns {string} resulting name that can be evaluated against a row
9095 */
9096 GridRow.prototype.getEntityQualifiedColField = function(col) {
9097 var base = 'entity';
9098 if ( col.field === uiGridConstants.ENTITY_BINDING ) {
9099 return base;
9100 }
9101 return gridUtil.preEval(base + '.' + col.field);
9102 };
9103
9104
9105 /**
9106 * @ngdoc function
9107 * @name setRowInvisible
9108 * @methodOf ui.grid.class:GridRow
9109 * @description Sets an override on the row that forces it to always
9110 * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.
9111 *
9112 * This method can be called from the api, passing in the gridRow we want
9113 * altered. It should really work by calling gridRow.setRowInvisible, but that's
9114 * not the way I coded it, and too late to change now. Changed to just call
9115 * the internal function row.setThisRowInvisible().
9116 *
9117 * @param {GridRow} row the row we want to set to invisible
9118 *
9119 */
9120 GridRow.prototype.setRowInvisible = function ( row ) {
9121 if (row && row.setThisRowInvisible) {
9122 row.setThisRowInvisible( 'user' );
9123 }
9124 };
9125
9126
9127 /**
9128 * @ngdoc function
9129 * @name clearRowInvisible
9130 * @methodOf ui.grid.class:GridRow
9131 * @description Clears an override on the row that forces it to always
9132 * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility.
9133 *
9134 * This method can be called from the api, passing in the gridRow we want
9135 * altered. It should really work by calling gridRow.clearRowInvisible, but that's
9136 * not the way I coded it, and too late to change now. Changed to just call
9137 * the internal function row.clearThisRowInvisible().
9138 *
9139 * @param {GridRow} row the row we want to clear the invisible flag
9140 *
9141 */
9142 GridRow.prototype.clearRowInvisible = function ( row ) {
9143 if (row && row.clearThisRowInvisible) {
9144 row.clearThisRowInvisible( 'user' );
9145 }
9146 };
9147
9148
9149 /**
9150 * @ngdoc function
9151 * @name setThisRowInvisible
9152 * @methodOf ui.grid.class:GridRow
9153 * @description Sets an override on the row that forces it to always
9154 * be invisible. Emits the rowsVisibleChanged event if it changed the row visibility
9155 *
9156 * @param {string} reason the reason (usually the module) for the row to be invisible.
9157 * E.g. grouping, user, filter
9158 * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility
9159 */
9160 GridRow.prototype.setThisRowInvisible = function ( reason, fromRowsProcessor ) {
9161 if ( !this.invisibleReason ) {
9162 this.invisibleReason = {};
9163 }
9164 this.invisibleReason[reason] = true;
9165 this.evaluateRowVisibility( fromRowsProcessor);
9166 };
9167
9168
9169 /**
9170 * @ngdoc function
9171 * @name clearRowInvisible
9172 * @methodOf ui.grid.class:GridRow
9173 * @description Clears any override on the row visibility, returning it
9174 * to normal visibility calculations. Emits the rowsVisibleChanged
9175 * event
9176 *
9177 * @param {string} reason the reason (usually the module) for the row to be invisible.
9178 * E.g. grouping, user, filter
9179 * @param {boolean} fromRowsProcessor whether we were called from a rowsProcessor, passed through to evaluateRowVisibility
9180 */
9181 GridRow.prototype.clearThisRowInvisible = function ( reason, fromRowsProcessor ) {
9182 if (typeof(this.invisibleReason) !== 'undefined' ) {
9183 delete this.invisibleReason[reason];
9184 }
9185 this.evaluateRowVisibility( fromRowsProcessor );
9186 };
9187
9188
9189 /**
9190 * @ngdoc function
9191 * @name evaluateRowVisibility
9192 * @methodOf ui.grid.class:GridRow
9193 * @description Determines whether the row should be visible based on invisibleReason,
9194 * and if it changes the row visibility, then emits the rowsVisibleChanged event.
9195 *
9196 * Queues a grid refresh, but doesn't call it directly to avoid hitting lots of grid refreshes.
9197 * @param {boolean} fromRowProcessor if true, then it won't raise events or queue the refresh, the
9198 * row processor does that already
9199 */
9200 GridRow.prototype.evaluateRowVisibility = function ( fromRowProcessor ) {
9201 var newVisibility = true;
9202 if ( typeof(this.invisibleReason) !== 'undefined' ) {
9203 angular.forEach(this.invisibleReason, function( value, key ) {
9204 if ( value ) {
9205 newVisibility = false;
9206 }
9207 });
9208 }
9209
9210 if ( typeof(this.visible) === 'undefined' || this.visible !== newVisibility ) {
9211 this.visible = newVisibility;
9212 if ( !fromRowProcessor ) {
9213 this.grid.queueGridRefresh();
9214 this.grid.api.core.raise.rowsVisibleChanged(this);
9215 }
9216 }
9217 };
9218
9219
9220 return GridRow;
9221 }]);
9222
9223 })();
9224
9225 (function() {
9226 'use strict';
9227 /**
9228 * @ngdoc object
9229 * @name ui.grid.class:GridRowColumn
9230 * @param {GridRow} row The row for this pair
9231 * @param {GridColumn} column The column for this pair
9232 * @description A row and column pair that represents the intersection of these two entities.
9233 * Must be instantiated as a constructor using the `new` keyword.
9234 */
9235 angular.module('ui.grid')
9236 .factory('GridRowColumn', ['$parse', '$filter',
9237 function GridRowColumnFactory($parse, $filter) {
9238 var GridRowColumn = function GridRowColumn(row, col) {
9239 if ( !(this instanceof GridRowColumn)) {
9240 throw "Using GridRowColumn as a function insead of as a constructor. Must be called with `new` keyword";
9241 }
9242
9243 /**
9244 * @ngdoc object
9245 * @name row
9246 * @propertyOf ui.grid.class:GridRowColumn
9247 * @description {@link ui.grid.class:GridRow }
9248 */
9249 this.row = row;
9250 /**
9251 * @ngdoc object
9252 * @name col
9253 * @propertyOf ui.grid.class:GridRowColumn
9254 * @description {@link ui.grid.class:GridColumn }
9255 */
9256 this.col = col;
9257 };
9258
9259 /**
9260 * @ngdoc function
9261 * @name getIntersectionValueRaw
9262 * @methodOf ui.grid.class:GridRowColumn
9263 * @description Gets the intersection of where the row and column meet.
9264 * @returns {String|Number|Object} The value from the grid data that this GridRowColumn points too.
9265 * If the column has a cellFilter this will NOT return the filtered value.
9266 */
9267 GridRowColumn.prototype.getIntersectionValueRaw = function() {
9268 var getter = $parse(this.row.getEntityQualifiedColField(this.col));
9269 var context = this.row;
9270 return getter(context);
9271 };
9272 return GridRowColumn;
9273 }
9274 ]);
9275 })();
9276
9277 (function () {
9278 angular.module('ui.grid')
9279 .factory('ScrollEvent', ['gridUtil', function (gridUtil) {
9280
9281 /**
9282 * @ngdoc function
9283 * @name ui.grid.class:ScrollEvent
9284 * @description Model for all scrollEvents
9285 * @param {Grid} grid that owns the scroll event
9286 * @param {GridRenderContainer} sourceRowContainer that owns the scroll event. Can be null
9287 * @param {GridRenderContainer} sourceColContainer that owns the scroll event. Can be null
9288 * @param {string} source the source of the event - from uiGridConstants.scrollEventSources or a string value of directive/service/factory.functionName
9289 */
9290 function ScrollEvent(grid, sourceRowContainer, sourceColContainer, source) {
9291 var self = this;
9292 if (!grid) {
9293 throw new Error("grid argument is required");
9294 }
9295
9296 /**
9297 * @ngdoc object
9298 * @name grid
9299 * @propertyOf ui.grid.class:ScrollEvent
9300 * @description A reference back to the grid
9301 */
9302 self.grid = grid;
9303
9304
9305
9306 /**
9307 * @ngdoc object
9308 * @name source
9309 * @propertyOf ui.grid.class:ScrollEvent
9310 * @description the source of the scroll event. limited to values from uiGridConstants.scrollEventSources
9311 */
9312 self.source = source;
9313
9314
9315 /**
9316 * @ngdoc object
9317 * @name noDelay
9318 * @propertyOf ui.grid.class:ScrollEvent
9319 * @description most scroll events from the mouse or trackpad require delay to operate properly
9320 * set to false to eliminate delay. Useful for scroll events that the grid causes, such as scrolling to make a row visible.
9321 */
9322 self.withDelay = true;
9323
9324 self.sourceRowContainer = sourceRowContainer;
9325 self.sourceColContainer = sourceColContainer;
9326
9327 self.newScrollLeft = null;
9328 self.newScrollTop = null;
9329 self.x = null;
9330 self.y = null;
9331
9332 self.verticalScrollLength = -9999999;
9333 self.horizontalScrollLength = -999999;
9334
9335
9336 /**
9337 * @ngdoc function
9338 * @name fireThrottledScrollingEvent
9339 * @methodOf ui.grid.class:ScrollEvent
9340 * @description fires a throttled event using grid.api.core.raise.scrollEvent
9341 */
9342 self.fireThrottledScrollingEvent = gridUtil.throttle(function(sourceContainerId) {
9343 self.grid.scrollContainers(sourceContainerId, self);
9344 }, self.grid.options.wheelScrollThrottle, {trailing: true});
9345
9346 }
9347
9348
9349 /**
9350 * @ngdoc function
9351 * @name getNewScrollLeft
9352 * @methodOf ui.grid.class:ScrollEvent
9353 * @description returns newScrollLeft property if available; calculates a new value if it isn't
9354 */
9355 ScrollEvent.prototype.getNewScrollLeft = function(colContainer, viewport) {
9356 var self = this;
9357
9358 if (!self.newScrollLeft) {
9359 var scrollWidth = (colContainer.getCanvasWidth() - colContainer.getViewportWidth());
9360
9361 var oldScrollLeft = gridUtil.normalizeScrollLeft(viewport, self.grid);
9362
9363 var scrollXPercentage;
9364 if (typeof(self.x.percentage) !== 'undefined' && self.x.percentage !== undefined) {
9365 scrollXPercentage = self.x.percentage;
9366 }
9367 else if (typeof(self.x.pixels) !== 'undefined' && self.x.pixels !== undefined) {
9368 scrollXPercentage = self.x.percentage = (oldScrollLeft + self.x.pixels) / scrollWidth;
9369 }
9370 else {
9371 throw new Error("No percentage or pixel value provided for scroll event X axis");
9372 }
9373
9374 return Math.max(0, scrollXPercentage * scrollWidth);
9375 }
9376
9377 return self.newScrollLeft;
9378 };
9379
9380
9381 /**
9382 * @ngdoc function
9383 * @name getNewScrollTop
9384 * @methodOf ui.grid.class:ScrollEvent
9385 * @description returns newScrollTop property if available; calculates a new value if it isn't
9386 */
9387 ScrollEvent.prototype.getNewScrollTop = function(rowContainer, viewport) {
9388 var self = this;
9389
9390
9391 if (!self.newScrollTop) {
9392 var scrollLength = rowContainer.getVerticalScrollLength();
9393
9394 var oldScrollTop = viewport[0].scrollTop;
9395
9396 var scrollYPercentage;
9397 if (typeof(self.y.percentage) !== 'undefined' && self.y.percentage !== undefined) {
9398 scrollYPercentage = self.y.percentage;
9399 }
9400 else if (typeof(self.y.pixels) !== 'undefined' && self.y.pixels !== undefined) {
9401 scrollYPercentage = self.y.percentage = (oldScrollTop + self.y.pixels) / scrollLength;
9402 }
9403 else {
9404 throw new Error("No percentage or pixel value provided for scroll event Y axis");
9405 }
9406
9407 return Math.max(0, scrollYPercentage * scrollLength);
9408 }
9409
9410 return self.newScrollTop;
9411 };
9412
9413 ScrollEvent.prototype.atTop = function(scrollTop) {
9414 return (this.y && (this.y.percentage === 0 || this.verticalScrollLength < 0) && scrollTop === 0);
9415 };
9416
9417 ScrollEvent.prototype.atBottom = function(scrollTop) {
9418 return (this.y && (this.y.percentage === 1 || this.verticalScrollLength === 0) && scrollTop > 0);
9419 };
9420
9421 ScrollEvent.prototype.atLeft = function(scrollLeft) {
9422 return (this.x && (this.x.percentage === 0 || this.horizontalScrollLength < 0) && scrollLeft === 0);
9423 };
9424
9425 ScrollEvent.prototype.atRight = function(scrollLeft) {
9426 return (this.x && (this.x.percentage === 1 || this.horizontalScrollLength ===0) && scrollLeft > 0);
9427 };
9428
9429
9430 ScrollEvent.Sources = {
9431 ViewPortScroll: 'ViewPortScroll',
9432 RenderContainerMouseWheel: 'RenderContainerMouseWheel',
9433 RenderContainerTouchMove: 'RenderContainerTouchMove',
9434 Other: 99
9435 };
9436
9437 return ScrollEvent;
9438 }]);
9439
9440
9441
9442 })();
9443
9444 (function () {
9445 'use strict';
9446 /**
9447 * @ngdoc object
9448 * @name ui.grid.service:gridClassFactory
9449 *
9450 * @description factory to return dom specific instances of a grid
9451 *
9452 */
9453 angular.module('ui.grid').service('gridClassFactory', ['gridUtil', '$q', '$compile', '$templateCache', 'uiGridConstants', 'Grid', 'GridColumn', 'GridRow',
9454 function (gridUtil, $q, $compile, $templateCache, uiGridConstants, Grid, GridColumn, GridRow) {
9455
9456 var service = {
9457 /**
9458 * @ngdoc method
9459 * @name createGrid
9460 * @methodOf ui.grid.service:gridClassFactory
9461 * @description Creates a new grid instance. Each instance will have a unique id
9462 * @param {object} options An object map of options to pass into the created grid instance.
9463 * @returns {Grid} grid
9464 */
9465 createGrid : function(options) {
9466 options = (typeof(options) !== 'undefined') ? options : {};
9467 options.id = gridUtil.newId();
9468 var grid = new Grid(options);
9469
9470 // NOTE/TODO: rowTemplate should always be defined...
9471 if (grid.options.rowTemplate) {
9472 var rowTemplateFnPromise = $q.defer();
9473 grid.getRowTemplateFn = rowTemplateFnPromise.promise;
9474
9475 gridUtil.getTemplate(grid.options.rowTemplate)
9476 .then(
9477 function (template) {
9478 var rowTemplateFn = $compile(template);
9479 rowTemplateFnPromise.resolve(rowTemplateFn);
9480 },
9481 function () {
9482 // Todo handle response error here?
9483 throw new Error("Couldn't fetch/use row template '" + grid.options.rowTemplate + "'");
9484 }).catch(angular.noop);
9485 }
9486
9487 grid.registerColumnBuilder(service.defaultColumnBuilder);
9488
9489 // Row builder for custom row templates
9490 grid.registerRowBuilder(service.rowTemplateAssigner);
9491
9492 // Reset all rows to visible initially
9493 grid.registerRowsProcessor(function allRowsVisible(rows) {
9494 rows.forEach(function (row) {
9495 row.evaluateRowVisibility( true );
9496 });
9497
9498 return rows;
9499 }, 50);
9500
9501 grid.registerColumnsProcessor(function applyColumnVisibility(columns) {
9502 columns.forEach(function (column) {
9503 column.visible = angular.isDefined(column.colDef.visible) ? column.colDef.visible : true;
9504 });
9505
9506 return columns;
9507 }, 50);
9508
9509 grid.registerRowsProcessor(grid.searchRows, 100);
9510
9511 // Register the default row processor, it sorts rows by selected columns
9512 if (grid.options.externalSort && angular.isFunction(grid.options.externalSort)) {
9513 grid.registerRowsProcessor(grid.options.externalSort, 200);
9514 }
9515 else {
9516 grid.registerRowsProcessor(grid.sortByColumn, 200);
9517 }
9518
9519 return grid;
9520 },
9521
9522 /**
9523 * @ngdoc function
9524 * @name defaultColumnBuilder
9525 * @methodOf ui.grid.service:gridClassFactory
9526 * @description Processes designTime column definitions and applies them to col for the
9527 * core grid features
9528 * @param {object} colDef reference to column definition
9529 * @param {GridColumn} col reference to gridCol
9530 * @param {object} gridOptions reference to grid options
9531 */
9532 defaultColumnBuilder: function (colDef, col, gridOptions) {
9533
9534 var templateGetPromises = [];
9535
9536 // Abstracts the standard template processing we do for every template type.
9537 var processTemplate = function( templateType, providedType, defaultTemplate, filterType, tooltipType ) {
9538 if ( !colDef[templateType] ) {
9539 col[providedType] = defaultTemplate;
9540 } else {
9541 col[providedType] = colDef[templateType];
9542 }
9543
9544 var templatePromise = gridUtil.getTemplate(col[providedType])
9545 .then(
9546 function (template) {
9547 if ( angular.isFunction(template) ) { template = template(); }
9548 var tooltipCall = ( tooltipType === 'cellTooltip' )
9549 ? 'col.cellTooltip(row,col)'
9550 : 'col.headerTooltip(col)';
9551 if ( tooltipType && col[tooltipType] === false ) {
9552 template = template.replace(uiGridConstants.TOOLTIP, '');
9553 } else if ( tooltipType && col[tooltipType] ) {
9554 template = template.replace(uiGridConstants.TOOLTIP, 'title="{{' + tooltipCall + ' CUSTOM_FILTERS }}"');
9555 }
9556
9557 if ( filterType ) {
9558 col[templateType] = template.replace(uiGridConstants.CUSTOM_FILTERS, function() {
9559 return col[filterType] ? "|" + col[filterType] : "";
9560 });
9561 } else {
9562 col[templateType] = template;
9563 }
9564 },
9565 function () {
9566 throw new Error("Couldn't fetch/use colDef." + templateType + " '" + colDef[templateType] + "'");
9567 }).catch(angular.noop);
9568
9569 templateGetPromises.push(templatePromise);
9570
9571 return templatePromise;
9572 };
9573
9574
9575 /**
9576 * @ngdoc property
9577 * @name cellTemplate
9578 * @propertyOf ui.grid.class:GridOptions.columnDef
9579 * @description a custom template for each cell in this column. The default
9580 * is ui-grid/uiGridCell. If you are using the cellNav feature, this template
9581 * must contain a div that can receive focus.
9582 *
9583 */
9584 col.cellTemplatePromise = processTemplate( 'cellTemplate', 'providedCellTemplate', 'ui-grid/uiGridCell', 'cellFilter', 'cellTooltip' );
9585
9586 /**
9587 * @ngdoc property
9588 * @name headerCellTemplate
9589 * @propertyOf ui.grid.class:GridOptions.columnDef
9590 * @description a custom template for the header for this column. The default
9591 * is ui-grid/uiGridHeaderCell
9592 *
9593 */
9594 col.headerCellTemplatePromise = processTemplate( 'headerCellTemplate', 'providedHeaderCellTemplate', 'ui-grid/uiGridHeaderCell', 'headerCellFilter', 'headerTooltip' );
9595
9596 /**
9597 * @ngdoc property
9598 * @name footerCellTemplate
9599 * @propertyOf ui.grid.class:GridOptions.columnDef
9600 * @description a custom template for the footer for this column. The default
9601 * is ui-grid/uiGridFooterCell
9602 *
9603 */
9604 col.footerCellTemplatePromise = processTemplate( 'footerCellTemplate', 'providedFooterCellTemplate', 'ui-grid/uiGridFooterCell', 'footerCellFilter' );
9605
9606 /**
9607 * @ngdoc property
9608 * @name filterHeaderTemplate
9609 * @propertyOf ui.grid.class:GridOptions.columnDef
9610 * @description a custom template for the filter input. The default is ui-grid/ui-grid-filter
9611 *
9612 */
9613 col.filterHeaderTemplatePromise = processTemplate( 'filterHeaderTemplate', 'providedFilterHeaderTemplate', 'ui-grid/ui-grid-filter' );
9614
9615 // Create a promise for the compiled element function
9616 col.compiledElementFnDefer = $q.defer();
9617
9618 return $q.all(templateGetPromises);
9619 },
9620
9621 rowTemplateAssigner: function rowTemplateAssigner(row) {
9622 var grid = this;
9623
9624 // Row has no template assigned to it
9625 if (!row.rowTemplate) {
9626 // Use the default row template from the grid
9627 row.rowTemplate = grid.options.rowTemplate;
9628
9629 // Use the grid's function for fetching the compiled row template function
9630 row.getRowTemplateFn = grid.getRowTemplateFn;
9631 }
9632 // Row has its own template assigned
9633 else {
9634 // Create a promise for the compiled row template function
9635 var perRowTemplateFnPromise = $q.defer();
9636 row.getRowTemplateFn = perRowTemplateFnPromise.promise;
9637
9638 // Get the row template
9639 gridUtil.getTemplate(row.rowTemplate)
9640 .then(function (template) {
9641 // Compile the template
9642 var rowTemplateFn = $compile(template);
9643
9644 // Resolve the compiled template function promise
9645 perRowTemplateFnPromise.resolve(rowTemplateFn);
9646 },
9647 function () {
9648 // Todo handle response error here?
9649 throw new Error("Couldn't fetch/use row template '" + row.rowTemplate + "'");
9650 });
9651 }
9652
9653 return row.getRowTemplateFn;
9654 }
9655 };
9656
9657 // class definitions (moved to separate factories)
9658
9659 return service;
9660 }]);
9661
9662 })();
9663
9664 (function() {
9665
9666 var module = angular.module('ui.grid');
9667
9668 function escapeRegExp(str) {
9669 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
9670 }
9671
9672
9673 /**
9674 * @ngdoc service
9675 * @name ui.grid.service:rowSearcher
9676 *
9677 * @description Service for searching/filtering rows based on column value conditions.
9678 */
9679 module.service('rowSearcher', ['gridUtil', 'uiGridConstants', function (gridUtil, uiGridConstants) {
9680 var defaultCondition = uiGridConstants.filter.CONTAINS;
9681
9682 var rowSearcher = {};
9683
9684 /**
9685 * @ngdoc function
9686 * @name getTerm
9687 * @methodOf ui.grid.service:rowSearcher
9688 * @description Get the term from a filter
9689 * Trims leading and trailing whitespace
9690 * @param {object} filter object to use
9691 * @returns {object} Parsed term
9692 */
9693 rowSearcher.getTerm = function getTerm(filter) {
9694 if (typeof(filter.term) === 'undefined') { return filter.term; }
9695
9696 var term = filter.term;
9697
9698 // Strip leading and trailing whitespace if the term is a string
9699 if (typeof(term) === 'string') {
9700 term = term.trim();
9701 }
9702
9703 return term;
9704 };
9705
9706 /**
9707 * @ngdoc function
9708 * @name stripTerm
9709 * @methodOf ui.grid.service:rowSearcher
9710 * @description Remove leading and trailing asterisk (*) from the filter's term
9711 * @param {object} filter object to use
9712 * @returns {uiGridConstants.filter<int>} Value representing the condition constant value
9713 */
9714 rowSearcher.stripTerm = function stripTerm(filter) {
9715 var term = rowSearcher.getTerm(filter);
9716
9717 if (typeof(term) === 'string') {
9718 return escapeRegExp(term.replace(/(^\*|\*$)/g, ''));
9719 }
9720 else {
9721 return term;
9722 }
9723 };
9724
9725
9726 /**
9727 * @ngdoc function
9728 * @name guessCondition
9729 * @methodOf ui.grid.service:rowSearcher
9730 * @description Guess the condition for a filter based on its term
9731 * <br>
9732 * Defaults to STARTS_WITH. Uses CONTAINS for strings beginning and ending with *s (*bob*).
9733 * Uses STARTS_WITH for strings ending with * (bo*). Uses ENDS_WITH for strings starting with * (*ob).
9734 * @param {object} filter object to use
9735 * @returns {uiGridConstants.filter<int>} Value representing the condition constant value
9736 */
9737 rowSearcher.guessCondition = function guessCondition(filter) {
9738 if (typeof(filter.term) === 'undefined' || !filter.term) {
9739 return defaultCondition;
9740 }
9741
9742 var term = rowSearcher.getTerm(filter);
9743
9744 if (/\*/.test(term)) {
9745 var regexpFlags = '';
9746 if (!filter.flags || !filter.flags.caseSensitive) {
9747 regexpFlags += 'i';
9748 }
9749
9750 var reText = term.replace(/(\\)?\*/g, function ($0, $1) { return $1 ? $0 : '[\\s\\S]*?'; });
9751 return new RegExp('^' + reText + '$', regexpFlags);
9752 }
9753 // Otherwise default to default condition
9754 else {
9755 return defaultCondition;
9756 }
9757 };
9758
9759
9760 /**
9761 * @ngdoc function
9762 * @name setupFilters
9763 * @methodOf ui.grid.service:rowSearcher
9764 * @description For a given columns filters (either col.filters, or [col.filter] can be passed in),
9765 * do all the parsing and pre-processing and store that data into a new filters object. The object
9766 * has the condition, the flags, the stripped term, and a parsed reg exp if there was one.
9767 *
9768 * We could use a forEach in here, since it's much less performance sensitive, but since we're using
9769 * for loops everywhere else in this module...
9770 *
9771 * @param {array} filters the filters from the column (col.filters or [col.filter])
9772 * @returns {array} An array of parsed/preprocessed filters
9773 */
9774 rowSearcher.setupFilters = function setupFilters( filters ) {
9775 var newFilters = [];
9776
9777 var filtersLength = filters.length;
9778 for ( var i = 0; i < filtersLength; i++ ) {
9779 var filter = filters[i];
9780
9781 if ( filter.noTerm || !gridUtil.isNullOrUndefined(filter.term) ) {
9782 var newFilter = {};
9783
9784 var regexpFlags = '';
9785 if (!filter.flags || !filter.flags.caseSensitive) {
9786 regexpFlags += 'i';
9787 }
9788
9789 if ( !gridUtil.isNullOrUndefined(filter.term) ) {
9790 // it is possible to have noTerm.
9791 if ( filter.rawTerm ) {
9792 newFilter.term = filter.term;
9793 } else {
9794 newFilter.term = rowSearcher.stripTerm(filter);
9795 }
9796 }
9797 newFilter.noTerm = filter.noTerm;
9798
9799 if ( filter.condition ) {
9800 newFilter.condition = filter.condition;
9801 } else {
9802 newFilter.condition = rowSearcher.guessCondition(filter);
9803 }
9804
9805 newFilter.flags = angular.extend( { caseSensitive: false, date: false }, filter.flags );
9806
9807 if (newFilter.condition === uiGridConstants.filter.STARTS_WITH) {
9808 newFilter.startswithRE = new RegExp('^' + newFilter.term, regexpFlags);
9809 }
9810
9811 if (newFilter.condition === uiGridConstants.filter.ENDS_WITH) {
9812 newFilter.endswithRE = new RegExp(newFilter.term + '$', regexpFlags);
9813 }
9814
9815 if (newFilter.condition === uiGridConstants.filter.CONTAINS) {
9816 newFilter.containsRE = new RegExp(newFilter.term, regexpFlags);
9817 }
9818
9819 if (newFilter.condition === uiGridConstants.filter.EXACT) {
9820 newFilter.exactRE = new RegExp('^' + newFilter.term + '$', regexpFlags);
9821 }
9822
9823 newFilters.push(newFilter);
9824 }
9825 }
9826 return newFilters;
9827 };
9828
9829
9830 /**
9831 * @ngdoc function
9832 * @name runColumnFilter
9833 * @methodOf ui.grid.service:rowSearcher
9834 * @description Runs a single pre-parsed filter against a cell, returning true
9835 * if the cell matches that one filter.
9836 *
9837 * @param {Grid} grid the grid we're working against
9838 * @param {GridRow} row the row we're matching against
9839 * @param {GridColumn} column the column that we're working against
9840 * @param {object} filter the specific, preparsed, filter that we want to test
9841 * @returns {boolean} true if we match (row stays visible)
9842 */
9843 rowSearcher.runColumnFilter = function runColumnFilter(grid, row, column, filter) {
9844 // Cache typeof condition
9845 var conditionType = typeof(filter.condition);
9846
9847 // Term to search for.
9848 var term = filter.term;
9849
9850 // Get the column value for this row
9851 var value;
9852 if ( column.filterCellFiltered ) {
9853 value = grid.getCellDisplayValue(row, column);
9854 } else {
9855 value = grid.getCellValue(row, column);
9856 }
9857
9858
9859 // If the filter's condition is a RegExp, then use it
9860 if (filter.condition instanceof RegExp) {
9861 return filter.condition.test(value);
9862 }
9863
9864 // If the filter's condition is a function, run it
9865 if (conditionType === 'function') {
9866 return filter.condition(term, value, row, column);
9867 }
9868
9869 if (filter.startswithRE) {
9870 return filter.startswithRE.test(value);
9871 }
9872
9873 if (filter.endswithRE) {
9874 return filter.endswithRE.test(value);
9875 }
9876
9877 if (filter.containsRE) {
9878 return filter.containsRE.test(value);
9879 }
9880
9881 if (filter.exactRE) {
9882 return filter.exactRE.test(value);
9883 }
9884
9885 if (filter.condition === uiGridConstants.filter.NOT_EQUAL) {
9886 var regex = new RegExp('^' + term + '$');
9887 return !regex.exec(value);
9888 }
9889
9890 if (typeof(value) === 'number' && typeof(term) === 'string' ) {
9891 // if the term has a decimal in it, it comes through as '9\.4', we need to take out the \
9892 // the same for negative numbers
9893 // TODO: I suspect the right answer is to look at escapeRegExp at the top of this code file, maybe it's not needed?
9894 var tempFloat = parseFloat(term.replace(/\\\./,'.').replace(/\\\-/,'-'));
9895 if (!isNaN(tempFloat)) {
9896 term = tempFloat;
9897 }
9898 }
9899
9900 if (filter.flags.date === true) {
9901 value = new Date(value);
9902 // If the term has a dash in it, it comes through as '\-' -- we need to take out the '\'.
9903 term = new Date(term.replace(/\\/g, ''));
9904 }
9905
9906 if (filter.condition === uiGridConstants.filter.GREATER_THAN) {
9907 return (value > term);
9908 }
9909
9910 if (filter.condition === uiGridConstants.filter.GREATER_THAN_OR_EQUAL) {
9911 return (value >= term);
9912 }
9913
9914 if (filter.condition === uiGridConstants.filter.LESS_THAN) {
9915 return (value < term);
9916 }
9917
9918 if (filter.condition === uiGridConstants.filter.LESS_THAN_OR_EQUAL) {
9919 return (value <= term);
9920 }
9921
9922 return true;
9923 };
9924
9925
9926 /**
9927 * @ngdoc boolean
9928 * @name useExternalFiltering
9929 * @propertyOf ui.grid.class:GridOptions
9930 * @description False by default. When enabled, this setting suppresses the internal filtering.
9931 * All UI logic will still operate, allowing filter conditions to be set and modified.
9932 *
9933 * The external filter logic can listen for the `filterChange` event, which fires whenever
9934 * a filter has been adjusted.
9935 */
9936 /**
9937 * @ngdoc function
9938 * @name searchColumn
9939 * @methodOf ui.grid.service:rowSearcher
9940 * @description Process provided filters on provided column against a given row. If the row meets
9941 * the conditions on all the filters, return true.
9942 * @param {Grid} grid Grid to search in
9943 * @param {GridRow} row Row to search on
9944 * @param {GridColumn} column Column with the filters to use
9945 * @param {array} filters array of pre-parsed/preprocessed filters to apply
9946 * @returns {boolean} Whether the column matches or not.
9947 */
9948 rowSearcher.searchColumn = function searchColumn(grid, row, column, filters) {
9949 if (grid.options.useExternalFiltering) {
9950 return true;
9951 }
9952
9953 var filtersLength = filters.length;
9954 for (var i = 0; i < filtersLength; i++) {
9955 var filter = filters[i];
9956
9957 if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ) {
9958 var ret = rowSearcher.runColumnFilter(grid, row, column, filter);
9959 if (!ret) {
9960 return false;
9961 }
9962 }
9963 }
9964
9965 return true;
9966 };
9967
9968
9969 /**
9970 * @ngdoc function
9971 * @name search
9972 * @methodOf ui.grid.service:rowSearcher
9973 * @description Run a search across the given rows and columns, marking any rows that don't
9974 * match the stored col.filters or col.filter as invisible.
9975 * @param {Grid} grid Grid instance to search inside
9976 * @param {Array[GridRow]} rows GridRows to filter
9977 * @param {Array[GridColumn]} columns GridColumns with filters to process
9978 */
9979 rowSearcher.search = function search(grid, rows, columns) {
9980 /*
9981 * Added performance optimisations into this code base, as this logic creates deeply nested
9982 * loops and is therefore very performance sensitive. In particular, avoiding forEach as
9983 * this impacts some browser optimisers (particularly Chrome), using iterators instead
9984 */
9985
9986 // Don't do anything if we weren't passed any rows
9987 if (!rows) {
9988 return;
9989 }
9990
9991 // don't filter if filtering currently disabled
9992 if (!grid.options.enableFiltering) {
9993 return rows;
9994 }
9995
9996 // Build list of filters to apply
9997 var filterData = [];
9998
9999 var colsLength = columns.length;
10000
10001 var hasTerm = function( filters ) {
10002 var hasTerm = false;
10003
10004 filters.forEach( function (filter) {
10005 if ( !gridUtil.isNullOrUndefined(filter.term) && filter.term !== '' || filter.noTerm ) {
10006 hasTerm = true;
10007 }
10008 });
10009
10010 return hasTerm;
10011 };
10012
10013 for (var i = 0; i < colsLength; i++) {
10014 var col = columns[i];
10015
10016 if (typeof(col.filters) !== 'undefined' && hasTerm(col.filters) ) {
10017 filterData.push( { col: col, filters: rowSearcher.setupFilters(col.filters) } );
10018 }
10019 }
10020
10021 if (filterData.length > 0) {
10022 // define functions outside the loop, performance optimisation
10023 var foreachRow = function(grid, row, col, filters) {
10024 if ( row.visible && !rowSearcher.searchColumn(grid, row, col, filters) ) {
10025 row.visible = false;
10026 }
10027 };
10028
10029 var foreachFilterCol = function(grid, filterData) {
10030 var rowsLength = rows.length;
10031 for ( var i = 0; i < rowsLength; i++) {
10032 foreachRow(grid, rows[i], filterData.col, filterData.filters);
10033 }
10034 };
10035
10036 // nested loop itself - foreachFilterCol, which in turn calls foreachRow
10037 var filterDataLength = filterData.length;
10038 for ( var j = 0; j < filterDataLength; j++) {
10039 foreachFilterCol( grid, filterData[j] );
10040 }
10041
10042 if (grid.api.core.raise.rowsVisibleChanged) {
10043 grid.api.core.raise.rowsVisibleChanged();
10044 }
10045
10046 // drop any invisible rows
10047 // keeping these, as needed with filtering for trees - we have to come back and make parent nodes visible if child nodes are selected in the filter
10048 // rows = rows.filter(function(row) { return row.visible; });
10049
10050 }
10051
10052 return rows;
10053 };
10054
10055 return rowSearcher;
10056 }]);
10057
10058 })();
10059
10060 (function() {
10061
10062 var module = angular.module('ui.grid');
10063
10064 /**
10065 * @ngdoc object
10066 * @name ui.grid.class:rowSorter
10067 * @description rowSorter provides the default sorting mechanisms,
10068 * including guessing column types and applying appropriate sort
10069 * algorithms
10070 *
10071 */
10072
10073 module.service('rowSorter', ['$parse', 'uiGridConstants', function ($parse, uiGridConstants) {
10074 var currencyRegexStr =
10075 '(' +
10076 uiGridConstants.CURRENCY_SYMBOLS
10077 .map(function (a) { return '\\' + a; }) // Escape all the currency symbols ($ at least will jack up this regex)
10078 .join('|') + // Join all the symbols together with |s
10079 ')?';
10080
10081 // /^[-+]?[£$¤¥]?[\d,.]+%?$/
10082 var numberStrRegex = new RegExp('^[-+]?' + currencyRegexStr + '[\\d,.]+' + currencyRegexStr + '%?$');
10083
10084 var rowSorter = {
10085 // Cache of sorting functions. Once we create them, we don't want to keep re-doing it
10086 // this takes a piece of data from the cell and tries to determine its type and what sorting
10087 // function to use for it
10088 colSortFnCache: {}
10089 };
10090
10091
10092 /**
10093 * @ngdoc method
10094 * @methodOf ui.grid.class:rowSorter
10095 * @name guessSortFn
10096 * @description Assigns a sort function to use based on the itemType in the column
10097 * @param {string} itemType one of 'number', 'boolean', 'string', 'date', 'object'. And
10098 * error will be thrown for any other type.
10099 * @returns {function} a sort function that will sort that type
10100 */
10101 rowSorter.guessSortFn = function guessSortFn(itemType) {
10102 switch (itemType) {
10103 case "number":
10104 return rowSorter.sortNumber;
10105 case "numberStr":
10106 return rowSorter.sortNumberStr;
10107 case "boolean":
10108 return rowSorter.sortBool;
10109 case "string":
10110 return rowSorter.sortAlpha;
10111 case "date":
10112 return rowSorter.sortDate;
10113 case "object":
10114 return rowSorter.basicSort;
10115 default:
10116 throw new Error('No sorting function found for type: ' + itemType);
10117 }
10118 };
10119
10120
10121 /**
10122 * @ngdoc method
10123 * @methodOf ui.grid.class:rowSorter
10124 * @name handleNulls
10125 * @description Sorts nulls and undefined to the bottom (top when
10126 * descending). Called by each of the internal sorters before
10127 * attempting to sort. Note that this method is available on the core api
10128 * via gridApi.core.sortHandleNulls
10129 * @param {object} a sort value a
10130 * @param {object} b sort value b
10131 * @returns {number} null if there were no nulls/undefineds, otherwise returns
10132 * a sort value that should be passed back from the sort function
10133 */
10134 rowSorter.handleNulls = function handleNulls(a, b) {
10135 // We want to allow zero values and false values to be evaluated in the sort function
10136 if ((!a && a !== 0 && a !== false) || (!b && b !== 0 && b !== false)) {
10137 // We want to force nulls and such to the bottom when we sort... which effectively is "greater than"
10138 if ((!a && a !== 0 && a !== false) && (!b && b !== 0 && b !== false)) {
10139 return 0;
10140 }
10141 else if (!a && a !== 0 && a !== false) {
10142 return 1;
10143 }
10144 else if (!b && b !== 0 && b !== false) {
10145 return -1;
10146 }
10147 }
10148 return null;
10149 };
10150
10151
10152 /**
10153 * @ngdoc method
10154 * @methodOf ui.grid.class:rowSorter
10155 * @name basicSort
10156 * @description Sorts any values that provide the < method, including strings
10157 * or numbers. Handles nulls and undefined through calling handleNulls
10158 * @param {object} a sort value a
10159 * @param {object} b sort value b
10160 * @returns {number} normal sort function, returns -ve, 0, +ve
10161 */
10162 rowSorter.basicSort = function basicSort(a, b) {
10163 var nulls = rowSorter.handleNulls(a, b);
10164 if ( nulls !== null ) {
10165 return nulls;
10166 } else {
10167 if (a === b) {
10168 return 0;
10169 }
10170 if (a < b) {
10171 return -1;
10172 }
10173 return 1;
10174 }
10175 };
10176
10177
10178 /**
10179 * @ngdoc method
10180 * @methodOf ui.grid.class:rowSorter
10181 * @name sortNumber
10182 * @description Sorts numerical values. Handles nulls and undefined through calling handleNulls
10183 * @param {object} a sort value a
10184 * @param {object} b sort value b
10185 * @returns {number} normal sort function, returns -ve, 0, +ve
10186 */
10187 rowSorter.sortNumber = function sortNumber(a, b) {
10188 var nulls = rowSorter.handleNulls(a, b);
10189 if ( nulls !== null ) {
10190 return nulls;
10191 } else {
10192 return a - b;
10193 }
10194 };
10195
10196
10197 /**
10198 * @ngdoc method
10199 * @methodOf ui.grid.class:rowSorter
10200 * @name sortNumberStr
10201 * @description Sorts numerical values that are stored in a string (i.e. parses them to numbers first).
10202 * Handles nulls and undefined through calling handleNulls
10203 * @param {object} a sort value a
10204 * @param {object} b sort value b
10205 * @returns {number} normal sort function, returns -ve, 0, +ve
10206 */
10207 rowSorter.sortNumberStr = function sortNumberStr(a, b) {
10208 var nulls = rowSorter.handleNulls(a, b);
10209 if ( nulls !== null ) {
10210 return nulls;
10211 } else {
10212 var numA, // The parsed number form of 'a'
10213 numB, // The parsed number form of 'b'
10214 badA = false,
10215 badB = false;
10216
10217 // Try to parse 'a' to a float
10218 numA = parseFloat(a.replace(/[^0-9.-]/g, ''));
10219
10220 // If 'a' couldn't be parsed to float, flag it as bad
10221 if (isNaN(numA)) {
10222 badA = true;
10223 }
10224
10225 // Try to parse 'b' to a float
10226 numB = parseFloat(b.replace(/[^0-9.-]/g, ''));
10227
10228 // If 'b' couldn't be parsed to float, flag it as bad
10229 if (isNaN(numB)) {
10230 badB = true;
10231 }
10232
10233 // We want bad ones to get pushed to the bottom... which effectively is "greater than"
10234 if (badA && badB) {
10235 return 0;
10236 }
10237
10238 if (badA) {
10239 return 1;
10240 }
10241
10242 if (badB) {
10243 return -1;
10244 }
10245
10246 return numA - numB;
10247 }
10248 };
10249
10250
10251 /**
10252 * @ngdoc method
10253 * @methodOf ui.grid.class:rowSorter
10254 * @name sortAlpha
10255 * @description Sorts string values. Handles nulls and undefined through calling handleNulls
10256 * @param {object} a sort value a
10257 * @param {object} b sort value b
10258 * @returns {number} normal sort function, returns -ve, 0, +ve
10259 */
10260 rowSorter.sortAlpha = function sortAlpha(a, b) {
10261 var nulls = rowSorter.handleNulls(a, b);
10262 if ( nulls !== null ) {
10263 return nulls;
10264 } else {
10265 var strA = a.toString().toLowerCase(),
10266 strB = b.toString().toLowerCase();
10267
10268 return strA === strB ? 0 : strA.localeCompare(strB);
10269 }
10270 };
10271
10272
10273 /**
10274 * @ngdoc method
10275 * @methodOf ui.grid.class:rowSorter
10276 * @name sortDate
10277 * @description Sorts date values. Handles nulls and undefined through calling handleNulls.
10278 * Handles date strings by converting to Date object if not already an instance of Date
10279 * @param {object} a sort value a
10280 * @param {object} b sort value b
10281 * @returns {number} normal sort function, returns -ve, 0, +ve
10282 */
10283 rowSorter.sortDate = function sortDate(a, b) {
10284 var nulls = rowSorter.handleNulls(a, b);
10285 if ( nulls !== null ) {
10286 return nulls;
10287 } else {
10288 if (!(a instanceof Date)) {
10289 a = new Date(a);
10290 }
10291 if (!(b instanceof Date)) {
10292 b = new Date(b);
10293 }
10294 var timeA = a.getTime(),
10295 timeB = b.getTime();
10296
10297 return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);
10298 }
10299 };
10300
10301
10302 /**
10303 * @ngdoc method
10304 * @methodOf ui.grid.class:rowSorter
10305 * @name sortBool
10306 * @description Sorts boolean values, true is considered larger than false.
10307 * Handles nulls and undefined through calling handleNulls
10308 * @param {object} a sort value a
10309 * @param {object} b sort value b
10310 * @returns {number} normal sort function, returns -ve, 0, +ve
10311 */
10312 rowSorter.sortBool = function sortBool(a, b) {
10313 var nulls = rowSorter.handleNulls(a, b);
10314 if ( nulls !== null ) {
10315 return nulls;
10316 } else {
10317 if (a && b) {
10318 return 0;
10319 }
10320
10321 if (!a && !b) {
10322 return 0;
10323 }
10324 else {
10325 return a ? 1 : -1;
10326 }
10327 }
10328 };
10329
10330
10331 /**
10332 * @ngdoc method
10333 * @methodOf ui.grid.class:rowSorter
10334 * @name getSortFn
10335 * @description Get the sort function for the column. Looks first in
10336 * rowSorter.colSortFnCache using the column name, failing that it
10337 * looks at col.sortingAlgorithm (and puts it in the cache), failing that
10338 * it guesses the sort algorithm based on the data type.
10339 *
10340 * The cache currently seems a bit pointless, as none of the work we do is
10341 * processor intensive enough to need caching. Presumably in future we might
10342 * inspect the row data itself to guess the sort function, and in that case
10343 * it would make sense to have a cache, the infrastructure is in place to allow
10344 * that.
10345 *
10346 * @param {Grid} grid the grid to consider
10347 * @param {GridColumn} col the column to find a function for
10348 * @param {array} rows an array of grid rows. Currently unused, but presumably in future
10349 * we might inspect the rows themselves to decide what sort of data might be there
10350 * @returns {function} the sort function chosen for the column
10351 */
10352 rowSorter.getSortFn = function getSortFn(grid, col, rows) {
10353 var sortFn, item;
10354
10355 // See if we already figured out what to use to sort the column and have it in the cache
10356 if (rowSorter.colSortFnCache[col.colDef.name]) {
10357 sortFn = rowSorter.colSortFnCache[col.colDef.name];
10358 }
10359 // If the column has its OWN sorting algorithm, use that
10360 else if (col.sortingAlgorithm !== undefined) {
10361 sortFn = col.sortingAlgorithm;
10362 rowSorter.colSortFnCache[col.colDef.name] = col.sortingAlgorithm;
10363 }
10364 // Always default to sortAlpha when sorting after a cellFilter
10365 else if ( col.sortCellFiltered && col.cellFilter ) {
10366 sortFn = rowSorter.sortAlpha;
10367 rowSorter.colSortFnCache[col.colDef.name] = sortFn;
10368 }
10369 // Try and guess what sort function to use
10370 else {
10371 // Guess the sort function
10372 sortFn = rowSorter.guessSortFn(col.colDef.type);
10373
10374 // If we found a sort function, cache it
10375 if (sortFn) {
10376 rowSorter.colSortFnCache[col.colDef.name] = sortFn;
10377 }
10378 else {
10379 // We assign the alpha sort because anything that is null/undefined will never get passed to
10380 // the actual sorting function. It will get caught in our null check and returned to be sorted
10381 // down to the bottom
10382 sortFn = rowSorter.sortAlpha;
10383 }
10384 }
10385
10386 return sortFn;
10387 };
10388
10389
10390
10391 /**
10392 * @ngdoc method
10393 * @methodOf ui.grid.class:rowSorter
10394 * @name prioritySort
10395 * @description Used where multiple columns are present in the sort criteria,
10396 * we determine which column should take precedence in the sort by sorting
10397 * the columns based on their sort.priority
10398 *
10399 * @param {gridColumn} a column a
10400 * @param {gridColumn} b column b
10401 * @returns {number} normal sort function, returns -ve, 0, +ve
10402 */
10403 rowSorter.prioritySort = function (a, b) {
10404 // Both columns have a sort priority
10405 if (a.sort.priority !== undefined && b.sort.priority !== undefined) {
10406 // A is higher priority
10407 if (a.sort.priority < b.sort.priority) {
10408 return -1;
10409 }
10410 // Equal
10411 else if (a.sort.priority === b.sort.priority) {
10412 return 0;
10413 }
10414 // B is higher
10415 else {
10416 return 1;
10417 }
10418 }
10419 // Only A has a priority
10420 else if (a.sort.priority !== undefined) {
10421 return -1;
10422 }
10423 // Only B has a priority
10424 else if (b.sort.priority !== undefined) {
10425 return 1;
10426 }
10427 // Neither has a priority
10428 else {
10429 return 0;
10430 }
10431 };
10432
10433
10434 /**
10435 * @ngdoc object
10436 * @name useExternalSorting
10437 * @propertyOf ui.grid.class:GridOptions
10438 * @description Prevents the internal sorting from executing. Events will
10439 * still be fired when the sort changes, and the sort information on
10440 * the columns will be updated, allowing an external sorter (for example,
10441 * server sorting) to be implemented. Defaults to false.
10442 *
10443 */
10444 /**
10445 * @ngdoc method
10446 * @methodOf ui.grid.class:rowSorter
10447 * @name sort
10448 * @description sorts the grid
10449 * @param {Object} grid the grid itself
10450 * @param {array} rows the rows to be sorted
10451 * @param {array} columns the columns in which to look
10452 * for sort criteria
10453 * @returns {array} sorted rows
10454 */
10455 rowSorter.sort = function rowSorterSort(grid, rows, columns) {
10456 // first make sure we are even supposed to do work
10457 if (!rows) {
10458 return;
10459 }
10460
10461 if (grid.options.useExternalSorting) {
10462 return rows;
10463 }
10464
10465 // Build the list of columns to sort by
10466 var sortCols = [];
10467 var defaultSortCols = [];
10468 columns.forEach(function (col) {
10469 if (col.sort && !col.sort.ignoreSort && col.sort.direction && (col.sort.direction === uiGridConstants.ASC || col.sort.direction === uiGridConstants.DESC)) {
10470 sortCols.push({
10471 col: col,
10472 sort: col.sort
10473 });
10474 } else if ( col.defaultSort && col.defaultSort.direction && (col.defaultSort.direction === uiGridConstants.ASC || col.defaultSort.direction === uiGridConstants.DESC) ) {
10475 defaultSortCols.push({
10476 col: col,
10477 sort: col.defaultSort
10478 });
10479 }
10480 });
10481
10482 // Sort the "sort columns" by their sort priority
10483 sortCols = sortCols.sort(rowSorter.prioritySort);
10484 defaultSortCols = defaultSortCols.sort(rowSorter.prioritySort);
10485 sortCols = sortCols.concat(defaultSortCols);
10486
10487 // Now rows to sort by, maintain original order
10488 if (sortCols.length === 0) {
10489 return rows;
10490 }
10491
10492 // Re-usable variables
10493 var col, direction;
10494
10495 // put a custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)
10496 var setIndex = function( row, idx ) {
10497 row.entity.$$uiGridIndex = idx;
10498 };
10499 rows.forEach(setIndex);
10500
10501 // IE9-11 HACK.... the 'rows' variable would be empty where we call rowSorter.getSortFn(...) below. We have to use a separate reference
10502 // var d = data.slice(0);
10503 var r = rows.slice(0);
10504
10505 // Now actually sort the data
10506 var rowSortFn = function (rowA, rowB) {
10507 var tem = 0,
10508 idx = 0,
10509 sortFn;
10510
10511 while (tem === 0 && idx < sortCols.length) {
10512 // grab the metadata for the rest of the logic
10513 col = sortCols[idx].col;
10514 direction = sortCols[idx].sort.direction;
10515
10516 sortFn = rowSorter.getSortFn(grid, col, r);
10517
10518 var propA, propB;
10519
10520 if ( col.sortCellFiltered ) {
10521 propA = grid.getCellDisplayValue(rowA, col);
10522 propB = grid.getCellDisplayValue(rowB, col);
10523 } else {
10524 propA = grid.getCellValue(rowA, col);
10525 propB = grid.getCellValue(rowB, col);
10526 }
10527
10528 tem = sortFn(propA, propB, rowA, rowB, direction, col);
10529
10530 idx++;
10531 }
10532
10533 // Chrome doesn't implement a stable sort function. If our sort returns 0
10534 // (i.e. the items are equal), and we're at the last sort column in the list,
10535 // then return the previous order using our custom
10536 // index variable
10537 if (tem === 0 ) {
10538 return rowA.entity.$$uiGridIndex - rowB.entity.$$uiGridIndex;
10539 }
10540
10541 // Made it this far, we don't have to worry about null & undefined
10542 if (direction === uiGridConstants.ASC) {
10543 return tem;
10544 } else {
10545 return 0 - tem;
10546 }
10547 };
10548
10549 var newRows = rows.sort(rowSortFn);
10550
10551 // remove the custom index field on each row, used to make a stable sort out of unstable sorts (e.g. Chrome)
10552 var clearIndex = function( row, idx ) {
10553 delete row.entity.$$uiGridIndex;
10554 };
10555 rows.forEach(clearIndex);
10556
10557 return newRows;
10558 };
10559
10560 return rowSorter;
10561 }]);
10562
10563 })();
10564
10565 (function() {
10566
10567 var module = angular.module('ui.grid');
10568
10569 var bindPolyfill;
10570 if (typeof Function.prototype.bind !== "function") {
10571 bindPolyfill = function() {
10572 var slice = Array.prototype.slice;
10573 return function(context) {
10574 var fn = this,
10575 args = slice.call(arguments, 1);
10576 if (args.length) {
10577 return function() {
10578 return arguments.length ? fn.apply(context, args.concat(slice.call(arguments))) : fn.apply(context, args);
10579 };
10580 }
10581 return function() {
10582 return arguments.length ? fn.apply(context, arguments) : fn.call(context);
10583 };
10584 };
10585 };
10586 }
10587
10588 function getStyles (elem) {
10589 var e = elem;
10590 if (typeof(e.length) !== 'undefined' && e.length) {
10591 e = elem[0];
10592 }
10593
10594 return e.ownerDocument.defaultView.getComputedStyle(e, null);
10595 }
10596
10597 var rnumnonpx = new RegExp( "^(" + (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source + ")(?!px)[a-z%]+$", "i" ),
10598 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
10599 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
10600 rdisplayswap = /^(block|none|table(?!-c[ea]).+)/,
10601 cssShow = { position: "absolute", visibility: "hidden", display: "block" };
10602
10603 function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
10604 var i = extra === ( isBorderBox ? 'border' : 'content' ) ?
10605 // If we already have the right measurement, avoid augmentation
10606 4 :
10607 // Otherwise initialize for horizontal or vertical properties
10608 name === 'width' ? 1 : 0,
10609
10610 val = 0;
10611
10612 var sides = ['Top', 'Right', 'Bottom', 'Left'];
10613
10614 for ( ; i < 4; i += 2 ) {
10615 var side = sides[i];
10616 // dump('side', side);
10617
10618 // both box models exclude margin, so add it if we want it
10619 if ( extra === 'margin' ) {
10620 var marg = parseFloat(styles[extra + side]);
10621 if (!isNaN(marg)) {
10622 val += marg;
10623 }
10624 }
10625 // dump('val1', val);
10626
10627 if ( isBorderBox ) {
10628 // border-box includes padding, so remove it if we want content
10629 if ( extra === 'content' ) {
10630 var padd = parseFloat(styles['padding' + side]);
10631 if (!isNaN(padd)) {
10632 val -= padd;
10633 // dump('val2', val);
10634 }
10635 }
10636
10637 // at this point, extra isn't border nor margin, so remove border
10638 if ( extra !== 'margin' ) {
10639 var bordermarg = parseFloat(styles['border' + side + 'Width']);
10640 if (!isNaN(bordermarg)) {
10641 val -= bordermarg;
10642 // dump('val3', val);
10643 }
10644 }
10645 }
10646 else {
10647 // at this point, extra isn't content, so add padding
10648 var nocontentPad = parseFloat(styles['padding' + side]);
10649 if (!isNaN(nocontentPad)) {
10650 val += nocontentPad;
10651 // dump('val4', val);
10652 }
10653
10654 // at this point, extra isn't content nor padding, so add border
10655 if ( extra !== 'padding') {
10656 var nocontentnopad = parseFloat(styles['border' + side + 'Width']);
10657 if (!isNaN(nocontentnopad)) {
10658 val += nocontentnopad;
10659 // dump('val5', val);
10660 }
10661 }
10662 }
10663 }
10664
10665 // dump('augVal', val);
10666
10667 return val;
10668 }
10669
10670 function getWidthOrHeight( elem, name, extra ) {
10671 // Start with offset property, which is equivalent to the border-box value
10672 var valueIsBorderBox = true,
10673 val, // = name === 'width' ? elem.offsetWidth : elem.offsetHeight,
10674 styles = getStyles(elem),
10675 isBorderBox = styles['boxSizing'] === 'border-box';
10676
10677 // some non-html elements return undefined for offsetWidth, so check for null/undefined
10678 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
10679 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
10680 if ( val <= 0 || val == null ) {
10681 // Fall back to computed then uncomputed css if necessary
10682 val = styles[name];
10683 if ( val < 0 || val == null ) {
10684 val = elem.style[ name ];
10685 }
10686
10687 // Computed unit is not pixels. Stop here and return.
10688 if ( rnumnonpx.test(val) ) {
10689 return val;
10690 }
10691
10692 // we need the check for style in case a browser which returns unreliable values
10693 // for getComputedStyle silently falls back to the reliable elem.style
10694 valueIsBorderBox = isBorderBox &&
10695 ( true || val === elem.style[ name ] ); // use 'true' instead of 'support.boxSizingReliable()'
10696
10697 // Normalize "", auto, and prepare for extra
10698 val = parseFloat( val ) || 0;
10699 }
10700
10701 // use the active box-sizing model to add/subtract irrelevant styles
10702 var ret = ( val +
10703 augmentWidthOrHeight(
10704 elem,
10705 name,
10706 extra || ( isBorderBox ? "border" : "content" ),
10707 valueIsBorderBox,
10708 styles
10709 )
10710 );
10711
10712 // dump('ret', ret, val);
10713 return ret;
10714 }
10715
10716 function getLineHeight(elm) {
10717 elm = angular.element(elm)[0];
10718 var parent = elm.parentElement;
10719
10720 if (!parent) {
10721 parent = document.getElementsByTagName('body')[0];
10722 }
10723
10724 return parseInt( getStyles(parent).fontSize ) || parseInt( getStyles(elm).fontSize ) || 16;
10725 }
10726
10727 var uid = ['0', '0', '0', '0'];
10728 var uidPrefix = 'uiGrid-';
10729
10730 /**
10731 * @ngdoc service
10732 * @name ui.grid.service:GridUtil
10733 *
10734 * @description Grid utility functions
10735 */
10736 module.service('gridUtil', ['$log', '$window', '$document', '$http', '$templateCache', '$timeout', '$interval', '$injector', '$q', '$interpolate', 'uiGridConstants',
10737 function ($log, $window, $document, $http, $templateCache, $timeout, $interval, $injector, $q, $interpolate, uiGridConstants) {
10738 var s = {
10739
10740 augmentWidthOrHeight: augmentWidthOrHeight,
10741
10742 getStyles: getStyles,
10743
10744 /**
10745 * @ngdoc method
10746 * @name createBoundedWrapper
10747 * @methodOf ui.grid.service:GridUtil
10748 *
10749 * @param {object} object to bind 'this' to
10750 * @param {method} method to bind
10751 * @returns {Function} The wrapper that performs the binding
10752 *
10753 * @description
10754 * Binds given method to given object.
10755 *
10756 * By means of a wrapper, ensures that ``method`` is always bound to
10757 * ``object`` regardless of its calling environment.
10758 * Iow, inside ``method``, ``this`` always points to ``object``.
10759 *
10760 * See http://alistapart.com/article/getoutbindingsituations
10761 *
10762 */
10763 createBoundedWrapper: function(object, method) {
10764 return function() {
10765 return method.apply(object, arguments);
10766 };
10767 },
10768
10769
10770 /**
10771 * @ngdoc method
10772 * @name readableColumnName
10773 * @methodOf ui.grid.service:GridUtil
10774 *
10775 * @param {string} columnName Column name as a string
10776 * @returns {string} Column name appropriately capitalized and split apart
10777 *
10778 @example
10779 <example module="app">
10780 <file name="app.js">
10781 var app = angular.module('app', ['ui.grid']);
10782
10783 app.controller('MainCtrl', ['$scope', 'gridUtil', function ($scope, gridUtil) {
10784 $scope.name = 'firstName';
10785 $scope.columnName = function(name) {
10786 return gridUtil.readableColumnName(name);
10787 };
10788 }]);
10789 </file>
10790 <file name="index.html">
10791 <div ng-controller="MainCtrl">
10792 <strong>Column name:</strong> <input ng-model="name" />
10793 <br>
10794 <strong>Output:</strong> <span ng-bind="columnName(name)"></span>
10795 </div>
10796 </file>
10797 </example>
10798 */
10799 readableColumnName: function (columnName) {
10800 // Convert underscores to spaces
10801 if (typeof(columnName) === 'undefined' || columnName === undefined || columnName === null) { return columnName; }
10802
10803 if (typeof(columnName) !== 'string') {
10804 columnName = String(columnName);
10805 }
10806
10807 return columnName.replace(/_+/g, ' ')
10808 // Replace a completely all-capsed word with a first-letter-capitalized version
10809 .replace(/^[A-Z]+$/, function (match) {
10810 return match.toLowerCase();
10811 })
10812 // Capitalize the first letter of words
10813 .replace(/([\w\u00C0-\u017F]+)/g, function (match) {
10814 return match.charAt(0).toUpperCase() + match.slice(1);
10815 })
10816 // Put a space in between words that have partial capilizations (i.e. 'firstName' becomes 'First Name')
10817 // .replace(/([A-Z]|[A-Z]\w+)([A-Z])/g, "$1 $2");
10818 // .replace(/(\w+?|\w)([A-Z])/g, "$1 $2");
10819 .replace(/(\w+?(?=[A-Z]))/g, '$1 ');
10820 },
10821
10822 /**
10823 * @ngdoc method
10824 * @name getColumnsFromData
10825 * @methodOf ui.grid.service:GridUtil
10826 * @description Return a list of column names, given a data set
10827 *
10828 * @param {string} data Data array for grid
10829 * @returns {Object} Column definitions with field accessor and column name
10830 *
10831 * @example
10832 <pre>
10833 var data = [
10834 { firstName: 'Bob', lastName: 'Jones' },
10835 { firstName: 'Frank', lastName: 'Smith' }
10836 ];
10837
10838 var columnDefs = GridUtil.getColumnsFromData(data, excludeProperties);
10839
10840 columnDefs == [
10841 {
10842 field: 'firstName',
10843 name: 'First Name'
10844 },
10845 {
10846 field: 'lastName',
10847 name: 'Last Name'
10848 }
10849 ];
10850 </pre>
10851 */
10852 getColumnsFromData: function (data, excludeProperties) {
10853 var columnDefs = [];
10854
10855 if (!data || typeof(data[0]) === 'undefined' || data[0] === undefined) { return []; }
10856 if (angular.isUndefined(excludeProperties)) { excludeProperties = []; }
10857
10858 var item = data[0];
10859
10860 angular.forEach(item,function (prop, propName) {
10861 if ( excludeProperties.indexOf(propName) === -1) {
10862 columnDefs.push({
10863 name: propName
10864 });
10865 }
10866 });
10867
10868 return columnDefs;
10869 },
10870
10871 /**
10872 * @ngdoc method
10873 * @name newId
10874 * @methodOf ui.grid.service:GridUtil
10875 * @description Return a unique ID string
10876 *
10877 * @returns {string} Unique string
10878 *
10879 * @example
10880 <pre>
10881 var id = GridUtil.newId();
10882
10883 # 1387305700482;
10884 </pre>
10885 */
10886 newId: (function() {
10887 var seedId = new Date().getTime();
10888 return function() {
10889 return seedId += 1;
10890 };
10891 })(),
10892
10893
10894 /**
10895 * @ngdoc method
10896 * @name getTemplate
10897 * @methodOf ui.grid.service:GridUtil
10898 * @description Get's template from cache / element / url
10899 *
10900 * @param {string|element|promise} template Either a string representing the template id, a string representing the template url,
10901 * an jQuery/Angualr element, or a promise that returns the template contents to use.
10902 * @returns {object} a promise resolving to template contents
10903 *
10904 * @example
10905 <pre>
10906 GridUtil.getTemplate(url).then(function (contents) {
10907 alert(contents);
10908 })
10909 </pre>
10910 */
10911 getTemplate: function (template) {
10912 // Try to fetch the template out of the templateCache
10913 if ($templateCache.get(template)) {
10914 return s.postProcessTemplate($templateCache.get(template));
10915 }
10916
10917 // See if the template is itself a promise
10918 if (angular.isFunction(template.then)) {
10919 return template.then(s.postProcessTemplate).catch(angular.noop);
10920 }
10921
10922 // If the template is an element, return the element
10923 try {
10924 if (angular.element(template).length > 0) {
10925 return $q.when(template).then(s.postProcessTemplate).catch(angular.noop);
10926 }
10927 }
10928 catch (err) {
10929 // do nothing; not valid html
10930 }
10931
10932 // s.logDebug('fetching url', template);
10933
10934 // Default to trying to fetch the template as a url with $http
10935 return $http({ method: 'GET', url: template})
10936 .then(
10937 function (result) {
10938 var templateHtml = result.data.trim();
10939 // put in templateCache for next call
10940 $templateCache.put(template, templateHtml);
10941 return templateHtml;
10942 },
10943 function (err) {
10944 throw new Error("Could not get template " + template + ": " + err);
10945 }
10946 )
10947 .then(s.postProcessTemplate).catch(angular.noop);
10948 },
10949
10950 //
10951 postProcessTemplate: function (template) {
10952 var startSym = $interpolate.startSymbol(),
10953 endSym = $interpolate.endSymbol();
10954
10955 // If either of the interpolation symbols have been changed, we need to alter this template
10956 if (startSym !== '{{' || endSym !== '}}') {
10957 template = template.replace(/\{\{/g, startSym);
10958 template = template.replace(/\}\}/g, endSym);
10959 }
10960
10961 return $q.when(template);
10962 },
10963
10964 /**
10965 * @ngdoc method
10966 * @name guessType
10967 * @methodOf ui.grid.service:GridUtil
10968 * @description guesses the type of an argument
10969 *
10970 * @param {string/number/bool/object} item variable to examine
10971 * @returns {string} one of the following
10972 * - 'string'
10973 * - 'boolean'
10974 * - 'number'
10975 * - 'date'
10976 * - 'object'
10977 */
10978 guessType : function (item) {
10979 var itemType = typeof(item);
10980
10981 // Check for numbers and booleans
10982 switch (itemType) {
10983 case "number":
10984 case "boolean":
10985 case "string":
10986 return itemType;
10987 default:
10988 if (angular.isDate(item)) {
10989 return "date";
10990 }
10991 return "object";
10992 }
10993 },
10994
10995
10996 /**
10997 * @ngdoc method
10998 * @name elementWidth
10999 * @methodOf ui.grid.service:GridUtil
11000 *
11001 * @param {element} elem DOM element
11002 * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element
11003 *
11004 * @returns {number} Element width in pixels, accounting for any borders, etc.
11005 */
11006 elementWidth: function (elem) {
11007
11008 },
11009
11010 /**
11011 * @ngdoc method
11012 * @name elementHeight
11013 * @methodOf ui.grid.service:GridUtil
11014 *
11015 * @param {element} elem DOM element
11016 * @param {string} [extra] Optional modifier for calculation. Use 'margin' to account for margins on element
11017 *
11018 * @returns {number} Element height in pixels, accounting for any borders, etc.
11019 */
11020 elementHeight: function (elem) {
11021
11022 },
11023
11024 // Thanks to http://stackoverflow.com/a/13382873/888165
11025 getScrollbarWidth: function() {
11026 var outer = document.createElement("div");
11027
11028 outer.style.visibility = "hidden";
11029 outer.style.width = "100px";
11030 outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
11031
11032 document.body.appendChild(outer);
11033
11034 var widthNoScroll = outer.offsetWidth;
11035 // force scrollbars
11036 outer.style.overflow = "scroll";
11037
11038 // add innerdiv
11039 var inner = document.createElement("div");
11040 inner.style.width = "100%";
11041 outer.appendChild(inner);
11042
11043 var widthWithScroll = inner.offsetWidth;
11044
11045 // remove divs
11046 outer.parentNode.removeChild(outer);
11047
11048 return widthNoScroll - widthWithScroll;
11049 },
11050
11051 swap: function( elem, options, callback, args ) {
11052 var ret, name,
11053 old = {};
11054
11055 // Remember the old values, and insert the new ones
11056 for ( name in options ) {
11057 old[ name ] = elem.style[ name ];
11058 elem.style[ name ] = options[ name ];
11059 }
11060
11061 ret = callback.apply( elem, args || [] );
11062
11063 // Revert the old values
11064 for ( name in options ) {
11065 elem.style[ name ] = old[ name ];
11066 }
11067
11068 return ret;
11069 },
11070
11071 fakeElement: function( elem, options, callback, args ) {
11072 var ret, name,
11073 newElement = angular.element(elem).clone()[0];
11074
11075 for ( name in options ) {
11076 newElement.style[ name ] = options[ name ];
11077 }
11078
11079 angular.element(document.body).append(newElement);
11080
11081 ret = callback.call( newElement, newElement );
11082
11083 angular.element(newElement).remove();
11084
11085 return ret;
11086 },
11087
11088 /**
11089 * @ngdoc method
11090 * @name normalizeWheelEvent
11091 * @methodOf ui.grid.service:GridUtil
11092 *
11093 * @param {event} event A mouse wheel event
11094 *
11095 * @returns {event} A normalized event
11096 *
11097 * @description
11098 * Given an event from this list:
11099 *
11100 * `wheel, mousewheel, DomMouseScroll, MozMousePixelScroll`
11101 *
11102 * "normalize" it
11103 * so that it stays consistent no matter what browser it comes from (i.e. scale it correctly and make sure the direction is right.)
11104 */
11105 normalizeWheelEvent: function (event) {
11106 // var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
11107 // var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
11108 var lowestDelta, lowestDeltaXY;
11109
11110 var orgEvent = event || window.event,
11111 args = [].slice.call(arguments, 1),
11112 delta = 0,
11113 deltaX = 0,
11114 deltaY = 0,
11115 absDelta = 0,
11116 absDeltaXY = 0,
11117 fn;
11118
11119 // event = $.event.fix(orgEvent);
11120 // event.type = 'mousewheel';
11121
11122 // NOTE: jQuery masks the event and stores it in the event as originalEvent
11123 if (orgEvent.originalEvent) {
11124 orgEvent = orgEvent.originalEvent;
11125 }
11126
11127 // Old school scrollwheel delta
11128 if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
11129 if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
11130
11131 // At a minimum, setup the deltaY to be delta
11132 deltaY = delta;
11133
11134 // Firefox < 17 related to DOMMouseScroll event
11135 if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
11136 deltaY = 0;
11137 deltaX = delta * -1;
11138 }
11139
11140 // New school wheel delta (wheel event)
11141 if ( orgEvent.deltaY ) {
11142 deltaY = orgEvent.deltaY * -1;
11143 delta = deltaY;
11144 }
11145 if ( orgEvent.deltaX ) {
11146 deltaX = orgEvent.deltaX;
11147 delta = deltaX * -1;
11148 }
11149
11150 // Webkit
11151 if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
11152 if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX; }
11153
11154 // Look for lowest delta to normalize the delta values
11155 absDelta = Math.abs(delta);
11156 if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
11157 absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
11158 if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
11159
11160 // Get a whole value for the deltas
11161 fn = delta > 0 ? 'floor' : 'ceil';
11162 delta = Math[fn](delta / lowestDelta);
11163 deltaX = Math[fn](deltaX / lowestDeltaXY);
11164 deltaY = Math[fn](deltaY / lowestDeltaXY);
11165
11166 return {
11167 delta: delta,
11168 deltaX: deltaX,
11169 deltaY: deltaY
11170 };
11171 },
11172
11173 // Stolen from Modernizr
11174 // TODO: make this, and everythign that flows from it, robust
11175 // http://www.stucox.com/blog/you-cant-detect-a-touchscreen/
11176 isTouchEnabled: function() {
11177 var bool;
11178
11179 if (('ontouchstart' in $window) || $window.DocumentTouch && $document instanceof DocumentTouch) {
11180 bool = true;
11181 }
11182
11183 return bool;
11184 },
11185
11186 isNullOrUndefined: function(obj) {
11187 return (obj === undefined || obj === null);
11188 },
11189
11190 endsWith: function(str, suffix) {
11191 if (!str || !suffix || typeof str !== "string") {
11192 return false;
11193 }
11194 return str.indexOf(suffix, str.length - suffix.length) !== -1;
11195 },
11196
11197 arrayContainsObjectWithProperty: function(array, propertyName, propertyValue) {
11198 var found = false;
11199 angular.forEach(array, function (object) {
11200 if (object[propertyName] === propertyValue) {
11201 found = true;
11202 }
11203 });
11204 return found;
11205 },
11206
11207 numericAndNullSort: function (a, b) {
11208 if (a === null) { return 1; }
11209 if (b === null) { return -1; }
11210 if (a === null && b === null) { return 0; }
11211 return a - b;
11212 },
11213
11214 // Disable ngAnimate animations on an element
11215 disableAnimations: function (element) {
11216 var $animate;
11217 try {
11218 $animate = $injector.get('$animate');
11219 // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate
11220 if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {
11221 $animate.enabled(element, false);
11222 } else {
11223 $animate.enabled(false, element);
11224 }
11225 }
11226 catch (e) {}
11227 },
11228
11229 enableAnimations: function (element) {
11230 var $animate;
11231 try {
11232 $animate = $injector.get('$animate');
11233 // See: http://brianhann.com/angular-1-4-breaking-changes-to-be-aware-of/#animate
11234 if (angular.version.major > 1 || (angular.version.major === 1 && angular.version.minor >= 4)) {
11235 $animate.enabled(element, true);
11236 } else {
11237 $animate.enabled(true, element);
11238 }
11239 return $animate;
11240 }
11241 catch (e) {}
11242 },
11243
11244 // Blatantly stolen from Angular as it isn't exposed (yet)
11245 nextUid: function nextUid() {
11246 var index = uid.length;
11247 var digit;
11248
11249 while (index) {
11250 index--;
11251 digit = uid[index].charCodeAt(0);
11252 if (digit === 57 /*'9'*/) {
11253 uid[index] = 'A';
11254 return uidPrefix + uid.join('');
11255 }
11256 if (digit === 90 /*'Z'*/) {
11257 uid[index] = '0';
11258 } else {
11259 uid[index] = String.fromCharCode(digit + 1);
11260 return uidPrefix + uid.join('');
11261 }
11262 }
11263 uid.unshift('0');
11264
11265 return uidPrefix + uid.join('');
11266 },
11267
11268 // Blatantly stolen from Angular as it isn't exposed (yet)
11269 hashKey: function hashKey(obj) {
11270 var objType = typeof obj,
11271 key;
11272
11273 if (objType === 'object' && obj !== null) {
11274 if (typeof (key = obj.$$hashKey) === 'function') {
11275 // must invoke on object to keep the right this
11276 key = obj.$$hashKey();
11277 }
11278 else if (typeof(obj.$$hashKey) !== 'undefined' && obj.$$hashKey) {
11279 key = obj.$$hashKey;
11280 }
11281 else if (key === undefined) {
11282 key = obj.$$hashKey = s.nextUid();
11283 }
11284 }
11285 else {
11286 key = obj;
11287 }
11288
11289 return objType + ': ' + key;
11290 },
11291
11292 resetUids: function () {
11293 uid = ['0', '0', '0'];
11294 },
11295
11296 /**
11297 * @ngdoc method
11298 * @methodOf ui.grid.service:GridUtil
11299 * @name logError
11300 * @description wraps the $log method, allowing us to choose different
11301 * treatment within ui-grid if we so desired. At present we only log
11302 * error messages if uiGridConstants.LOG_ERROR_MESSAGES is set to true
11303 * @param {string} logMessage message to be logged to the console
11304 *
11305 */
11306 logError: function( logMessage ) {
11307 if ( uiGridConstants.LOG_ERROR_MESSAGES ) {
11308 $log.error( logMessage );
11309 }
11310 },
11311
11312 /**
11313 * @ngdoc method
11314 * @methodOf ui.grid.service:GridUtil
11315 * @name logWarn
11316 * @description wraps the $log method, allowing us to choose different
11317 * treatment within ui-grid if we so desired. At present we only log
11318 * warning messages if uiGridConstants.LOG_WARN_MESSAGES is set to true
11319 * @param {string} logMessage message to be logged to the console
11320 *
11321 */
11322 logWarn: function( logMessage ) {
11323 if ( uiGridConstants.LOG_WARN_MESSAGES ) {
11324 $log.warn( logMessage );
11325 }
11326 },
11327
11328 /**
11329 * @ngdoc method
11330 * @methodOf ui.grid.service:GridUtil
11331 * @name logDebug
11332 * @description wraps the $log method, allowing us to choose different
11333 * treatment within ui-grid if we so desired. At present we only log
11334 * debug messages if uiGridConstants.LOG_DEBUG_MESSAGES is set to true
11335 *
11336 */
11337 logDebug: function() {
11338 if ( uiGridConstants.LOG_DEBUG_MESSAGES ) {
11339 $log.debug.apply($log, arguments);
11340 }
11341 }
11342
11343 };
11344
11345 /**
11346 * @ngdoc object
11347 * @name focus
11348 * @propertyOf ui.grid.service:GridUtil
11349 * @description Provides a set of methods to set the document focus inside the grid.
11350 * See {@link ui.grid.service:GridUtil.focus} for more information.
11351 */
11352
11353 /**
11354 * @ngdoc object
11355 * @name ui.grid.service:GridUtil.focus
11356 * @description Provides a set of methods to set the document focus inside the grid.
11357 * Timeouts are utilized to ensure that the focus is invoked after any other event has been triggered.
11358 * e.g. click events that need to run before the focus or
11359 * inputs elements that are in a disabled state but are enabled when those events
11360 * are triggered.
11361 */
11362 s.focus = {
11363 queue: [],
11364 // http://stackoverflow.com/questions/25596399/set-element-focus-in-angular-way
11365 /**
11366 * @ngdoc method
11367 * @methodOf ui.grid.service:GridUtil.focus
11368 * @name byId
11369 * @description Sets the focus of the document to the given id value.
11370 * If provided with the grid object it will automatically append the grid id.
11371 * This is done to encourage unique dom id's as it allows for multiple grids on a
11372 * page.
11373 * @param {String} id the id of the dom element to set the focus on
11374 * @param {Object=} Grid the grid object for this grid instance. See: {@link ui.grid.class:Grid}
11375 * @param {Number} Grid.id the unique id for this grid. Already set on an initialized grid object.
11376 * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
11377 * then the promise will fail with the `'canceled'` reason.
11378 */
11379 byId: function (id, Grid) {
11380 this._purgeQueue();
11381 var promise = $timeout(function() {
11382 var elementID = (Grid && Grid.id ? Grid.id + '-' : '') + id;
11383 var element = $window.document.getElementById(elementID);
11384 if (element) {
11385 element.focus();
11386 } else {
11387 s.logWarn('[focus.byId] Element id ' + elementID + ' was not found.');
11388 }
11389 }, 0, false);
11390 this.queue.push(promise);
11391 return promise;
11392 },
11393
11394 /**
11395 * @ngdoc method
11396 * @methodOf ui.grid.service:GridUtil.focus
11397 * @name byElement
11398 * @description Sets the focus of the document to the given dom element.
11399 * @param {(element|angular.element)} element the DOM element to set the focus on
11400 * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
11401 * then the promise will fail with the `'canceled'` reason.
11402 */
11403 byElement: function(element) {
11404 if (!angular.isElement(element)) {
11405 s.logWarn("Trying to focus on an element that isn\'t an element.");
11406 return $q.reject('not-element');
11407 }
11408 element = angular.element(element);
11409 this._purgeQueue();
11410 var promise = $timeout(function() {
11411 if (element) {
11412 element[0].focus();
11413 }
11414 }, 0, false);
11415 this.queue.push(promise);
11416 return promise;
11417 },
11418 /**
11419 * @ngdoc method
11420 * @methodOf ui.grid.service:GridUtil.focus
11421 * @name bySelector
11422 * @description Sets the focus of the document to the given dom element.
11423 * @param {(element|angular.element)} parentElement the parent/ancestor of the dom element that you are selecting using the query selector
11424 * @param {String} querySelector finds the dom element using the {@link http://www.w3schools.com/jsref/met_document_queryselector.asp querySelector}
11425 * @param {boolean} [aSync=false] If true then the selector will be querried inside of a timeout. Otherwise the selector will be querried imidately
11426 * then the focus will be called.
11427 * @returns {Promise} The `$timeout` promise that will be resolved once focus is set. If another focus is requested before this request is evaluated.
11428 * then the promise will fail with the `'canceled'` reason.
11429 */
11430 bySelector: function(parentElement, querySelector, aSync) {
11431 var self = this;
11432 if (!angular.isElement(parentElement)) {
11433 throw new Error("The parent element is not an element.");
11434 }
11435 // Ensure that this is an angular element.
11436 // It is fine if this is already an angular element.
11437 parentElement = angular.element(parentElement);
11438 var focusBySelector = function() {
11439 var element = parentElement[0].querySelector(querySelector);
11440 return self.byElement(element);
11441 };
11442 this._purgeQueue();
11443 if (aSync) { // Do this asynchronysly
11444 var promise = $timeout(focusBySelector, 0, false);
11445 this.queue.push(promise);
11446 return promise;
11447 } else {
11448 return focusBySelector();
11449 }
11450 },
11451 _purgeQueue: function() {
11452 this.queue.forEach(function(element) {
11453 $timeout.cancel(element);
11454 });
11455 this.queue = [];
11456 }
11457 };
11458
11459
11460 ['width', 'height'].forEach(function (name) {
11461 var capsName = name.charAt(0).toUpperCase() + name.substr(1);
11462
11463 s['element' + capsName] = function (elem, extra) {
11464 var e = elem;
11465 if (e && typeof(e.length) !== 'undefined' && e.length) {
11466 e = elem[0];
11467 }
11468
11469 if (e && e !== null) {
11470 var styles = getStyles(e);
11471 return e.offsetWidth === 0 && rdisplayswap.test(styles.display) ?
11472 s.swap(e, cssShow, function() {
11473 return getWidthOrHeight(e, name, extra );
11474 }) :
11475 getWidthOrHeight( e, name, extra );
11476 } else {
11477 return null;
11478 }
11479 };
11480
11481 s['outerElement' + capsName] = function (elem, margin) {
11482 return elem ? s['element' + capsName].call(this, elem, margin ? 'margin' : 'border') : null;
11483 };
11484 });
11485
11486 // http://stackoverflow.com/a/24107550/888165
11487 s.closestElm = function closestElm(el, selector) {
11488 if (typeof(el.length) !== 'undefined' && el.length) {
11489 el = el[0];
11490 }
11491
11492 var matchesFn;
11493
11494 // find vendor prefix
11495 ['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn) {
11496 if (typeof document.body[fn] === 'function') {
11497 matchesFn = fn;
11498 return true;
11499 }
11500 return false;
11501 });
11502
11503 // traverse parents
11504 var parent;
11505 while (el !== null) {
11506 parent = el.parentElement;
11507 if (parent !== null && parent[matchesFn](selector)) {
11508 return parent;
11509 }
11510 el = parent;
11511 }
11512
11513 return null;
11514 };
11515
11516 s.type = function (obj) {
11517 var text = Function.prototype.toString.call(obj.constructor);
11518 return text.match(/function (.*?)\(/)[1];
11519 };
11520
11521 s.getBorderSize = function getBorderSize(elem, borderType) {
11522 if (typeof(elem.length) !== 'undefined' && elem.length) {
11523 elem = elem[0];
11524 }
11525
11526 var styles = getStyles(elem);
11527
11528 // If a specific border is supplied, like 'top', read the 'borderTop' style property
11529 if (borderType) {
11530 borderType = 'border' + borderType.charAt(0).toUpperCase() + borderType.slice(1);
11531 }
11532 else {
11533 borderType = 'border';
11534 }
11535
11536 borderType += 'Width';
11537
11538 var val = parseInt(styles[borderType], 10);
11539
11540 if (isNaN(val)) {
11541 return 0;
11542 }
11543 else {
11544 return val;
11545 }
11546 };
11547
11548 // http://stackoverflow.com/a/22948274/888165
11549 // TODO: Opera? Mobile?
11550 s.detectBrowser = function detectBrowser() {
11551 var userAgent = $window.navigator.userAgent;
11552
11553 var browsers = {chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i, ie: /internet explorer|trident\//i};
11554
11555 for (var key in browsers) {
11556 if (browsers[key].test(userAgent)) {
11557 return key;
11558 }
11559 }
11560
11561 return 'unknown';
11562 };
11563
11564 // Borrowed from https://github.com/othree/jquery.rtl-scroll-type
11565 // Determine the scroll "type" this browser is using for RTL
11566 s.rtlScrollType = function rtlScrollType() {
11567 if (rtlScrollType.type) {
11568 return rtlScrollType.type;
11569 }
11570
11571 var definer = angular.element('<div dir="rtl" style="font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll">A</div>')[0],
11572 type = 'reverse';
11573
11574 document.body.appendChild(definer);
11575
11576 if (definer.scrollLeft > 0) {
11577 type = 'default';
11578 }
11579 else {
11580 definer.scrollLeft = 1;
11581 if (definer.scrollLeft === 0) {
11582 type = 'negative';
11583 }
11584 }
11585
11586 angular.element(definer).remove();
11587 rtlScrollType.type = type;
11588
11589 return type;
11590 };
11591
11592 /**
11593 * @ngdoc method
11594 * @name normalizeScrollLeft
11595 * @methodOf ui.grid.service:GridUtil
11596 *
11597 * @param {element} element The element to get the `scrollLeft` from.
11598 * @param {grid} grid - grid used to normalize (uses the rtl property)
11599 *
11600 * @returns {number} A normalized scrollLeft value for the current browser.
11601 *
11602 * @description
11603 * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method normalizes them
11604 */
11605 s.normalizeScrollLeft = function normalizeScrollLeft(element, grid) {
11606 if (typeof(element.length) !== 'undefined' && element.length) {
11607 element = element[0];
11608 }
11609
11610 var scrollLeft = element.scrollLeft;
11611
11612 if (grid.isRTL()) {
11613 switch (s.rtlScrollType()) {
11614 case 'default':
11615 return element.scrollWidth - scrollLeft - element.clientWidth;
11616 case 'negative':
11617 return Math.abs(scrollLeft);
11618 case 'reverse':
11619 return scrollLeft;
11620 }
11621 }
11622
11623 return scrollLeft;
11624 };
11625
11626 /**
11627 * @ngdoc method
11628 * @name denormalizeScrollLeft
11629 * @methodOf ui.grid.service:GridUtil
11630 *
11631 * @param {element} element The element to normalize the `scrollLeft` value for
11632 * @param {number} scrollLeft The `scrollLeft` value to denormalize.
11633 * @param {grid} grid The grid that owns the scroll event.
11634 *
11635 * @returns {number} A normalized scrollLeft value for the current browser.
11636 *
11637 * @description
11638 * Browsers currently handle RTL in different ways, resulting in inconsistent scrollLeft values. This method denormalizes a value for the current browser.
11639 */
11640 s.denormalizeScrollLeft = function denormalizeScrollLeft(element, scrollLeft, grid) {
11641 if (typeof(element.length) !== 'undefined' && element.length) {
11642 element = element[0];
11643 }
11644
11645 if (grid.isRTL()) {
11646 switch (s.rtlScrollType()) {
11647 case 'default':
11648 // Get the max scroll for the element
11649 var maxScrollLeft = element.scrollWidth - element.clientWidth;
11650
11651 // Subtract the current scroll amount from the max scroll
11652 return maxScrollLeft - scrollLeft;
11653 case 'negative':
11654 return scrollLeft * -1;
11655 case 'reverse':
11656 return scrollLeft;
11657 }
11658 }
11659
11660 return scrollLeft;
11661 };
11662
11663 /**
11664 * @ngdoc method
11665 * @name preEval
11666 * @methodOf ui.grid.service:GridUtil
11667 *
11668 * @param {string} path Path to evaluate
11669 *
11670 * @returns {string} A path that is normalized.
11671 *
11672 * @description
11673 * Takes a field path and converts it to bracket notation to allow for special characters in path
11674 * @example
11675 * <pre>
11676 * gridUtil.preEval('property') == 'property'
11677 * gridUtil.preEval('nested.deep.prop-erty') = "nested['deep']['prop-erty']"
11678 * </pre>
11679 */
11680 s.preEval = function (path) {
11681 var m = uiGridConstants.BRACKET_REGEXP.exec(path);
11682 if (m) {
11683 return (m[1] ? s.preEval(m[1]) : m[1]) + m[2] + (m[3] ? s.preEval(m[3]) : m[3]);
11684 } else {
11685 path = path.replace(uiGridConstants.APOS_REGEXP, '\\\'');
11686 var parts = path.split(uiGridConstants.DOT_REGEXP);
11687 var preparsed = [parts.shift()]; // first item must be var notation, thus skip
11688 angular.forEach(parts, function (part) {
11689 preparsed.push(part.replace(uiGridConstants.FUNC_REGEXP, '\']$1'));
11690 });
11691 return preparsed.join('[\'');
11692 }
11693 };
11694
11695 /**
11696 * @ngdoc method
11697 * @name debounce
11698 * @methodOf ui.grid.service:GridUtil
11699 *
11700 * @param {function} func function to debounce
11701 * @param {number} wait milliseconds to delay
11702 * @param {boolean} immediate execute before delay
11703 *
11704 * @returns {function} A function that can be executed as debounced function
11705 *
11706 * @description
11707 * Copied from https://github.com/shahata/angular-debounce
11708 * Takes a function, decorates it to execute only 1 time after multiple calls, and returns the decorated function
11709 * @example
11710 * <pre>
11711 * var debouncedFunc = gridUtil.debounce(function() {alert('debounced');}, 500);
11712 * debouncedFunc();
11713 * debouncedFunc();
11714 * debouncedFunc();
11715 * </pre>
11716 */
11717 s.debounce = function (func, wait, immediate) {
11718 var timeout, args, context, result;
11719 function debounce() {
11720 /* jshint validthis: true */
11721 context = this;
11722 args = arguments;
11723 var later = function () {
11724 timeout = null;
11725 if (!immediate) {
11726 result = func.apply(context, args);
11727 }
11728 };
11729 var callNow = immediate && !timeout;
11730 if (timeout) {
11731 $timeout.cancel(timeout);
11732 }
11733 timeout = $timeout(later, wait, false);
11734 if (callNow) {
11735 result = func.apply(context, args);
11736 }
11737 return result;
11738 }
11739 debounce.cancel = function () {
11740 $timeout.cancel(timeout);
11741 timeout = null;
11742 };
11743 return debounce;
11744 };
11745
11746 /**
11747 * @ngdoc method
11748 * @name throttle
11749 * @methodOf ui.grid.service:GridUtil
11750 *
11751 * @param {function} func function to throttle
11752 * @param {number} wait milliseconds to delay after first trigger
11753 * @param {Object} options to use in throttle.
11754 *
11755 * @returns {function} A function that can be executed as throttled function
11756 *
11757 * @description
11758 * Adapted from debounce function (above)
11759 * Potential keys for Params Object are:
11760 * trailing (bool) - whether to trigger after throttle time ends if called multiple times
11761 * Updated to use $interval rather than $timeout, as protractor (e2e tests) is able to work with $interval,
11762 * but not with $timeout
11763 *
11764 * Note that when using throttle, you need to use throttle to create a new function upfront, then use the function
11765 * return from that call each time you need to call throttle. If you call throttle itself repeatedly, the lastCall
11766 * variable will get overwritten and the throttling won't work
11767 *
11768 * @example
11769 * <pre>
11770 * var throttledFunc = gridUtil.throttle(function() {console.log('throttled');}, 500, {trailing: true});
11771 * throttledFunc(); //=> logs throttled
11772 * throttledFunc(); //=> queues attempt to log throttled for ~500ms (since trailing param is truthy)
11773 * throttledFunc(); //=> updates arguments to keep most-recent request, but does not do anything else.
11774 * </pre>
11775 */
11776 s.throttle = function(func, wait, options) {
11777 options = options || {};
11778 var lastCall = 0, queued = null, context, args;
11779
11780 function runFunc(endDate) {
11781 lastCall = +new Date();
11782 func.apply(context, args);
11783 $interval(function() {queued = null; }, 0, 1, false);
11784 }
11785
11786 return function() {
11787 /* jshint validthis: true */
11788 context = this;
11789 args = arguments;
11790 if (queued === null) {
11791 var sinceLast = +new Date() - lastCall;
11792 if (sinceLast > wait) {
11793 runFunc();
11794 }
11795 else if (options.trailing) {
11796 queued = $interval(runFunc, wait - sinceLast, 1, false);
11797 }
11798 }
11799 };
11800 };
11801
11802 s.on = {};
11803 s.off = {};
11804 s._events = {};
11805
11806 s.addOff = function (eventName) {
11807 s.off[eventName] = function (elm, fn) {
11808 var idx = s._events[eventName].indexOf(fn);
11809 if (idx > 0) {
11810 s._events[eventName].removeAt(idx);
11811 }
11812 };
11813 };
11814
11815 var mouseWheeltoBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
11816 nullLowestDeltaTimeout,
11817 lowestDelta;
11818
11819 s.on.mousewheel = function (elm, fn) {
11820 if (!elm || !fn) { return; }
11821
11822 var $elm = angular.element(elm);
11823
11824 // Store the line height and page height for this particular element
11825 $elm.data('mousewheel-line-height', getLineHeight($elm));
11826 $elm.data('mousewheel-page-height', s.elementHeight($elm));
11827 if (!$elm.data('mousewheel-callbacks')) { $elm.data('mousewheel-callbacks', {}); }
11828
11829 var cbs = $elm.data('mousewheel-callbacks');
11830 cbs[fn] = (Function.prototype.bind || bindPolyfill).call(mousewheelHandler, $elm[0], fn);
11831
11832 // Bind all the mousew heel events
11833 for ( var i = mouseWheeltoBind.length; i; ) {
11834 $elm.on(mouseWheeltoBind[--i], cbs[fn]);
11835 }
11836 $elm.on('$destroy', function unbindEvents() {
11837 for ( var i = mouseWheeltoBind.length; i; ) {
11838 $elm.off(mouseWheeltoBind[--i], cbs[fn]);
11839 }
11840 });
11841 };
11842 s.off.mousewheel = function (elm, fn) {
11843 var $elm = angular.element(elm);
11844
11845 var cbs = $elm.data('mousewheel-callbacks');
11846 var handler = cbs[fn];
11847
11848 if (handler) {
11849 for ( var i = mouseWheeltoBind.length; i; ) {
11850 $elm.off(mouseWheeltoBind[--i], handler);
11851 }
11852 }
11853
11854 delete cbs[fn];
11855
11856 if (Object.keys(cbs).length === 0) {
11857 $elm.removeData('mousewheel-line-height');
11858 $elm.removeData('mousewheel-page-height');
11859 $elm.removeData('mousewheel-callbacks');
11860 }
11861 };
11862
11863 function mousewheelHandler(fn, event) {
11864 var $elm = angular.element(this);
11865
11866 var delta = 0,
11867 deltaX = 0,
11868 deltaY = 0,
11869 absDelta = 0,
11870 offsetX = 0,
11871 offsetY = 0;
11872
11873 // jQuery masks events
11874 if (event.originalEvent) { event = event.originalEvent; }
11875
11876 if ( 'detail' in event ) { deltaY = event.detail * -1; }
11877 if ( 'wheelDelta' in event ) { deltaY = event.wheelDelta; }
11878 if ( 'wheelDeltaY' in event ) { deltaY = event.wheelDeltaY; }
11879 if ( 'wheelDeltaX' in event ) { deltaX = event.wheelDeltaX * -1; }
11880
11881 // Firefox < 17 horizontal scrolling related to DOMMouseScroll event
11882 if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
11883 deltaX = deltaY * -1;
11884 deltaY = 0;
11885 }
11886
11887 // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
11888 delta = deltaY === 0 ? deltaX : deltaY;
11889
11890 // New school wheel delta (wheel event)
11891 if ( 'deltaY' in event ) {
11892 deltaY = event.deltaY * -1;
11893 delta = deltaY;
11894 }
11895 if ( 'deltaX' in event ) {
11896 deltaX = event.deltaX;
11897 if ( deltaY === 0 ) { delta = deltaX * -1; }
11898 }
11899
11900 // No change actually happened, no reason to go any further
11901 if ( deltaY === 0 && deltaX === 0 ) { return; }
11902
11903 // Need to convert lines and pages to pixels if we aren't already in pixels
11904 // There are three delta modes:
11905 // * deltaMode 0 is by pixels, nothing to do
11906 // * deltaMode 1 is by lines
11907 // * deltaMode 2 is by pages
11908 if ( event.deltaMode === 1 ) {
11909 var lineHeight = $elm.data('mousewheel-line-height');
11910 delta *= lineHeight;
11911 deltaY *= lineHeight;
11912 deltaX *= lineHeight;
11913 }
11914 else if ( event.deltaMode === 2 ) {
11915 var pageHeight = $elm.data('mousewheel-page-height');
11916 delta *= pageHeight;
11917 deltaY *= pageHeight;
11918 deltaX *= pageHeight;
11919 }
11920
11921 // Store lowest absolute delta to normalize the delta values
11922 absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
11923
11924 if ( !lowestDelta || absDelta < lowestDelta ) {
11925 lowestDelta = absDelta;
11926
11927 // Adjust older deltas if necessary
11928 if ( shouldAdjustOldDeltas(event, absDelta) ) {
11929 lowestDelta /= 40;
11930 }
11931 }
11932
11933 // Get a whole, normalized value for the deltas
11934 delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
11935 deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
11936 deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
11937
11938 var newEvent = {
11939 originalEvent: event,
11940 deltaX: deltaX,
11941 deltaY: deltaY,
11942 deltaFactor: lowestDelta,
11943 preventDefault: function () { event.preventDefault(); },
11944 stopPropagation: function () { event.stopPropagation(); }
11945 };
11946
11947 // Clearout lowestDelta after sometime to better
11948 // handle multiple device types that give
11949 // a different lowestDelta
11950 // Ex: trackpad = 3 and mouse wheel = 120
11951 if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
11952 nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
11953
11954 fn.call($elm[0], newEvent);
11955 }
11956
11957 function nullLowestDelta() {
11958 lowestDelta = null;
11959 }
11960
11961 function shouldAdjustOldDeltas(orgEvent, absDelta) {
11962 // If this is an older event and the delta is divisable by 120,
11963 // then we are assuming that the browser is treating this as an
11964 // older mouse wheel event and that we should divide the deltas
11965 // by 40 to try and get a more usable deltaFactor.
11966 // Side note, this actually impacts the reported scroll distance
11967 // in older browsers and can cause scrolling to be slower than native.
11968 // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
11969 return orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
11970 }
11971
11972 return s;
11973 }]);
11974
11975 // Add 'px' to the end of a number string if it doesn't have it already
11976 module.filter('px', function() {
11977 return function(str) {
11978 if (str.match(/^[\d\.]+$/)) {
11979 return str + 'px';
11980 }
11981 else {
11982 return str;
11983 }
11984 };
11985 });
11986
11987 })();
11988
11989 (function() {
11990 angular.module('ui.grid').config(['$provide', function($provide) {
11991 $provide.decorator('i18nService', ['$delegate', function($delegate) {
11992 $delegate.add('ar', {
11993 "headerCell": {
11994 "aria": {
11995 "defaultFilterLabel": "التصفيه بالعمود",
11996 "removeFilter": "محو التصفيه",
11997 "columnMenuButtonLabel": "قاءمه الاعمده"
11998 },
11999 "priority": "أولويه : ",
12000 "filterLabel": "تصفيه بالاعمده :"
12001 },
12002 "aggregate": {
12003 "label": "العناصر"
12004 },
12005 "groupPanel": {
12006 "description": "اسحب رأس العمود هنا وأسقطه لإنشاء مجموعه"
12007 },
12008 "search": {
12009 "placeholder": "بحث ...",
12010 "showingItems": "العناصر الظاهره :",
12011 "selectedItems": "العناصر المحدده :",
12012 "totalItems": "عدد العناصر :",
12013 "size": "حجم الصفحه :",
12014 "first": "اول صفحه",
12015 "next": "الصفحه التاليه",
12016 "previous": "الصفحه الصابقه",
12017 "last": "الصفحه الاخيره"
12018 },
12019 "menu": {
12020 "text": "اختيار العمود :"
12021 },
12022 "sort": {
12023 "ascending": "ترتيب تصاعدى",
12024 "descending": "ترتيب تنازلى",
12025 "none": "عدم التحديد",
12026 "remove": "حذف الترتيب"
12027 },
12028 "column": {
12029 "hide": "إخفاء عمود"
12030 },
12031 "aggregation": {
12032 "count": "عدد الصفوف: ",
12033 "sum": "جمع: ",
12034 "avg": "المتوسط الحسابى: ",
12035 "min": "الادنى: ",
12036 "max": "الاقصى: "
12037 },
12038 "pinning": {
12039 "pinLeft": "تثبيت لليسار",
12040 "pinRight": "تثبيت لليمين",
12041 "unpin": "فك التثبيت"
12042 },
12043 "columnMenu": {
12044 "close": "غلق"
12045 },
12046 "gridMenu": {
12047 "aria": {
12048 "buttonLabel": "قائمه الجدول"
12049 },
12050 "columns": "الاعمده:",
12051 "importerTitle": "إدخال ملف",
12052 "exporterAllAsCsv": "إخراج كل البيانات ك(csv)",
12053 "exporterVisibleAsCsv": "إخراج كل البيانات الواضحه ك (csv)",
12054 "exporterSelectedAsCsv": "إخراج كل البيانات المحدده ك (csv)",
12055 "exporterAllAsPdf": "إخراج كل البيانات ك(pdf)",
12056 "exporterVisibleAsPdf": "إخراج كل البيانات الواضحه ك (pdf)",
12057 "exporterSelectedAsPdf": "إخراج كل البيانات المحدده ك (pdf)",
12058 "clearAllFilters": "محو كل الترشيح"
12059 },
12060 "importer": {
12061 "noHeaders": "اسماء هؤلاء الاعمده غير واضحه، هل يوجد رأس للملف؟",
12062 "noObjects": "Objects were not able to be derived, was there data in the file other than headers?",
12063 "invalidCsv": "الملف غير قادر على الاتمام ، هل ال (CSV) صحيح؟",
12064 "invalidJson": "الملف غير قادر على الاتمام ، هل ال (JSON) صحيح؟",
12065 "jsonNotArray": "Imported json file must contain an array, aborting."
12066 },
12067 "pagination": {
12068 "aria": {
12069 "pageToFirst": "الصفحه الاولى",
12070 "pageBack": "الصفه السابقه",
12071 "pageSelected": "الصفحه المحدده",
12072 "pageForward": "الصفحه التاليه",
12073 "pageToLast": "الصفحه الاخيره"
12074 },
12075 "sizes": "عدد العناصر فى الصفحه",
12076 "totalItems": "عناصر",
12077 "through": "إلى",
12078 "of": "من"
12079 },
12080 "grouping": {
12081 "group": "جمع",
12082 "ungroup": "فك الجمع",
12083 "aggregate_count": "جمله : العدد",
12084 "aggregate_sum": "جمله : الحاصل",
12085 "aggregate_max": "جمله : الاقصى",
12086 "aggregate_min": "جمله : الاقل",
12087 "aggregate_avg": "جمله :المتوسط ",
12088 "aggregate_remove": "جمله : حذف"
12089 },
12090 "validate": {
12091 "error": "خطأ :",
12092 "minLength": "القيمه لابد ان لا تقل عن THRESHOLD حرف.",
12093 "maxLength": "القيمه لابد ان لا تزيد عن THRESHOLD حرف.",
12094 "required": "مطلوب قيمه"
12095 }
12096 });
12097 return $delegate;
12098 }]);
12099 }]);
12100 })();
12101
12102 (function () {
12103 angular.module('ui.grid').config(['$provide', function($provide) {
12104 $provide.decorator('i18nService', ['$delegate', function($delegate) {
12105 $delegate.add('bg', {
12106 headerCell: {
12107 aria: {
12108 defaultFilterLabel: 'Филттър за колоната',
12109 removeFilter: 'Премахни филтър',
12110 columnMenuButtonLabel: 'Меню на колоната'
12111 },
12112 priority: 'Приоритет:',
12113 filterLabel: "Филтър за колоната: "
12114 },
12115 aggregate: {
12116 label: 'обекти'
12117 },
12118 search: {
12119 placeholder: 'Търсене...',
12120 showingItems: 'Показани обекти:',
12121 selectedItems: 'избрани обекти:',
12122 totalItems: 'Общо:',
12123 size: 'Размер на страницата:',
12124 first: 'Първа страница',
12125 next: 'Следваща страница',
12126 previous: 'Предишна страница',
12127 last: 'Последна страница'
12128 },
12129 menu: {
12130 text: 'Избери колони:'
12131 },
12132 sort: {
12133 ascending: 'Сортиране по възходящ ред',
12134 descending: 'Сортиране по низходящ ред',
12135 none: 'Без сортиране',
12136 remove: 'Премахни сортирането'
12137 },
12138 column: {
12139 hide: 'Скрий колоната'
12140 },
12141 aggregation: {
12142 count: 'Общо редове: ',
12143 sum: 'общо: ',
12144 avg: 'средно: ',
12145 min: 'най-малко: ',
12146 max: 'най-много: '
12147 },
12148 pinning: {
12149 pinLeft: 'Прикрепи вляво',
12150 pinRight: 'Прикрепи вдясно',
12151 unpin: 'Премахване'
12152 },
12153 columnMenu: {
12154 close: 'Затвори'
12155 },
12156 gridMenu: {
12157 aria: {
12158 buttonLabel: 'Меню на таблицата'
12159 },
12160 columns: 'Колони:',
12161 importerTitle: 'Импортиране на файл',
12162 exporterAllAsCsv: 'Експортиране на данните като csv',
12163 exporterVisibleAsCsv: 'Експортиране на видимите данни като csv',
12164 exporterSelectedAsCsv: 'Експортиране на избраните данни като csv',
12165 exporterAllAsPdf: 'Експортиране на данните като pdf',
12166 exporterVisibleAsPdf: 'Експортиране на видимите данни като pdf',
12167 exporterSelectedAsPdf: 'Експортиране на избраните данни като pdf',
12168 clearAllFilters: 'Премахни всички филтри'
12169 },
12170 importer: {
12171 noHeaders: 'Имената на колоните не успяха да бъдат извлечени, файлът има ли хедър?',
12172 noObjects: 'Обектите не успяха да бъдат извлечени, файлът съдържа ли данни, различни от хедър?',
12173 invalidCsv: 'Файлът не може да бъде обработеб, уверете се, че е валиден CSV файл',
12174 invalidJson: 'Файлът не може да бъде обработеб, уверете се, че е валиден JSON файл',
12175 jsonNotArray: 'Импортираният JSON файл трябва да съдържа масив, прекратяване.'
12176 },
12177 pagination: {
12178 aria: {
12179 pageToFirst: 'Към първа страница',
12180 pageBack: 'Страница назад',
12181 pageSelected: 'Избрана страница',
12182 pageForward: 'Страница напред',
12183 pageToLast: 'Към последна страница'
12184 },
12185 sizes: 'обекта на страница',
12186 totalItems: 'обекта',
12187 through: 'до',
12188 of: 'от'
12189 },
12190 grouping: {
12191 group: 'Групиране',
12192 ungroup: 'Премахване на групирането',
12193 aggregate_count: 'Сбор: Брой',
12194 aggregate_sum: 'Сбор: Сума',
12195 aggregate_max: 'Сбор: Максимум',
12196 aggregate_min: 'Сбор: Минимум',
12197 aggregate_avg: 'Сбор: Средно',
12198 aggregate_remove: 'Сбор: Премахване'
12199 },
12200 validate: {
12201 error: 'Грешка:',
12202 minLength: 'Стойността трябва да съдържа поне THRESHOLD символа.',
12203 maxLength: 'Стойността не трябва да съдържа повече от THRESHOLD символа.',
12204 required: 'Необходима е стойност.'
12205 }
12206 });
12207 return $delegate;
12208 }]);
12209 }]);
12210 })();
12211
12212 (function () {
12213 angular.module('ui.grid').config(['$provide', function($provide) {
12214 $provide.decorator('i18nService', ['$delegate', function($delegate) {
12215 var lang = {
12216 aggregate: {
12217 label: 'položky'
12218 },
12219 groupPanel: {
12220 description: 'Přesuňte záhlaví zde pro vytvoření skupiny dle sloupce.'
12221 },
12222 search: {
12223 placeholder: 'Hledat...',
12224 showingItems: 'Zobrazuji položky:',
12225 selectedItems: 'Vybrané položky:',
12226 totalItems: 'Celkem položek:',
12227 size: 'Velikost strany:',
12228 first: 'První strana',
12229 next: 'Další strana',
12230 previous: 'Předchozí strana',
12231 last: 'Poslední strana'
12232 },
12233 menu: {
12234 text: 'Vyberte sloupec:'
12235 },
12236 sort: {
12237 ascending: 'Seřadit od A-Z',
12238 descending: 'Seřadit od Z-A',
12239 remove: 'Odebrat seřazení'
12240 },
12241 column: {
12242 hide: 'Schovat sloupec'
12243 },
12244 aggregation: {
12245 count: 'celkem řádků: ',
12246 sum: 'celkem: ',
12247 avg: 'avg: ',
12248 min: 'min.: ',
12249 max: 'max.: '
12250 },
12251 pinning: {
12252 pinLeft: 'Zamknout vlevo',
12253 pinRight: 'Zamknout vpravo',
12254 unpin: 'Odemknout'
12255 },
12256 gridMenu: {
12257 columns: 'Sloupce:',
12258 importerTitle: 'Importovat soubor',
12259 exporterAllAsCsv: 'Exportovat všechna data do csv',
12260 exporterVisibleAsCsv: 'Exportovat viditelná data do csv',
12261 exporterSelectedAsCsv: 'Exportovat vybraná data do csv',
12262 exporterAllAsPdf: 'Exportovat všechna data do pdf',
12263 exporterVisibleAsPdf: 'Exportovat viditelná data do pdf',
12264 exporterSelectedAsPdf: 'Exportovat vybraná data do pdf',
12265 exporterAllAsExcel: 'Exportovat všechna data do excel',
12266 exporterVisibleAsExcel: 'Exportovat viditelná data do excel',
12267 exporterSelectedAsExcel: 'Exportovat vybraná data do excel',
12268 clearAllFilters: 'Odstranit všechny filtry'
12269 },
12270 importer: {
12271 noHeaders: 'Názvy sloupců se nepodařilo získat, obsahuje soubor záhlaví?',
12272 noObjects: 'Data se nepodařilo zpracovat, obsahuje soubor řádky mimo záhlaví?',
12273 invalidCsv: 'Soubor nelze zpracovat, jedná se o CSV?',
12274 invalidJson: 'Soubor nelze zpracovat, je to JSON?',
12275 jsonNotArray: 'Soubor musí obsahovat json. Ukončuji..'
12276 },
12277 pagination: {
12278 sizes: 'položek na stránku',
12279 totalItems: 'položek'
12280 },
12281 grouping: {
12282 group: 'Seskupit',
12283 ungroup: 'Odebrat seskupení',
12284 aggregate_count: 'Agregace: Count',
12285 aggregate_sum: 'Agregace: Sum',
12286 aggregate_max: 'Agregace: Max',
12287 aggregate_min: 'Agregace: Min',
12288 aggregate_avg: 'Agregace: Avg',
12289 aggregate_remove: 'Agregace: Odebrat'
12290 }
12291 };
12292
12293 // support varianty of different czech keys.
12294 $delegate.add('cs', lang);
12295 $delegate.add('cz', lang);
12296 $delegate.add('cs-cz', lang);
12297 $delegate.add('cs-CZ', lang);
12298 return $delegate;
12299 }]);
12300 }]);
12301 })();
12302
12303 (function() {
12304 angular.module('ui.grid').config(['$provide', function($provide) {
12305 $provide.decorator('i18nService', ['$delegate', function($delegate) {
12306 $delegate.add('da', {
12307 aggregate: {
12308 label: 'artikler'
12309 },
12310 groupPanel: {
12311 description: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.'
12312 },
12313 search: {
12314 placeholder: 'Søg...',
12315 showingItems: 'Viste rækker:',
12316 selectedItems: 'Valgte rækker:',
12317 totalItems: 'Rækker totalt:',
12318 size: 'Side størrelse:',
12319 first: 'Første side',
12320 next: 'Næste side',
12321 previous: 'Forrige side',
12322 last: 'Sidste side'
12323 },
12324 menu: {
12325 text: 'Vælg kolonner:'
12326 },
12327 sort: {
12328 ascending: 'Sorter stigende',
12329 descending: 'Sorter faldende',
12330 none: 'Sorter ingen',
12331 remove: 'Fjern sortering'
12332 },
12333 column: {
12334 hide: 'Skjul kolonne'
12335 },
12336 aggregation: {
12337 count: 'antal rækker: ',
12338 sum: 'sum: ',
12339 avg: 'gns: ',
12340 min: 'min: ',
12341 max: 'max: '
12342 },
12343 pinning: {
12344 pinLeft: 'Fastgør til venstre',
12345 pinRight: 'Fastgør til højre',
12346 unpin: 'Frigør'
12347 },
12348 gridMenu: {
12349 columns: 'Kolonner:',
12350 importerTitle: 'Importer fil',
12351 exporterAllAsCsv: 'Eksporter alle data som csv',
12352 exporterVisibleAsCsv: 'Eksporter synlige data som csv',
12353 exporterSelectedAsCsv: 'Eksporter markerede data som csv',
12354 exporterAllAsPdf: 'Eksporter alle data som pdf',
12355 exporterVisibleAsPdf: 'Eksporter synlige data som pdf',
12356 exporterSelectedAsPdf: 'Eksporter markerede data som pdf',
12357 exporterAllAsExcel: 'Eksporter alle data som excel',
12358 exporterVisibleAsExcel: 'Eksporter synlige data som excel',
12359 exporterSelectedAsExcel: 'Eksporter markerede data som excel',
12360 clearAllFilters: 'Clear all filters'
12361 },
12362 importer: {
12363 noHeaders: 'Column names were unable to be derived, does the file have a header?',
12364 noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
12365 invalidCsv: 'File was unable to be processed, is it valid CSV?',
12366 invalidJson: 'File was unable to be processed, is it valid Json?',
12367 jsonNotArray: 'Imported json file must contain an array, aborting.'
12368 },
12369 pagination: {
12370 aria: {
12371 pageToFirst: 'Gå til første',
12372 pageBack: 'Gå tilbage',
12373 pageSelected: 'Valgte side',
12374 pageForward: 'Gå frem',
12375 pageToLast: 'Gå til sidste'
12376 },
12377 sizes: 'genstande per side',
12378 totalItems: 'genstande',
12379 through: 'gennem',
12380 of: 'af'
12381 }
12382 });
12383 return $delegate;
12384 }]);
12385 }]);
12386 })();
12387
12388 (function () {
12389 angular.module('ui.grid').config(['$provide', function ($provide) {
12390 $provide.decorator('i18nService', ['$delegate', function ($delegate) {
12391 $delegate.add('de', {
12392 headerCell: {
12393 aria: {
12394 defaultFilterLabel: 'Filter für Spalte',
12395 removeFilter: 'Filter löschen',
12396 columnMenuButtonLabel: 'Spaltenmenü',
12397 column: 'Spalte'
12398 },
12399 priority: 'Priorität:',
12400 filterLabel: "Filter für Spalte: "
12401 },
12402 aggregate: {
12403 label: 'Eintrag'
12404 },
12405 groupPanel: {
12406 description: 'Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren.'
12407 },
12408 search: {
12409 aria: {
12410 selected: 'Zeile markiert',
12411 notSelected: 'Zeile nicht markiert'
12412 },
12413 placeholder: 'Suche...',
12414 showingItems: 'Zeige Einträge:',
12415 selectedItems: 'Ausgewählte Einträge:',
12416 totalItems: 'Einträge gesamt:',
12417 size: 'Einträge pro Seite:',
12418 first: 'Erste Seite',
12419 next: 'Nächste Seite',
12420 previous: 'Vorherige Seite',
12421 last: 'Letzte Seite'
12422 },
12423 menu: {
12424 text: 'Spalten auswählen:'
12425 },
12426 sort: {
12427 ascending: 'aufsteigend sortieren',
12428 descending: 'absteigend sortieren',
12429 none: 'keine Sortierung',
12430 remove: 'Sortierung zurücksetzen'
12431 },
12432 column: {
12433 hide: 'Spalte ausblenden'
12434 },
12435 aggregation: {
12436 count: 'Zeilen insgesamt: ',
12437 sum: 'gesamt: ',
12438 avg: 'Durchschnitt: ',
12439 min: 'min: ',
12440 max: 'max: '
12441 },
12442 pinning: {
12443 pinLeft: 'Links anheften',
12444 pinRight: 'Rechts anheften',
12445 unpin: 'Lösen'
12446 },
12447 columnMenu: {
12448 close: 'Schließen'
12449 },
12450 gridMenu: {
12451 aria: {
12452 buttonLabel: 'Tabellenmenü'
12453 },
12454 columns: 'Spalten:',
12455 importerTitle: 'Datei importieren',
12456 exporterAllAsCsv: 'Alle Daten als CSV exportieren',
12457 exporterVisibleAsCsv: 'Sichtbare Daten als CSV exportieren',
12458 exporterSelectedAsCsv: 'Markierte Daten als CSV exportieren',
12459 exporterAllAsPdf: 'Alle Daten als PDF exportieren',
12460 exporterVisibleAsPdf: 'Sichtbare Daten als PDF exportieren',
12461 exporterSelectedAsPdf: 'Markierte Daten als PDF exportieren',
12462 exporterAllAsExcel: 'Alle Daten als Excel exportieren',
12463 exporterVisibleAsExcel: 'Sichtbare Daten als Excel exportieren',
12464 exporterSelectedAsExcel: 'Markierte Daten als Excel exportieren',
12465 clearAllFilters: 'Alle Filter zurücksetzen'
12466 },
12467 importer: {
12468 noHeaders: 'Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?',
12469 noObjects: 'Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?',
12470 invalidCsv: 'Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?',
12471 invalidJson: 'Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?',
12472 jsonNotArray: 'Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab.'
12473 },
12474 pagination: {
12475 aria: {
12476 pageToFirst: 'Zum Anfang',
12477 pageBack: 'Seite zurück',
12478 pageSelected: 'Ausgewählte Seite',
12479 pageForward: 'Seite vor',
12480 pageToLast: 'Zum Ende'
12481 },
12482 sizes: 'Einträge pro Seite',
12483 totalItems: 'Einträgen',
12484 through: 'bis',
12485 of: 'von'
12486 },
12487 grouping: {
12488 group: 'Gruppieren',
12489 ungroup: 'Gruppierung aufheben',
12490 aggregate_count: 'Agg: Anzahl',
12491 aggregate_sum: 'Agg: Summe',
12492 aggregate_max: 'Agg: Maximum',
12493 aggregate_min: 'Agg: Minimum',
12494 aggregate_avg: 'Agg: Mittelwert',
12495 aggregate_remove: 'Aggregation entfernen'
12496 }
12497 });
12498 return $delegate;
12499 }]);
12500 }]);
12501 })();
12502
12503 (function () {
12504 angular.module('ui.grid').config(['$provide', function($provide) {
12505 $provide.decorator('i18nService', ['$delegate', function($delegate) {
12506 $delegate.add('en', {
12507 headerCell: {
12508 aria: {
12509 defaultFilterLabel: 'Filter for column',
12510 removeFilter: 'Remove Filter',
12511 columnMenuButtonLabel: 'Column Menu',
12512 column: 'Column'
12513 },
12514 priority: 'Priority:',
12515 filterLabel: "Filter for column: "
12516 },
12517 aggregate: {
12518 label: 'items'
12519 },
12520 groupPanel: {
12521 description: 'Drag a column header here and drop it to group by that column.'
12522 },
12523 search: {
12524 aria: {
12525 selected: 'Row selected',
12526 notSelected: 'Row not selected'
12527 },
12528 placeholder: 'Search...',
12529 showingItems: 'Showing Items:',
12530 selectedItems: 'Selected Items:',
12531 totalItems: 'Total Items:',
12532 size: 'Page Size:',
12533 first: 'First Page',
12534 next: 'Next Page',
12535 previous: 'Previous Page',
12536 last: 'Last Page'
12537 },
12538 menu: {
12539 text: 'Choose Columns:'
12540 },
12541 sort: {
12542 ascending: 'Sort Ascending',
12543 descending: 'Sort Descending',
12544 none: 'Sort None',
12545 remove: 'Remove Sort'
12546 },
12547 column: {
12548 hide: 'Hide Column'
12549 },
12550 aggregation: {
12551 count: 'total rows: ',
12552 sum: 'total: ',
12553 avg: 'avg: ',
12554 min: 'min: ',
12555 max: 'max: '
12556 },
12557 pinning: {
12558 pinLeft: 'Pin Left',
12559 pinRight: 'Pin Right',
12560 unpin: 'Unpin'
12561 },
12562 columnMenu: {
12563 close: 'Close'
12564 },
12565 gridMenu: {
12566 aria: {
12567 buttonLabel: 'Grid Menu'
12568 },
12569 columns: 'Columns:',
12570 importerTitle: 'Import file',
12571 exporterAllAsCsv: 'Export all data as csv',
12572 exporterVisibleAsCsv: 'Export visible data as csv',
12573 exporterSelectedAsCsv: 'Export selected data as csv',
12574 exporterAllAsPdf: 'Export all data as pdf',
12575 exporterVisibleAsPdf: 'Export visible data as pdf',
12576 exporterSelectedAsPdf: 'Export selected data as pdf',
12577 exporterAllAsExcel: 'Export all data as excel',
12578 exporterVisibleAsExcel: 'Export visible data as excel',
12579 exporterSelectedAsExcel: 'Export selected data as excel',
12580 clearAllFilters: 'Clear all filters'
12581 },
12582 importer: {
12583 noHeaders: 'Column names were unable to be derived, does the file have a header?',
12584 noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
12585 invalidCsv: 'File was unable to be processed, is it valid CSV?',
12586 invalidJson: 'File was unable to be processed, is it valid Json?',
12587 jsonNotArray: 'Imported json file must contain an array, aborting.'
12588 },
12589 pagination: {
12590 aria: {
12591 pageToFirst: 'Page to first',
12592 pageBack: 'Page back',
12593 pageSelected: 'Selected page',
12594 pageForward: 'Page forward',
12595 pageToLast: 'Page to last'
12596 },
12597 sizes: 'items per page',
12598 totalItems: 'items',
12599 through: 'through',
12600 of: 'of'
12601 },
12602 grouping: {
12603 group: 'Group',
12604 ungroup: 'Ungroup',
12605 aggregate_count: 'Agg: Count',
12606 aggregate_sum: 'Agg: Sum',
12607 aggregate_max: 'Agg: Max',
12608 aggregate_min: 'Agg: Min',
12609 aggregate_avg: 'Agg: Avg',
12610 aggregate_remove: 'Agg: Remove'
12611 },
12612 validate: {
12613 error: 'Error:',
12614 minLength: 'Value should be at least THRESHOLD characters long.',
12615 maxLength: 'Value should be at most THRESHOLD characters long.',
12616 required: 'A value is needed.'
12617 }
12618 });
12619 return $delegate;
12620 }]);
12621 }]);
12622 })();
12623
12624 (function () {
12625 angular.module('ui.grid').config(['$provide', function($provide) {
12626 $provide.decorator('i18nService', ['$delegate', function($delegate) {
12627 $delegate.add('es-ct', {
12628 headerCell: {
12629 aria: {
12630 defaultFilterLabel: 'Filtre per columna',
12631 removeFilter: 'Elimina el filtre',
12632 columnMenuButtonLabel: 'Menú de Columna',
12633 column: 'Columna'
12634 },
12635 priority: 'Priority:',
12636 filterLabel: 'Filtre per columna: '
12637 },
12638 aggregate: {
12639 label: 'items'
12640 },
12641 groupPanel: {
12642 description: 'Arrossegueu una capçalera de columna aquí i deixeu-lo anar per agrupar per aquesta columna.'
12643 },
12644 search: {
12645 aria: {
12646 selected: 'Fila seleccionada',
12647 notSelected: 'Fila no seleccionada'
12648 },
12649 placeholder: 'Cerca...',
12650 showingItems: 'Ítems Mostrats:',
12651 selectedItems: 'Ítems Seleccionats:',
12652 totalItems: 'Ítems Totals:',
12653 size: 'Mida de la pàgina:',
12654 first: 'Primera Pàgina',
12655 next: 'Propera Pàgina',
12656 previous: 'Pàgina Anterior',
12657 last: 'Última Pàgina'
12658 },
12659 menu: {
12660 text: 'Triar Columnes:'
12661 },
12662 sort: {
12663 ascending: 'Ordena Ascendent',
12664 descending: 'Ordena Descendent',
12665 none: 'Sense Ordre',
12666 remove: 'Eliminar Ordre'
12667 },
12668 column: {
12669 hide: 'Amaga la Columna'
12670 },
12671 aggregation: {
12672 count: 'Files Totals: ',
12673 sum: 'total: ',
12674 avg: 'mitjà: ',
12675 min: 'mín: ',
12676 max: 'màx: '
12677 },
12678 pinning: {
12679 pinLeft: "Fixar a l'Esquerra",
12680 pinRight: 'Fixar a la Dreta',
12681 unpin: 'Treure Fixació'
12682 },
12683 columnMenu: {
12684 close: 'Tanca'
12685 },
12686 gridMenu: {
12687 aria: {
12688 buttonLabel: 'Menú de Quadrícula'
12689 },
12690 columns: 'Columnes:',
12691 importerTitle: 'Importa el fitxer',
12692 exporterAllAsCsv: 'Exporta tot com CSV',
12693 exporterVisibleAsCsv: 'Exporta les dades visibles com a CSV',
12694 exporterSelectedAsCsv: 'Exporta les dades seleccionades com a CSV',
12695 exporterAllAsPdf: 'Exporta tot com PDF',
12696 exporterVisibleAsPdf: 'Exporta les dades visibles com a PDF',
12697 exporterSelectedAsPdf: 'Exporta les dades seleccionades com a PDF',
12698 exporterAllAsExcel: 'Exporta tot com Excel',
12699 exporterVisibleAsExcel: 'Exporta les dades visibles com Excel',
12700 exporterSelectedAsExcel: 'Exporta les dades seleccionades com Excel',
12701 clearAllFilters: 'Netejar tots els filtres'
12702 },
12703 importer: {
12704 noHeaders: "No va ser possible derivar els noms de les columnes, té encapçalats l'arxiu?",
12705 noObjects: "No va ser possible obtenir registres, conté dades l'arxiu, a part de les capçaleres?",
12706 invalidCsv: "No va ser possible processar l'arxiu, ¿és un CSV vàlid?",
12707 invalidJson: "No va ser possible processar l'arxiu, ¿és un JSON vàlid?",
12708 jsonNotArray: 'El fitxer json importat ha de contenir una matriu, avortant.'
12709 },
12710 pagination: {
12711 aria: {
12712 pageToFirst: 'Page to first',
12713 pageBack: 'Page back',
12714 pageSelected: 'Selected page',
12715 pageForward: 'Page forward',
12716 pageToLast: 'Page to last'
12717 },
12718 sizes: 'ítems per pàgina',
12719 totalItems: 'ítems',
12720 through: 'a',
12721 of: 'de'
12722 },
12723 grouping: {
12724 group: 'Agrupar',
12725 ungroup: 'Desagrupar',
12726 aggregate_count: 'Agr: Compte',
12727 aggregate_sum: 'Agr: Sum',
12728 aggregate_max: 'Agr: Máx',
12729 aggregate_min: 'Agr: Mín',
12730 aggregate_avg: 'Agr: Mitjà',
12731 aggregate_remove: 'Agr: Treure'
12732 },
12733 validate: {
12734 error: 'Error:',
12735 minLength: 'El valor ha de tenir almenys caràcters THRESHOLD.',
12736 maxLength: 'El valor ha de tenir com a màxim caràcters THRESHOLD.',
12737 required: 'Un valor és necessari.'
12738 }
12739 });
12740 return $delegate;
12741 }]);
12742 }]);
12743 })();
12744
12745 (function () {
12746 angular.module('ui.grid').config(['$provide', function($provide) {
12747 $provide.decorator('i18nService', ['$delegate', function($delegate) {
12748 $delegate.add('es', {
12749 aggregate: {
12750 label: 'Artículos'
12751 },
12752 groupPanel: {
12753 description: 'Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna.'
12754 },
12755 search: {
12756 placeholder: 'Buscar...',
12757 showingItems: 'Artículos Mostrados:',
12758 selectedItems: 'Artículos Seleccionados:',
12759 totalItems: 'Artículos Totales:',
12760 size: 'Tamaño de Página:',
12761 first: 'Primera Página',
12762 next: 'Página Siguiente',
12763 previous: 'Página Anterior',
12764 last: 'Última Página'
12765 },
12766 menu: {
12767 text: 'Elegir columnas:'
12768 },
12769 sort: {
12770 ascending: 'Orden Ascendente',
12771 descending: 'Orden Descendente',
12772 remove: 'Sin Ordenar'
12773 },
12774 column: {
12775 hide: 'Ocultar la columna'
12776 },
12777 aggregation: {
12778 count: 'filas totales: ',
12779 sum: 'total: ',
12780 avg: 'media: ',
12781 min: 'min: ',
12782 max: 'max: '
12783 },
12784 pinning: {
12785 pinLeft: 'Fijar a la Izquierda',
12786 pinRight: 'Fijar a la Derecha',
12787 unpin: 'Quitar Fijación'
12788 },
12789 gridMenu: {
12790 columns: 'Columnas:',
12791 importerTitle: 'Importar archivo',
12792 exporterAllAsCsv: 'Exportar todo como csv',
12793 exporterVisibleAsCsv: 'Exportar vista como csv',
12794 exporterSelectedAsCsv: 'Exportar selección como csv',
12795 exporterAllAsPdf: 'Exportar todo como pdf',
12796 exporterVisibleAsPdf: 'Exportar vista como pdf',
12797 exporterSelectedAsPdf: 'Exportar selección como pdf',
12798 exporterAllAsExcel: 'Exportar todo como excel',
12799 exporterVisibleAsExcel: 'Exportar vista como excel',
12800 exporterSelectedAsExcel: 'Exportar selección como excel',
12801 clearAllFilters: 'Limpiar todos los filtros'
12802 },
12803 importer: {
12804 noHeaders: 'No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?',
12805 noObjects: 'No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?',
12806 invalidCsv: 'No fue posible procesar el archivo, ¿es un CSV válido?',
12807 invalidJson: 'No fue posible procesar el archivo, ¿es un Json válido?',
12808 jsonNotArray: 'El archivo json importado debe contener un array, abortando.'
12809 },
12810 pagination: {
12811 sizes: 'registros por página',
12812 totalItems: 'registros',
12813 of: 'de'
12814 },
12815 grouping: {
12816 group: 'Agrupar',
12817 ungroup: 'Desagrupar',
12818 aggregate_count: 'Agr: Cont',
12819 aggregate_sum: 'Agr: Sum',
12820 aggregate_max: 'Agr: Máx',
12821 aggregate_min: 'Agr: Min',
12822 aggregate_avg: 'Agr: Prom',
12823 aggregate_remove: 'Agr: Quitar'
12824 }
12825 });
12826 return $delegate;
12827 }]);
12828 }]);
12829 })();
12830
12831 /**
12832 * Translated by: R. Salarmehr
12833 * M. Hosseynzade
12834 * Using Vajje.com online dictionary.
12835 */
12836 (function () {
12837 angular.module('ui.grid').config(['$provide', function ($provide) {
12838 $provide.decorator('i18nService', ['$delegate', function ($delegate) {
12839 $delegate.add('fa', {
12840 aggregate: {
12841 label: 'قلم'
12842 },
12843 groupPanel: {
12844 description: 'عنوان یک ستون را بگیر و به گروهی از آن ستون رها کن.'
12845 },
12846 search: {
12847 placeholder: 'جستجو...',
12848 showingItems: 'نمایش اقلام:',
12849 selectedItems: 'قلم\u200cهای انتخاب شده:',
12850 totalItems: 'مجموع اقلام:',
12851 size: 'اندازه\u200cی صفحه:',
12852 first: 'اولین صفحه',
12853 next: 'صفحه\u200cی\u200cبعدی',
12854 previous: 'صفحه\u200cی\u200c قبلی',
12855 last: 'آخرین صفحه'
12856 },
12857 menu: {
12858 text: 'ستون\u200cهای انتخابی:'
12859 },
12860 sort: {
12861 ascending: 'ترتیب صعودی',
12862 descending: 'ترتیب نزولی',
12863 remove: 'حذف مرتب کردن'
12864 },
12865 column: {
12866 hide: 'پنهان\u200cکردن ستون'
12867 },
12868 aggregation: {
12869 count: 'تعداد: ',
12870 sum: 'مجموع: ',
12871 avg: 'میانگین: ',
12872 min: 'کمترین: ',
12873 max: 'بیشترین: '
12874 },
12875 pinning: {
12876 pinLeft: 'پین کردن سمت چپ',
12877 pinRight: 'پین کردن سمت راست',
12878 unpin: 'حذف پین'
12879 },
12880 gridMenu: {
12881 columns: 'ستون\u200cها:',
12882 importerTitle: 'وارد کردن فایل',
12883 exporterAllAsCsv: 'خروجی تمام داده\u200cها در فایل csv',
12884 exporterVisibleAsCsv: 'خروجی داده\u200cهای قابل مشاهده در فایل csv',
12885 exporterSelectedAsCsv: 'خروجی داده\u200cهای انتخاب\u200cشده در فایل csv',
12886 exporterAllAsPdf: 'خروجی تمام داده\u200cها در فایل pdf',
12887 exporterVisibleAsPdf: 'خروجی داده\u200cهای قابل مشاهده در فایل pdf',
12888 exporterSelectedAsPdf: 'خروجی داده\u200cهای انتخاب\u200cشده در فایل pdf',
12889 clearAllFilters: 'پاک کردن تمام فیلتر'
12890 },
12891 importer: {
12892 noHeaders: 'نام ستون قابل استخراج نیست. آیا فایل عنوان دارد؟',
12893 noObjects: 'اشیا قابل استخراج نیستند. آیا به جز عنوان\u200cها در فایل داده وجود دارد؟',
12894 invalidCsv: 'فایل قابل پردازش نیست. آیا فرمت csv معتبر است؟',
12895 invalidJson: 'فایل قابل پردازش نیست. آیا فرمت json معتبر است؟',
12896 jsonNotArray: 'فایل json وارد شده باید حاوی آرایه باشد. عملیات ساقط شد.'
12897 },
12898 pagination: {
12899 sizes: 'اقلام در هر صفحه',
12900 totalItems: 'اقلام',
12901 of: 'از'
12902 },
12903 grouping: {
12904 group: 'گروه\u200cبندی',
12905 ungroup: 'حذف گروه\u200cبندی',
12906 aggregate_count: 'Agg: تعداد',
12907 aggregate_sum: 'Agg: جمع',
12908 aggregate_max: 'Agg: بیشینه',
12909 aggregate_min: 'Agg: کمینه',
12910 aggregate_avg: 'Agg: میانگین',
12911 aggregate_remove: 'Agg: حذف'
12912 }
12913 });
12914 return $delegate;
12915 }]);
12916 }]);
12917 })();
12918
12919 (function () {
12920 angular.module('ui.grid').config(['$provide', function($provide) {
12921 $provide.decorator('i18nService', ['$delegate', function($delegate) {
12922 $delegate.add('fi', {
12923 aggregate: {
12924 label: 'rivit'
12925 },
12926 groupPanel: {
12927 description: 'Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan.'
12928 },
12929 search: {
12930 placeholder: 'Hae...',
12931 showingItems: 'Näytetään rivejä:',
12932 selectedItems: 'Valitut rivit:',
12933 totalItems: 'Rivejä yht.:',
12934 size: 'Näytä:',
12935 first: 'Ensimmäinen sivu',
12936 next: 'Seuraava sivu',
12937 previous: 'Edellinen sivu',
12938 last: 'Viimeinen sivu'
12939 },
12940 menu: {
12941 text: 'Valitse sarakkeet:'
12942 },
12943 sort: {
12944 ascending: 'Järjestä nouseva',
12945 descending: 'Järjestä laskeva',
12946 remove: 'Poista järjestys'
12947 },
12948 column: {
12949 hide: 'Piilota sarake'
12950 },
12951 aggregation: {
12952 count: 'Rivejä yht.: ',
12953 sum: 'Summa: ',
12954 avg: 'K.a.: ',
12955 min: 'Min: ',
12956 max: 'Max: '
12957 },
12958 pinning: {
12959 pinLeft: 'Lukitse vasemmalle',
12960 pinRight: 'Lukitse oikealle',
12961 unpin: 'Poista lukitus'
12962 },
12963 gridMenu: {
12964 columns: 'Sarakkeet:',
12965 importerTitle: 'Tuo tiedosto',
12966 exporterAllAsCsv: 'Vie tiedot csv-muodossa',
12967 exporterVisibleAsCsv: 'Vie näkyvä tieto csv-muodossa',
12968 exporterSelectedAsCsv: 'Vie valittu tieto csv-muodossa',
12969 exporterAllAsPdf: 'Vie tiedot pdf-muodossa',
12970 exporterVisibleAsPdf: 'Vie näkyvä tieto pdf-muodossa',
12971 exporterSelectedAsPdf: 'Vie valittu tieto pdf-muodossa',
12972 exporterAllAsExcel: 'Vie tiedot excel-muodossa',
12973 exporterVisibleAsExcel: 'Vie näkyvä tieto excel-muodossa',
12974 exporterSelectedAsExcel: 'Vie valittu tieto excel-muodossa',
12975 clearAllFilters: 'Puhdista kaikki suodattimet'
12976 },
12977 importer: {
12978 noHeaders: 'Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?',
12979 noObjects: 'Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?',
12980 invalidCsv: 'Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?',
12981 invalidJson: 'Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?',
12982 jsonNotArray: 'Tiedosto ei sisältänyt taulukkoa, lopetetaan.'
12983 }
12984 });
12985 return $delegate;
12986 }]);
12987 }]);
12988 })();
12989
12990 (function () {
12991 angular.module('ui.grid').config(['$provide', function($provide) {
12992 $provide.decorator('i18nService', ['$delegate', function($delegate) {
12993 $delegate.add('fr', {
12994 headerCell: {
12995 aria: {
12996 defaultFilterLabel: 'Filtre de la colonne',
12997 removeFilter: 'Supprimer le filtre',
12998 columnMenuButtonLabel: 'Menu de la colonne'
12999 },
13000 priority: 'Priorité:',
13001 filterLabel: "Filtre de la colonne: "
13002 },
13003 aggregate: {
13004 label: 'éléments'
13005 },
13006 groupPanel: {
13007 description: 'Faites glisser une en-tête de colonne ici pour créer un groupe de colonnes.'
13008 },
13009 search: {
13010 placeholder: 'Recherche...',
13011 showingItems: 'Affichage des éléments :',
13012 selectedItems: 'Éléments sélectionnés :',
13013 totalItems: 'Nombre total d\'éléments:',
13014 size: 'Taille de page:',
13015 first: 'Première page',
13016 next: 'Page Suivante',
13017 previous: 'Page précédente',
13018 last: 'Dernière page'
13019 },
13020 menu: {
13021 text: 'Choisir des colonnes :'
13022 },
13023 sort: {
13024 ascending: 'Trier par ordre croissant',
13025 descending: 'Trier par ordre décroissant',
13026 none: 'Aucun tri',
13027 remove: 'Enlever le tri'
13028 },
13029 column: {
13030 hide: 'Cacher la colonne'
13031 },
13032 aggregation: {
13033 count: 'lignes totales: ',
13034 sum: 'total: ',
13035 avg: 'moy: ',
13036 min: 'min: ',
13037 max: 'max: '
13038 },
13039 pinning: {
13040 pinLeft: 'Épingler à gauche',
13041 pinRight: 'Épingler à droite',
13042 unpin: 'Détacher'
13043 },
13044 columnMenu: {
13045 close: 'Fermer'
13046 },
13047 gridMenu: {
13048 aria: {
13049 buttonLabel: 'Menu du tableau'
13050 },
13051 columns: 'Colonnes:',
13052 importerTitle: 'Importer un fichier',
13053 exporterAllAsCsv: 'Exporter toutes les données en CSV',
13054 exporterVisibleAsCsv: 'Exporter les données visibles en CSV',
13055 exporterSelectedAsCsv: 'Exporter les données sélectionnées en CSV',
13056 exporterAllAsPdf: 'Exporter toutes les données en PDF',
13057 exporterVisibleAsPdf: 'Exporter les données visibles en PDF',
13058 exporterSelectedAsPdf: 'Exporter les données sélectionnées en PDF',
13059 exporterAllAsExcel: 'Exporter toutes les données en Excel',
13060 exporterVisibleAsExcel: 'Exporter les données visibles en Excel',
13061 exporterSelectedAsExcel: 'Exporter les données sélectionnées en Excel',
13062 clearAllFilters: 'Nettoyez tous les filtres'
13063 },
13064 importer: {
13065 noHeaders: 'Impossible de déterminer le nom des colonnes, le fichier possède-t-il une en-tête ?',
13066 noObjects: 'Aucun objet trouvé, le fichier possède-t-il des données autres que l\'en-tête ?',
13067 invalidCsv: 'Le fichier n\'a pas pu être traité, le CSV est-il valide ?',
13068 invalidJson: 'Le fichier n\'a pas pu être traité, le JSON est-il valide ?',
13069 jsonNotArray: 'Le fichier JSON importé doit contenir un tableau, abandon.'
13070 },
13071 pagination: {
13072 aria: {
13073 pageToFirst: 'Aller à la première page',
13074 pageBack: 'Page précédente',
13075 pageSelected: 'Page sélectionnée',
13076 pageForward: 'Page suivante',
13077 pageToLast: 'Aller à la dernière page'
13078 },
13079 sizes: 'éléments par page',
13080 totalItems: 'éléments',
13081 through: 'à',
13082 of: 'sur'
13083 },
13084 grouping: {
13085 group: 'Grouper',
13086 ungroup: 'Dégrouper',
13087 aggregate_count: 'Agg: Compter',
13088 aggregate_sum: 'Agg: Somme',
13089 aggregate_max: 'Agg: Max',
13090 aggregate_min: 'Agg: Min',
13091 aggregate_avg: 'Agg: Moy',
13092 aggregate_remove: 'Agg: Retirer'
13093 },
13094 validate: {
13095 error: 'Erreur:',
13096 minLength: 'La valeur doit être supérieure ou égale à THRESHOLD caractères.',
13097 maxLength: 'La valeur doit être inférieure ou égale à THRESHOLD caractères.',
13098 required: 'Une valeur est nécéssaire.'
13099 }
13100 });
13101 return $delegate;
13102 }]);
13103 }]);
13104 })();
13105
13106 (function () {
13107 angular.module('ui.grid').config(['$provide', function ($provide) {
13108 $provide.decorator('i18nService', ['$delegate', function ($delegate) {
13109 $delegate.add('he', {
13110 aggregate: {
13111 label: 'items'
13112 },
13113 groupPanel: {
13114 description: 'גרור עמודה לכאן ושחרר בכדי לקבץ עמודה זו.'
13115 },
13116 search: {
13117 placeholder: 'חפש...',
13118 showingItems: 'מציג:',
13119 selectedItems: 'סה"כ נבחרו:',
13120 totalItems: 'סה"כ רשומות:',
13121 size: 'תוצאות בדף:',
13122 first: 'דף ראשון',
13123 next: 'דף הבא',
13124 previous: 'דף קודם',
13125 last: 'דף אחרון'
13126 },
13127 menu: {
13128 text: 'בחר עמודות:'
13129 },
13130 sort: {
13131 ascending: 'סדר עולה',
13132 descending: 'סדר יורד',
13133 remove: 'בטל'
13134 },
13135 column: {
13136 hide: 'טור הסתר'
13137 },
13138 aggregation: {
13139 count: 'total rows: ',
13140 sum: 'total: ',
13141 avg: 'avg: ',
13142 min: 'min: ',
13143 max: 'max: '
13144 },
13145 gridMenu: {
13146 columns: 'Columns:',
13147 importerTitle: 'Import file',
13148 exporterAllAsCsv: 'Export all data as csv',
13149 exporterVisibleAsCsv: 'Export visible data as csv',
13150 exporterSelectedAsCsv: 'Export selected data as csv',
13151 exporterAllAsPdf: 'Export all data as pdf',
13152 exporterVisibleAsPdf: 'Export visible data as pdf',
13153 exporterSelectedAsPdf: 'Export selected data as pdf',
13154 exporterAllAsExcel: 'Export all data as excel',
13155 exporterVisibleAsExcel: 'Export visible data as excel',
13156 exporterSelectedAsExcel: 'Export selected data as excel',
13157 clearAllFilters: 'Clean all filters'
13158 },
13159 importer: {
13160 noHeaders: 'Column names were unable to be derived, does the file have a header?',
13161 noObjects: 'Objects were not able to be derived, was there data in the file other than headers?',
13162 invalidCsv: 'File was unable to be processed, is it valid CSV?',
13163 invalidJson: 'File was unable to be processed, is it valid Json?',
13164 jsonNotArray: 'Imported json file must contain an array, aborting.'
13165 }
13166 });
13167 return $delegate;
13168 }]);
13169 }]);
13170 })();
13171
13172 (function () {
13173 angular.module('ui.grid').config(['$provide', function($provide) {
13174 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13175 $delegate.add('hy', {
13176 aggregate: {
13177 label: 'տվյալներ'
13178 },
13179 groupPanel: {
13180 description: 'Ըստ սյան խմբավորելու համար քաշեք և գցեք վերնագիրն այստեղ։'
13181 },
13182 search: {
13183 placeholder: 'Փնտրում...',
13184 showingItems: 'Ցուցադրված տվյալներ՝',
13185 selectedItems: 'Ընտրված:',
13186 totalItems: 'Ընդամենը՝',
13187 size: 'Տողերի քանակը էջում՝',
13188 first: 'Առաջին էջ',
13189 next: 'Հաջորդ էջ',
13190 previous: 'Նախորդ էջ',
13191 last: 'Վերջին էջ'
13192 },
13193 menu: {
13194 text: 'Ընտրել սյուները:'
13195 },
13196 sort: {
13197 ascending: 'Աճման կարգով',
13198 descending: 'Նվազման կարգով',
13199 remove: 'Հանել '
13200 },
13201 column: {
13202 hide: 'Թաքցնել սյունը'
13203 },
13204 aggregation: {
13205 count: 'ընդամենը տող՝ ',
13206 sum: 'ընդամենը՝ ',
13207 avg: 'միջին՝ ',
13208 min: 'մին՝ ',
13209 max: 'մաքս՝ '
13210 },
13211 pinning: {
13212 pinLeft: 'Կպցնել ձախ կողմում',
13213 pinRight: 'Կպցնել աջ կողմում',
13214 unpin: 'Արձակել'
13215 },
13216 gridMenu: {
13217 columns: 'Սյուներ:',
13218 importerTitle: 'Ներմուծել ֆայլ',
13219 exporterAllAsCsv: 'Արտահանել ամբողջը CSV',
13220 exporterVisibleAsCsv: 'Արտահանել երևացող տվյալները CSV',
13221 exporterSelectedAsCsv: 'Արտահանել ընտրված տվյալները CSV',
13222 exporterAllAsPdf: 'Արտահանել PDF',
13223 exporterVisibleAsPdf: 'Արտահանել երևացող տվյալները PDF',
13224 exporterSelectedAsPdf: 'Արտահանել ընտրված տվյալները PDF',
13225 exporterAllAsExcel: 'Արտահանել excel',
13226 exporterVisibleAsExcel: 'Արտահանել երևացող տվյալները excel',
13227 exporterSelectedAsExcel: 'Արտահանել ընտրված տվյալները excel',
13228 clearAllFilters: 'Մաքրել բոլոր ֆիլտրերը'
13229 },
13230 importer: {
13231 noHeaders: 'Հնարավոր չեղավ որոշել սյան վերնագրերը։ Արդյո՞ք ֆայլը ունի վերնագրեր։',
13232 noObjects: 'Հնարավոր չեղավ կարդալ տվյալները։ Արդյո՞ք ֆայլում կան տվյալներ։',
13233 invalidCsv: 'Հնարավոր չեղավ մշակել ֆայլը։ Արդյո՞ք այն վավեր CSV է։',
13234 invalidJson: 'Հնարավոր չեղավ մշակել ֆայլը։ Արդյո՞ք այն վավեր Json է։',
13235 jsonNotArray: 'Ներմուծված json ֆայլը պետք է պարունակի զանգված, կասեցվում է։'
13236 }
13237 });
13238 return $delegate;
13239 }]);
13240 }]);
13241 })();
13242
13243 (function () {
13244 angular.module('ui.grid').config(['$provide', function($provide) {
13245 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13246 $delegate.add('is', {
13247 headerCell: {
13248 aria: {
13249 defaultFilterLabel: 'Sía fyrir dálk',
13250 removeFilter: 'Fjarlægja síu',
13251 columnMenuButtonLabel: 'Dálkavalmynd'
13252 },
13253 priority: 'Forgangsröðun:',
13254 filterLabel: "Sía fyrir dálka: "
13255 },
13256 aggregate: {
13257 label: 'hlutir'
13258 },
13259 groupPanel: {
13260 description: 'Dragðu dálkhaus hingað til að flokka saman eftir þeim dálki.'
13261 },
13262 search: {
13263 placeholder: 'Leita...',
13264 showingItems: 'Sýni hluti:',
13265 selectedItems: 'Valdir hlutir:',
13266 totalItems: 'Hlutir alls:',
13267 size: 'Stærð síðu:',
13268 first: 'Fyrsta síða',
13269 next: 'Næsta síða',
13270 previous: 'Fyrri síða',
13271 last: 'Síðasta síða'
13272 },
13273 menu: {
13274 text: 'Veldu dálka:'
13275 },
13276 sort: {
13277 ascending: 'Raða hækkandi',
13278 descending: 'Raða lækkandi',
13279 none: 'Engin röðun',
13280 remove: 'Fjarlægja röðun'
13281 },
13282 column: {
13283 hide: 'Fela dálk'
13284 },
13285 aggregation: {
13286 count: 'fjöldi raða: ',
13287 sum: 'summa: ',
13288 avg: 'meðaltal: ',
13289 min: 'lágmark: ',
13290 max: 'hámark: '
13291 },
13292 pinning: {
13293 pinLeft: 'Festa til vinstri',
13294 pinRight: 'Festa til hægri',
13295 unpin: 'Losa'
13296 },
13297 columnMenu: {
13298 close: 'Loka'
13299 },
13300 gridMenu: {
13301 aria: {
13302 buttonLabel: 'Töflu valmynd'
13303 },
13304 columns: 'Dálkar:',
13305 importerTitle: 'Flytja inn skjal',
13306 exporterAllAsCsv: 'Flytja út gögn sem csv',
13307 exporterVisibleAsCsv: 'Flytja út sýnileg gögn sem csv',
13308 exporterSelectedAsCsv: 'Flytja út valin gögn sem csv',
13309 exporterAllAsPdf: 'Flytja út öll gögn sem pdf',
13310 exporterVisibleAsPdf: 'Flytja út sýnileg gögn sem pdf',
13311 exporterSelectedAsPdf: 'Flytja út valin gögn sem pdf',
13312 clearAllFilters: 'Hreinsa allar síur'
13313 },
13314 importer: {
13315 noHeaders: 'Ekki hægt að vinna dálkanöfn úr skjalinu, er skjalið örugglega með haus?',
13316 noObjects: 'Ekki hægt að vinna hluti úr skjalinu, voru örugglega gögn í skjalinu önnur en hausinn?',
13317 invalidCsv: 'Tókst ekki að vinna skjal, er það örggulega gilt CSV?',
13318 invalidJson: 'Tókst ekki að vinna skjal, er það örugglega gilt Json?',
13319 jsonNotArray: 'Innflutt json skjal verður að innihalda fylki, hætti við.'
13320 },
13321 pagination: {
13322 aria: {
13323 pageToFirst: 'Fletta að fyrstu',
13324 pageBack: 'Fletta til baka',
13325 pageSelected: 'Valin síða',
13326 pageForward: 'Fletta áfram',
13327 pageToLast: 'Fletta að síðustu'
13328 },
13329 sizes: 'hlutir á síðu',
13330 totalItems: 'hlutir',
13331 through: 'gegnum',
13332 of: 'af'
13333 },
13334 grouping: {
13335 group: 'Flokka',
13336 ungroup: 'Sundurliða',
13337 aggregate_count: 'Fjöldi: ',
13338 aggregate_sum: 'Summa: ',
13339 aggregate_max: 'Hámark: ',
13340 aggregate_min: 'Lágmark: ',
13341 aggregate_avg: 'Meðaltal: ',
13342 aggregate_remove: 'Fjarlægja: '
13343 },
13344 validate: {
13345 error: 'Villa:',
13346 minLength: 'Gildi ætti að vera a.m.k. THRESHOLD stafa langt.',
13347 maxLength: 'Gildi ætti að vera í mesta lagi THRESHOLD stafa langt.',
13348 required: 'Þarf að hafa gildi.'
13349 }
13350 });
13351 return $delegate;
13352 }]);
13353 }]);
13354 })();
13355
13356 (function () {
13357 angular.module('ui.grid').config(['$provide', function($provide) {
13358 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13359 $delegate.add('it', {
13360 aggregate: {
13361 label: 'elementi'
13362 },
13363 groupPanel: {
13364 description: 'Trascina un\'intestazione all\'interno del gruppo della colonna.'
13365 },
13366 search: {
13367 placeholder: 'Ricerca...',
13368 showingItems: 'Mostra:',
13369 selectedItems: 'Selezionati:',
13370 totalItems: 'Totali:',
13371 size: 'Tot Pagine:',
13372 first: 'Prima',
13373 next: 'Prossima',
13374 previous: 'Precedente',
13375 last: 'Ultima'
13376 },
13377 menu: {
13378 text: 'Scegli le colonne:'
13379 },
13380 sort: {
13381 ascending: 'Asc.',
13382 descending: 'Desc.',
13383 remove: 'Annulla ordinamento'
13384 },
13385 column: {
13386 hide: 'Nascondi'
13387 },
13388 aggregation: {
13389 count: 'righe totali: ',
13390 sum: 'tot: ',
13391 avg: 'media: ',
13392 min: 'minimo: ',
13393 max: 'massimo: '
13394 },
13395 pinning: {
13396 pinLeft: 'Blocca a sx',
13397 pinRight: 'Blocca a dx',
13398 unpin: 'Blocca in alto'
13399 },
13400 gridMenu: {
13401 columns: 'Colonne:',
13402 importerTitle: 'Importa',
13403 exporterAllAsCsv: 'Esporta tutti i dati in CSV',
13404 exporterVisibleAsCsv: 'Esporta i dati visibili in CSV',
13405 exporterSelectedAsCsv: 'Esporta i dati selezionati in CSV',
13406 exporterAllAsPdf: 'Esporta tutti i dati in PDF',
13407 exporterVisibleAsPdf: 'Esporta i dati visibili in PDF',
13408 exporterSelectedAsPdf: 'Esporta i dati selezionati in PDF',
13409 exporterAllAsExcel: 'Esporta tutti i dati in excel',
13410 exporterVisibleAsExcel: 'Esporta i dati visibili in excel',
13411 exporterSelectedAsExcel: 'Esporta i dati selezionati in excel',
13412 clearAllFilters: 'Pulire tutti i filtri'
13413 },
13414 importer: {
13415 noHeaders: 'Impossibile reperire i nomi delle colonne, sicuro che siano indicati all\'interno del file?',
13416 noObjects: 'Impossibile reperire gli oggetti, sicuro che siano indicati all\'interno del file?',
13417 invalidCsv: 'Impossibile elaborare il file, sicuro che sia un CSV?',
13418 invalidJson: 'Impossibile elaborare il file, sicuro che sia un JSON valido?',
13419 jsonNotArray: 'Errore! Il file JSON da importare deve contenere un array.'
13420 },
13421 pagination: {
13422 aria: {
13423 pageToFirst: 'Prima',
13424 pageBack: 'Indietro',
13425 pageSelected: 'Pagina selezionata',
13426 pageForward: 'Avanti',
13427 pageToLast: 'Ultima'
13428 },
13429 sizes: 'elementi per pagina',
13430 totalItems: 'elementi',
13431 through: 'a',
13432 of: 'di'
13433 },
13434 grouping: {
13435 group: 'Raggruppa',
13436 ungroup: 'Separa',
13437 aggregate_count: 'Agg: N. Elem.',
13438 aggregate_sum: 'Agg: Somma',
13439 aggregate_max: 'Agg: Massimo',
13440 aggregate_min: 'Agg: Minimo',
13441 aggregate_avg: 'Agg: Media',
13442 aggregate_remove: 'Agg: Rimuovi'
13443 },
13444 validate: {
13445 error: 'Errore:',
13446 minLength: 'Lunghezza minima pari a THRESHOLD caratteri.',
13447 maxLength: 'Lunghezza massima pari a THRESHOLD caratteri.',
13448 required: 'Necessario inserire un valore.'
13449 }
13450 });
13451 return $delegate;
13452 }]);
13453 }]);
13454 })();
13455
13456 (function() {
13457 angular.module('ui.grid').config(['$provide', function($provide) {
13458 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13459 $delegate.add('ja', {
13460 headerCell: {
13461 aria: {
13462 defaultFilterLabel: '列のフィルター',
13463 removeFilter: 'フィルターの解除',
13464 columnMenuButtonLabel: '列のメニュー'
13465 },
13466 priority: '優先度:',
13467 filterLabel: "列フィルター: "
13468 },
13469 aggregate: {
13470 label: '項目'
13471 },
13472 groupPanel: {
13473 description: 'ここに列ヘッダをドラッグアンドドロップして、その列でグループ化します。'
13474 },
13475 search: {
13476 placeholder: '検索...',
13477 showingItems: '表示中の項目:',
13478 selectedItems: '選択した項目:',
13479 totalItems: '項目の総数:',
13480 size: 'ページサイズ:',
13481 first: '最初のページ',
13482 next: '次のページ',
13483 previous: '前のページ',
13484 last: '前のページ'
13485 },
13486 menu: {
13487 text: '列の選択:'
13488 },
13489 sort: {
13490 ascending: '昇順に並べ替え',
13491 descending: '降順に並べ替え',
13492 none: '並べ替え無し',
13493 remove: '並べ替えの解除'
13494 },
13495 column: {
13496 hide: '列の非表示'
13497 },
13498 aggregation: {
13499 count: '行数: ',
13500 sum: '合計: ',
13501 avg: '平均: ',
13502 min: '最小: ',
13503 max: '最大: '
13504 },
13505 pinning: {
13506 pinLeft: '左に固定',
13507 pinRight: '右に固定',
13508 unpin: '固定解除'
13509 },
13510 columnMenu: {
13511 close: '閉じる'
13512 },
13513 gridMenu: {
13514 aria: {
13515 buttonLabel: 'グリッドメニュー'
13516 },
13517 columns: '列の表示/非表示:',
13518 importerTitle: 'ファイルのインポート',
13519 exporterAllAsCsv: 'すべてのデータをCSV形式でエクスポート',
13520 exporterVisibleAsCsv: '表示中のデータをCSV形式でエクスポート',
13521 exporterSelectedAsCsv: '選択したデータをCSV形式でエクスポート',
13522 exporterAllAsPdf: 'すべてのデータをPDF形式でエクスポート',
13523 exporterVisibleAsPdf: '表示中のデータをPDF形式でエクスポート',
13524 exporterSelectedAsPdf: '選択したデータをPDF形式でエクスポート',
13525 clearAllFilters: 'すべてのフィルタをクリア'
13526 },
13527 importer: {
13528 noHeaders: '列名を取得できません。ファイルにヘッダが含まれていることを確認してください。',
13529 noObjects: 'オブジェクトを取得できません。ファイルにヘッダ以外のデータが含まれていることを確認してください。',
13530 invalidCsv: 'ファイルを処理できません。ファイルが有効なCSV形式であることを確認してください。',
13531 invalidJson: 'ファイルを処理できません。ファイルが有効なJSON形式であることを確認してください。',
13532 jsonNotArray: 'インポートしたJSONファイルには配列が含まれている必要があります。処理を中止します。'
13533 },
13534 pagination: {
13535 aria: {
13536 pageToFirst: '最初のページ',
13537 pageBack: '前のページ',
13538 pageSelected: '現在のページ',
13539 pageForward: '次のページ',
13540 pageToLast: '最後のページ'
13541 },
13542 sizes: '件/ページ',
13543 totalItems: '件',
13544 through: 'から',
13545 of: '件/全'
13546 },
13547 grouping: {
13548 group: 'グループ化',
13549 ungroup: 'グループ化の解除',
13550 aggregate_count: '集計表示: 行数',
13551 aggregate_sum: '集計表示: 合計',
13552 aggregate_max: '集計表示: 最大',
13553 aggregate_min: '集計表示: 最小',
13554 aggregate_avg: '集計表示: 平均',
13555 aggregate_remove: '集計表示: 解除'
13556 },
13557 validate: {
13558 error: 'Error:',
13559 minLength: 'THRESHOLD 文字以上で入力してください。',
13560 maxLength: 'THRESHOLD 文字以下で入力してください。',
13561 required: '値が必要です。'
13562 }
13563 });
13564 return $delegate;
13565 }]);
13566 }]);
13567 })();
13568
13569 (function () {
13570 angular.module('ui.grid').config(['$provide', function($provide) {
13571 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13572 $delegate.add('ko', {
13573 aggregate: {
13574 label: '아이템'
13575 },
13576 groupPanel: {
13577 description: '컬럼으로 그룹핑하기 위해서는 컬럼 헤더를 끌어 떨어뜨려 주세요.'
13578 },
13579 search: {
13580 placeholder: '검색...',
13581 showingItems: '항목 보여주기:',
13582 selectedItems: '선택 항목:',
13583 totalItems: '전체 항목:',
13584 size: '페이지 크기:',
13585 first: '첫번째 페이지',
13586 next: '다음 페이지',
13587 previous: '이전 페이지',
13588 last: '마지막 페이지'
13589 },
13590 menu: {
13591 text: '컬럼을 선택하세요:'
13592 },
13593 sort: {
13594 ascending: '오름차순 정렬',
13595 descending: '내림차순 정렬',
13596 remove: '소팅 제거'
13597 },
13598 column: {
13599 hide: '컬럼 제거'
13600 },
13601 aggregation: {
13602 count: '전체 갯수: ',
13603 sum: '전체: ',
13604 avg: '평균: ',
13605 min: '최소: ',
13606 max: '최대: '
13607 },
13608 pinning: {
13609 pinLeft: '왼쪽 핀',
13610 pinRight: '오른쪽 핀',
13611 unpin: '핀 제거'
13612 },
13613 gridMenu: {
13614 columns: '컬럼:',
13615 importerTitle: '파일 가져오기',
13616 exporterAllAsCsv: 'csv로 모든 데이터 내보내기',
13617 exporterVisibleAsCsv: 'csv로 보이는 데이터 내보내기',
13618 exporterSelectedAsCsv: 'csv로 선택된 데이터 내보내기',
13619 exporterAllAsPdf: 'pdf로 모든 데이터 내보내기',
13620 exporterVisibleAsPdf: 'pdf로 보이는 데이터 내보내기',
13621 exporterSelectedAsPdf: 'pdf로 선택 데이터 내보내기',
13622 clearAllFilters: '모든 필터를 청소'
13623 },
13624 importer: {
13625 noHeaders: '컬럼명이 지정되어 있지 않습니다. 파일에 헤더가 명시되어 있는지 확인해 주세요.',
13626 noObjects: '데이터가 지정되어 있지 않습니다. 데이터가 파일에 있는지 확인해 주세요.',
13627 invalidCsv: '파일을 처리할 수 없습니다. 올바른 csv인지 확인해 주세요.',
13628 invalidJson: '파일을 처리할 수 없습니다. 올바른 json인지 확인해 주세요.',
13629 jsonNotArray: 'json 파일은 배열을 포함해야 합니다.'
13630 },
13631 pagination: {
13632 sizes: '페이지당 항목',
13633 totalItems: '전체 항목'
13634 }
13635 });
13636 return $delegate;
13637 }]);
13638 }]);
13639 })();
13640
13641 (function () {
13642 angular.module('ui.grid').config(['$provide', function($provide) {
13643 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13644 $delegate.add('nl', {
13645 aggregate: {
13646 label: 'items'
13647 },
13648 groupPanel: {
13649 description: 'Sleep hier een kolomnaam heen om op te groeperen.'
13650 },
13651 search: {
13652 placeholder: 'Zoeken...',
13653 showingItems: 'Getoonde items:',
13654 selectedItems: 'Geselecteerde items:',
13655 totalItems: 'Totaal aantal items:',
13656 size: 'Items per pagina:',
13657 first: 'Eerste pagina',
13658 next: 'Volgende pagina',
13659 previous: 'Vorige pagina',
13660 last: 'Laatste pagina'
13661 },
13662 menu: {
13663 text: 'Kies kolommen:'
13664 },
13665 sort: {
13666 ascending: 'Sorteer oplopend',
13667 descending: 'Sorteer aflopend',
13668 remove: 'Verwijder sortering'
13669 },
13670 column: {
13671 hide: 'Verberg kolom'
13672 },
13673 aggregation: {
13674 count: 'Aantal rijen: ',
13675 sum: 'Som: ',
13676 avg: 'Gemiddelde: ',
13677 min: 'Min: ',
13678 max: 'Max: '
13679 },
13680 pinning: {
13681 pinLeft: 'Zet links vast',
13682 pinRight: 'Zet rechts vast',
13683 unpin: 'Maak los'
13684 },
13685 gridMenu: {
13686 columns: 'Kolommen:',
13687 importerTitle: 'Importeer bestand',
13688 exporterAllAsCsv: 'Exporteer alle data als csv',
13689 exporterVisibleAsCsv: 'Exporteer zichtbare data als csv',
13690 exporterSelectedAsCsv: 'Exporteer geselecteerde data als csv',
13691 exporterAllAsPdf: 'Exporteer alle data als pdf',
13692 exporterVisibleAsPdf: 'Exporteer zichtbare data als pdf',
13693 exporterSelectedAsPdf: 'Exporteer geselecteerde data als pdf',
13694 exporterAllAsExcel: 'Exporteer alle data als excel',
13695 exporterVisibleAsExcel: 'Exporteer zichtbare data als excel',
13696 exporterSelectedAsExcel: 'Exporteer alle data als excel',
13697 clearAllFilters: 'Reinig alle filters'
13698 },
13699 importer: {
13700 noHeaders: 'Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?',
13701 noObjects: 'Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?',
13702 invalidCsv: 'Het bestand kan niet verwerkt worden. Is het een valide csv bestand?',
13703 invalidJson: 'Het bestand kan niet verwerkt worden. Is het valide json?',
13704 jsonNotArray: 'Het json bestand moet een array bevatten. De actie wordt geannuleerd.'
13705 },
13706 pagination: {
13707 sizes: 'items per pagina',
13708 totalItems: 'items',
13709 of: 'van de'
13710 },
13711 grouping: {
13712 group: 'Groepeer',
13713 ungroup: 'Groepering opheffen',
13714 aggregate_count: 'Agg: Aantal',
13715 aggregate_sum: 'Agg: Som',
13716 aggregate_max: 'Agg: Max',
13717 aggregate_min: 'Agg: Min',
13718 aggregate_avg: 'Agg: Gem',
13719 aggregate_remove: 'Agg: Verwijder'
13720 }
13721 });
13722 return $delegate;
13723 }]);
13724 }]);
13725 })();
13726
13727 (function () {
13728 angular.module('ui.grid').config(['$provide', function($provide) {
13729 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13730 $delegate.add('no', {
13731 headerCell: {
13732 aria: {
13733 defaultFilterLabel: 'Filter for kolonne',
13734 removeFilter: 'Fjern filter',
13735 columnMenuButtonLabel: 'Kolonnemeny'
13736 },
13737 priority: 'Prioritet:',
13738 filterLabel: "Filter for kolonne: "
13739 },
13740 aggregate: {
13741 label: 'elementer'
13742 },
13743 groupPanel: {
13744 description: 'Trekk en kolonneoverskrift hit og slipp den for å gruppere etter den kolonnen.'
13745 },
13746 search: {
13747 placeholder: 'Søk...',
13748 showingItems: 'Viste elementer:',
13749 selectedItems: 'Valgte elementer:',
13750 totalItems: 'Antall elementer:',
13751 size: 'Sidestørrelse:',
13752 first: 'Første side',
13753 next: 'Neste side',
13754 previous: 'Forrige side',
13755 last: 'Siste side'
13756 },
13757 menu: {
13758 text: 'Velg kolonner:'
13759 },
13760 sort: {
13761 ascending: 'Sortere stigende',
13762 descending: 'Sortere fallende',
13763 none: 'Ingen sortering',
13764 remove: 'Fjern sortering'
13765 },
13766 column: {
13767 hide: 'Skjul kolonne'
13768 },
13769 aggregation: {
13770 count: 'antall rader: ',
13771 sum: 'total: ',
13772 avg: 'gjennomsnitt: ',
13773 min: 'minimum: ',
13774 max: 'maksimum: '
13775 },
13776 pinning: {
13777 pinLeft: 'Fest til venstre',
13778 pinRight: 'Fest til høyre',
13779 unpin: 'Løsne'
13780 },
13781 columnMenu: {
13782 close: 'Lukk'
13783 },
13784 gridMenu: {
13785 aria: {
13786 buttonLabel: 'Grid Menu'
13787 },
13788 columns: 'Kolonner:',
13789 importerTitle: 'Importer fil',
13790 exporterAllAsCsv: 'Eksporter alle data som csv',
13791 exporterVisibleAsCsv: 'Eksporter synlige data som csv',
13792 exporterSelectedAsCsv: 'Eksporter utvalgte data som csv',
13793 exporterAllAsPdf: 'Eksporter alle data som pdf',
13794 exporterVisibleAsPdf: 'Eksporter synlige data som pdf',
13795 exporterSelectedAsPdf: 'Eksporter utvalgte data som pdf',
13796 exporterAllAsExcel: 'Eksporter alle data som excel',
13797 exporterVisibleAsExcel: 'Eksporter synlige data som excel',
13798 exporterSelectedAsExcel: 'Eksporter utvalgte data som excel',
13799 clearAllFilters: 'Clear all filters'
13800 },
13801 importer: {
13802 noHeaders: 'Kolonnenavn kunne ikke avledes. Har filen en overskrift?',
13803 noObjects: 'Objekter kunne ikke avledes. Er der andre data i filen enn overskriften?',
13804 invalidCsv: 'Filen kunne ikke behandles. Er den gyldig CSV?',
13805 invalidJson: 'Filen kunne ikke behandles. Er den gyldig JSON?',
13806 jsonNotArray: 'Importert JSON-fil må inneholde en liste. Avbryter.'
13807 },
13808 pagination: {
13809 aria: {
13810 pageToFirst: 'Gå til første side',
13811 pageBack: 'Gå til forrige side',
13812 pageSelected: 'Valgte side',
13813 pageForward: 'Gå til neste side',
13814 pageToLast: 'Gå til siste side'
13815 },
13816 sizes: 'elementer per side',
13817 totalItems: 'elementer',
13818 through: 'til',
13819 of: 'av'
13820 },
13821 grouping: {
13822 group: 'Gruppere',
13823 ungroup: 'Fjerne gruppering',
13824 aggregate_count: 'Agr: Antall',
13825 aggregate_sum: 'Agr: Sum',
13826 aggregate_max: 'Agr: Maksimum',
13827 aggregate_min: 'Agr: Minimum',
13828 aggregate_avg: 'Agr: Gjennomsnitt',
13829 aggregate_remove: 'Agr: Fjern'
13830 }
13831 });
13832 return $delegate;
13833 }]);
13834 }]);
13835 })();
13836
13837 (function () {
13838 angular.module('ui.grid').config(['$provide', function($provide) {
13839 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13840 $delegate.add('pl', {
13841 headerCell: {
13842 aria: {
13843 defaultFilterLabel: 'Filtr dla kolumny',
13844 removeFilter: 'Usuń filtr',
13845 columnMenuButtonLabel: 'Opcje kolumny',
13846 column: 'Kolumna'
13847 },
13848 priority: 'Priorytet:',
13849 filterLabel: "Filtr dla kolumny: "
13850 },
13851 aggregate: {
13852 label: 'pozycji'
13853 },
13854 groupPanel: {
13855 description: 'Przeciągnij nagłówek kolumny tutaj, aby pogrupować według niej.'
13856 },
13857 search: {
13858 aria: {
13859 selected: 'Wiersz zaznaczony',
13860 notSelected: 'Wiersz niezaznaczony'
13861 },
13862 placeholder: 'Szukaj...',
13863 showingItems: 'Widoczne pozycje:',
13864 selectedItems: 'Zaznaczone pozycje:',
13865 totalItems: 'Wszystkich pozycji:',
13866 size: 'Rozmiar strony:',
13867 first: 'Pierwsza strona',
13868 next: 'Następna strona',
13869 previous: 'Poprzednia strona',
13870 last: 'Ostatnia strona'
13871 },
13872 menu: {
13873 text: 'Wybierz kolumny:'
13874 },
13875 sort: {
13876 ascending: 'Sortuj rosnąco',
13877 descending: 'Sortuj malejąco',
13878 none: 'Brak sortowania',
13879 remove: 'Wyłącz sortowanie'
13880 },
13881 column: {
13882 hide: 'Ukryj kolumnę'
13883 },
13884 aggregation: {
13885 count: 'Razem pozycji: ',
13886 sum: 'Razem: ',
13887 avg: 'Średnia: ',
13888 min: 'Min: ',
13889 max: 'Max: '
13890 },
13891 pinning: {
13892 pinLeft: 'Przypnij do lewej',
13893 pinRight: 'Przypnij do prawej',
13894 unpin: 'Odepnij'
13895 },
13896 columnMenu: {
13897 close: 'Zamknij'
13898 },
13899 gridMenu: {
13900 aria: {
13901 buttonLabel: 'Opcje tabeli'
13902 },
13903 columns: 'Kolumny:',
13904 importerTitle: 'Importuj plik',
13905 exporterAllAsCsv: 'Eksportuj wszystkie dane do csv',
13906 exporterVisibleAsCsv: 'Eksportuj widoczne dane do csv',
13907 exporterSelectedAsCsv: 'Eksportuj zaznaczone dane do csv',
13908 exporterAllAsPdf: 'Eksportuj wszystkie dane do pdf',
13909 exporterVisibleAsPdf: 'Eksportuj widoczne dane do pdf',
13910 exporterSelectedAsPdf: 'Eksportuj zaznaczone dane do pdf',
13911 exporterAllAsExcel: 'Eksportuj wszystkie dane do excel',
13912 exporterVisibleAsExcel: 'Eksportuj widoczne dane do excel',
13913 exporterSelectedAsExcel: 'Eksportuj zaznaczone dane do excel',
13914 clearAllFilters: 'Wyczyść filtry'
13915 },
13916 importer: {
13917 noHeaders: 'Nie udało się wczytać nazw kolumn. Czy plik posiada nagłówek?',
13918 noObjects: 'Nie udalo się wczytać pozycji. Czy plik zawiera dane?',
13919 invalidCsv: 'Nie udało się przetworzyć pliku. Czy to prawidłowy plik CSV?',
13920 invalidJson: 'Nie udało się przetworzyć pliku. Czy to prawidłowy plik JSON?',
13921 jsonNotArray: 'Importowany plik JSON musi zawierać tablicę. Importowanie przerwane.'
13922 },
13923 pagination: {
13924 aria: {
13925 pageToFirst: 'Pierwsza strona',
13926 pageBack: 'Poprzednia strona',
13927 pageSelected: 'Wybrana strona',
13928 pageForward: 'Następna strona',
13929 pageToLast: 'Ostatnia strona'
13930 },
13931 sizes: 'pozycji na stronę',
13932 totalItems: 'pozycji',
13933 through: 'do',
13934 of: 'z'
13935 },
13936 grouping: {
13937 group: 'Grupuj',
13938 ungroup: 'Rozgrupuj',
13939 aggregate_count: 'Zbiorczo: Razem',
13940 aggregate_sum: 'Zbiorczo: Suma',
13941 aggregate_max: 'Zbiorczo: Max',
13942 aggregate_min: 'Zbiorczo: Min',
13943 aggregate_avg: 'Zbiorczo: Średnia',
13944 aggregate_remove: 'Zbiorczo: Usuń'
13945 },
13946 validate: {
13947 error: 'Błąd:',
13948 minLength: 'Wartość powinna składać się z co najmniej THRESHOLD znaków.',
13949 maxLength: 'Wartość powinna składać się z przynajmniej THRESHOLD znaków.',
13950 required: 'Wartość jest wymagana.'
13951 }
13952 });
13953 return $delegate;
13954 }]);
13955 }]);
13956 })();
13957
13958 (function () {
13959 angular.module('ui.grid').config(['$provide', function($provide) {
13960 $provide.decorator('i18nService', ['$delegate', function($delegate) {
13961 $delegate.add('pt-br', {
13962 headerCell: {
13963 aria: {
13964 defaultFilterLabel: 'Filtro por coluna',
13965 removeFilter: 'Remover filtro',
13966 columnMenuButtonLabel: 'Menu coluna',
13967 column: 'Coluna'
13968 },
13969 priority: 'Prioridade:',
13970 filterLabel: "Filtro por coluna: "
13971 },
13972 aggregate: {
13973 label: 'itens'
13974 },
13975 groupPanel: {
13976 description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'
13977 },
13978 search: {
13979 aria: {
13980 selected: 'Linha selecionada',
13981 notSelected: 'Linha não está selecionada'
13982 },
13983 placeholder: 'Procurar...',
13984 showingItems: 'Mostrando os Itens:',
13985 selectedItems: 'Items Selecionados:',
13986 totalItems: 'Total de Itens:',
13987 size: 'Tamanho da Página:',
13988 first: 'Primeira Página',
13989 next: 'Próxima Página',
13990 previous: 'Página Anterior',
13991 last: 'Última Página'
13992 },
13993 menu: {
13994 text: 'Selecione as colunas:'
13995 },
13996 sort: {
13997 ascending: 'Ordenar Ascendente',
13998 descending: 'Ordenar Descendente',
13999 none: 'Nenhuma Ordem',
14000 remove: 'Remover Ordenação'
14001 },
14002 column: {
14003 hide: 'Esconder coluna'
14004 },
14005 aggregation: {
14006 count: 'total de linhas: ',
14007 sum: 'total: ',
14008 avg: 'med: ',
14009 min: 'min: ',
14010 max: 'max: '
14011 },
14012 pinning: {
14013 pinLeft: 'Fixar Esquerda',
14014 pinRight: 'Fixar Direita',
14015 unpin: 'Desprender'
14016 },
14017 columnMenu: {
14018 close: 'Fechar'
14019 },
14020 gridMenu: {
14021 aria: {
14022 buttonLabel: 'Menu Grid'
14023 },
14024 columns: 'Colunas:',
14025 importerTitle: 'Importar arquivo',
14026 exporterAllAsCsv: 'Exportar todos os dados como csv',
14027 exporterVisibleAsCsv: 'Exportar dados visíveis como csv',
14028 exporterSelectedAsCsv: 'Exportar dados selecionados como csv',
14029 exporterAllAsPdf: 'Exportar todos os dados como pdf',
14030 exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',
14031 exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',
14032 exporterAllAsExcel: 'Exportar todos os dados como excel',
14033 exporterVisibleAsExcel: 'Exportar dados visíveis como excel',
14034 exporterSelectedAsExcel: 'Exportar dados selecionados como excel',
14035 clearAllFilters: 'Limpar todos os filtros'
14036 },
14037 importer: {
14038 noHeaders: 'Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?',
14039 noObjects: 'Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?',
14040 invalidCsv: 'Arquivo não pode ser processado. É um CSV válido?',
14041 invalidJson: 'Arquivo não pode ser processado. É um Json válido?',
14042 jsonNotArray: 'Arquivo json importado tem que conter um array. Abortando.'
14043 },
14044 pagination: {
14045 aria: {
14046 pageToFirst: 'Primeira página',
14047 pageBack: 'Página anterior',
14048 pageSelected: 'Página Selecionada',
14049 pageForward: 'Proxima',
14050 pageToLast: 'Anterior'
14051 },
14052 sizes: 'itens por página',
14053 totalItems: 'itens',
14054 through: 'através dos',
14055 of: 'de'
14056 },
14057 grouping: {
14058 group: 'Agrupar',
14059 ungroup: 'Desagrupar',
14060 aggregate_count: 'Agr: Contar',
14061 aggregate_sum: 'Agr: Soma',
14062 aggregate_max: 'Agr: Max',
14063 aggregate_min: 'Agr: Min',
14064 aggregate_avg: 'Agr: Med',
14065 aggregate_remove: 'Agr: Remover'
14066 },
14067 validate: {
14068 error: 'Erro:',
14069 minLength: 'O valor deve ter, no minimo, THRESHOLD caracteres.',
14070 maxLength: 'O valor deve ter, no máximo, THRESHOLD caracteres.',
14071 required: 'Um valor é necessário.'
14072 }
14073 });
14074 return $delegate;
14075 }]);
14076 }]);
14077 })();
14078
14079 (function () {
14080 angular.module('ui.grid').config(['$provide', function($provide) {
14081 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14082 $delegate.add('pt', {
14083 headerCell: {
14084 aria: {
14085 defaultFilterLabel: 'Filtro por coluna',
14086 removeFilter: 'Remover filtro',
14087 columnMenuButtonLabel: 'Menu coluna',
14088 column: 'Coluna'
14089 },
14090 priority: 'Prioridade:',
14091 filterLabel: "Filtro por coluna: "
14092 },
14093 aggregate: {
14094 label: 'itens'
14095 },
14096 groupPanel: {
14097 description: 'Arraste e solte uma coluna aqui para agrupar por essa coluna'
14098 },
14099 search: {
14100 aria: {
14101 selected: 'Linha selecionada',
14102 notSelected: 'Linha não está selecionada'
14103 },
14104 placeholder: 'Procurar...',
14105 showingItems: 'Mostrando os Itens:',
14106 selectedItems: 'Itens Selecionados:',
14107 totalItems: 'Total de Itens:',
14108 size: 'Tamanho da Página:',
14109 first: 'Primeira Página',
14110 next: 'Próxima Página',
14111 previous: 'Página Anterior',
14112 last: 'Última Página'
14113 },
14114 menu: {
14115 text: 'Selecione as colunas:'
14116 },
14117 sort: {
14118 ascending: 'Ordenar Ascendente',
14119 descending: 'Ordenar Descendente',
14120 none: 'Nenhuma Ordem',
14121 remove: 'Remover Ordenação'
14122 },
14123 column: {
14124 hide: 'Esconder coluna'
14125 },
14126 aggregation: {
14127 count: 'total de linhas: ',
14128 sum: 'total: ',
14129 avg: 'med: ',
14130 min: 'min: ',
14131 max: 'max: '
14132 },
14133 pinning: {
14134 pinLeft: 'Fixar Esquerda',
14135 pinRight: 'Fixar Direita',
14136 unpin: 'Desprender'
14137 },
14138 columnMenu: {
14139 close: 'Fechar'
14140 },
14141 gridMenu: {
14142 aria: {
14143 buttonLabel: 'Menu Grid'
14144 },
14145 columns: 'Colunas:',
14146 importerTitle: 'Importar ficheiro',
14147 exporterAllAsCsv: 'Exportar todos os dados como csv',
14148 exporterVisibleAsCsv: 'Exportar dados visíveis como csv',
14149 exporterSelectedAsCsv: 'Exportar dados selecionados como csv',
14150 exporterAllAsPdf: 'Exportar todos os dados como pdf',
14151 exporterVisibleAsPdf: 'Exportar dados visíveis como pdf',
14152 exporterSelectedAsPdf: 'Exportar dados selecionados como pdf',
14153 exporterAllAsExcel: 'Exportar todos os dados como excel',
14154 exporterVisibleAsExcel: 'Exportar dados visíveis como excel',
14155 exporterSelectedAsExcel: 'Exportar dados selecionados como excel',
14156 clearAllFilters: 'Limpar todos os filtros'
14157 },
14158 importer: {
14159 noHeaders: 'Nomes de colunas não puderam ser derivados. O ficheiro tem um cabeçalho?',
14160 noObjects: 'Objetos não puderam ser derivados. Havia dados no ficheiro, além dos cabeçalhos?',
14161 invalidCsv: 'Ficheiro não pode ser processado. É um CSV válido?',
14162 invalidJson: 'Ficheiro não pode ser processado. É um Json válido?',
14163 jsonNotArray: 'Ficheiro json importado tem que conter um array. Interrompendo.'
14164 },
14165 pagination: {
14166 aria: {
14167 pageToFirst: 'Primeira página',
14168 pageBack: 'Página anterior',
14169 pageSelected: 'Página Selecionada',
14170 pageForward: 'Próxima',
14171 pageToLast: 'Anterior'
14172 },
14173 sizes: 'itens por página',
14174 totalItems: 'itens',
14175 through: 'a',
14176 of: 'de'
14177 },
14178 grouping: {
14179 group: 'Agrupar',
14180 ungroup: 'Desagrupar',
14181 aggregate_count: 'Agr: Contar',
14182 aggregate_sum: 'Agr: Soma',
14183 aggregate_max: 'Agr: Max',
14184 aggregate_min: 'Agr: Min',
14185 aggregate_avg: 'Agr: Med',
14186 aggregate_remove: 'Agr: Remover'
14187 },
14188 validate: {
14189 error: 'Erro:',
14190 minLength: 'O valor deve ter, no minimo, THRESHOLD caracteres.',
14191 maxLength: 'O valor deve ter, no máximo, THRESHOLD caracteres.',
14192 required: 'Um valor é necessário.'
14193 }
14194 });
14195 return $delegate;
14196 }]);
14197 }]);
14198 })();
14199
14200 (function () {
14201 angular.module('ui.grid').config(['$provide', function($provide) {
14202 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14203 $delegate.add('ro', {
14204 headerCell: {
14205 aria: {
14206 defaultFilterLabel: 'Filtru pentru coloana',
14207 removeFilter: 'Sterge filtru',
14208 columnMenuButtonLabel: 'Column Menu'
14209 },
14210 priority: 'Prioritate:',
14211 filterLabel: "Filtru pentru coloana:"
14212 },
14213 aggregate: {
14214 label: 'Elemente'
14215 },
14216 groupPanel: {
14217 description: 'Trage un cap de coloana aici pentru a grupa elementele dupa coloana respectiva'
14218 },
14219 search: {
14220 placeholder: 'Cauta...',
14221 showingItems: 'Arata elementele:',
14222 selectedItems: 'Elementele selectate:',
14223 totalItems: 'Total elemente:',
14224 size: 'Marime pagina:',
14225 first: 'Prima pagina',
14226 next: 'Pagina urmatoare',
14227 previous: 'Pagina anterioara',
14228 last: 'Ultima pagina'
14229 },
14230 menu: {
14231 text: 'Alege coloane:'
14232 },
14233 sort: {
14234 ascending: 'Ordoneaza crescator',
14235 descending: 'Ordoneaza descrescator',
14236 none: 'Fara ordonare',
14237 remove: 'Sterge ordonarea'
14238 },
14239 column: {
14240 hide: 'Ascunde coloana'
14241 },
14242 aggregation: {
14243 count: 'total linii: ',
14244 sum: 'total: ',
14245 avg: 'medie: ',
14246 min: 'min: ',
14247 max: 'max: '
14248 },
14249 pinning: {
14250 pinLeft: 'Pin la stanga',
14251 pinRight: 'Pin la dreapta',
14252 unpin: 'Sterge pinul'
14253 },
14254 columnMenu: {
14255 close: 'Inchide'
14256 },
14257 gridMenu: {
14258 aria: {
14259 buttonLabel: 'Grid Menu'
14260 },
14261 columns: 'Coloane:',
14262 importerTitle: 'Incarca fisier',
14263 exporterAllAsCsv: 'Exporta toate datele ca csv',
14264 exporterVisibleAsCsv: 'Exporta datele vizibile ca csv',
14265 exporterSelectedAsCsv: 'Exporta datele selectate ca csv',
14266 exporterAllAsPdf: 'Exporta toate datele ca pdf',
14267 exporterVisibleAsPdf: 'Exporta datele vizibile ca pdf',
14268 exporterSelectedAsPdf: 'Exporta datele selectate ca csv pdf',
14269 clearAllFilters: 'Sterge toate filtrele'
14270 },
14271 importer: {
14272 noHeaders: 'Numele coloanelor nu a putut fi incarcat, acest fisier are un header?',
14273 noObjects: 'Datele nu au putut fi incarcate, exista date in fisier in afara numelor de coloane?',
14274 invalidCsv: 'Fisierul nu a putut fi procesat, ati incarcat un CSV valid ?',
14275 invalidJson: 'Fisierul nu a putut fi procesat, ati incarcat un Json valid?',
14276 jsonNotArray: 'Json-ul incarcat trebuie sa contina un array, inchidere.'
14277 },
14278 pagination: {
14279 aria: {
14280 pageToFirst: 'Prima pagina',
14281 pageBack: 'O pagina inapoi',
14282 pageSelected: 'Pagina selectata',
14283 pageForward: 'O pagina inainte',
14284 pageToLast: 'Ultima pagina'
14285 },
14286 sizes: 'Elemente per pagina',
14287 totalItems: 'elemente',
14288 through: 'prin',
14289 of: 'of'
14290 },
14291 grouping: {
14292 group: 'Grupeaza',
14293 ungroup: 'Opreste gruparea',
14294 aggregate_count: 'Agg: Count',
14295 aggregate_sum: 'Agg: Sum',
14296 aggregate_max: 'Agg: Max',
14297 aggregate_min: 'Agg: Min',
14298 aggregate_avg: 'Agg: Avg',
14299 aggregate_remove: 'Agg: Remove'
14300 }
14301 });
14302 return $delegate;
14303 }]);
14304 }]);
14305 })();
14306
14307 (function() {
14308 angular.module('ui.grid').config(['$provide', function($provide) {
14309 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14310 $delegate.add('rs-lat', {
14311 headerCell: {
14312 aria: {
14313 defaultFilterLabel: 'Filter za kolonu',
14314 removeFilter: 'Ukloni Filter',
14315 columnMenuButtonLabel: 'Meni Kolone',
14316 column: 'Kolona'
14317 },
14318 priority: 'Prioritet:',
14319 filterLabel: "Filter za kolonu: "
14320 },
14321 aggregate: {
14322 label: 'stavke'
14323 },
14324 groupPanel: {
14325 description: 'Ovde prevuci zaglavlje kolone i spusti do grupe pored te kolone.'
14326 },
14327 search: {
14328 aria: {
14329 selected: 'Red odabran',
14330 notSelected: 'Red nije odabran'
14331 },
14332 placeholder: 'Pretraga...',
14333 showingItems: 'Prikazane Stavke:',
14334 selectedItems: 'Odabrane Stavke:',
14335 totalItems: 'Ukupno Stavki:',
14336 size: 'Veličina Stranice:',
14337 first: 'Prva Stranica',
14338 next: 'Sledeća Stranica',
14339 previous: 'Prethodna Stranica',
14340 last: 'Poslednja Stranica'
14341 },
14342 menu: {
14343 text: 'Odaberite kolonu:'
14344 },
14345 sort: {
14346 ascending: 'Sortiraj po rastućem redosledu',
14347 descending: 'Sortiraj po opadajućem redosledu',
14348 none: 'Bez Sortiranja',
14349 remove: 'Ukloni Sortiranje'
14350 },
14351 column: {
14352 hide: 'Sakrij Kolonu'
14353 },
14354 aggregation: {
14355 count: 'ukupno redova: ',
14356 sum: 'ukupno: ',
14357 avg: 'prosecno: ',
14358 min: 'minimum: ',
14359 max: 'maksimum: '
14360 },
14361 pinning: {
14362 pinLeft: 'Zakači Levo',
14363 pinRight: 'Zakači Desno',
14364 unpin: 'Otkači'
14365 },
14366 columnMenu: {
14367 close: 'Zatvori'
14368 },
14369 gridMenu: {
14370 aria: {
14371 buttonLabel: 'Rešetkasti Meni'
14372 },
14373 columns: 'Kolone:',
14374 importerTitle: 'Importuj fajl',
14375 exporterAllAsCsv: 'Eksportuj sve podatke kao csv',
14376 exporterVisibleAsCsv: 'Eksportuj vidljive podatke kao csv',
14377 exporterSelectedAsCsv: 'Eksportuj obeležene podatke kao csv',
14378 exporterAllAsPdf: 'Eksportuj sve podatke kao pdf',
14379 exporterVisibleAsPdf: 'Eksportuj vidljive podake kao pdf',
14380 exporterSelectedAsPdf: 'Eksportuj odabrane podatke kao pdf',
14381 exporterAllAsExcel: 'Eksportuj sve podatke kao excel',
14382 exporterVisibleAsExcel: 'Eksportuj vidljive podatke kao excel',
14383 exporterSelectedAsExcel: 'Eksportuj odabrane podatke kao excel',
14384 clearAllFilters: 'Obriši sve filtere'
14385 },
14386 importer: {
14387 noHeaders: 'Kolone se nisu mogle podeliti, da li fajl poseduje heder?',
14388 noObjects: 'Objecti nisu mogli biti podeljeni, da li je bilo i drugih podataka sem hedera?',
14389 invalidCsv: 'Fajl nije bilo moguće procesirati, da li je ispravni CSV?',
14390 invalidJson: 'Fajl nije bilo moguće procesirati, da li je ispravni JSON',
14391 jsonNotArray: 'Importovani json fajl mora da sadrži niz, prekidam operaciju.'
14392 },
14393 pagination: {
14394 aria: {
14395 pageToFirst: 'Prva stranica',
14396 pageBack: 'Stranica pre',
14397 pageSelected: 'Odabrana stranica',
14398 pageForward: 'Sledeća stranica',
14399 pageToLast: 'Poslednja stranica'
14400 },
14401 sizes: 'stavki po stranici',
14402 totalItems: 'stavke',
14403 through: 'kroz',
14404 of: 'od'
14405 },
14406 grouping: {
14407 group: 'Grupiši',
14408 ungroup: 'Odrupiši',
14409 aggregate_count: 'Agg: Broj',
14410 aggregate_sum: 'Agg: Suma',
14411 aggregate_max: 'Agg: Maksimum',
14412 aggregate_min: 'Agg: Minimum',
14413 aggregate_avg: 'Agg: Prosečna',
14414 aggregate_remove: 'Agg: Ukloni'
14415 },
14416 validate: {
14417 error: 'Greška:',
14418 minLength: 'Vrednost bi trebala da bude duga bar THRESHOLD karaktera.',
14419 maxLength: 'Vrednost bi trebalo da bude najviše duga THRESHOLD karaktera.',
14420 required: 'Portreba je vrednost.'
14421 }
14422 });
14423 return $delegate;
14424 }]);
14425 }]);
14426 })();
14427
14428 (function () {
14429 angular.module('ui.grid').config(['$provide', function($provide) {
14430 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14431 $delegate.add('ru', {
14432 headerCell: {
14433 aria: {
14434 defaultFilterLabel: 'Фильтр столбца',
14435 removeFilter: 'Удалить фильтр',
14436 columnMenuButtonLabel: 'Меню столбца'
14437 },
14438 priority: 'Приоритет:',
14439 filterLabel: "Фильтр столбца: "
14440 },
14441 aggregate: {
14442 label: 'элементы'
14443 },
14444 groupPanel: {
14445 description: 'Для группировки по столбцу перетащите сюда его название.'
14446 },
14447 search: {
14448 placeholder: 'Поиск...',
14449 showingItems: 'Показать элементы:',
14450 selectedItems: 'Выбранные элементы:',
14451 totalItems: 'Всего элементов:',
14452 size: 'Размер страницы:',
14453 first: 'Первая страница',
14454 next: 'Следующая страница',
14455 previous: 'Предыдущая страница',
14456 last: 'Последняя страница'
14457 },
14458 menu: {
14459 text: 'Выбрать столбцы:'
14460 },
14461 sort: {
14462 ascending: 'По возрастанию',
14463 descending: 'По убыванию',
14464 none: 'Без сортировки',
14465 remove: 'Убрать сортировку'
14466 },
14467 column: {
14468 hide: 'Спрятать столбец'
14469 },
14470 aggregation: {
14471 count: 'всего строк: ',
14472 sum: 'итого: ',
14473 avg: 'среднее: ',
14474 min: 'мин: ',
14475 max: 'макс: '
14476 },
14477 pinning: {
14478 pinLeft: 'Закрепить слева',
14479 pinRight: 'Закрепить справа',
14480 unpin: 'Открепить'
14481 },
14482 columnMenu: {
14483 close: 'Закрыть'
14484 },
14485 gridMenu: {
14486 aria: {
14487 buttonLabel: 'Меню'
14488 },
14489 columns: 'Столбцы:',
14490 importerTitle: 'Импортировать файл',
14491 exporterAllAsCsv: 'Экспортировать всё в CSV',
14492 exporterVisibleAsCsv: 'Экспортировать видимые данные в CSV',
14493 exporterSelectedAsCsv: 'Экспортировать выбранные данные в CSV',
14494 exporterAllAsPdf: 'Экспортировать всё в PDF',
14495 exporterVisibleAsPdf: 'Экспортировать видимые данные в PDF',
14496 exporterSelectedAsPdf: 'Экспортировать выбранные данные в PDF',
14497 clearAllFilters: 'Очистите все фильтры'
14498 },
14499 importer: {
14500 noHeaders: 'Не удалось получить названия столбцов, есть ли в файле заголовок?',
14501 noObjects: 'Не удалось получить данные, есть ли в файле строки кроме заголовка?',
14502 invalidCsv: 'Не удалось обработать файл, это правильный CSV-файл?',
14503 invalidJson: 'Не удалось обработать файл, это правильный JSON?',
14504 jsonNotArray: 'Импортируемый JSON-файл должен содержать массив, операция отменена.'
14505 },
14506 pagination: {
14507 aria: {
14508 pageToFirst: 'Первая страница',
14509 pageBack: 'Предыдущая страница',
14510 pageSelected: 'Выбранная страница',
14511 pageForward: 'Следующая страница',
14512 pageToLast: 'Последняя страница'
14513 },
14514 sizes: 'строк на страницу',
14515 totalItems: 'строк',
14516 through: 'по',
14517 of: 'из'
14518 },
14519 grouping: {
14520 group: 'Группировать',
14521 ungroup: 'Разгруппировать',
14522 aggregate_count: 'Группировать: Count',
14523 aggregate_sum: 'Для группы: Сумма',
14524 aggregate_max: 'Для группы: Максимум',
14525 aggregate_min: 'Для группы: Минимум',
14526 aggregate_avg: 'Для группы: Среднее',
14527 aggregate_remove: 'Для группы: Пусто'
14528 }
14529 });
14530 return $delegate;
14531 }]);
14532 }]);
14533 })();
14534
14535 (function() {
14536 angular.module('ui.grid').config(['$provide', function($provide) {
14537 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14538 $delegate.add('sk', {
14539 headerCell: {
14540 aria: {
14541 defaultFilterLabel: 'Filter pre stĺpec',
14542 removeFilter: 'Odstrániť filter',
14543 columnMenuButtonLabel: 'Menu pre stĺpec',
14544 column: 'Stĺpec'
14545 },
14546 priority: 'Priorita:',
14547 filterLabel: "Filter pre stĺpec: "
14548 },
14549 aggregate: {
14550 label: 'položky'
14551 },
14552 groupPanel: {
14553 description: 'Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca.'
14554 },
14555 search: {
14556 aria: {
14557 selected: 'Označený riadok',
14558 notSelected: 'Neoznačený riadok'
14559 },
14560 placeholder: 'Hľadaj...',
14561 showingItems: 'Zobrazujem položky:',
14562 selectedItems: 'Vybraté položky:',
14563 totalItems: 'Počet položiek:',
14564 size: 'Počet:',
14565 first: 'Prvá strana',
14566 next: 'Ďalšia strana',
14567 previous: 'Predchádzajúca strana',
14568 last: 'Posledná strana'
14569 },
14570 menu: {
14571 text: 'Vyberte stĺpce:'
14572 },
14573 sort: {
14574 ascending: 'Zotriediť vzostupne',
14575 descending: 'Zotriediť zostupne',
14576 none: 'Nezotriediť',
14577 remove: 'Vymazať triedenie'
14578 },
14579 column: {
14580 hide: 'Skryť stĺpec'
14581 },
14582 aggregation: {
14583 count: 'počet riadkov: ',
14584 sum: 'spolu: ',
14585 avg: 'avg: ',
14586 min: 'min: ',
14587 max: 'max: '
14588 },
14589 pinning: {
14590 pinLeft: 'Pripnúť vľavo',
14591 pinRight: 'Pripnúť vpravo',
14592 unpin: 'Odopnúť'
14593 },
14594 columnMenu: {
14595 close: 'Zavrieť'
14596 },
14597 gridMenu: {
14598 aria: {
14599 buttonLabel: 'Grid Menu'
14600 },
14601 columns: 'Stĺpce:',
14602 importerTitle: 'Importovať súbor',
14603 exporterAllAsCsv: 'Exportovať všetky údaje ako CSV',
14604 exporterVisibleAsCsv: 'Exportovť viditeľné údaje ako CSV',
14605 exporterSelectedAsCsv: 'Exportovať označené údaje ako CSV',
14606 exporterAllAsPdf: 'Exportovať všetky údaje ako pdf',
14607 exporterVisibleAsPdf: 'Exportovať viditeľné údaje ako pdf',
14608 exporterSelectedAsPdf: 'Exportovať označené údaje ako pdf',
14609 exporterAllAsExcel: 'Exportovať všetky údaje ako excel',
14610 exporterVisibleAsExcel: 'Exportovať viditeľné údaje ako excel',
14611 exporterSelectedAsExcel: 'Exportovať označené údaje ako excel',
14612 clearAllFilters: 'Zrušiť všetky filtre'
14613 },
14614 importer: {
14615 noHeaders: 'Názvy stĺpcov sa nedali odvodiť, má súbor hlavičku?',
14616 noObjects: 'Objekty nebolo možné odvodiť, existovali iné údaje v súbore ako hlavičky?',
14617 invalidCsv: 'Súbor sa nepodarilo spracovať, je to platný súbor CSV?',
14618 invalidJson: 'Súbor nebolo možné spracovať, je to platný súbor typu Json?',
14619 jsonNotArray: 'Importovaný súbor json musí obsahovať pole, ukončujem.'
14620 },
14621 pagination: {
14622 aria: {
14623 pageToFirst: 'Strana na začiatok',
14624 pageBack: 'Strana dozadu',
14625 pageSelected: 'Označená strana',
14626 pageForward: 'Strana dopredu',
14627 pageToLast: 'Strana na koniec'
14628 },
14629 sizes: 'položky na stranu',
14630 totalItems: 'položky spolu',
14631 through: 'do konca',
14632 of: 'z'
14633 },
14634 grouping: {
14635 group: 'Zoskupiť',
14636 ungroup: 'Zrušiť zoskupenie',
14637 aggregate_count: 'Agg: Počet',
14638
14639 aggregate_sum: 'Agg: Suma',
14640 aggregate_max: 'Agg: Max',
14641 aggregate_min: 'Agg: Min',
14642 aggregate_avg: 'Agg: Avg',
14643 aggregate_remove: 'Agg: Zrušiť'
14644 },
14645 validate: {
14646 error: 'Chyba:',
14647 minLength: 'Hodnota by mala mať aspoň THRESHOLD znakov dlhá.',
14648 maxLength: 'Hodnota by mala byť maximálne THRESHOLD znakov dlhá.',
14649 required: 'Vyžaduje sa hodnota.'
14650 }
14651 });
14652 return $delegate;
14653 }]);
14654 }]);
14655 })();
14656
14657 (function () {
14658 angular.module('ui.grid').config(['$provide', function($provide) {
14659 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14660 $delegate.add('sv', {
14661 aggregate: {
14662 label: 'Artiklar'
14663 },
14664 groupPanel: {
14665 description: 'Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen.'
14666 },
14667 search: {
14668 placeholder: 'Sök...',
14669 showingItems: 'Visar artiklar:',
14670 selectedItems: 'Valda artiklar:',
14671 totalItems: 'Antal artiklar:',
14672 size: 'Sidstorlek:',
14673 first: 'Första sidan',
14674 next: 'Nästa sida',
14675 previous: 'Föregående sida',
14676 last: 'Sista sidan'
14677 },
14678 menu: {
14679 text: 'Välj kolumner:'
14680 },
14681 sort: {
14682 ascending: 'Sortera stigande',
14683 descending: 'Sortera fallande',
14684 remove: 'Inaktivera sortering'
14685 },
14686 column: {
14687 hide: 'Göm kolumn'
14688 },
14689 aggregation: {
14690 count: 'Antal rader: ',
14691 sum: 'Summa: ',
14692 avg: 'Genomsnitt: ',
14693 min: 'Min: ',
14694 max: 'Max: '
14695 },
14696 pinning: {
14697 pinLeft: 'Fäst vänster',
14698 pinRight: 'Fäst höger',
14699 unpin: 'Lösgör'
14700 },
14701 gridMenu: {
14702 columns: 'Kolumner:',
14703 importerTitle: 'Importera fil',
14704 exporterAllAsCsv: 'Exportera all data som CSV',
14705 exporterVisibleAsCsv: 'Exportera synlig data som CSV',
14706 exporterSelectedAsCsv: 'Exportera markerad data som CSV',
14707 exporterAllAsPdf: 'Exportera all data som PDF',
14708 exporterVisibleAsPdf: 'Exportera synlig data som PDF',
14709 exporterSelectedAsPdf: 'Exportera markerad data som PDF',
14710 clearAllFilters: 'Rengör alla filter'
14711 },
14712 importer: {
14713 noHeaders: 'Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?',
14714 noObjects: 'Objekt kunde inte härledas. Har filen data undantaget sidhuvud?',
14715 invalidCsv: 'Filen kunde inte behandlas, är den en giltig CSV?',
14716 invalidJson: 'Filen kunde inte behandlas, är den en giltig JSON?',
14717 jsonNotArray: 'Importerad JSON-fil måste innehålla ett fält. Import avbruten.'
14718 },
14719 pagination: {
14720 sizes: 'Artiklar per sida',
14721 totalItems: 'Artiklar'
14722 }
14723 });
14724 return $delegate;
14725 }]);
14726 }]);
14727 })();
14728
14729 (function () {
14730 angular.module('ui.grid').config(['$provide', function($provide) {
14731 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14732 $delegate.add('ta', {
14733 aggregate: {
14734 label: 'உருப்படிகள்'
14735 },
14736 groupPanel: {
14737 description: 'ஒரு பத்தியை குழுவாக அமைக்க அப்பத்தியின் தலைப்பை இங்கே இழுத்து வரவும் '
14738 },
14739 search: {
14740 placeholder: 'தேடல் ...',
14741 showingItems: 'உருப்படிகளை காண்பித்தல்:',
14742 selectedItems: 'தேர்ந்தெடுக்கப்பட்ட உருப்படிகள்:',
14743 totalItems: 'மொத்த உருப்படிகள்:',
14744 size: 'பக்க அளவு: ',
14745 first: 'முதல் பக்கம்',
14746 next: 'அடுத்த பக்கம்',
14747 previous: 'முந்தைய பக்கம் ',
14748 last: 'இறுதி பக்கம்'
14749 },
14750 menu: {
14751 text: 'பத்திகளை தேர்ந்தெடு:'
14752 },
14753 sort: {
14754 ascending: 'மேலிருந்து கீழாக',
14755 descending: 'கீழிருந்து மேலாக',
14756 remove: 'வரிசையை நீக்கு'
14757 },
14758 column: {
14759 hide: 'பத்தியை மறைத்து வை '
14760 },
14761 aggregation: {
14762 count: 'மொத்த வரிகள்:',
14763 sum: 'மொத்தம்: ',
14764 avg: 'சராசரி: ',
14765 min: 'குறைந்தபட்ச: ',
14766 max: 'அதிகபட்ச: '
14767 },
14768 pinning: {
14769 pinLeft: 'இடதுபுறமாக தைக்க ',
14770 pinRight: 'வலதுபுறமாக தைக்க',
14771 unpin: 'பிரி'
14772 },
14773 gridMenu: {
14774 columns: 'பத்திகள்:',
14775 importerTitle: 'கோப்பு : படித்தல்',
14776 exporterAllAsCsv: 'எல்லா தரவுகளையும் கோப்பாக்கு: csv',
14777 exporterVisibleAsCsv: 'இருக்கும் தரவுகளை கோப்பாக்கு: csv',
14778 exporterSelectedAsCsv: 'தேர்ந்தெடுத்த தரவுகளை கோப்பாக்கு: csv',
14779 exporterAllAsPdf: 'எல்லா தரவுகளையும் கோப்பாக்கு: pdf',
14780 exporterVisibleAsPdf: 'இருக்கும் தரவுகளை கோப்பாக்கு: pdf',
14781 exporterSelectedAsPdf: 'தேர்ந்தெடுத்த தரவுகளை கோப்பாக்கு: pdf',
14782 clearAllFilters: 'Clear all filters'
14783 },
14784 importer: {
14785 noHeaders: 'பத்தியின் தலைப்புகளை பெற இயலவில்லை, கோப்பிற்கு தலைப்பு உள்ளதா?',
14786 noObjects: 'இலக்குகளை உருவாக்க முடியவில்லை, கோப்பில் தலைப்புகளை தவிர தரவு ஏதேனும் உள்ளதா? ',
14787 invalidCsv: 'சரிவர நடைமுறை படுத்த இயலவில்லை, கோப்பு சரிதானா? - csv',
14788 invalidJson: 'சரிவர நடைமுறை படுத்த இயலவில்லை, கோப்பு சரிதானா? - json',
14789 jsonNotArray: 'படித்த கோப்பில் வரிசைகள் உள்ளது, நடைமுறை ரத்து செய் : json'
14790 },
14791 pagination: {
14792 sizes : 'உருப்படிகள் / பக்கம்',
14793 totalItems : 'உருப்படிகள் '
14794 },
14795 grouping: {
14796 group : 'குழு',
14797 ungroup : 'பிரி',
14798 aggregate_count : 'மதிப்பீட்டு : எண்ணு',
14799 aggregate_sum : 'மதிப்பீட்டு : கூட்டல்',
14800 aggregate_max : 'மதிப்பீட்டு : அதிகபட்சம்',
14801 aggregate_min : 'மதிப்பீட்டு : குறைந்தபட்சம்',
14802 aggregate_avg : 'மதிப்பீட்டு : சராசரி',
14803 aggregate_remove : 'மதிப்பீட்டு : நீக்கு'
14804 }
14805 });
14806 return $delegate;
14807 }]);
14808 }]);
14809 })();
14810
14811 (function() {
14812 angular.module('ui.grid').config(['$provide', function($provide) {
14813 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14814 $delegate.add('tr', {
14815 headerCell: {
14816 aria: {
14817 defaultFilterLabel: 'Sütun için filtre',
14818 removeFilter: 'Filtreyi Kaldır',
14819 columnMenuButtonLabel: 'Sütun Menüsü'
14820 },
14821 priority: 'Öncelik:',
14822 filterLabel: "Sütun için filtre: "
14823 },
14824 aggregate: {
14825 label: 'kayıtlar'
14826 },
14827 groupPanel: {
14828 description: 'Sütuna göre gruplamak için sütun başlığını buraya sürükleyin ve bırakın.'
14829 },
14830 search: {
14831 placeholder: 'Arama...',
14832 showingItems: 'Gösterilen Kayıt:',
14833 selectedItems: 'Seçili Kayıt:',
14834 totalItems: 'Toplam Kayıt:',
14835 size: 'Sayfa Boyutu:',
14836 first: 'İlk Sayfa',
14837 next: 'Sonraki Sayfa',
14838 previous: 'Önceki Sayfa',
14839 last: 'Son Sayfa'
14840 },
14841 menu: {
14842 text: 'Sütunları Seç:'
14843 },
14844 sort: {
14845 ascending: 'Artan Sırada Sırala',
14846 descending: 'Azalan Sırada Sırala',
14847 none: 'Sıralama Yapma',
14848 remove: 'Sıralamayı Kaldır'
14849 },
14850 column: {
14851 hide: 'Sütunu Gizle'
14852 },
14853 aggregation: {
14854 count: 'toplam satır: ',
14855 sum: 'toplam: ',
14856 avg: 'ort: ',
14857 min: 'min: ',
14858 max: 'maks: '
14859 },
14860 pinning: {
14861 pinLeft: 'Sola Sabitle',
14862 pinRight: 'Sağa Sabitle',
14863 unpin: 'Sabitlemeyi Kaldır'
14864 },
14865 columnMenu: {
14866 close: 'Kapat'
14867 },
14868 gridMenu: {
14869 aria: {
14870 buttonLabel: 'Tablo Menü'
14871 },
14872 columns: 'Sütunlar:',
14873 importerTitle: 'Dosya içeri aktar',
14874 exporterAllAsCsv: 'Bütün veriyi CSV olarak dışarı aktar',
14875 exporterVisibleAsCsv: 'Görünen veriyi CSV olarak dışarı aktar',
14876 exporterSelectedAsCsv: 'Seçili veriyi CSV olarak dışarı aktar',
14877 exporterAllAsPdf: 'Bütün veriyi PDF olarak dışarı aktar',
14878 exporterVisibleAsPdf: 'Görünen veriyi PDF olarak dışarı aktar',
14879 exporterSelectedAsPdf: 'Seçili veriyi PDF olarak dışarı aktar',
14880 clearAllFilters: 'Bütün filtreleri kaldır'
14881 },
14882 importer: {
14883 noHeaders: 'Sütun isimleri üretilemiyor, dosyanın bir başlığı var mı?',
14884 noObjects: 'Nesneler üretilemiyor, dosyada başlıktan başka bir veri var mı?',
14885 invalidCsv: 'Dosya işlenemedi, geçerli bir CSV dosyası mı?',
14886 invalidJson: 'Dosya işlenemedi, geçerli bir Json dosyası mı?',
14887 jsonNotArray: 'Alınan Json dosyasında bir dizi bulunmalıdır, işlem iptal ediliyor.'
14888 },
14889 pagination: {
14890 aria: {
14891 pageToFirst: 'İlk sayfaya',
14892 pageBack: 'Geri git',
14893 pageSelected: 'Seçili sayfa',
14894 pageForward: 'İleri git',
14895 pageToLast: 'Sona git'
14896 },
14897 sizes: 'Sayfadaki nesne sayısı',
14898 totalItems: 'kayıtlar',
14899 through: '', // note(fsw) : turkish dont have this preposition
14900 of: '' // note(fsw) : turkish dont have this preposition
14901 },
14902 grouping: {
14903 group: 'Grupla',
14904 ungroup: 'Gruplama',
14905 aggregate_count: 'Yekun: Sayı',
14906 aggregate_sum: 'Yekun: Toplam',
14907 aggregate_max: 'Yekun: Maks',
14908 aggregate_min: 'Yekun: Min',
14909 aggregate_avg: 'Yekun: Ort',
14910 aggregate_remove: 'Yekun: Sil'
14911 }
14912 });
14913 return $delegate;
14914 }]);
14915 }]);
14916 })();
14917
14918 (function () {
14919 angular.module('ui.grid').config(['$provide', function($provide) {
14920 $provide.decorator('i18nService', ['$delegate', function($delegate) {
14921 $delegate.add('ua', {
14922 headerCell: {
14923 aria: {
14924 defaultFilterLabel: 'Фільтр стовпчика',
14925 removeFilter: 'Видалити фільтр',
14926 columnMenuButtonLabel: 'Меню ствпчика'
14927 },
14928 priority: 'Пріоритет:',
14929 filterLabel: "Фільтр стовпчика: "
14930 },
14931 aggregate: {
14932 label: 'елементи'
14933 },
14934 groupPanel: {
14935 description: 'Для групування за стовпчиком перетягніть сюди його назву.'
14936 },
14937 search: {
14938 placeholder: 'Пошук...',
14939 showingItems: 'Показати елементи:',
14940 selectedItems: 'Обрані елементи:',
14941 totalItems: 'Усього елементів:',
14942 size: 'Розмір сторінки:',
14943 first: 'Перша сторінка',
14944 next: 'Наступна сторінка',
14945 previous: 'Попередня сторінка',
14946 last: 'Остання сторінка'
14947 },
14948 menu: {
14949 text: 'Обрати ствпчики:'
14950 },
14951 sort: {
14952 ascending: 'За зростанням',
14953 descending: 'За спаданням',
14954 none: 'Без сортування',
14955 remove: 'Прибрати сортування'
14956 },
14957 column: {
14958 hide: 'Приховати стовпчик'
14959 },
14960 aggregation: {
14961 count: 'усього рядків: ',
14962 sum: 'ітого: ',
14963 avg: 'середнє: ',
14964 min: 'мін: ',
14965 max: 'макс: '
14966 },
14967 pinning: {
14968 pinLeft: 'Закріпити ліворуч',
14969 pinRight: 'Закріпити праворуч',
14970 unpin: 'Відкріпити'
14971 },
14972 columnMenu: {
14973 close: 'Закрити'
14974 },
14975 gridMenu: {
14976 aria: {
14977 buttonLabel: 'Меню'
14978 },
14979 columns: 'Стовпчики:',
14980 importerTitle: 'Імпортувати файл',
14981 exporterAllAsCsv: 'Експортувати все в CSV',
14982 exporterVisibleAsCsv: 'Експортувати видимі дані в CSV',
14983 exporterSelectedAsCsv: 'Експортувати обрані дані в CSV',
14984 exporterAllAsPdf: 'Експортувати все в PDF',
14985 exporterVisibleAsPdf: 'Експортувати видимі дані в PDF',
14986 exporterSelectedAsPdf: 'Експортувати обрані дані в PDF',
14987 clearAllFilters: 'Очистити всі фільтри'
14988 },
14989 importer: {
14990 noHeaders: 'Не вдалося отримати назви стовпчиків, чи є в файлі заголовок?',
14991 noObjects: 'Не вдалося отримати дані, чи є в файлі рядки окрім заголовка?',
14992 invalidCsv: 'Не вдалося обробити файл, чи це коректний CSV-файл?',
14993 invalidJson: 'Не вдалося обробити файл, чи це коректний JSON?',
14994 jsonNotArray: 'JSON-файл що імпортується повинен містити масив, операцію скасовано.'
14995 },
14996 pagination: {
14997 aria: {
14998 pageToFirst: 'Перша сторінка',
14999 pageBack: 'Попередня сторінка',
15000 pageSelected: 'Обрана сторінка',
15001 pageForward: 'Наступна сторінка',
15002 pageToLast: 'Остання сторінка'
15003 },
15004 sizes: 'рядків на сторінку',
15005 totalItems: 'рядків',
15006 through: 'по',
15007 of: 'з'
15008 },
15009 grouping: {
15010 group: 'Групувати',
15011 ungroup: 'Розгрупувати',
15012 aggregate_count: 'Групувати: Кількість',
15013 aggregate_sum: 'Для групи: Сума',
15014 aggregate_max: 'Для групи: Максимум',
15015 aggregate_min: 'Для групи: Мінімум',
15016 aggregate_avg: 'Для групи: Серднє',
15017 aggregate_remove: 'Для групи: Пусто'
15018 }
15019 });
15020 return $delegate;
15021 }]);
15022 }]);
15023 })();
15024
15025 /**
15026 * @ngdoc overview
15027 * @name ui.grid.i18n
15028 * @description
15029 *
15030 * # ui.grid.i18n
15031 * This module provides i18n functions to ui.grid and any application that wants to use it
15032
15033 *
15034 * <div doc-module-components="ui.grid.i18n"></div>
15035 */
15036
15037 (function () {
15038 var DIRECTIVE_ALIASES = ['uiT', 'uiTranslate'];
15039 var FILTER_ALIASES = ['t', 'uiTranslate'];
15040
15041 var module = angular.module('ui.grid.i18n');
15042
15043
15044 /**
15045 * @ngdoc object
15046 * @name ui.grid.i18n.constant:i18nConstants
15047 *
15048 * @description constants available in i18n module
15049 */
15050 module.constant('i18nConstants', {
15051 MISSING: '[MISSING]',
15052 UPDATE_EVENT: '$uiI18n',
15053
15054 LOCALE_DIRECTIVE_ALIAS: 'uiI18n',
15055 // default to english
15056 DEFAULT_LANG: 'en'
15057 });
15058
15059 // module.config(['$provide', function($provide) {
15060 // $provide.decorator('i18nService', ['$delegate', function($delegate) {}])}]);
15061
15062 /**
15063 * @ngdoc service
15064 * @name ui.grid.i18n.service:i18nService
15065 *
15066 * @description Services for i18n
15067 */
15068 module.service('i18nService', ['$log', '$parse', 'i18nConstants', '$rootScope',
15069 function ($log, $parse, i18nConstants, $rootScope) {
15070
15071 var langCache = {
15072 _langs: {},
15073 current: null,
15074 fallback: i18nConstants.DEFAULT_LANG,
15075 get: function (lang) {
15076 var self = this,
15077 fallbackLang = self.getFallbackLang();
15078
15079 if (lang !== self.fallback) {
15080 return angular.extend({}, self._langs[fallbackLang],
15081 self._langs[lang.toLowerCase()]);
15082 }
15083
15084 return self._langs[lang.toLowerCase()];
15085 },
15086 add: function (lang, strings) {
15087 var lower = lang.toLowerCase();
15088 if (!this._langs[lower]) {
15089 this._langs[lower] = {};
15090 }
15091 angular.merge(this._langs[lower], strings);
15092 },
15093 getAllLangs: function () {
15094 var langs = [];
15095 if (!this._langs) {
15096 return langs;
15097 }
15098
15099 for (var key in this._langs) {
15100 langs.push(key);
15101 }
15102
15103 return langs;
15104 },
15105 setCurrent: function (lang) {
15106 this.current = lang.toLowerCase();
15107 },
15108 setFallback: function (lang) {
15109 this.fallback = lang.toLowerCase();
15110 },
15111 getCurrentLang: function () {
15112 return this.current;
15113 },
15114 getFallbackLang: function () {
15115 return this.fallback.toLowerCase();
15116 }
15117 };
15118
15119 var service = {
15120
15121 /**
15122 * @ngdoc service
15123 * @name add
15124 * @methodOf ui.grid.i18n.service:i18nService
15125 * @description Adds the languages and strings to the cache. Decorate this service to
15126 * add more translation strings
15127 * @param {string} langs languages to add
15128 * @param {object} stringMaps of strings to add grouped by property names
15129 * @example
15130 * <pre>
15131 * i18nService.add('en', {
15132 * aggregate: {
15133 * label1: 'items',
15134 * label2: 'some more items'
15135 * }
15136 * },
15137 * groupPanel: {
15138 * description: 'Drag a column header here and drop it to group by that column.'
15139 * }
15140 * }
15141 * </pre>
15142 */
15143 add: function (langs, stringMaps) {
15144 if (typeof(langs) === 'object') {
15145 angular.forEach(langs, function (lang) {
15146 if (lang) {
15147 langCache.add(lang, stringMaps);
15148 }
15149 });
15150 } else {
15151 langCache.add(langs, stringMaps);
15152 }
15153 },
15154
15155 /**
15156 * @ngdoc service
15157 * @name getAllLangs
15158 * @methodOf ui.grid.i18n.service:i18nService
15159 * @description return all currently loaded languages
15160 * @returns {array} string
15161 */
15162 getAllLangs: function () {
15163 return langCache.getAllLangs();
15164 },
15165
15166 /**
15167 * @ngdoc service
15168 * @name get
15169 * @methodOf ui.grid.i18n.service:i18nService
15170 * @description return all currently loaded languages
15171 * @param {string} lang to return. If not specified, returns current language
15172 * @returns {object} the translation string maps for the language
15173 */
15174 get: function (lang) {
15175 var language = lang ? lang : service.getCurrentLang();
15176 return langCache.get(language);
15177 },
15178
15179 /**
15180 * @ngdoc service
15181 * @name getSafeText
15182 * @methodOf ui.grid.i18n.service:i18nService
15183 * @description returns the text specified in the path or a Missing text if text is not found
15184 * @param {String} path property path to use for retrieving text from string map
15185 * @param {String} [lang] to return. If not specified, returns current language
15186 * @returns {object} the translation for the path
15187 * @example
15188 * <pre>
15189 * i18nService.getSafeText('sort.ascending')
15190 * </pre>
15191 */
15192 getSafeText: function (path, lang) {
15193 var language = lang || service.getCurrentLang(),
15194 trans = langCache.get(language),
15195 missing = i18nConstants.MISSING + path,
15196 getter = $parse(path);
15197
15198 if (!trans) {
15199 return missing;
15200 }
15201
15202 return getter(trans) || missing;
15203 },
15204
15205 /**
15206 * @ngdoc service
15207 * @name setCurrentLang
15208 * @methodOf ui.grid.i18n.service:i18nService
15209 * @description sets the current language to use in the application
15210 * $broadcasts the i18nConstants.UPDATE_EVENT on the $rootScope
15211 * @param {string} lang to set
15212 * @example
15213 * <pre>
15214 * i18nService.setCurrentLang('fr');
15215 * </pre>
15216 */
15217 setCurrentLang: function (lang) {
15218 if (lang) {
15219 langCache.setCurrent(lang);
15220 $rootScope.$broadcast(i18nConstants.UPDATE_EVENT);
15221 }
15222 },
15223
15224 /**
15225 * @ngdoc service
15226 * @name setFallbackLang
15227 * @methodOf ui.grid.i18n.service:i18nService
15228 * @description sets the fallback language to use in the application.
15229 * The default fallback language is english.
15230 * @param {string} lang to set
15231 * @example
15232 * <pre>
15233 * i18nService.setFallbackLang('en');
15234 * </pre>
15235 */
15236 setFallbackLang: function (lang) {
15237 if (lang) {
15238 langCache.setFallback(lang);
15239 }
15240 },
15241
15242 /**
15243 * @ngdoc service
15244 * @name getCurrentLang
15245 * @methodOf ui.grid.i18n.service:i18nService
15246 * @description returns the current language used in the application
15247 */
15248 getCurrentLang: function () {
15249 var lang = langCache.getCurrentLang();
15250 if (!lang) {
15251 lang = i18nConstants.DEFAULT_LANG;
15252 langCache.setCurrent(lang);
15253 }
15254 return lang;
15255 },
15256
15257 /**
15258 * @ngdoc service
15259 * @name getFallbackLang
15260 * @methodOf ui.grid.i18n.service:i18nService
15261 * @description returns the fallback language used in the application
15262 */
15263 getFallbackLang: function () {
15264 return langCache.getFallbackLang();
15265 }
15266 };
15267
15268 return service;
15269 }]);
15270
15271 function localeDirective(i18nService, i18nConstants) {
15272 return {
15273 compile: function () {
15274 return {
15275 pre: function ($scope, $elm, $attrs) {
15276 var alias = i18nConstants.LOCALE_DIRECTIVE_ALIAS;
15277 // check for watchable property
15278 var lang = $scope.$eval($attrs[alias]);
15279 if (lang) {
15280 $scope.$watch($attrs[alias], function () {
15281 i18nService.setCurrentLang(lang);
15282 });
15283 } else if ($attrs.$$observers) {
15284 $attrs.$observe(alias, function () {
15285 i18nService.setCurrentLang($attrs[alias] || i18nConstants.DEFAULT_LANG);
15286 });
15287 }
15288 }
15289 };
15290 }
15291 };
15292 }
15293
15294 module.directive('uiI18n', ['i18nService', 'i18nConstants', localeDirective]);
15295
15296 // directive syntax
15297 function uitDirective(i18nService, i18nConstants) {
15298 return {
15299 restrict: 'EA',
15300 compile: function () {
15301 return {
15302 pre: function ($scope, $elm, $attrs) {
15303 var listener, observer, prop,
15304 alias1 = DIRECTIVE_ALIASES[0],
15305 alias2 = DIRECTIVE_ALIASES[1],
15306 token = $attrs[alias1] || $attrs[alias2] || $elm.html();
15307
15308 function translateToken(property) {
15309 var safeText = i18nService.getSafeText(property);
15310
15311 $elm.html(safeText);
15312 }
15313
15314 if ($attrs.$$observers) {
15315 prop = $attrs[alias1] ? alias1 : alias2;
15316 observer = $attrs.$observe(prop, function (result) {
15317 if (result) {
15318 translateToken(result);
15319 }
15320 });
15321 }
15322
15323 listener = $scope.$on(i18nConstants.UPDATE_EVENT, function() {
15324 if (observer) {
15325 observer($attrs[alias1] || $attrs[alias2]);
15326 } else {
15327 // set text based on i18n current language
15328 translateToken(token);
15329 }
15330 });
15331 $scope.$on('$destroy', listener);
15332
15333 translateToken(token);
15334 }
15335 };
15336 }
15337 };
15338 }
15339
15340 angular.forEach(DIRECTIVE_ALIASES, function ( alias ) {
15341 module.directive(alias, ['i18nService', 'i18nConstants', uitDirective]);
15342 });
15343
15344 // optional filter syntax
15345 function uitFilter(i18nService) {
15346 return function (data, lang) {
15347 // set text based on i18n current language
15348 return i18nService.getSafeText(data, lang);
15349 };
15350 }
15351
15352 angular.forEach(FILTER_ALIASES, function ( alias ) {
15353 module.filter(alias, ['i18nService', uitFilter]);
15354 });
15355 })();
15356
15357 (function() {
15358 angular.module('ui.grid').config(['$provide', function($provide) {
15359 $provide.decorator('i18nService', ['$delegate', function($delegate) {
15360 $delegate.add('zh-cn', {
15361 headerCell: {
15362 aria: {
15363 defaultFilterLabel: '列过滤器',
15364 removeFilter: '移除过滤器',
15365 columnMenuButtonLabel: '列菜单'
15366 },
15367 priority: '优先级:',
15368 filterLabel: "列过滤器: "
15369 },
15370 aggregate: {
15371 label: '行'
15372 },
15373 groupPanel: {
15374 description: '拖曳表头到此处进行分组'
15375 },
15376 search: {
15377 placeholder: '查找',
15378 showingItems: '已显示行数:',
15379 selectedItems: '已选择行数:',
15380 totalItems: '总行数:',
15381 size: '每页显示行数:',
15382 first: '首页',
15383 next: '下一页',
15384 previous: '上一页',
15385 last: '末页'
15386 },
15387 menu: {
15388 text: '选择列:'
15389 },
15390 sort: {
15391 ascending: '升序',
15392 descending: '降序',
15393 none: '无序',
15394 remove: '取消排序'
15395 },
15396 column: {
15397 hide: '隐藏列'
15398 },
15399 aggregation: {
15400 count: '计数:',
15401 sum: '求和:',
15402 avg: '均值:',
15403 min: '最小值:',
15404 max: '最大值:'
15405 },
15406 pinning: {
15407 pinLeft: '左侧固定',
15408 pinRight: '右侧固定',
15409 unpin: '取消固定'
15410 },
15411 columnMenu: {
15412 close: '关闭'
15413 },
15414 gridMenu: {
15415 aria: {
15416 buttonLabel: '表格菜单'
15417 },
15418 columns: '列:',
15419 importerTitle: '导入文件',
15420 exporterAllAsCsv: '导出全部数据到CSV',
15421 exporterVisibleAsCsv: '导出可见数据到CSV',
15422 exporterSelectedAsCsv: '导出已选数据到CSV',
15423 exporterAllAsPdf: '导出全部数据到PDF',
15424 exporterVisibleAsPdf: '导出可见数据到PDF',
15425 exporterSelectedAsPdf: '导出已选数据到PDF',
15426 clearAllFilters: '清除所有过滤器'
15427 },
15428 importer: {
15429 noHeaders: '无法获取列名,确定文件包含表头?',
15430 noObjects: '无法获取数据,确定文件包含数据?',
15431 invalidCsv: '无法处理文件,确定是合法的CSV文件?',
15432 invalidJson: '无法处理文件,确定是合法的JSON文件?',
15433 jsonNotArray: '导入的文件不是JSON数组!'
15434 },
15435 pagination: {
15436 aria: {
15437 pageToFirst: '第一页',
15438 pageBack: '上一页',
15439 pageSelected: '当前页',
15440 pageForward: '下一页',
15441 pageToLast: '最后一页'
15442 },
15443 sizes: '行每页',
15444 totalItems: '行',
15445 through: '至',
15446 of: '共'
15447 },
15448 grouping: {
15449 group: '分组',
15450 ungroup: '取消分组',
15451 aggregate_count: '合计: 计数',
15452 aggregate_sum: '合计: 求和',
15453 aggregate_max: '合计: 最大',
15454 aggregate_min: '合计: 最小',
15455 aggregate_avg: '合计: 平均',
15456 aggregate_remove: '合计: 移除'
15457 }
15458 });
15459 return $delegate;
15460 }]);
15461 }]);
15462 })();
15463
15464 (function() {
15465 angular.module('ui.grid').config(['$provide', function($provide) {
15466 $provide.decorator('i18nService', ['$delegate', function($delegate) {
15467 $delegate.add('zh-tw', {
15468 aggregate: {
15469 label: '行'
15470 },
15471 groupPanel: {
15472 description: '拖曳表頭到此處進行分組'
15473 },
15474 search: {
15475 placeholder: '查找',
15476 showingItems: '已顯示行數:',
15477 selectedItems: '已選擇行數:',
15478 totalItems: '總行數:',
15479 size: '每頁顯示行數:',
15480 first: '首頁',
15481 next: '下壹頁',
15482 previous: '上壹頁',
15483 last: '末頁'
15484 },
15485 menu: {
15486 text: '選擇列:'
15487 },
15488 sort: {
15489 ascending: '升序',
15490 descending: '降序',
15491 remove: '取消排序'
15492 },
15493 column: {
15494 hide: '隱藏列'
15495 },
15496 aggregation: {
15497 count: '計數:',
15498 sum: '求和:',
15499 avg: '均值:',
15500 min: '最小值:',
15501 max: '最大值:'
15502 },
15503 pinning: {
15504 pinLeft: '左側固定',
15505 pinRight: '右側固定',
15506 unpin: '取消固定'
15507 },
15508 gridMenu: {
15509 columns: '列:',
15510 importerTitle: '導入文件',
15511 exporterAllAsCsv: '導出全部數據到CSV',
15512 exporterVisibleAsCsv: '導出可見數據到CSV',
15513 exporterSelectedAsCsv: '導出已選數據到CSV',
15514 exporterAllAsPdf: '導出全部數據到PDF',
15515 exporterVisibleAsPdf: '導出可見數據到PDF',
15516 exporterSelectedAsPdf: '導出已選數據到PDF',
15517 clearAllFilters: '清除所有过滤器'
15518 },
15519 importer: {
15520 noHeaders: '無法獲取列名,確定文件包含表頭?',
15521 noObjects: '無法獲取數據,確定文件包含數據?',
15522 invalidCsv: '無法處理文件,確定是合法的CSV文件?',
15523 invalidJson: '無法處理文件,確定是合法的JSON文件?',
15524 jsonNotArray: '導入的文件不是JSON數組!'
15525 },
15526 pagination: {
15527 sizes: '行每頁',
15528 totalItems: '行'
15529 }
15530 });
15531 return $delegate;
15532 }]);
15533 }]);
15534 })();
15535
15536 (function() {
15537 'use strict';
15538 /**
15539 * @ngdoc overview
15540 * @name ui.grid.autoResize
15541 *
15542 * @description
15543 *
15544 * #ui.grid.autoResize
15545 *
15546 * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
15547 *
15548 * This module provides auto-resizing functionality to UI-Grid.
15549 */
15550 var module = angular.module('ui.grid.autoResize', ['ui.grid']);
15551
15552 /**
15553 * @ngdoc directive
15554 * @name ui.grid.autoResize.directive:uiGridAutoResize
15555 * @element div
15556 * @restrict A
15557 *
15558 * @description Stacks on top of the ui-grid directive and
15559 * adds the a watch to the grid's height and width which refreshes
15560 * the grid content whenever its dimensions change.
15561 *
15562 */
15563 module.directive('uiGridAutoResize', ['gridUtil', function(gridUtil) {
15564 return {
15565 require: 'uiGrid',
15566 scope: false,
15567 link: function($scope, $elm, $attrs, uiGridCtrl) {
15568 var debouncedRefresh;
15569
15570 function getDimensions() {
15571 return {
15572 width: gridUtil.elementWidth($elm),
15573 height: gridUtil.elementHeight($elm)
15574 };
15575 }
15576
15577 function refreshGrid(prevWidth, prevHeight, width, height) {
15578 if ($elm[0].offsetParent !== null) {
15579 uiGridCtrl.grid.gridWidth = width;
15580 uiGridCtrl.grid.gridHeight = height;
15581 uiGridCtrl.grid.queueGridRefresh()
15582 .then(function() {
15583 uiGridCtrl.grid.api.core.raise.gridDimensionChanged(prevHeight, prevWidth, height, width);
15584 });
15585 }
15586 }
15587
15588 debouncedRefresh = gridUtil.debounce(refreshGrid, 400);
15589
15590 $scope.$watchCollection(getDimensions, function(newValues, oldValues) {
15591 if (!angular.equals(newValues, oldValues)) {
15592 debouncedRefresh(oldValues.width, oldValues.height, newValues.width, newValues.height);
15593 }
15594 });
15595 }
15596 };
15597 }]);
15598 })();
15599
15600 (function () {
15601 'use strict';
15602
15603 /**
15604 * @ngdoc overview
15605 * @name ui.grid.cellNav
15606 *
15607 * @description
15608
15609 #ui.grid.cellNav
15610
15611 <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
15612
15613 This module provides cell navigation functionality to UI-Grid.
15614 */
15615 var module = angular.module('ui.grid.cellNav', ['ui.grid']);
15616
15617 /**
15618 * @ngdoc object
15619 * @name ui.grid.cellNav.constant:uiGridCellNavConstants
15620 *
15621 * @description constants available in cellNav
15622 */
15623 module.constant('uiGridCellNavConstants', {
15624 FEATURE_NAME: 'gridCellNav',
15625 CELL_NAV_EVENT: 'cellNav',
15626 direction: {LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, PG_UP: 4, PG_DOWN: 5},
15627 EVENT_TYPE: {
15628 KEYDOWN: 0,
15629 CLICK: 1,
15630 CLEAR: 2
15631 }
15632 });
15633
15634
15635 module.factory('uiGridCellNavFactory', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', 'GridRowColumn', '$q',
15636 function (gridUtil, uiGridConstants, uiGridCellNavConstants, GridRowColumn, $q) {
15637 /**
15638 * @ngdoc object
15639 * @name ui.grid.cellNav.object:CellNav
15640 * @description returns a CellNav prototype function
15641 * @param {object} rowContainer container for rows
15642 * @param {object} colContainer parent column container
15643 * @param {object} leftColContainer column container to the left of parent
15644 * @param {object} rightColContainer column container to the right of parent
15645 */
15646 var UiGridCellNav = function UiGridCellNav(rowContainer, colContainer, leftColContainer, rightColContainer) {
15647 this.rows = rowContainer.visibleRowCache;
15648 this.columns = colContainer.visibleColumnCache;
15649 this.leftColumns = leftColContainer ? leftColContainer.visibleColumnCache : [];
15650 this.rightColumns = rightColContainer ? rightColContainer.visibleColumnCache : [];
15651 this.bodyContainer = rowContainer;
15652 };
15653
15654 /** returns focusable columns of all containers */
15655 UiGridCellNav.prototype.getFocusableCols = function () {
15656 var allColumns = this.leftColumns.concat(this.columns, this.rightColumns);
15657
15658 return allColumns.filter(function (col) {
15659 return col.colDef.allowCellFocus;
15660 });
15661 };
15662
15663 /**
15664 * @ngdoc object
15665 * @name ui.grid.cellNav.api:GridRow
15666 *
15667 * @description GridRow settings for cellNav feature, these are available to be
15668 * set only internally (for example, by other features)
15669 */
15670
15671 /**
15672 * @ngdoc object
15673 * @name allowCellFocus
15674 * @propertyOf ui.grid.cellNav.api:GridRow
15675 * @description Enable focus on a cell within this row. If set to false then no cells
15676 * in this row can be focused - group header rows as an example would set this to false.
15677 * <br/>Defaults to true
15678 */
15679 /** returns focusable rows */
15680 UiGridCellNav.prototype.getFocusableRows = function () {
15681 return this.rows.filter(function(row) {
15682 return row.allowCellFocus !== false;
15683 });
15684 };
15685
15686 UiGridCellNav.prototype.getNextRowCol = function (direction, curRow, curCol) {
15687 switch (direction) {
15688 case uiGridCellNavConstants.direction.LEFT:
15689 return this.getRowColLeft(curRow, curCol);
15690 case uiGridCellNavConstants.direction.RIGHT:
15691 return this.getRowColRight(curRow, curCol);
15692 case uiGridCellNavConstants.direction.UP:
15693 return this.getRowColUp(curRow, curCol);
15694 case uiGridCellNavConstants.direction.DOWN:
15695 return this.getRowColDown(curRow, curCol);
15696 case uiGridCellNavConstants.direction.PG_UP:
15697 return this.getRowColPageUp(curRow, curCol);
15698 case uiGridCellNavConstants.direction.PG_DOWN:
15699 return this.getRowColPageDown(curRow, curCol);
15700 }
15701 };
15702
15703 UiGridCellNav.prototype.initializeSelection = function () {
15704 var focusableCols = this.getFocusableCols();
15705 var focusableRows = this.getFocusableRows();
15706 if (focusableCols.length === 0 || focusableRows.length === 0) {
15707 return null;
15708 }
15709
15710 return new GridRowColumn(focusableRows[0], focusableCols[0]); // return same row
15711 };
15712
15713 UiGridCellNav.prototype.getRowColLeft = function (curRow, curCol) {
15714 var focusableCols = this.getFocusableCols();
15715 var focusableRows = this.getFocusableRows();
15716 var curColIndex = focusableCols.indexOf(curCol);
15717 var curRowIndex = focusableRows.indexOf(curRow);
15718
15719 // could not find column in focusable Columns so set it to 1
15720 if (curColIndex === -1) {
15721 curColIndex = 1;
15722 }
15723
15724 var nextColIndex = curColIndex === 0 ? focusableCols.length - 1 : curColIndex - 1;
15725
15726 // get column to left
15727 if (nextColIndex >= curColIndex) {
15728 // On the first row
15729 // if (curRowIndex === 0 && curColIndex === 0) {
15730 // return null;
15731 // }
15732 if (curRowIndex === 0) {
15733 return new GridRowColumn(curRow, focusableCols[nextColIndex]); // return same row
15734 }
15735 else {
15736 // up one row and far right column
15737 return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[nextColIndex]);
15738 }
15739 }
15740 else {
15741 return new GridRowColumn(curRow, focusableCols[nextColIndex]);
15742 }
15743 };
15744
15745
15746
15747 UiGridCellNav.prototype.getRowColRight = function (curRow, curCol) {
15748 var focusableCols = this.getFocusableCols();
15749 var focusableRows = this.getFocusableRows();
15750 var curColIndex = focusableCols.indexOf(curCol);
15751 var curRowIndex = focusableRows.indexOf(curRow);
15752
15753 // could not find column in focusable Columns so set it to 0
15754 if (curColIndex === -1) {
15755 curColIndex = 0;
15756 }
15757 var nextColIndex = curColIndex === focusableCols.length - 1 ? 0 : curColIndex + 1;
15758
15759 if (nextColIndex <= curColIndex) {
15760 if (curRowIndex === focusableRows.length - 1) {
15761 return new GridRowColumn(curRow, focusableCols[nextColIndex]); // return same row
15762 }
15763 else {
15764 // down one row and far left column
15765 return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[nextColIndex]);
15766 }
15767 }
15768 else {
15769 return new GridRowColumn(curRow, focusableCols[nextColIndex]);
15770 }
15771 };
15772
15773 UiGridCellNav.prototype.getRowColDown = function (curRow, curCol) {
15774 var focusableCols = this.getFocusableCols();
15775 var focusableRows = this.getFocusableRows();
15776 var curColIndex = focusableCols.indexOf(curCol);
15777 var curRowIndex = focusableRows.indexOf(curRow);
15778
15779 // could not find column in focusable Columns so set it to 0
15780 if (curColIndex === -1) {
15781 curColIndex = 0;
15782 }
15783
15784 if (curRowIndex === focusableRows.length - 1) {
15785 return new GridRowColumn(curRow, focusableCols[curColIndex]); // return same row
15786 }
15787 else {
15788 // down one row
15789 return new GridRowColumn(focusableRows[curRowIndex + 1], focusableCols[curColIndex]);
15790 }
15791 };
15792
15793 UiGridCellNav.prototype.getRowColPageDown = function (curRow, curCol) {
15794 var focusableCols = this.getFocusableCols();
15795 var focusableRows = this.getFocusableRows();
15796 var curColIndex = focusableCols.indexOf(curCol);
15797 var curRowIndex = focusableRows.indexOf(curRow);
15798
15799 // could not find column in focusable Columns so set it to 0
15800 if (curColIndex === -1) {
15801 curColIndex = 0;
15802 }
15803
15804 var pageSize = this.bodyContainer.minRowsToRender();
15805 if (curRowIndex >= focusableRows.length - pageSize) {
15806 return new GridRowColumn(focusableRows[focusableRows.length - 1], focusableCols[curColIndex]); // return last row
15807 }
15808 else {
15809 // down one page
15810 return new GridRowColumn(focusableRows[curRowIndex + pageSize], focusableCols[curColIndex]);
15811 }
15812 };
15813
15814 UiGridCellNav.prototype.getRowColUp = function (curRow, curCol) {
15815 var focusableCols = this.getFocusableCols();
15816 var focusableRows = this.getFocusableRows();
15817 var curColIndex = focusableCols.indexOf(curCol);
15818 var curRowIndex = focusableRows.indexOf(curRow);
15819
15820 // could not find column in focusable Columns so set it to 0
15821 if (curColIndex === -1) {
15822 curColIndex = 0;
15823 }
15824
15825 if (curRowIndex === 0) {
15826 return new GridRowColumn(curRow, focusableCols[curColIndex]); // return same row
15827 }
15828 else {
15829 // up one row
15830 return new GridRowColumn(focusableRows[curRowIndex - 1], focusableCols[curColIndex]);
15831 }
15832 };
15833
15834 UiGridCellNav.prototype.getRowColPageUp = function (curRow, curCol) {
15835 var focusableCols = this.getFocusableCols();
15836 var focusableRows = this.getFocusableRows();
15837 var curColIndex = focusableCols.indexOf(curCol);
15838 var curRowIndex = focusableRows.indexOf(curRow);
15839
15840 // could not find column in focusable Columns so set it to 0
15841 if (curColIndex === -1) {
15842 curColIndex = 0;
15843 }
15844
15845 var pageSize = this.bodyContainer.minRowsToRender();
15846 if (curRowIndex - pageSize < 0) {
15847 return new GridRowColumn(focusableRows[0], focusableCols[curColIndex]); // return first row
15848 }
15849 else {
15850 // up one page
15851 return new GridRowColumn(focusableRows[curRowIndex - pageSize], focusableCols[curColIndex]);
15852 }
15853 };
15854 return UiGridCellNav;
15855 }]);
15856
15857 /**
15858 * @ngdoc service
15859 * @name ui.grid.cellNav.service:uiGridCellNavService
15860 *
15861 * @description Services for cell navigation features. If you don't like the key maps we use,
15862 * or the direction cells navigation, override with a service decorator (see angular docs)
15863 */
15864 module.service('uiGridCellNavService', ['gridUtil', 'uiGridConstants', 'uiGridCellNavConstants', '$q', 'uiGridCellNavFactory', 'GridRowColumn', 'ScrollEvent',
15865 function (gridUtil, uiGridConstants, uiGridCellNavConstants, $q, UiGridCellNav, GridRowColumn, ScrollEvent) {
15866
15867 var service = {
15868
15869 initializeGrid: function (grid) {
15870 grid.registerColumnBuilder(service.cellNavColumnBuilder);
15871
15872
15873 /**
15874 * @ngdoc object
15875 * @name ui.grid.cellNav.Grid:cellNav
15876 * @description cellNav properties added to grid class
15877 */
15878 grid.cellNav = {};
15879 grid.cellNav.lastRowCol = null;
15880 grid.cellNav.focusedCells = [];
15881
15882 service.defaultGridOptions(grid.options);
15883
15884 /**
15885 * @ngdoc object
15886 * @name ui.grid.cellNav.api:PublicApi
15887 *
15888 * @description Public Api for cellNav feature
15889 */
15890 var publicApi = {
15891 events: {
15892 cellNav: {
15893 /**
15894 * @ngdoc event
15895 * @name navigate
15896 * @eventOf ui.grid.cellNav.api:PublicApi
15897 * @description raised when the active cell is changed
15898 * <pre>
15899 * gridApi.cellNav.on.navigate(scope,function(newRowcol, oldRowCol) {})
15900 * </pre>
15901 * @param {object} newRowCol new position
15902 * @param {object} oldRowCol old position
15903 */
15904 navigate: function (newRowCol, oldRowCol) {},
15905 /**
15906 * @ngdoc event
15907 * @name viewPortKeyDown
15908 * @eventOf ui.grid.cellNav.api:PublicApi
15909 * @description is raised when the viewPort receives a keyDown event. Cells never get focus in uiGrid
15910 * due to the difficulties of setting focus on a cell that is not visible in the viewport. Use this
15911 * event whenever you need a keydown event on a cell
15912 * <br/>
15913 * @param {object} event keydown event
15914 * @param {object} rowCol current rowCol position
15915 */
15916 viewPortKeyDown: function (event, rowCol) {},
15917
15918 /**
15919 * @ngdoc event
15920 * @name viewPortKeyPress
15921 * @eventOf ui.grid.cellNav.api:PublicApi
15922 * @description is raised when the viewPort receives a keyPress event. Cells never get focus in uiGrid
15923 * due to the difficulties of setting focus on a cell that is not visible in the viewport. Use this
15924 * event whenever you need a keypress event on a cell
15925 * <br/>
15926 * @param {object} event keypress event
15927 * @param {object} rowCol current rowCol position
15928 */
15929 viewPortKeyPress: function (event, rowCol) {}
15930 }
15931 },
15932 methods: {
15933 cellNav: {
15934 /**
15935 * @ngdoc function
15936 * @name scrollToFocus
15937 * @methodOf ui.grid.cellNav.api:PublicApi
15938 * @description brings the specified row and column into view, and sets focus
15939 * to that cell
15940 * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus
15941 * @param {object} colDef to make visible and set focus
15942 * @returns {promise} a promise that is resolved after any scrolling is finished
15943 */
15944 scrollToFocus: function (rowEntity, colDef) {
15945 return service.scrollToFocus(grid, rowEntity, colDef);
15946 },
15947
15948 /**
15949 * @ngdoc function
15950 * @name getFocusedCell
15951 * @methodOf ui.grid.cellNav.api:PublicApi
15952 * @description returns the current (or last if Grid does not have focus) focused row and column
15953 * <br> value is null if no selection has occurred
15954 */
15955 getFocusedCell: function () {
15956 return grid.cellNav.lastRowCol;
15957 },
15958
15959 /**
15960 * @ngdoc function
15961 * @name getCurrentSelection
15962 * @methodOf ui.grid.cellNav.api:PublicApi
15963 * @description returns an array containing the current selection
15964 * <br> array is empty if no selection has occurred
15965 */
15966 getCurrentSelection: function () {
15967 return grid.cellNav.focusedCells;
15968 },
15969
15970 /**
15971 * @ngdoc function
15972 * @name rowColSelectIndex
15973 * @methodOf ui.grid.cellNav.api:PublicApi
15974 * @description returns the index in the order in which the GridRowColumn was selected, returns -1 if the GridRowColumn
15975 * isn't selected
15976 * @param {object} rowCol the rowCol to evaluate
15977 */
15978 rowColSelectIndex: function (rowCol) {
15979 // return gridUtil.arrayContainsObjectWithProperty(grid.cellNav.focusedCells, 'col.uid', rowCol.col.uid) &&
15980 var index = -1;
15981 for (var i = 0; i < grid.cellNav.focusedCells.length; i++) {
15982 if (grid.cellNav.focusedCells[i].col.uid === rowCol.col.uid &&
15983 grid.cellNav.focusedCells[i].row.uid === rowCol.row.uid) {
15984 index = i;
15985 break;
15986 }
15987 }
15988 return index;
15989 }
15990 }
15991 }
15992 };
15993
15994 grid.api.registerEventsFromObject(publicApi.events);
15995
15996 grid.api.registerMethodsFromObject(publicApi.methods);
15997 },
15998
15999 defaultGridOptions: function (gridOptions) {
16000 /**
16001 * @ngdoc object
16002 * @name ui.grid.cellNav.api:GridOptions
16003 *
16004 * @description GridOptions for cellNav feature, these are available to be
16005 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
16006 */
16007
16008 /**
16009 * @ngdoc object
16010 * @name modifierKeysToMultiSelectCells
16011 * @propertyOf ui.grid.cellNav.api:GridOptions
16012 * @description Enable multiple cell selection only when using the ctrlKey or shiftKey.
16013 * <br/>Defaults to false
16014 */
16015 gridOptions.modifierKeysToMultiSelectCells = gridOptions.modifierKeysToMultiSelectCells === true;
16016
16017 /**
16018 * @ngdoc array
16019 * @name keyDownOverrides
16020 * @propertyOf ui.grid.cellNav.api:GridOptions
16021 * @description An array of event objects to override on keydown. If an event is overridden, the viewPortKeyDown event will
16022 * be raised with the overridden events, allowing custom keydown behavior.
16023 * <br/>Defaults to []
16024 */
16025 gridOptions.keyDownOverrides = gridOptions.keyDownOverrides || [];
16026
16027 },
16028
16029 /**
16030 * @ngdoc service
16031 * @name decorateRenderContainers
16032 * @methodOf ui.grid.cellNav.service:uiGridCellNavService
16033 * @description decorates grid renderContainers with cellNav functions
16034 */
16035 decorateRenderContainers: function (grid) {
16036
16037 var rightContainer = grid.hasRightContainer() ? grid.renderContainers.right : null;
16038 var leftContainer = grid.hasLeftContainer() ? grid.renderContainers.left : null;
16039
16040 if (leftContainer !== null) {
16041 grid.renderContainers.left.cellNav = new UiGridCellNav(grid.renderContainers.body, leftContainer, rightContainer, grid.renderContainers.body);
16042 }
16043 if (rightContainer !== null) {
16044 grid.renderContainers.right.cellNav = new UiGridCellNav(grid.renderContainers.body, rightContainer, grid.renderContainers.body, leftContainer);
16045 }
16046
16047 grid.renderContainers.body.cellNav = new UiGridCellNav(grid.renderContainers.body, grid.renderContainers.body, leftContainer, rightContainer);
16048 },
16049
16050 /**
16051 * @ngdoc service
16052 * @name getDirection
16053 * @methodOf ui.grid.cellNav.service:uiGridCellNavService
16054 * @description determines which direction to for a given keyDown event
16055 * @returns {uiGridCellNavConstants.direction} direction
16056 */
16057 getDirection: function (evt) {
16058 if (evt.keyCode === uiGridConstants.keymap.LEFT ||
16059 (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey)) {
16060 return uiGridCellNavConstants.direction.LEFT;
16061 }
16062 if (evt.keyCode === uiGridConstants.keymap.RIGHT ||
16063 evt.keyCode === uiGridConstants.keymap.TAB) {
16064 return uiGridCellNavConstants.direction.RIGHT;
16065 }
16066
16067 if (evt.keyCode === uiGridConstants.keymap.UP ||
16068 (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ) {
16069 return uiGridCellNavConstants.direction.UP;
16070 }
16071
16072 if (evt.keyCode === uiGridConstants.keymap.PG_UP) {
16073 return uiGridCellNavConstants.direction.PG_UP;
16074 }
16075
16076 if (evt.keyCode === uiGridConstants.keymap.DOWN ||
16077 evt.keyCode === uiGridConstants.keymap.ENTER && !(evt.ctrlKey || evt.altKey)) {
16078 return uiGridCellNavConstants.direction.DOWN;
16079 }
16080
16081 if (evt.keyCode === uiGridConstants.keymap.PG_DOWN) {
16082 return uiGridCellNavConstants.direction.PG_DOWN;
16083 }
16084
16085 return null;
16086 },
16087
16088 /**
16089 * @ngdoc service
16090 * @name cellNavColumnBuilder
16091 * @methodOf ui.grid.cellNav.service:uiGridCellNavService
16092 * @description columnBuilder function that adds cell navigation properties to grid column
16093 * @returns {promise} promise that will load any needed templates when resolved
16094 */
16095 cellNavColumnBuilder: function (colDef, col, gridOptions) {
16096 var promises = [];
16097
16098 /**
16099 * @ngdoc object
16100 * @name ui.grid.cellNav.api:ColumnDef
16101 *
16102 * @description Column Definitions for cellNav feature, these are available to be
16103 * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
16104 */
16105
16106 /**
16107 * @ngdoc object
16108 * @name allowCellFocus
16109 * @propertyOf ui.grid.cellNav.api:ColumnDef
16110 * @description Enable focus on a cell within this column.
16111 * <br/>Defaults to true
16112 */
16113 colDef.allowCellFocus = colDef.allowCellFocus === undefined ? true : colDef.allowCellFocus;
16114
16115 return $q.all(promises);
16116 },
16117
16118 /**
16119 * @ngdoc method
16120 * @methodOf ui.grid.cellNav.service:uiGridCellNavService
16121 * @name scrollToFocus
16122 * @description Scroll the grid such that the specified
16123 * row and column is in view, and set focus to the cell in that row and column
16124 * @param {Grid} grid the grid you'd like to act upon, usually available
16125 * from gridApi.grid
16126 * @param {object} rowEntity gridOptions.data[] array instance to make visible and set focus to
16127 * @param {object} colDef to make visible and set focus to
16128 * @returns {promise} a promise that is resolved after any scrolling is finished
16129 */
16130 scrollToFocus: function (grid, rowEntity, colDef) {
16131 var gridRow = null, gridCol = null;
16132
16133 if (typeof(rowEntity) !== 'undefined' && rowEntity !== null) {
16134 gridRow = grid.getRow(rowEntity);
16135 }
16136
16137 if (typeof(colDef) !== 'undefined' && colDef !== null) {
16138 gridCol = grid.getColumn(colDef.name ? colDef.name : colDef.field);
16139 }
16140 return grid.api.core.scrollToIfNecessary(gridRow, gridCol).then(function () {
16141 var rowCol = { row: gridRow, col: gridCol };
16142
16143 // Broadcast the navigation
16144 if (gridRow !== null && gridCol !== null) {
16145 grid.cellNav.broadcastCellNav(rowCol, null, null);
16146 }
16147 });
16148 },
16149
16150
16151 /**
16152 * @ngdoc method
16153 * @methodOf ui.grid.cellNav.service:uiGridCellNavService
16154 * @name getLeftWidth
16155 * @description Get the current drawn width of the columns in the
16156 * grid up to the numbered column, and add an apportionment for the
16157 * column that we're on. So if we are on column 0, we want to scroll
16158 * 0% (i.e. exclude this column from calc). If we're on the last column
16159 * we want to scroll to 100% (i.e. include this column in the calc). So
16160 * we include (thisColIndex / totalNumberCols) % of this column width
16161 * @param {Grid} grid the grid you'd like to act upon, usually available
16162 * from gridApi.grid
16163 * @param {GridColumn} upToCol the column to total up to and including
16164 */
16165 getLeftWidth: function (grid, upToCol) {
16166 var width = 0;
16167
16168 if (!upToCol) {
16169 return width;
16170 }
16171
16172 var lastIndex = grid.renderContainers.body.visibleColumnCache.indexOf( upToCol );
16173
16174 // total column widths up-to but not including the passed in column
16175 grid.renderContainers.body.visibleColumnCache.forEach( function( col, index ) {
16176 if ( index < lastIndex ) {
16177 width += col.drawnWidth;
16178 }
16179 });
16180
16181 // pro-rata the final column based on % of total columns.
16182 var percentage = lastIndex === 0 ? 0 : (lastIndex + 1) / grid.renderContainers.body.visibleColumnCache.length;
16183 width += upToCol.drawnWidth * percentage;
16184
16185 return width;
16186 }
16187 };
16188
16189 return service;
16190 }]);
16191
16192 /**
16193 * @ngdoc directive
16194 * @name ui.grid.cellNav.directive:uiCellNav
16195 * @element div
16196 * @restrict EA
16197 *
16198 * @description Adds cell navigation features to the grid columns
16199 *
16200 * @example
16201 <example module="app">
16202 <file name="app.js">
16203 var app = angular.module('app', ['ui.grid', 'ui.grid.cellNav']);
16204
16205 app.controller('MainCtrl', ['$scope', function ($scope) {
16206 $scope.data = [
16207 { name: 'Bob', title: 'CEO' },
16208 { name: 'Frank', title: 'Lowly Developer' }
16209 ];
16210
16211 $scope.columnDefs = [
16212 {name: 'name'},
16213 {name: 'title'}
16214 ];
16215 }]);
16216 </file>
16217 <file name="index.html">
16218 <div ng-controller="MainCtrl">
16219 <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-cellnav></div>
16220 </div>
16221 </file>
16222 </example>
16223 */
16224 module.directive('uiGridCellnav', ['gridUtil', 'uiGridCellNavService', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn', '$timeout', '$compile', 'i18nService',
16225 function (gridUtil, uiGridCellNavService, uiGridCellNavConstants, uiGridConstants, GridRowColumn, $timeout, $compile, i18nService) {
16226 return {
16227 replace: true,
16228 priority: -150,
16229 require: '^uiGrid',
16230 scope: false,
16231 controller: function () {},
16232 compile: function () {
16233 return {
16234 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
16235 var _scope = $scope;
16236
16237 var grid = uiGridCtrl.grid;
16238 uiGridCellNavService.initializeGrid(grid);
16239
16240 uiGridCtrl.cellNav = {};
16241
16242 // Ensure that the object has all of the methods we expect it to
16243 uiGridCtrl.cellNav.makeRowCol = function (obj) {
16244 if (!(obj instanceof GridRowColumn)) {
16245 obj = new GridRowColumn(obj.row, obj.col);
16246 }
16247 return obj;
16248 };
16249
16250 uiGridCtrl.cellNav.getActiveCell = function () {
16251 var elms = $elm[0].getElementsByClassName('ui-grid-cell-focus');
16252 if (elms.length > 0) {
16253 return elms[0];
16254 }
16255
16256 return undefined;
16257 };
16258
16259 uiGridCtrl.cellNav.broadcastCellNav = grid.cellNav.broadcastCellNav = function (newRowCol, modifierDown, originEvt) {
16260 modifierDown = !(modifierDown === undefined || !modifierDown);
16261
16262 newRowCol = uiGridCtrl.cellNav.makeRowCol(newRowCol);
16263
16264 uiGridCtrl.cellNav.broadcastFocus(newRowCol, modifierDown, originEvt);
16265 _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT, newRowCol, modifierDown, originEvt);
16266 };
16267
16268 uiGridCtrl.cellNav.clearFocus = grid.cellNav.clearFocus = function () {
16269 grid.cellNav.focusedCells = [];
16270 _scope.$broadcast(uiGridCellNavConstants.CELL_NAV_EVENT);
16271 };
16272
16273 uiGridCtrl.cellNav.broadcastFocus = function (rowCol, modifierDown, originEvt) {
16274 modifierDown = !(modifierDown === undefined || !modifierDown);
16275
16276 rowCol = uiGridCtrl.cellNav.makeRowCol(rowCol);
16277
16278 var row = rowCol.row,
16279 col = rowCol.col;
16280
16281 var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);
16282
16283 if (grid.cellNav.lastRowCol === null || rowColSelectIndex === -1 || (grid.cellNav.lastRowCol.col === col && grid.cellNav.lastRowCol.row === row)) {
16284 var newRowCol = new GridRowColumn(row, col);
16285
16286 if (grid.cellNav.lastRowCol === null || grid.cellNav.lastRowCol.row !== newRowCol.row || grid.cellNav.lastRowCol.col !== newRowCol.col || grid.options.enableCellEditOnFocus) {
16287 grid.api.cellNav.raise.navigate(newRowCol, grid.cellNav.lastRowCol, originEvt);
16288 grid.cellNav.lastRowCol = newRowCol;
16289 }
16290 if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells && modifierDown) {
16291 grid.cellNav.focusedCells.push(rowCol);
16292 } else {
16293 grid.cellNav.focusedCells = [rowCol];
16294 }
16295 } else if (grid.options.modifierKeysToMultiSelectCells && modifierDown &&
16296 rowColSelectIndex >= 0) {
16297
16298 grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
16299 }
16300 };
16301
16302 uiGridCtrl.cellNav.handleKeyDown = function (evt) {
16303 var direction = uiGridCellNavService.getDirection(evt);
16304 if (direction === null) {
16305 return null;
16306 }
16307
16308 var containerId = 'body';
16309 if (evt.uiGridTargetRenderContainerId) {
16310 containerId = evt.uiGridTargetRenderContainerId;
16311 }
16312
16313 // Get the last-focused row+col combo
16314 var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
16315 if (lastRowCol) {
16316 // Figure out which new row+combo we're navigating to
16317 var rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(direction, lastRowCol.row, lastRowCol.col);
16318 var focusableCols = uiGridCtrl.grid.renderContainers[containerId].cellNav.getFocusableCols();
16319 var rowColSelectIndex = uiGridCtrl.grid.api.cellNav.rowColSelectIndex(rowCol);
16320 // Shift+tab on top-left cell should exit cellnav on render container
16321 if (
16322 // Navigating left
16323 direction === uiGridCellNavConstants.direction.LEFT &&
16324 // New col is last col (i.e. wrap around)
16325 rowCol.col === focusableCols[focusableCols.length - 1] &&
16326 // Staying on same row, which means we're at first row
16327 rowCol.row === lastRowCol.row &&
16328 evt.keyCode === uiGridConstants.keymap.TAB &&
16329 evt.shiftKey
16330 ) {
16331 grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
16332 uiGridCtrl.cellNav.clearFocus();
16333 return true;
16334 }
16335 // Tab on bottom-right cell should exit cellnav on render container
16336 else if (
16337 direction === uiGridCellNavConstants.direction.RIGHT &&
16338 // New col is first col (i.e. wrap around)
16339 rowCol.col === focusableCols[0] &&
16340 // Staying on same row, which means we're at first row
16341 rowCol.row === lastRowCol.row &&
16342 evt.keyCode === uiGridConstants.keymap.TAB &&
16343 !evt.shiftKey
16344 ) {
16345 grid.cellNav.focusedCells.splice(rowColSelectIndex, 1);
16346 uiGridCtrl.cellNav.clearFocus();
16347 return true;
16348 }
16349
16350 // Scroll to the new cell, if it's not completely visible within the render container's viewport
16351 grid.scrollToIfNecessary(rowCol.row, rowCol.col).then(function () {
16352 uiGridCtrl.cellNav.broadcastCellNav(rowCol, null, evt);
16353 });
16354
16355
16356 evt.stopPropagation();
16357 evt.preventDefault();
16358
16359 return false;
16360 }
16361 };
16362 },
16363 post: function ($scope, $elm, $attrs, uiGridCtrl) {
16364 var grid = uiGridCtrl.grid;
16365 var usesAria = true;
16366
16367 // Detect whether we are using ngAria
16368 // (if ngAria module is not used then the stuff inside addAriaLiveRegion
16369 // is not used and provides extra fluff)
16370 try {
16371 angular.module('ngAria');
16372 }
16373 catch (err) {
16374 usesAria = false;
16375 }
16376
16377 function addAriaLiveRegion() {
16378 // Thanks to google docs for the inspiration behind how to do this
16379 // XXX: Why is this entire mess nessasary?
16380 // Because browsers take a lot of coercing to get them to read out live regions
16381 // http://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/
16382 var ariaNotifierDomElt = '<div ' +
16383 'id="' + grid.id +'-aria-speakable" ' +
16384 'class="ui-grid-a11y-ariascreenreader-speakable ui-grid-offscreen" ' +
16385 'aria-live="assertive" ' +
16386 'role="alert" ' +
16387 'aria-atomic="true" ' +
16388 'aria-hidden="false" ' +
16389 'aria-relevant="additions" ' +
16390 '>' +
16391 '&nbsp;' +
16392 '</div>';
16393
16394 var ariaNotifier = $compile(ariaNotifierDomElt)($scope);
16395 $elm.prepend(ariaNotifier);
16396 $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, function (evt, rowCol, modifierDown, originEvt) {
16397 /*
16398 * If the cell nav event was because of a focus event then we don't want to
16399 * change the notifier text.
16400 * Reasoning: Voice Over fires a focus events when moving arround the grid.
16401 * If the screen reader is handing the grid nav properly then we don't need to
16402 * use the alert to notify the user of the movement.
16403 * In all other cases we do want a notification event.
16404 */
16405 if (originEvt && originEvt.type === 'focus') {return;}
16406
16407 function setNotifyText(text) {
16408 if (text === ariaNotifier.text().trim()) {return;}
16409 ariaNotifier[0].style.clip = 'rect(0px,0px,0px,0px)';
16410 /*
16411 * This is how google docs handles clearing the div. Seems to work better than setting the text of the div to ''
16412 */
16413 ariaNotifier[0].innerHTML = "";
16414 ariaNotifier[0].style.visibility = 'hidden';
16415 ariaNotifier[0].style.visibility = 'visible';
16416 if (text !== '') {
16417 ariaNotifier[0].style.clip = 'auto';
16418 /*
16419 * The space after the text is something that google docs does.
16420 */
16421 ariaNotifier[0].appendChild(document.createTextNode(text + " "));
16422 ariaNotifier[0].style.visibility = 'hidden';
16423 ariaNotifier[0].style.visibility = 'visible';
16424 }
16425 }
16426
16427 function getAppendedColumnHeaderText(col) {
16428 return ', ' + i18nService.getSafeText('headerCell.aria.column') + ' ' + col.displayName;
16429 }
16430
16431 function getCellDisplayValue(currentRowColumn) {
16432 if (currentRowColumn.col.field === 'selectionRowHeaderCol') {
16433 // This is the case when the 'selection' feature is used in the grid and the user has moved
16434 // to or inside of the left grid container which holds the checkboxes for selecting rows.
16435 // This is necessary for Accessibility. Without this a screen reader cannot determine if the row
16436 // is or is not currently selected.
16437 return currentRowColumn.row.isSelected ? i18nService.getSafeText('search.aria.selected') : i18nService.getSafeText('search.aria.notSelected');
16438 } else {
16439 return grid.getCellDisplayValue(currentRowColumn.row, currentRowColumn.col);
16440 }
16441 }
16442
16443 var values = [];
16444 var currentSelection = grid.api.cellNav.getCurrentSelection();
16445 for (var i = 0; i < currentSelection.length; i++) {
16446 var cellDisplayValue = getCellDisplayValue(currentSelection[i]) + getAppendedColumnHeaderText(currentSelection[i].col);
16447 values.push(cellDisplayValue);
16448 }
16449 var cellText = values.toString();
16450 setNotifyText(cellText);
16451
16452 });
16453 }
16454 // Only add the ngAria stuff it will be used
16455 if (usesAria) {
16456 addAriaLiveRegion();
16457 }
16458 }
16459 };
16460 }
16461 };
16462 }]);
16463
16464 module.directive('uiGridRenderContainer', ['$timeout', '$document', 'gridUtil', 'uiGridConstants', 'uiGridCellNavService', '$compile','uiGridCellNavConstants',
16465 function ($timeout, $document, gridUtil, uiGridConstants, uiGridCellNavService, $compile, uiGridCellNavConstants) {
16466 return {
16467 replace: true,
16468 priority: -99999, // this needs to run very last
16469 require: ['^uiGrid', 'uiGridRenderContainer', '?^uiGridCellnav'],
16470 scope: false,
16471 compile: function () {
16472 return {
16473 post: function ($scope, $elm, $attrs, controllers) {
16474 var uiGridCtrl = controllers[0],
16475 renderContainerCtrl = controllers[1],
16476 uiGridCellnavCtrl = controllers[2];
16477
16478 // Skip attaching cell-nav specific logic if the directive is not attached above us
16479 if (!uiGridCtrl.grid.api.cellNav) { return; }
16480
16481 var containerId = renderContainerCtrl.containerId;
16482
16483 var grid = uiGridCtrl.grid;
16484
16485 // run each time a render container is created
16486 uiGridCellNavService.decorateRenderContainers(grid);
16487
16488 // focusser only created for body
16489 if (containerId !== 'body') {
16490 return;
16491 }
16492
16493 if (uiGridCtrl.grid.options.modifierKeysToMultiSelectCells) {
16494 $elm.attr('aria-multiselectable', true);
16495 }
16496 else {
16497 $elm.attr('aria-multiselectable', false);
16498 }
16499
16500 // add an element with no dimensions that can be used to set focus and capture keystrokes
16501 var focuser = $compile('<div class="ui-grid-focuser" role="region" aria-live="assertive" aria-atomic="false" tabindex="0" aria-controls="' + grid.id +'-aria-speakable '+ grid.id + '-grid-container' +'" aria-owns="' + grid.id + '-grid-container' + '"></div>')($scope);
16502 $elm.append(focuser);
16503
16504 focuser.on('focus', function (evt) {
16505 evt.uiGridTargetRenderContainerId = containerId;
16506 var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
16507 if (rowCol === null) {
16508 rowCol = uiGridCtrl.grid.renderContainers[containerId].cellNav.getNextRowCol(uiGridCellNavConstants.direction.DOWN, null, null);
16509 if (rowCol.row && rowCol.col) {
16510 uiGridCtrl.cellNav.broadcastCellNav(rowCol);
16511 }
16512 }
16513 });
16514
16515 uiGridCellnavCtrl.setAriaActivedescendant = function(id) {
16516 $elm.attr('aria-activedescendant', id);
16517 };
16518
16519 uiGridCellnavCtrl.removeAriaActivedescendant = function(id) {
16520 if ($elm.attr('aria-activedescendant') === id) {
16521 $elm.attr('aria-activedescendant', '');
16522 }
16523 };
16524
16525
16526 uiGridCtrl.focus = function () {
16527 gridUtil.focus.byElement(focuser[0]);
16528 // allow for first time grid focus
16529 };
16530
16531 var viewPortKeyDownWasRaisedForRowCol = null;
16532 // Bind to keydown events in the render container
16533 focuser.on('keydown', function (evt) {
16534 evt.uiGridTargetRenderContainerId = containerId;
16535 var rowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
16536 var raiseViewPortKeyDown = uiGridCtrl.grid.options.keyDownOverrides.some(function (override) {
16537 return Object.keys(override).every( function (property) {
16538 return override[property] === evt[property];
16539 });
16540 });
16541 var result = raiseViewPortKeyDown ? null : uiGridCtrl.cellNav.handleKeyDown(evt);
16542 if (result === null) {
16543 uiGridCtrl.grid.api.cellNav.raise.viewPortKeyDown(evt, rowCol, uiGridCtrl.cellNav.handleKeyDown);
16544 viewPortKeyDownWasRaisedForRowCol = rowCol;
16545 }
16546 });
16547 // Bind to keypress events in the render container
16548 // keypress events are needed by edit function so the key press
16549 // that initiated an edit is not lost
16550 // must fire the event in a timeout so the editor can
16551 // initialize and subscribe to the event on another event loop
16552 focuser.on('keypress', function (evt) {
16553 if (viewPortKeyDownWasRaisedForRowCol) {
16554 $timeout(function () {
16555 uiGridCtrl.grid.api.cellNav.raise.viewPortKeyPress(evt, viewPortKeyDownWasRaisedForRowCol);
16556 }, 4);
16557
16558 viewPortKeyDownWasRaisedForRowCol = null;
16559 }
16560 });
16561
16562 $scope.$on('$destroy', function() {
16563 // Remove all event handlers associated with this focuser.
16564 focuser.off();
16565 });
16566 }
16567 };
16568 }
16569 };
16570 }]);
16571
16572 module.directive('uiGridViewport',
16573 function () {
16574 return {
16575 replace: true,
16576 priority: -99999, // this needs to run very last
16577 require: ['^uiGrid', '^uiGridRenderContainer', '?^uiGridCellnav'],
16578 scope: false,
16579 compile: function () {
16580 return {
16581 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
16582 },
16583 post: function ($scope, $elm, $attrs, controllers) {
16584 var uiGridCtrl = controllers[0],
16585 renderContainerCtrl = controllers[1];
16586
16587 // Skip attaching cell-nav specific logic if the directive is not attached above us
16588 if (!uiGridCtrl.grid.api.cellNav) { return; }
16589
16590 var containerId = renderContainerCtrl.containerId;
16591 // no need to process for other containers
16592 if (containerId !== 'body') {
16593 return;
16594 }
16595
16596 var grid = uiGridCtrl.grid;
16597
16598 grid.api.core.on.scrollBegin($scope, function () {
16599
16600 // Skip if there's no currently-focused cell
16601 var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
16602 if (lastRowCol === null) {
16603 return;
16604 }
16605
16606 // if not in my container, move on
16607 // todo: worry about horiz scroll
16608 if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {
16609 return;
16610 }
16611
16612 uiGridCtrl.cellNav.clearFocus();
16613
16614 });
16615
16616 grid.api.core.on.scrollEnd($scope, function (args) {
16617 // Skip if there's no currently-focused cell
16618 var lastRowCol = uiGridCtrl.grid.api.cellNav.getFocusedCell();
16619 if (lastRowCol === null) {
16620 return;
16621 }
16622
16623 // if not in my container, move on
16624 // todo: worry about horiz scroll
16625 if (!renderContainerCtrl.colContainer.containsColumn(lastRowCol.col)) {
16626 return;
16627 }
16628
16629 uiGridCtrl.cellNav.broadcastCellNav(lastRowCol);
16630 });
16631
16632 grid.api.cellNav.on.navigate($scope, function () {
16633 // focus again because it can be lost
16634 uiGridCtrl.focus();
16635 });
16636 }
16637 };
16638 }
16639 };
16640 });
16641
16642 /**
16643 * @ngdoc directive
16644 * @name ui.grid.cellNav.directive:uiGridCell
16645 * @element div
16646 * @restrict A
16647 * @description Stacks on top of ui.grid.uiGridCell to provide cell navigation
16648 */
16649 module.directive('uiGridCell', ['$timeout', '$document', 'uiGridCellNavService', 'gridUtil', 'uiGridCellNavConstants', 'uiGridConstants', 'GridRowColumn',
16650 function ($timeout, $document, uiGridCellNavService, gridUtil, uiGridCellNavConstants, uiGridConstants, GridRowColumn) {
16651 return {
16652 priority: -150, // run after default uiGridCell directive and ui.grid.edit uiGridCell
16653 restrict: 'A',
16654 require: ['^uiGrid', '?^uiGridCellnav'],
16655 scope: false,
16656 link: function ($scope, $elm, $attrs, controllers) {
16657 var uiGridCtrl = controllers[0],
16658 uiGridCellnavCtrl = controllers[1];
16659 // Skip attaching cell-nav specific logic if the directive is not attached above us
16660 if (!uiGridCtrl.grid.api.cellNav) { return; }
16661
16662 if (!$scope.col.colDef.allowCellFocus) {
16663 return;
16664 }
16665
16666 // Convinience local variables
16667 var grid = uiGridCtrl.grid;
16668 $scope.focused = false;
16669
16670 // Make this cell focusable but only with javascript/a mouse click
16671 $elm.attr('tabindex', -1);
16672
16673 // When a cell is clicked, broadcast a cellNav event saying that this row+col combo is now focused
16674 $elm.find('div').on('click', function (evt) {
16675 uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), evt.ctrlKey || evt.metaKey, evt);
16676
16677 evt.stopPropagation();
16678 $scope.$apply();
16679 });
16680
16681
16682 /*
16683 * XXX Hack for screen readers.
16684 * This allows the grid to focus using only the screen reader cursor.
16685 * Since the focus event doesn't include key press information we can't use it
16686 * as our primary source of the event.
16687 */
16688 $elm.on('mousedown', preventMouseDown);
16689
16690 // turn on and off for edit events
16691 if (uiGridCtrl.grid.api.edit) {
16692 uiGridCtrl.grid.api.edit.on.beginCellEdit($scope, function () {
16693 $elm.off('mousedown', preventMouseDown);
16694 });
16695
16696 uiGridCtrl.grid.api.edit.on.afterCellEdit($scope, function () {
16697 $elm.on('mousedown', preventMouseDown);
16698 });
16699
16700 uiGridCtrl.grid.api.edit.on.cancelCellEdit($scope, function () {
16701 $elm.on('mousedown', preventMouseDown);
16702 });
16703 }
16704
16705 // In case we created a new row, and we are the new created row by ngRepeat
16706 // then this cell content might have been selected previously
16707 refreshCellFocus();
16708
16709 function preventMouseDown(evt) {
16710 // Prevents the foucus event from firing if the click event is already going to fire.
16711 // If both events fire it will cause bouncing behavior.
16712 evt.preventDefault();
16713 }
16714
16715 // You can only focus on elements with a tabindex value
16716 $elm.on('focus', function (evt) {
16717 uiGridCtrl.cellNav.broadcastCellNav(new GridRowColumn($scope.row, $scope.col), false, evt);
16718 evt.stopPropagation();
16719 $scope.$apply();
16720 });
16721
16722 // This event is fired for all cells. If the cell matches, then focus is set
16723 $scope.$on(uiGridCellNavConstants.CELL_NAV_EVENT, refreshCellFocus);
16724
16725 // Refresh cell focus when a new row id added to the grid
16726 var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {
16727 // Clear the focus if it's set to avoid the wrong cell getting focused during
16728 // a short period of time (from now until $timeout function executed)
16729 clearFocus();
16730
16731 $scope.$applyAsync(refreshCellFocus);
16732 }, [uiGridConstants.dataChange.ROW]);
16733
16734 function refreshCellFocus() {
16735 var isFocused = grid.cellNav.focusedCells.some(function (focusedRowCol, index) {
16736 return (focusedRowCol.row === $scope.row && focusedRowCol.col === $scope.col);
16737 });
16738 if (isFocused) {
16739 setFocused();
16740 } else {
16741 clearFocus();
16742 }
16743 }
16744
16745 function setFocused() {
16746 if (!$scope.focused) {
16747 var div = $elm.find('div');
16748 div.addClass('ui-grid-cell-focus');
16749 $elm.attr('aria-selected', true);
16750 uiGridCellnavCtrl.setAriaActivedescendant($elm.attr('id'));
16751 $scope.focused = true;
16752 }
16753 }
16754
16755 function clearFocus() {
16756 if ($scope.focused) {
16757 var div = $elm.find('div');
16758 div.removeClass('ui-grid-cell-focus');
16759 $elm.attr('aria-selected', false);
16760 uiGridCellnavCtrl.removeAriaActivedescendant($elm.attr('id'));
16761 $scope.focused = false;
16762 }
16763 }
16764
16765 $scope.$on('$destroy', function () {
16766 dataChangeDereg();
16767
16768 // .off withouth paramaters removes all handlers
16769 $elm.find('div').off();
16770 $elm.off();
16771 });
16772 }
16773 };
16774 }]);
16775 })();
16776
16777 (function () {
16778 'use strict';
16779
16780 /**
16781 * @ngdoc overview
16782 * @name ui.grid.edit
16783 * @description
16784 *
16785 * # ui.grid.edit
16786 *
16787 * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
16788 *
16789 * This module provides cell editing capability to ui.grid. The goal was to emulate keying data in a spreadsheet via
16790 * a keyboard.
16791 * <br/>
16792 * <br/>
16793 * To really get the full spreadsheet-like data entry, the ui.grid.cellNav module should be used. This will allow the
16794 * user to key data and then tab, arrow, or enter to the cells beside or below.
16795 *
16796 * <div doc-module-components="ui.grid.edit"></div>
16797 */
16798
16799 var module = angular.module('ui.grid.edit', ['ui.grid']);
16800
16801 /**
16802 * @ngdoc object
16803 * @name ui.grid.edit.constant:uiGridEditConstants
16804 *
16805 * @description constants available in edit module
16806 */
16807 module.constant('uiGridEditConstants', {
16808 EDITABLE_CELL_TEMPLATE: /EDITABLE_CELL_TEMPLATE/g,
16809 // must be lowercase because template bulder converts to lower
16810 EDITABLE_CELL_DIRECTIVE: /editable_cell_directive/g,
16811 events: {
16812 BEGIN_CELL_EDIT: 'uiGridEventBeginCellEdit',
16813 END_CELL_EDIT: 'uiGridEventEndCellEdit',
16814 CANCEL_CELL_EDIT: 'uiGridEventCancelCellEdit'
16815 }
16816 });
16817
16818 /**
16819 * @ngdoc service
16820 * @name ui.grid.edit.service:uiGridEditService
16821 *
16822 * @description Services for editing features
16823 */
16824 module.service('uiGridEditService', ['$q', 'uiGridConstants', 'gridUtil',
16825 function ($q, uiGridConstants, gridUtil) {
16826
16827 var service = {
16828
16829 initializeGrid: function (grid) {
16830
16831 service.defaultGridOptions(grid.options);
16832
16833 grid.registerColumnBuilder(service.editColumnBuilder);
16834 grid.edit = {};
16835
16836 /**
16837 * @ngdoc object
16838 * @name ui.grid.edit.api:PublicApi
16839 *
16840 * @description Public Api for edit feature
16841 */
16842 var publicApi = {
16843 events: {
16844 edit: {
16845 /**
16846 * @ngdoc event
16847 * @name afterCellEdit
16848 * @eventOf ui.grid.edit.api:PublicApi
16849 * @description raised when cell editing is complete
16850 * <pre>
16851 * gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef) {})
16852 * </pre>
16853 * @param {object} rowEntity the options.data element that was edited
16854 * @param {object} colDef the column that was edited
16855 * @param {object} newValue new value
16856 * @param {object} oldValue old value
16857 */
16858 afterCellEdit: function (rowEntity, colDef, newValue, oldValue) {
16859 },
16860 /**
16861 * @ngdoc event
16862 * @name beginCellEdit
16863 * @eventOf ui.grid.edit.api:PublicApi
16864 * @description raised when cell editing starts on a cell
16865 * <pre>
16866 * gridApi.edit.on.beginCellEdit(scope,function(rowEntity, colDef) {})
16867 * </pre>
16868 * @param {object} rowEntity the options.data element that was edited
16869 * @param {object} colDef the column that was edited
16870 * @param {object} triggerEvent the event that triggered the edit. Useful to prevent losing keystrokes on some
16871 * complex editors
16872 */
16873 beginCellEdit: function (rowEntity, colDef, triggerEvent) {
16874 },
16875 /**
16876 * @ngdoc event
16877 * @name cancelCellEdit
16878 * @eventOf ui.grid.edit.api:PublicApi
16879 * @description raised when cell editing is cancelled on a cell
16880 * <pre>
16881 * gridApi.edit.on.cancelCellEdit(scope,function(rowEntity, colDef) {})
16882 * </pre>
16883 * @param {object} rowEntity the options.data element that was edited
16884 * @param {object} colDef the column that was edited
16885 */
16886 cancelCellEdit: function (rowEntity, colDef) {
16887 }
16888 }
16889 },
16890 methods: {
16891 edit: { }
16892 }
16893 };
16894
16895 grid.api.registerEventsFromObject(publicApi.events);
16896 // grid.api.registerMethodsFromObject(publicApi.methods);
16897 },
16898
16899 defaultGridOptions: function (gridOptions) {
16900
16901 /**
16902 * @ngdoc object
16903 * @name ui.grid.edit.api:GridOptions
16904 *
16905 * @description Options for configuring the edit feature, these are available to be
16906 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
16907 */
16908
16909 /**
16910 * @ngdoc object
16911 * @name enableCellEdit
16912 * @propertyOf ui.grid.edit.api:GridOptions
16913 * @description If defined, sets the default value for the editable flag on each individual colDefs
16914 * if their individual enableCellEdit configuration is not defined. Defaults to undefined.
16915 */
16916
16917 /**
16918 * @ngdoc object
16919 * @name cellEditableCondition
16920 * @propertyOf ui.grid.edit.api:GridOptions
16921 * @description If specified, either a value or function to be used by all columns before editing.
16922 * If false, then editing of cell is not allowed.
16923 * @example
16924 * <pre>
16925 * function($scope, triggerEvent) {
16926 * //use $scope.row.entity, $scope.col.colDef and triggerEvent to determine if editing is allowed
16927 * return true;
16928 * }
16929 * </pre>
16930 */
16931 gridOptions.cellEditableCondition = gridOptions.cellEditableCondition === undefined ? true : gridOptions.cellEditableCondition;
16932
16933 /**
16934 * @ngdoc object
16935 * @name editableCellTemplate
16936 * @propertyOf ui.grid.edit.api:GridOptions
16937 * @description If specified, cellTemplate to use as the editor for all columns.
16938 * <br/> defaults to 'ui-grid/cellTextEditor'
16939 */
16940
16941 /**
16942 * @ngdoc object
16943 * @name enableCellEditOnFocus
16944 * @propertyOf ui.grid.edit.api:GridOptions
16945 * @description If true, then editor is invoked as soon as cell receives focus. Default false.
16946 * <br/>_requires cellNav feature and the edit feature to be enabled_
16947 */
16948 // enableCellEditOnFocus can only be used if cellnav module is used
16949 gridOptions.enableCellEditOnFocus = gridOptions.enableCellEditOnFocus === undefined ? false : gridOptions.enableCellEditOnFocus;
16950 },
16951
16952 /**
16953 * @ngdoc service
16954 * @name editColumnBuilder
16955 * @methodOf ui.grid.edit.service:uiGridEditService
16956 * @description columnBuilder function that adds edit properties to grid column
16957 * @returns {promise} promise that will load any needed templates when resolved
16958 */
16959 editColumnBuilder: function (colDef, col, gridOptions) {
16960
16961 var promises = [];
16962
16963 /**
16964 * @ngdoc object
16965 * @name ui.grid.edit.api:ColumnDef
16966 *
16967 * @description Column Definition for edit feature, these are available to be
16968 * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
16969 */
16970
16971 /**
16972 * @ngdoc object
16973 * @name enableCellEdit
16974 * @propertyOf ui.grid.edit.api:ColumnDef
16975 * @description enable editing on column
16976 */
16977 colDef.enableCellEdit = colDef.enableCellEdit === undefined ? (gridOptions.enableCellEdit === undefined ?
16978 (colDef.type !== 'object') : gridOptions.enableCellEdit) : colDef.enableCellEdit;
16979
16980 /**
16981 * @ngdoc object
16982 * @name cellEditableCondition
16983 * @propertyOf ui.grid.edit.api:ColumnDef
16984 * @description If specified, either a value or function evaluated before editing cell. If falsy, then editing of cell is not allowed.
16985 * @example
16986 * <pre>
16987 * function($scope, triggerEvent) {
16988 * //use $scope.row.entity, $scope.col.colDef and triggerEvent to determine if editing is allowed
16989 * return true;
16990 * }
16991 * </pre>
16992 */
16993 colDef.cellEditableCondition = colDef.cellEditableCondition === undefined ? gridOptions.cellEditableCondition : colDef.cellEditableCondition;
16994
16995 /**
16996 * @ngdoc object
16997 * @name editableCellTemplate
16998 * @propertyOf ui.grid.edit.api:ColumnDef
16999 * @description cell template to be used when editing this column. Can be Url or text template
17000 * <br/>Defaults to gridOptions.editableCellTemplate
17001 */
17002 if (colDef.enableCellEdit) {
17003 colDef.editableCellTemplate = colDef.editableCellTemplate || gridOptions.editableCellTemplate || 'ui-grid/cellEditor';
17004
17005 promises.push(gridUtil.getTemplate(colDef.editableCellTemplate)
17006 .then(
17007 function (template) {
17008 col.editableCellTemplate = template;
17009 },
17010 function (res) {
17011 // Todo handle response error here?
17012 throw new Error("Couldn't fetch/use colDef.editableCellTemplate '" + colDef.editableCellTemplate + "'");
17013 }));
17014 }
17015
17016 /**
17017 * @ngdoc object
17018 * @name enableCellEditOnFocus
17019 * @propertyOf ui.grid.edit.api:ColumnDef
17020 * @requires ui.grid.cellNav
17021 * @description If true, then editor is invoked as soon as cell receives focus. Default false.
17022 * <br>_requires both the cellNav feature and the edit feature to be enabled_
17023 */
17024 // enableCellEditOnFocus can only be used if cellnav module is used
17025 colDef.enableCellEditOnFocus = colDef.enableCellEditOnFocus === undefined ? gridOptions.enableCellEditOnFocus : colDef.enableCellEditOnFocus;
17026
17027
17028 /**
17029 * @ngdoc string
17030 * @name editModelField
17031 * @propertyOf ui.grid.edit.api:ColumnDef
17032 * @description a bindable string value that is used when binding to edit controls instead of colDef.field
17033 * <br/> example: You have a complex property on and object like state:{abbrev: 'MS',name: 'Mississippi'}. The
17034 * grid should display state.name in the cell and sort/filter based on the state.name property but the editor
17035 * requires the full state object.
17036 * <br/>colDef.field = 'state.name'
17037 * <br/>colDef.editModelField = 'state'
17038 */
17039 // colDef.editModelField
17040
17041 return $q.all(promises);
17042 },
17043
17044 /**
17045 * @ngdoc service
17046 * @name isStartEditKey
17047 * @methodOf ui.grid.edit.service:uiGridEditService
17048 * @description Determines if a keypress should start editing. Decorate this service to override with your
17049 * own key events. See service decorator in angular docs.
17050 * @param {Event} evt keydown event
17051 * @returns {boolean} true if an edit should start
17052 */
17053 isStartEditKey: function (evt) {
17054 return !(evt.metaKey ||
17055 evt.keyCode === uiGridConstants.keymap.ESC ||
17056 evt.keyCode === uiGridConstants.keymap.SHIFT ||
17057 evt.keyCode === uiGridConstants.keymap.CTRL ||
17058 evt.keyCode === uiGridConstants.keymap.ALT ||
17059 evt.keyCode === uiGridConstants.keymap.WIN ||
17060 evt.keyCode === uiGridConstants.keymap.CAPSLOCK ||
17061
17062 evt.keyCode === uiGridConstants.keymap.LEFT ||
17063 (evt.keyCode === uiGridConstants.keymap.TAB && evt.shiftKey) ||
17064
17065 evt.keyCode === uiGridConstants.keymap.RIGHT ||
17066 evt.keyCode === uiGridConstants.keymap.TAB ||
17067
17068 evt.keyCode === uiGridConstants.keymap.UP ||
17069 (evt.keyCode === uiGridConstants.keymap.ENTER && evt.shiftKey) ||
17070
17071 evt.keyCode === uiGridConstants.keymap.DOWN ||
17072 evt.keyCode === uiGridConstants.keymap.ENTER);
17073 }
17074 };
17075
17076 return service;
17077
17078 }]);
17079
17080 /**
17081 * @ngdoc directive
17082 * @name ui.grid.edit.directive:uiGridEdit
17083 * @element div
17084 * @restrict A
17085 *
17086 * @description Adds editing features to the ui-grid directive.
17087 *
17088 * @example
17089 <example module="app">
17090 <file name="app.js">
17091 var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);
17092
17093 app.controller('MainCtrl', ['$scope', function ($scope) {
17094 $scope.data = [
17095 { name: 'Bob', title: 'CEO' },
17096 { name: 'Frank', title: 'Lowly Developer' }
17097 ];
17098
17099 $scope.columnDefs = [
17100 {name: 'name', enableCellEdit: true},
17101 {name: 'title', enableCellEdit: true}
17102 ];
17103 }]);
17104 </file>
17105 <file name="index.html">
17106 <div ng-controller="MainCtrl">
17107 <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-edit></div>
17108 </div>
17109 </file>
17110 </example>
17111 */
17112 module.directive('uiGridEdit', ['gridUtil', 'uiGridEditService', function (gridUtil, uiGridEditService) {
17113 return {
17114 replace: true,
17115 priority: 0,
17116 require: '^uiGrid',
17117 scope: false,
17118 compile: function () {
17119 return {
17120 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
17121 uiGridEditService.initializeGrid(uiGridCtrl.grid);
17122 },
17123 post: function ($scope, $elm, $attrs, uiGridCtrl) {
17124 }
17125 };
17126 }
17127 };
17128 }]);
17129
17130 /**
17131 * @ngdoc directive
17132 * @name ui.grid.edit.directive:uiGridRenderContainer
17133 * @element div
17134 * @restrict A
17135 *
17136 * @description Adds keydown listeners to renderContainer element so we can capture when to begin edits
17137 *
17138 */
17139 module.directive('uiGridViewport', [ 'uiGridEditConstants',
17140 function ( uiGridEditConstants) {
17141 return {
17142 replace: true,
17143 priority: -99998, // run before cellNav
17144 require: ['^uiGrid', '^uiGridRenderContainer'],
17145 scope: false,
17146 compile: function () {
17147 return {
17148 post: function ($scope, $elm, $attrs, controllers) {
17149 var uiGridCtrl = controllers[0];
17150
17151 // Skip attaching if edit and cellNav is not enabled
17152 if (!uiGridCtrl.grid.api.edit || !uiGridCtrl.grid.api.cellNav) { return; }
17153
17154 var containerId = controllers[1].containerId;
17155 // no need to process for other containers
17156 if (containerId !== 'body') {
17157 return;
17158 }
17159
17160 // refocus on the grid
17161 $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {
17162 uiGridCtrl.focus();
17163 });
17164 $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {
17165 uiGridCtrl.focus();
17166 });
17167 }
17168 };
17169 }
17170 };
17171 }]);
17172
17173 /**
17174 * @ngdoc directive
17175 * @name ui.grid.edit.directive:uiGridCell
17176 * @element div
17177 * @restrict A
17178 *
17179 * @description Stacks on top of ui.grid.uiGridCell to provide in-line editing capabilities to the cell
17180 * Editing Actions.
17181 *
17182 * Binds edit start events to the uiGridCell element. When the events fire, the gridCell element is appended
17183 * with the columnDef.editableCellTemplate element ('cellEditor.html' by default).
17184 *
17185 * The editableCellTemplate should respond to uiGridEditConstants.events.BEGIN\_CELL\_EDIT angular event
17186 * and do the initial steps needed to edit the cell (setfocus on input element, etc).
17187 *
17188 * When the editableCellTemplate recognizes that the editing is ended (blur event, Enter key, etc.)
17189 * it should emit the uiGridEditConstants.events.END\_CELL\_EDIT event.
17190 *
17191 * If editableCellTemplate recognizes that the editing has been cancelled (esc key)
17192 * it should emit the uiGridEditConstants.events.CANCEL\_CELL\_EDIT event. The original value
17193 * will be set back on the model by the uiGridCell directive.
17194 *
17195 * Events that invoke editing:
17196 * - dblclick
17197 * - F2 keydown (when using cell selection)
17198 *
17199 * Events that end editing:
17200 * - Dependent on the specific editableCellTemplate
17201 * - Standards should be blur and enter keydown
17202 *
17203 * Events that cancel editing:
17204 * - Dependent on the specific editableCellTemplate
17205 * - Standards should be Esc keydown
17206 *
17207 * Grid Events that end editing:
17208 * - uiGridConstants.events.GRID_SCROLL
17209 *
17210 */
17211
17212 /**
17213 * @ngdoc object
17214 * @name ui.grid.edit.api:GridRow
17215 *
17216 * @description GridRow options for edit feature, these are available to be
17217 * set internally only, by other features
17218 */
17219
17220 /**
17221 * @ngdoc object
17222 * @name enableCellEdit
17223 * @propertyOf ui.grid.edit.api:GridRow
17224 * @description enable editing on row, grouping for example might disable editing on group header rows
17225 */
17226
17227 module.directive('uiGridCell',
17228 ['$compile', '$injector', '$timeout', 'uiGridConstants', 'uiGridEditConstants', 'gridUtil', '$parse', 'uiGridEditService', '$rootScope', '$q',
17229 function ($compile, $injector, $timeout, uiGridConstants, uiGridEditConstants, gridUtil, $parse, uiGridEditService, $rootScope, $q) {
17230 var touchstartTimeout = 500;
17231 if ($injector.has('uiGridCellNavService')) {
17232 var uiGridCellNavService = $injector.get('uiGridCellNavService');
17233 }
17234
17235 return {
17236 priority: -100, // run after default uiGridCell directive
17237 restrict: 'A',
17238 scope: false,
17239 require: '?^uiGrid',
17240 link: function ($scope, $elm, $attrs, uiGridCtrl) {
17241 var html,
17242 origCellValue,
17243 cellModel,
17244 cancelTouchstartTimeout,
17245 inEdit = false;
17246
17247 var editCellScope;
17248
17249 if (!$scope.col.colDef.enableCellEdit) {
17250 return;
17251 }
17252
17253 var cellNavNavigateDereg = function() {};
17254 var viewPortKeyDownDereg = function() {};
17255
17256
17257 var setEditable = function() {
17258 if ($scope.col.colDef.enableCellEdit && $scope.row.enableCellEdit !== false) {
17259 if (!$scope.beginEditEventsWired) { // prevent multiple attachments
17260 registerBeginEditEvents();
17261 }
17262 } else {
17263 if ($scope.beginEditEventsWired) {
17264 cancelBeginEditEvents();
17265 }
17266 }
17267 };
17268
17269 setEditable();
17270
17271 var rowWatchDereg = $scope.$watch('row', function (n, o) {
17272 if (n !== o) {
17273 setEditable();
17274 }
17275 });
17276
17277
17278 $scope.$on('$destroy', function destroyEvents() {
17279 rowWatchDereg();
17280 // unbind all jquery events in order to avoid memory leaks
17281 $elm.off();
17282 });
17283
17284 function registerBeginEditEvents() {
17285 $elm.on('dblclick', beginEdit);
17286
17287 // Add touchstart handling. If the users starts a touch and it doesn't end after X milliseconds, then start the edit
17288 $elm.on('touchstart', touchStart);
17289
17290 if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
17291
17292 viewPortKeyDownDereg = uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
17293 if (rowCol === null) {
17294 return;
17295 }
17296
17297 if (rowCol.row === $scope.row && rowCol.col === $scope.col && !$scope.col.colDef.enableCellEditOnFocus) {
17298 // important to do this before scrollToIfNecessary
17299 beginEditKeyDown(evt);
17300 }
17301 });
17302
17303 cellNavNavigateDereg = uiGridCtrl.grid.api.cellNav.on.navigate($scope, function (newRowCol, oldRowCol, evt) {
17304 if ($scope.col.colDef.enableCellEditOnFocus) {
17305 // Don't begin edit if the cell hasn't changed
17306 if (newRowCol.row === $scope.row && newRowCol.col === $scope.col &&
17307 (evt === null || (evt && (evt.type === 'click' || evt.type === 'keydown')))) {
17308 $timeout(function() {
17309 beginEdit(evt);
17310 });
17311 }
17312 }
17313 });
17314 }
17315
17316 $scope.beginEditEventsWired = true;
17317 }
17318
17319 function touchStart(event) {
17320 // jQuery masks events
17321 if (typeof(event.originalEvent) !== 'undefined' && event.originalEvent !== undefined) {
17322 event = event.originalEvent;
17323 }
17324
17325 // Bind touchend handler
17326 $elm.on('touchend', touchEnd);
17327
17328 // Start a timeout
17329 cancelTouchstartTimeout = $timeout(function() { }, touchstartTimeout);
17330
17331 // Timeout's done! Start the edit
17332 cancelTouchstartTimeout.then(function () {
17333 // Use setTimeout to start the edit because beginEdit expects to be outside of $digest
17334 setTimeout(beginEdit, 0);
17335
17336 // Undbind the touchend handler, we don't need it anymore
17337 $elm.off('touchend', touchEnd);
17338 });
17339 }
17340
17341 // Cancel any touchstart timeout
17342 function touchEnd() {
17343 $timeout.cancel(cancelTouchstartTimeout);
17344 $elm.off('touchend', touchEnd);
17345 }
17346
17347 function cancelBeginEditEvents() {
17348 $elm.off('dblclick', beginEdit);
17349 $elm.off('keydown', beginEditKeyDown);
17350 $elm.off('touchstart', touchStart);
17351 cellNavNavigateDereg();
17352 viewPortKeyDownDereg();
17353 $scope.beginEditEventsWired = false;
17354 }
17355
17356 function beginEditKeyDown(evt) {
17357 if (uiGridEditService.isStartEditKey(evt)) {
17358 beginEdit(evt);
17359 }
17360 }
17361
17362 function shouldEdit(col, row, triggerEvent) {
17363 return !row.isSaving &&
17364 ( angular.isFunction(col.colDef.cellEditableCondition) ?
17365 col.colDef.cellEditableCondition($scope, triggerEvent) :
17366 col.colDef.cellEditableCondition );
17367 }
17368
17369
17370 function beginEdit(triggerEvent) {
17371 // we need to scroll the cell into focus before invoking the editor
17372 $scope.grid.api.core.scrollToIfNecessary($scope.row, $scope.col)
17373 .then(function () {
17374 beginEditAfterScroll(triggerEvent);
17375 });
17376 }
17377
17378 /**
17379 * @ngdoc property
17380 * @name editDropdownOptionsArray
17381 * @propertyOf ui.grid.edit.api:ColumnDef
17382 * @description an array of values in the format
17383 * [ {id: xxx, value: xxx} ], which is populated
17384 * into the edit dropdown
17385 *
17386 */
17387 /**
17388 * @ngdoc property
17389 * @name editDropdownIdLabel
17390 * @propertyOf ui.grid.edit.api:ColumnDef
17391 * @description the label for the "id" field
17392 * in the editDropdownOptionsArray. Defaults
17393 * to 'id'
17394 * @example
17395 * <pre>
17396 * $scope.gridOptions = {
17397 * columnDefs: [
17398 * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
17399 * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
17400 * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
17401 * ],
17402 * </pre>
17403 *
17404 */
17405 /**
17406 * @ngdoc property
17407 * @name editDropdownRowEntityOptionsArrayPath
17408 * @propertyOf ui.grid.edit.api:ColumnDef
17409 * @description a path to a property on row.entity containing an
17410 * array of values in the format
17411 * [ {id: xxx, value: xxx} ], which will be used to populate
17412 * the edit dropdown. This can be used when the dropdown values are dependent on
17413 * the backing row entity.
17414 * If this property is set then editDropdownOptionsArray will be ignored.
17415 * @example
17416 * <pre>
17417 * $scope.gridOptions = {
17418 * columnDefs: [
17419 * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
17420 * editDropdownRowEntityOptionsArrayPath: 'foo.bars[0].baz',
17421 * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
17422 * ],
17423 * </pre>
17424 *
17425 */
17426 /**
17427 * @ngdoc service
17428 * @name editDropdownOptionsFunction
17429 * @methodOf ui.grid.edit.api:ColumnDef
17430 * @description a function returning an array of values in the format
17431 * [ {id: xxx, value: xxx} ], which will be used to populate
17432 * the edit dropdown. This can be used when the dropdown values are dependent on
17433 * the backing row entity with some kind of algorithm.
17434 * If this property is set then both editDropdownOptionsArray and
17435 * editDropdownRowEntityOptionsArrayPath will be ignored.
17436 * @param {object} rowEntity the options.data element that the returned array refers to
17437 * @param {object} colDef the column that implements this dropdown
17438 * @returns {object} an array of values in the format
17439 * [ {id: xxx, value: xxx} ] used to populate the edit dropdown
17440 * @example
17441 * <pre>
17442 * $scope.gridOptions = {
17443 * columnDefs: [
17444 * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
17445 * editDropdownOptionsFunction: function(rowEntity, colDef) {
17446 * if (rowEntity.foo === 'bar') {
17447 * return [{id: 'bar1', value: 'BAR 1'},
17448 * {id: 'bar2', value: 'BAR 2'},
17449 * {id: 'bar3', value: 'BAR 3'}];
17450 * } else {
17451 * return [{id: 'foo1', value: 'FOO 1'},
17452 * {id: 'foo2', value: 'FOO 2'}];
17453 * }
17454 * },
17455 * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
17456 * ],
17457 * </pre>
17458 *
17459 */
17460 /**
17461 * @ngdoc property
17462 * @name editDropdownValueLabel
17463 * @propertyOf ui.grid.edit.api:ColumnDef
17464 * @description the label for the "value" field
17465 * in the editDropdownOptionsArray. Defaults
17466 * to 'value'
17467 * @example
17468 * <pre>
17469 * $scope.gridOptions = {
17470 * columnDefs: [
17471 * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
17472 * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
17473 * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status' }
17474 * ],
17475 * </pre>
17476 *
17477 */
17478 /**
17479 * @ngdoc property
17480 * @name editDropdownFilter
17481 * @propertyOf ui.grid.edit.api:ColumnDef
17482 * @description A filter that you would like to apply to the values in the options list
17483 * of the dropdown. For example if you were using angular-translate you might set this
17484 * to `'translate'`
17485 * @example
17486 * <pre>
17487 * $scope.gridOptions = {
17488 * columnDefs: [
17489 * {name: 'status', editableCellTemplate: 'ui-grid/dropdownEditor',
17490 * editDropdownOptionsArray: [{code: 1, status: 'active'}, {code: 2, status: 'inactive'}],
17491 * editDropdownIdLabel: 'code', editDropdownValueLabel: 'status', editDropdownFilter: 'translate' }
17492 * ],
17493 * </pre>
17494 *
17495 */
17496 function beginEditAfterScroll(triggerEvent) {
17497 // If we are already editing, then just skip this so we don't try editing twice...
17498 if (inEdit) {
17499 return;
17500 }
17501
17502 if (!shouldEdit($scope.col, $scope.row, triggerEvent)) {
17503 return;
17504 }
17505
17506 var modelField = $scope.row.getQualifiedColField($scope.col);
17507 if ($scope.col.colDef.editModelField) {
17508 modelField = gridUtil.preEval('row.entity.' + $scope.col.colDef.editModelField);
17509 }
17510
17511 cellModel = $parse(modelField);
17512
17513 // get original value from the cell
17514 origCellValue = cellModel($scope);
17515
17516 html = $scope.col.editableCellTemplate;
17517 html = html.replace(uiGridConstants.MODEL_COL_FIELD, modelField);
17518 html = html.replace(uiGridConstants.COL_FIELD, 'grid.getCellValue(row, col)');
17519
17520 var optionFilter = $scope.col.colDef.editDropdownFilter ? '|' + $scope.col.colDef.editDropdownFilter : '';
17521 html = html.replace(uiGridConstants.CUSTOM_FILTERS, optionFilter);
17522
17523 var inputType = 'text';
17524 switch ($scope.col.colDef.type) {
17525 case 'boolean':
17526 inputType = 'checkbox';
17527 break;
17528 case 'number':
17529 inputType = 'number';
17530 break;
17531 case 'date':
17532 inputType = 'date';
17533 break;
17534 }
17535 html = html.replace('INPUT_TYPE', inputType);
17536
17537 // In order to fill dropdown options we use:
17538 // - A function/promise or
17539 // - An array inside of row entity if no function exists or
17540 // - A single array for the whole column if none of the previous exists.
17541 var editDropdownOptionsFunction = $scope.col.colDef.editDropdownOptionsFunction;
17542 if (editDropdownOptionsFunction) {
17543 $q.when(editDropdownOptionsFunction($scope.row.entity, $scope.col.colDef))
17544 .then(function(result) {
17545 $scope.editDropdownOptionsArray = result;
17546 });
17547 } else {
17548 var editDropdownRowEntityOptionsArrayPath = $scope.col.colDef.editDropdownRowEntityOptionsArrayPath;
17549 if (editDropdownRowEntityOptionsArrayPath) {
17550 $scope.editDropdownOptionsArray = resolveObjectFromPath($scope.row.entity, editDropdownRowEntityOptionsArrayPath);
17551 }
17552 else {
17553 $scope.editDropdownOptionsArray = $scope.col.colDef.editDropdownOptionsArray;
17554 }
17555 }
17556 $scope.editDropdownIdLabel = $scope.col.colDef.editDropdownIdLabel ? $scope.col.colDef.editDropdownIdLabel : 'id';
17557 $scope.editDropdownValueLabel = $scope.col.colDef.editDropdownValueLabel ? $scope.col.colDef.editDropdownValueLabel : 'value';
17558
17559 var createEditor = function() {
17560 inEdit = true;
17561 cancelBeginEditEvents();
17562 var cellElement = angular.element(html);
17563 $elm.append(cellElement);
17564 editCellScope = $scope.$new();
17565 $compile(cellElement)(editCellScope);
17566 var gridCellContentsEl = angular.element($elm.children()[0]);
17567 gridCellContentsEl.addClass('ui-grid-cell-contents-hidden');
17568 };
17569 if (!$rootScope.$$phase) {
17570 $scope.$apply(createEditor);
17571 } else {
17572 createEditor();
17573 }
17574
17575 // stop editing when grid is scrolled
17576 var deregOnGridScroll = $scope.col.grid.api.core.on.scrollBegin($scope, function () {
17577 if ($scope.grid.disableScrolling) {
17578 return;
17579 }
17580 endEdit();
17581 $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);
17582 deregOnGridScroll();
17583 deregOnEndCellEdit();
17584 deregOnCancelCellEdit();
17585 });
17586
17587 // end editing
17588 var deregOnEndCellEdit = $scope.$on(uiGridEditConstants.events.END_CELL_EDIT, function () {
17589 endEdit();
17590 $scope.grid.api.edit.raise.afterCellEdit($scope.row.entity, $scope.col.colDef, cellModel($scope), origCellValue);
17591 deregOnEndCellEdit();
17592 deregOnGridScroll();
17593 deregOnCancelCellEdit();
17594 });
17595
17596 // cancel editing
17597 var deregOnCancelCellEdit = $scope.$on(uiGridEditConstants.events.CANCEL_CELL_EDIT, function () {
17598 cancelEdit();
17599 deregOnCancelCellEdit();
17600 deregOnGridScroll();
17601 deregOnEndCellEdit();
17602 });
17603
17604 $scope.$broadcast(uiGridEditConstants.events.BEGIN_CELL_EDIT, triggerEvent);
17605 $timeout(function () {
17606 // execute in a timeout to give any complex editor templates a cycle to completely render
17607 $scope.grid.api.edit.raise.beginCellEdit($scope.row.entity, $scope.col.colDef, triggerEvent);
17608 });
17609 }
17610
17611 function endEdit() {
17612 $scope.grid.disableScrolling = false;
17613 if (!inEdit) {
17614 return;
17615 }
17616
17617 // sometimes the events can't keep up with the keyboard and grid focus is lost, so always focus
17618 // back to grid here. The focus call needs to be before the $destroy and removal of the control,
17619 // otherwise ng-model-options of UpdateOn: 'blur' will not work.
17620 if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
17621 uiGridCtrl.focus();
17622 }
17623
17624 var gridCellContentsEl = angular.element($elm.children()[0]);
17625 // remove edit element
17626 editCellScope.$destroy();
17627 var children = $elm.children();
17628 for (var i = 1; i < children.length; i++) {
17629 angular.element(children[i]).remove();
17630 }
17631 gridCellContentsEl.removeClass('ui-grid-cell-contents-hidden');
17632 inEdit = false;
17633 registerBeginEditEvents();
17634 $scope.grid.api.core.notifyDataChange( uiGridConstants.dataChange.EDIT );
17635 }
17636
17637 function cancelEdit() {
17638 $scope.grid.disableScrolling = false;
17639 if (!inEdit) {
17640 return;
17641 }
17642 cellModel.assign($scope, origCellValue);
17643 $scope.$apply();
17644
17645 $scope.grid.api.edit.raise.cancelCellEdit($scope.row.entity, $scope.col.colDef);
17646 endEdit();
17647 }
17648
17649 // resolves a string path against the given object
17650 // shamelessly borrowed from
17651 // http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key
17652 function resolveObjectFromPath(object, path) {
17653 path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
17654 path = path.replace(/^\./, ''); // strip a leading dot
17655 var a = path.split('.');
17656 while (a.length) {
17657 var n = a.shift();
17658 if (n in object) {
17659 object = object[n];
17660 } else {
17661 return;
17662 }
17663 }
17664 return object;
17665 }
17666 }
17667 };
17668 }]);
17669
17670 /**
17671 * @ngdoc directive
17672 * @name ui.grid.edit.directive:uiGridEditor
17673 * @element div
17674 * @restrict A
17675 *
17676 * @description input editor directive for editable fields.
17677 * Provides EndEdit and CancelEdit events
17678 *
17679 * Events that end editing:
17680 * blur and enter keydown
17681 *
17682 * Events that cancel editing:
17683 * - Esc keydown
17684 *
17685 */
17686 module.directive('uiGridEditor',
17687 ['gridUtil', 'uiGridConstants', 'uiGridEditConstants','$timeout', 'uiGridEditService',
17688 function (gridUtil, uiGridConstants, uiGridEditConstants, $timeout, uiGridEditService) {
17689 return {
17690 scope: true,
17691 require: ['?^uiGrid', '?^uiGridRenderContainer', 'ngModel'],
17692 compile: function () {
17693 return {
17694 pre: function ($scope, $elm, $attrs) {
17695
17696 },
17697 post: function ($scope, $elm, $attrs, controllers) {
17698 var uiGridCtrl, renderContainerCtrl, ngModel;
17699 if (controllers[0]) { uiGridCtrl = controllers[0]; }
17700 if (controllers[1]) { renderContainerCtrl = controllers[1]; }
17701 if (controllers[2]) { ngModel = controllers[2]; }
17702
17703 // set focus at start of edit
17704 $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
17705 // must be in a timeout since it requires a new digest cycle
17706 $timeout(function () {
17707 $elm[0].focus();
17708 // only select text if it is not being replaced below in the cellNav viewPortKeyPress
17709 if ($elm[0].select && ($scope.col.colDef.enableCellEditOnFocus || !(uiGridCtrl && uiGridCtrl.grid.api.cellNav))) {
17710 $elm[0].select();
17711 }
17712 else {
17713 // some browsers (Chrome) stupidly, imo, support the w3 standard that number, email, ...
17714 // fields should not allow setSelectionRange. We ignore the error for those browsers
17715 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=24796
17716 try {
17717 $elm[0].setSelectionRange($elm[0].value.length, $elm[0].value.length);
17718 }
17719 catch (ex) {
17720 // ignore
17721 }
17722 }
17723 });
17724
17725 // set the keystroke that started the edit event
17726 // we must do this because the BeginEdit is done in a different event loop than the intitial
17727 // keydown event
17728 // fire this event for the keypress that is received
17729 if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
17730 var viewPortKeyDownUnregister = uiGridCtrl.grid.api.cellNav.on.viewPortKeyPress($scope, function (evt, rowCol) {
17731 if (uiGridEditService.isStartEditKey(evt)) {
17732 var code = typeof evt.which === 'number' ? evt.which : evt.keyCode;
17733 if (code > 0) {
17734 ngModel.$setViewValue(String.fromCharCode(code), evt);
17735 ngModel.$render();
17736 }
17737 }
17738 viewPortKeyDownUnregister();
17739 });
17740 }
17741
17742 // macOS will blur the checkbox when clicked in Safari and Firefox,
17743 // to get around this, we disable the blur handler on mousedown,
17744 // and then focus the checkbox and re-enable the blur handler after $timeout
17745 $elm.on('mousedown', function(evt) {
17746 if ($elm[0].type === 'checkbox') {
17747 $elm.off('blur', $scope.stopEdit);
17748 $timeout(function() {
17749 $elm[0].focus();
17750 $elm.on('blur', $scope.stopEdit);
17751 });
17752 }
17753 });
17754
17755 $elm.on('blur', $scope.stopEdit);
17756 });
17757
17758
17759 $scope.deepEdit = false;
17760
17761 $scope.stopEdit = function (evt) {
17762 if ($scope.inputForm && !$scope.inputForm.$valid) {
17763 evt.stopPropagation();
17764 $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
17765 }
17766 else {
17767 $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
17768 }
17769 $scope.deepEdit = false;
17770 };
17771
17772
17773 $elm.on('click', function (evt) {
17774 if ($elm[0].type !== 'checkbox') {
17775 $scope.deepEdit = true;
17776 $scope.$applyAsync(function () {
17777 $scope.grid.disableScrolling = true;
17778 });
17779 }
17780 });
17781
17782 $elm.on('keydown', function (evt) {
17783 switch (evt.keyCode) {
17784 case uiGridConstants.keymap.ESC:
17785 evt.stopPropagation();
17786 $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
17787 break;
17788 }
17789
17790 if ($scope.deepEdit &&
17791 (evt.keyCode === uiGridConstants.keymap.LEFT ||
17792 evt.keyCode === uiGridConstants.keymap.RIGHT ||
17793 evt.keyCode === uiGridConstants.keymap.UP ||
17794 evt.keyCode === uiGridConstants.keymap.DOWN)) {
17795 evt.stopPropagation();
17796 }
17797 // Pass the keydown event off to the cellNav service, if it exists
17798 else if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
17799 evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
17800 if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
17801 $scope.stopEdit(evt);
17802 }
17803 }
17804 else {
17805 // handle enter and tab for editing not using cellNav
17806 switch (evt.keyCode) {
17807 case uiGridConstants.keymap.ENTER: // Enter (Leave Field)
17808 case uiGridConstants.keymap.TAB:
17809 evt.stopPropagation();
17810 evt.preventDefault();
17811 $scope.stopEdit(evt);
17812 break;
17813 }
17814 }
17815
17816 return true;
17817 });
17818
17819 $scope.$on('$destroy', function unbindEvents() {
17820 // unbind all jquery events in order to avoid memory leaks
17821 $elm.off();
17822 });
17823 }
17824 };
17825 }
17826 };
17827 }]);
17828
17829 /**
17830 * @ngdoc directive
17831 * @name ui.grid.edit.directive:input
17832 * @element input
17833 * @restrict E
17834 *
17835 * @description directive to provide binding between input[date] value and ng-model for angular 1.2
17836 * It is similar to input[date] directive of angular 1.3
17837 *
17838 * Supported date format for input is 'yyyy-MM-dd'
17839 * The directive will set the $valid property of input element and the enclosing form to false if
17840 * model is invalid date or value of input is entered wrong.
17841 *
17842 */
17843 module.directive('uiGridEditor', ['$filter', function ($filter) {
17844 function parseDateString(dateString) {
17845 if (typeof(dateString) === 'undefined' || dateString === '') {
17846 return null;
17847 }
17848 var parts = dateString.split('-');
17849 if (parts.length !== 3) {
17850 return null;
17851 }
17852 var year = parseInt(parts[0], 10);
17853 var month = parseInt(parts[1], 10);
17854 var day = parseInt(parts[2], 10);
17855
17856 if (month < 1 || year < 1 || day < 1) {
17857 return null;
17858 }
17859 return new Date(year, (month - 1), day);
17860 }
17861 return {
17862 priority: -100, // run after default uiGridEditor directive
17863 require: '?ngModel',
17864 link: function (scope, element, attrs, ngModel) {
17865 if (angular.version.minor === 2 && attrs.type && attrs.type === 'date' && ngModel) {
17866 ngModel.$formatters.push(function (modelValue) {
17867 ngModel.$setValidity(null,(!modelValue || !isNaN(modelValue.getTime())));
17868 return $filter('date')(modelValue, 'yyyy-MM-dd');
17869 });
17870
17871 ngModel.$parsers.push(function (viewValue) {
17872 if (viewValue && viewValue.length > 0) {
17873 var dateValue = parseDateString(viewValue);
17874 ngModel.$setValidity(null, (dateValue && !isNaN(dateValue.getTime())));
17875 return dateValue;
17876 }
17877 else {
17878 ngModel.$setValidity(null, true);
17879 return null;
17880 }
17881 });
17882 }
17883 }
17884 };
17885 }]);
17886
17887
17888 /**
17889 * @ngdoc directive
17890 * @name ui.grid.edit.directive:uiGridEditDropdown
17891 * @element div
17892 * @restrict A
17893 *
17894 * @description dropdown editor for editable fields.
17895 * Provides EndEdit and CancelEdit events
17896 *
17897 * Events that end editing:
17898 * blur and enter keydown, and any left/right nav
17899 *
17900 * Events that cancel editing:
17901 * - Esc keydown
17902 *
17903 */
17904 module.directive('uiGridEditDropdown',
17905 ['uiGridConstants', 'uiGridEditConstants', '$timeout',
17906 function (uiGridConstants, uiGridEditConstants, $timeout) {
17907 return {
17908 require: ['?^uiGrid', '?^uiGridRenderContainer'],
17909 scope: true,
17910 compile: function () {
17911 return {
17912 pre: function ($scope, $elm, $attrs) {
17913
17914 },
17915 post: function ($scope, $elm, $attrs, controllers) {
17916 var uiGridCtrl = controllers[0];
17917 var renderContainerCtrl = controllers[1];
17918
17919 // set focus at start of edit
17920 $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
17921 $timeout(function() {
17922 $elm[0].focus();
17923 });
17924
17925 $elm[0].style.width = ($elm[0].parentElement.offsetWidth - 1) + 'px';
17926 $elm.on('blur', function (evt) {
17927 $scope.stopEdit(evt);
17928 });
17929 });
17930
17931
17932 $scope.stopEdit = function (evt) {
17933 // no need to validate a dropdown - invalid values shouldn't be
17934 // available in the list
17935 $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
17936 };
17937
17938 $elm.on('keydown', function (evt) {
17939 switch (evt.keyCode) {
17940 case uiGridConstants.keymap.ESC:
17941 evt.stopPropagation();
17942 $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
17943 break;
17944 }
17945 if (uiGridCtrl && uiGridCtrl.grid.api.cellNav) {
17946 evt.uiGridTargetRenderContainerId = renderContainerCtrl.containerId;
17947 if (uiGridCtrl.cellNav.handleKeyDown(evt) !== null) {
17948 $scope.stopEdit(evt);
17949 }
17950 }
17951 else {
17952 // handle enter and tab for editing not using cellNav
17953 switch (evt.keyCode) {
17954 case uiGridConstants.keymap.ENTER: // Enter (Leave Field)
17955 case uiGridConstants.keymap.TAB:
17956 evt.stopPropagation();
17957 evt.preventDefault();
17958 $scope.stopEdit(evt);
17959 break;
17960 }
17961 }
17962 return true;
17963 });
17964
17965 $scope.$on('$destroy', function unbindEvents() {
17966 // unbind jquery events to prevent memory leaks
17967 $elm.off();
17968 });
17969 }
17970 };
17971 }
17972 };
17973 }]);
17974
17975 /**
17976 * @ngdoc directive
17977 * @name ui.grid.edit.directive:uiGridEditFileChooser
17978 * @element div
17979 * @restrict A
17980 *
17981 * @description input editor directive for editable fields.
17982 * Provides EndEdit and CancelEdit events
17983 *
17984 * Events that end editing:
17985 * blur and enter keydown
17986 *
17987 * Events that cancel editing:
17988 * - Esc keydown
17989 *
17990 */
17991 module.directive('uiGridEditFileChooser',
17992 ['gridUtil', 'uiGridConstants', 'uiGridEditConstants',
17993 function (gridUtil, uiGridConstants, uiGridEditConstants) {
17994 return {
17995 scope: true,
17996 require: ['?^uiGrid', '?^uiGridRenderContainer'],
17997 compile: function () {
17998 return {
17999 pre: function ($scope, $elm, $attrs) {
18000
18001 },
18002 post: function ($scope, $elm) {
18003 function handleFileSelect(event) {
18004 var target = event.srcElement || event.target;
18005
18006 if (target && target.files && target.files.length > 0) {
18007 /**
18008 * @ngdoc property
18009 * @name editFileChooserCallback
18010 * @propertyOf ui.grid.edit.api:ColumnDef
18011 * @description A function that should be called when any files have been chosen
18012 * by the user. You should use this to process the files appropriately for your
18013 * application.
18014 *
18015 * It passes the gridCol, the gridRow (from which you can get gridRow.entity),
18016 * and the files. The files are in the format as returned from the file chooser,
18017 * an array of files, with each having useful information such as:
18018 * - `files[0].lastModifiedDate`
18019 * - `files[0].name`
18020 * - `files[0].size` (appears to be in bytes)
18021 * - `files[0].type` (MIME type by the looks)
18022 *
18023 * Typically you would do something with these files - most commonly you would
18024 * use the filename or read the file itself in. The example function does both.
18025 *
18026 * @example
18027 * <pre>
18028 * editFileChooserCallBack: function(gridRow, gridCol, files ) {
18029 * // ignore all but the first file, it can only choose one anyway
18030 * // set the filename into this column
18031 * gridRow.entity.filename = file[0].name;
18032 *
18033 * // read the file and set it into a hidden column, which we may do stuff with later
18034 * var setFile = function(fileContent) {
18035 * gridRow.entity.file = fileContent.currentTarget.result;
18036 * };
18037 * var reader = new FileReader();
18038 * reader.onload = setFile;
18039 * reader.readAsText( files[0] );
18040 * }
18041 * </pre>
18042 */
18043 if ( typeof($scope.col.colDef.editFileChooserCallback) === 'function' ) {
18044 $scope.col.colDef.editFileChooserCallback($scope.row, $scope.col, target.files);
18045 } else {
18046 gridUtil.logError('You need to set colDef.editFileChooserCallback to use the file chooser');
18047 }
18048
18049 target.form.reset();
18050 $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
18051 } else {
18052 $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
18053 }
18054 $elm[0].removeEventListener('change', handleFileSelect, false);
18055 }
18056
18057 $elm[0].addEventListener('change', handleFileSelect, false);
18058
18059 $scope.$on(uiGridEditConstants.events.BEGIN_CELL_EDIT, function () {
18060 $elm[0].focus();
18061 $elm[0].select();
18062
18063 $elm.on('blur', function () {
18064 $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
18065 $elm.off();
18066 });
18067 });
18068 }
18069 };
18070 }
18071 };
18072 }]);
18073 })();
18074
18075 (function () {
18076 'use strict';
18077
18078 /**
18079 * @ngdoc overview
18080 * @name ui.grid.emptyBaseLayer
18081 * @description
18082 *
18083 * # ui.grid.emptyBaseLayer
18084 *
18085 * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
18086 *
18087 * This module provides the ability to have the background of the ui-grid be empty rows, this would be displayed in the case were
18088 * the grid height is greater then the amount of rows displayed.
18089 *
18090 * <div doc-module-components="ui.grid.emptyBaseLayer"></div>
18091 */
18092 var module = angular.module('ui.grid.emptyBaseLayer', ['ui.grid']);
18093
18094
18095 /**
18096 * @ngdoc service
18097 * @name ui.grid.emptyBaseLayer.service:uiGridBaseLayerService
18098 *
18099 * @description Services for the empty base layer grid
18100 */
18101 module.service('uiGridBaseLayerService', ['gridUtil', '$compile', function (gridUtil, $compile) {
18102 return {
18103 initializeGrid: function (grid, disableEmptyBaseLayer) {
18104
18105 /**
18106 * @ngdoc object
18107 * @name ui.grid.emptyBaseLayer.api:GridOptions
18108 *
18109 * @description GridOptions for emptyBaseLayer feature, these are available to be
18110 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
18111 */
18112 grid.baseLayer = {
18113 emptyRows: []
18114 };
18115
18116 /**
18117 * @ngdoc object
18118 * @name enableEmptyGridBaseLayer
18119 * @propertyOf ui.grid.emptyBaseLayer.api:GridOptions
18120 * @description Enable empty base layer, which shows empty rows as background on the entire grid
18121 * <br/>Defaults to true, if the directive is used.
18122 * <br/>Set to false either by setting this attribute or passing false to the directive.
18123 */
18124 // default option to true unless it was explicitly set to false
18125 if (grid.options.enableEmptyGridBaseLayer !== false) {
18126 grid.options.enableEmptyGridBaseLayer = !disableEmptyBaseLayer;
18127 }
18128 },
18129
18130 setNumberOfEmptyRows: function(viewportHeight, grid) {
18131 var rowHeight = grid.options.rowHeight,
18132 rows = Math.ceil(viewportHeight / rowHeight);
18133
18134 if (rows > 0) {
18135 grid.baseLayer.emptyRows = [];
18136 for (var i = 0; i < rows; i++) {
18137 grid.baseLayer.emptyRows.push({});
18138 }
18139 }
18140 }
18141 };
18142 }]);
18143
18144 /**
18145 * @ngdoc object
18146 * @name ui.grid.emptyBaseLayer.directive:uiGridEmptyBaseLayer
18147 * @description Shows empty rows in the background of the ui-grid, these span
18148 * the full height of the ui-grid, so that there won't be blank space below the shown rows.
18149 * @example
18150 * <pre>
18151 * <div ui-grid="gridOptions" class="grid" ui-grid-empty-base-layer></div>
18152 * </pre>
18153 * Or you can enable/disable it dynamically by passing in true or false. It doesn't
18154 * the value, so it would only be set on initial render.
18155 * <pre>
18156 * <div ui-grid="gridOptions" class="grid" ui-grid-empty-base-layer="false"></div>
18157 * </pre>
18158 */
18159 module.directive('uiGridEmptyBaseLayer', ['gridUtil', 'uiGridBaseLayerService',
18160 '$parse',
18161 function (gridUtil, uiGridBaseLayerService, $parse) {
18162 return {
18163 require: '^uiGrid',
18164 scope: false,
18165 compile: function () {
18166 return {
18167 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
18168 var disableEmptyBaseLayer = $parse($attrs.uiGridEmptyBaseLayer)($scope) === false;
18169
18170 uiGridBaseLayerService.initializeGrid(uiGridCtrl.grid, disableEmptyBaseLayer);
18171 },
18172 post: function ($scope, $elm, $attrs, uiGridCtrl) {
18173 if (!uiGridCtrl.grid.options.enableEmptyGridBaseLayer) {
18174 return;
18175 }
18176
18177 var renderBodyContainer = uiGridCtrl.grid.renderContainers.body,
18178 viewportHeight = renderBodyContainer.getViewportHeight();
18179
18180 function heightHasChanged() {
18181 var newViewPortHeight = renderBodyContainer.getViewportHeight();
18182
18183 if (newViewPortHeight !== viewportHeight) {
18184 viewportHeight = newViewPortHeight;
18185 return true;
18186 }
18187 return false;
18188 }
18189
18190 function getEmptyBaseLayerCss(viewportHeight) {
18191 // Set ui-grid-empty-base-layer height
18192 return '.grid' + uiGridCtrl.grid.id +
18193 ' .ui-grid-render-container ' +
18194 '.ui-grid-empty-base-layer-container.ui-grid-canvas ' +
18195 '{ height: ' + viewportHeight + 'px; }';
18196 }
18197
18198 uiGridCtrl.grid.registerStyleComputation({
18199 func: function() {
18200 if (heightHasChanged()) {
18201 uiGridBaseLayerService.setNumberOfEmptyRows(viewportHeight, uiGridCtrl.grid);
18202 }
18203 return getEmptyBaseLayerCss(viewportHeight);
18204 }
18205 });
18206 }
18207 };
18208 }
18209 };
18210 }]);
18211
18212 /**
18213 * @ngdoc directive
18214 * @name ui.grid.emptyBaseLayer.directive:uiGridViewport
18215 * @description stacks on the uiGridViewport directive to append the empty grid base layer html elements to the
18216 * default gridRow template
18217 */
18218 module.directive('uiGridViewport',
18219 ['$compile', 'gridUtil', '$templateCache',
18220 function ($compile, gridUtil, $templateCache) {
18221 return {
18222 priority: -200,
18223 scope: false,
18224 compile: function ($elm) {
18225 var emptyBaseLayerContainer = $templateCache.get('ui-grid/emptyBaseLayerContainer');
18226 $elm.prepend(emptyBaseLayerContainer);
18227 return {
18228 pre: function ($scope, $elm, $attrs, controllers) {
18229 },
18230 post: function ($scope, $elm, $attrs, controllers) {
18231 }
18232 };
18233 }
18234 };
18235 }]);
18236
18237 })();
18238
18239 (function () {
18240 'use strict';
18241
18242 /**
18243 * @ngdoc overview
18244 * @name ui.grid.expandable
18245 * @description
18246 *
18247 * # ui.grid.expandable
18248 *
18249 * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
18250 *
18251 * This module provides the ability to create subgrids with the ability to expand a row
18252 * to show the subgrid.
18253 *
18254 * <div doc-module-components="ui.grid.expandable"></div>
18255 */
18256 var module = angular.module('ui.grid.expandable', ['ui.grid']);
18257
18258 /**
18259 * @ngdoc service
18260 * @name ui.grid.expandable.service:uiGridExpandableService
18261 *
18262 * @description Services for the expandable grid
18263 */
18264 module.service('uiGridExpandableService', ['gridUtil', function (gridUtil) {
18265 var service = {
18266 initializeGrid: function (grid) {
18267
18268 grid.expandable = {};
18269 grid.expandable.expandedAll = false;
18270
18271 /**
18272 * @ngdoc boolean
18273 * @name enableOnDblClickExpand
18274 * @propertyOf ui.grid.expandable.api:GridOptions
18275 * @description Defaults to true.
18276 * @example
18277 * <pre>
18278 * $scope.gridOptions = {
18279 * onDblClickExpand: false
18280 * }
18281 * </pre>
18282 */
18283 grid.options.enableOnDblClickExpand = grid.options.enableOnDblClickExpand !== false;
18284 /**
18285 * @ngdoc boolean
18286 * @name enableExpandable
18287 * @propertyOf ui.grid.expandable.api:GridOptions
18288 * @description Whether or not to use expandable feature, allows you to turn off expandable on specific grids
18289 * within your application, or in specific modes on _this_ grid. Defaults to true.
18290 * @example
18291 * <pre>
18292 * $scope.gridOptions = {
18293 * enableExpandable: false
18294 * }
18295 * </pre>
18296 */
18297 grid.options.enableExpandable = grid.options.enableExpandable !== false;
18298
18299 /**
18300 * @ngdoc object
18301 * @name showExpandAllButton
18302 * @propertyOf ui.grid.expandable.api:GridOptions
18303 * @description Whether or not to display the expand all button, allows you to hide expand all button on specific grids
18304 * within your application, or in specific modes on _this_ grid. Defaults to true.
18305 * @example
18306 * <pre>
18307 * $scope.gridOptions = {
18308 * showExpandAllButton: false
18309 * }
18310 * </pre>
18311 */
18312 grid.options.showExpandAllButton = grid.options.showExpandAllButton !== false;
18313
18314 /**
18315 * @ngdoc object
18316 * @name expandableRowHeight
18317 * @propertyOf ui.grid.expandable.api:GridOptions
18318 * @description Height in pixels of the expanded subgrid. Defaults to
18319 * 150
18320 * @example
18321 * <pre>
18322 * $scope.gridOptions = {
18323 * expandableRowHeight: 150
18324 * }
18325 * </pre>
18326 */
18327 grid.options.expandableRowHeight = grid.options.expandableRowHeight || 150;
18328
18329 /**
18330 * @ngdoc object
18331 * @name expandableRowHeaderWidth
18332 * @propertyOf ui.grid.expandable.api:GridOptions
18333 * @description Width in pixels of the expandable column. Defaults to 40
18334 * @example
18335 * <pre>
18336 * $scope.gridOptions = {
18337 * expandableRowHeaderWidth: 40
18338 * }
18339 * </pre>
18340 */
18341 grid.options.expandableRowHeaderWidth = grid.options.expandableRowHeaderWidth || 40;
18342
18343 /**
18344 * @ngdoc object
18345 * @name expandableRowTemplate
18346 * @propertyOf ui.grid.expandable.api:GridOptions
18347 * @description Mandatory. The template for your expanded row
18348 * @example
18349 * <pre>
18350 * $scope.gridOptions = {
18351 * expandableRowTemplate: 'expandableRowTemplate.html'
18352 * }
18353 * </pre>
18354 */
18355 if ( grid.options.enableExpandable && !grid.options.expandableRowTemplate ) {
18356 gridUtil.logError( 'You have not set the expandableRowTemplate, disabling expandable module' );
18357 grid.options.enableExpandable = false;
18358 }
18359
18360 /**
18361 * @ngdoc object
18362 * @name ui.grid.expandable.api:PublicApi
18363 *
18364 * @description Public Api for expandable feature
18365 */
18366 /**
18367 * @ngdoc object
18368 * @name ui.grid.expandable.api:GridRow
18369 *
18370 * @description Additional properties added to GridRow when using the expandable module
18371 */
18372 /**
18373 * @ngdoc object
18374 * @name ui.grid.expandable.api:GridOptions
18375 *
18376 * @description Options for configuring the expandable feature, these are available to be
18377 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
18378 */
18379 var publicApi = {
18380 events: {
18381 expandable: {
18382 /**
18383 * @ngdoc event
18384 * @name rowExpandedBeforeStateChanged
18385 * @eventOf ui.grid.expandable.api:PublicApi
18386 * @description raised when row is expanding or collapsing
18387 * <pre>
18388 * gridApi.expandable.on.rowExpandedBeforeStateChanged(scope,function(row, event) {})
18389 * </pre>
18390 * @param {scope} scope the application scope
18391 * @param {GridRow} row the row that was expanded
18392 * @param {Event} evt object if raised from an event
18393 */
18394 rowExpandedBeforeStateChanged: function(scope, row, evt) {},
18395
18396 /**
18397 * @ngdoc event
18398 * @name rowExpandedStateChanged
18399 * @eventOf ui.grid.expandable.api:PublicApi
18400 * @description raised when row expanded or collapsed
18401 * <pre>
18402 * gridApi.expandable.on.rowExpandedStateChanged(scope,function(row, event) {})
18403 * </pre>
18404 * @param {scope} scope the application scope
18405 * @param {GridRow} row the row that was expanded
18406 * @param {Event} evt object if raised from an event
18407 */
18408 rowExpandedStateChanged: function (scope, row, evt) {},
18409
18410 /**
18411 * @ngdoc event
18412 * @name rowExpandedRendered
18413 * @eventOf ui.grid.expandable.api:PublicApi
18414 * @description raised when expanded row is rendered
18415 * <pre>
18416 * gridApi.expandable.on.rowExpandedRendered(scope,function(row, event) {})
18417 * </pre>
18418 * @param {scope} scope the application scope
18419 * @param {GridRow} row the row that was expanded
18420 * @param {Event} evt object if raised from an event
18421 */
18422 rowExpandedRendered: function (scope, row, evt) {}
18423 }
18424 },
18425
18426 methods: {
18427 expandable: {
18428 /**
18429 * @ngdoc method
18430 * @name toggleRowExpansion
18431 * @methodOf ui.grid.expandable.api:PublicApi
18432 * @description Toggle a specific row
18433 * <pre>
18434 * gridApi.expandable.toggleRowExpansion(rowEntity, event);
18435 * </pre>
18436 * @param {object} rowEntity the data entity for the row you want to expand
18437 * @param {Event} [e] event (if exist)
18438 */
18439 toggleRowExpansion: function (rowEntity, e) {
18440 var row = grid.getRow(rowEntity);
18441
18442 if (row !== null) {
18443 service.toggleRowExpansion(grid, row, e);
18444 }
18445 },
18446
18447 /**
18448 * @ngdoc method
18449 * @name expandAllRows
18450 * @methodOf ui.grid.expandable.api:PublicApi
18451 * @description Expand all subgrids.
18452 * <pre>
18453 * gridApi.expandable.expandAllRows();
18454 * </pre>
18455 */
18456 expandAllRows: function() {
18457 service.expandAllRows(grid);
18458 },
18459
18460 /**
18461 * @ngdoc method
18462 * @name collapseAllRows
18463 * @methodOf ui.grid.expandable.api:PublicApi
18464 * @description Collapse all subgrids.
18465 * <pre>
18466 * gridApi.expandable.collapseAllRows();
18467 * </pre>
18468 */
18469 collapseAllRows: function() {
18470 service.collapseAllRows(grid);
18471 },
18472
18473 /**
18474 * @ngdoc method
18475 * @name toggleAllRows
18476 * @methodOf ui.grid.expandable.api:PublicApi
18477 * @description Toggle all subgrids.
18478 * <pre>
18479 * gridApi.expandable.toggleAllRows();
18480 * </pre>
18481 */
18482 toggleAllRows: function() {
18483 service.toggleAllRows(grid);
18484 },
18485 /**
18486 * @ngdoc function
18487 * @name expandRow
18488 * @methodOf ui.grid.expandable.api:PublicApi
18489 * @description Expand the data row
18490 * @param {object} rowEntity gridOptions.data[] array instance
18491 */
18492 expandRow: function (rowEntity) {
18493 var row = grid.getRow(rowEntity);
18494
18495 if (row !== null && !row.isExpanded) {
18496 service.toggleRowExpansion(grid, row);
18497 }
18498 },
18499 /**
18500 * @ngdoc function
18501 * @name collapseRow
18502 * @methodOf ui.grid.expandable.api:PublicApi
18503 * @description Collapse the data row
18504 * @param {object} rowEntity gridOptions.data[] array instance
18505 */
18506 collapseRow: function (rowEntity) {
18507 var row = grid.getRow(rowEntity);
18508
18509 if (row !== null && row.isExpanded) {
18510 service.toggleRowExpansion(grid, row);
18511 }
18512 },
18513 /**
18514 * @ngdoc function
18515 * @name getExpandedRows
18516 * @methodOf ui.grid.expandable.api:PublicApi
18517 * @description returns all expandedRow's entity references
18518 */
18519 getExpandedRows: function () {
18520 return service.getExpandedRows(grid).map(function (gridRow) {
18521 return gridRow.entity;
18522 });
18523 }
18524 }
18525 }
18526 };
18527 grid.api.registerEventsFromObject(publicApi.events);
18528 grid.api.registerMethodsFromObject(publicApi.methods);
18529 },
18530
18531 /**
18532 *
18533 * @param grid
18534 * @param row
18535 * @param {Event} [e] event (if exist)
18536 */
18537 toggleRowExpansion: function (grid, row, e) {
18538 // trigger the "before change" event. Can change row height dynamically this way.
18539 grid.api.expandable.raise.rowExpandedBeforeStateChanged(row);
18540 /**
18541 * @ngdoc object
18542 * @name isExpanded
18543 * @propertyOf ui.grid.expandable.api:GridRow
18544 * @description Whether or not the row is currently expanded.
18545 * @example
18546 * <pre>
18547 * $scope.api.expandable.on.rowExpandedStateChanged($scope, function (row) {
18548 * if (row.isExpanded) {
18549 * //...
18550 * }
18551 * });
18552 * </pre>
18553 */
18554 row.isExpanded = !row.isExpanded;
18555 if (angular.isUndefined(row.expandedRowHeight)) {
18556 row.expandedRowHeight = grid.options.expandableRowHeight;
18557 }
18558
18559 if (row.isExpanded) {
18560 row.height = row.grid.options.rowHeight + row.expandedRowHeight;
18561 grid.expandable.expandedAll = service.getExpandedRows(grid).length === grid.rows.length;
18562 }
18563 else {
18564 row.height = row.grid.options.rowHeight;
18565 grid.expandable.expandedAll = false;
18566 }
18567 grid.api.expandable.raise.rowExpandedStateChanged(row, e);
18568
18569 // fire event on render complete
18570 function _tWatcher() {
18571 if (row.expandedRendered) {
18572 grid.api.expandable.raise.rowExpandedRendered(row, e);
18573 }
18574 else {
18575 window.setTimeout(_tWatcher, 1e2);
18576 }
18577 }
18578 _tWatcher();
18579 },
18580
18581 expandAllRows: function(grid) {
18582 grid.renderContainers.body.visibleRowCache.forEach( function(row) {
18583 if (!row.isExpanded && !(row.entity.subGridOptions && row.entity.subGridOptions.disableRowExpandable)) {
18584 service.toggleRowExpansion(grid, row);
18585 }
18586 });
18587 grid.expandable.expandedAll = true;
18588 grid.queueGridRefresh();
18589 },
18590
18591 collapseAllRows: function(grid) {
18592 grid.renderContainers.body.visibleRowCache.forEach( function(row) {
18593 if (row.isExpanded) {
18594 service.toggleRowExpansion(grid, row);
18595 }
18596 });
18597 grid.expandable.expandedAll = false;
18598 grid.queueGridRefresh();
18599 },
18600
18601 toggleAllRows: function(grid) {
18602 if (grid.expandable.expandedAll) {
18603 service.collapseAllRows(grid);
18604 }
18605 else {
18606 service.expandAllRows(grid);
18607 }
18608 },
18609
18610 getExpandedRows: function (grid) {
18611 return grid.rows.filter(function (row) {
18612 return row.isExpanded;
18613 });
18614 }
18615 };
18616 return service;
18617 }]);
18618
18619 /**
18620 * @ngdoc object
18621 * @name enableExpandableRowHeader
18622 * @propertyOf ui.grid.expandable.api:GridOptions
18623 * @description Show a rowHeader to provide the expandable buttons. If set to false then implies
18624 * you're going to use a custom method for expanding and collapsing the subgrids. Defaults to true.
18625 * @example
18626 * <pre>
18627 * $scope.gridOptions = {
18628 * enableExpandableRowHeader: false
18629 * }
18630 * </pre>
18631 */
18632
18633 module.directive('uiGridExpandable', ['uiGridExpandableService', '$templateCache',
18634 function (uiGridExpandableService, $templateCache) {
18635 return {
18636 replace: true,
18637 priority: 0,
18638 require: '^uiGrid',
18639 scope: false,
18640 compile: function () {
18641 return {
18642 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
18643 uiGridExpandableService.initializeGrid(uiGridCtrl.grid);
18644
18645 if (!uiGridCtrl.grid.options.enableExpandable) {
18646 return;
18647 }
18648
18649 if (uiGridCtrl.grid.options.enableExpandableRowHeader !== false ) {
18650 var expandableRowHeaderColDef = {
18651 name: 'expandableButtons',
18652 displayName: '',
18653 exporterSuppressExport: true,
18654 enableColumnResizing: false,
18655 enableColumnMenu: false,
18656 width: uiGridCtrl.grid.options.expandableRowHeaderWidth || 30
18657 };
18658
18659 expandableRowHeaderColDef.cellTemplate = $templateCache.get('ui-grid/expandableRowHeader');
18660 expandableRowHeaderColDef.headerCellTemplate = $templateCache.get('ui-grid/expandableTopRowHeader');
18661 uiGridCtrl.grid.addRowHeaderColumn(expandableRowHeaderColDef, -90);
18662 }
18663 },
18664 post: function ($scope, $elm, $attrs, uiGridCtrl) {}
18665 };
18666 }
18667 };
18668 }]);
18669
18670 /**
18671 * @ngdoc directive
18672 * @name ui.grid.expandable.directive:uiGrid
18673 * @description stacks on the uiGrid directive to register child grid with parent row when child is created
18674 */
18675 module.directive('uiGrid',
18676 function () {
18677 return {
18678 replace: true,
18679 priority: 599,
18680 require: '^uiGrid',
18681 scope: false,
18682 compile: function () {
18683 return {
18684 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
18685
18686 uiGridCtrl.grid.api.core.on.renderingComplete($scope, function() {
18687 // if a parent grid row is on the scope, then add the parentRow property to this childGrid
18688 if ($scope.row && $scope.row.grid && $scope.row.grid.options
18689 && $scope.row.grid.options.enableExpandable) {
18690
18691 /**
18692 * @ngdoc directive
18693 * @name ui.grid.expandable.class:Grid
18694 * @description Additional Grid properties added by expandable module
18695 */
18696
18697 /**
18698 * @ngdoc object
18699 * @name parentRow
18700 * @propertyOf ui.grid.expandable.class:Grid
18701 * @description reference to the expanded parent row that owns this grid
18702 */
18703 uiGridCtrl.grid.parentRow = $scope.row;
18704
18705 // todo: adjust height on parent row when child grid height changes. we need some sort of gridHeightChanged event
18706 // uiGridCtrl.grid.core.on.canvasHeightChanged($scope, function(oldHeight, newHeight) {
18707 // uiGridCtrl.grid.parentRow = newHeight;
18708 // });
18709 }
18710 });
18711 },
18712 post: function ($scope, $elm, $attrs, uiGridCtrl) {}
18713 };
18714 }
18715 };
18716 });
18717
18718 /**
18719 * @ngdoc directive
18720 * @name ui.grid.expandable.directive:uiGridExpandableRow
18721 * @description directive to render the Row template on Expand
18722 */
18723 module.directive('uiGridExpandableRow',
18724 ['uiGridExpandableService', '$compile', 'uiGridConstants','gridUtil',
18725 function (uiGridExpandableService, $compile, uiGridConstants, gridUtil) {
18726
18727 return {
18728 replace: false,
18729 priority: 0,
18730 scope: false,
18731 compile: function () {
18732 return {
18733 pre: function ($scope, $elm) {
18734 gridUtil.getTemplate($scope.grid.options.expandableRowTemplate).then(
18735 function (template) {
18736 if ($scope.grid.options.expandableRowScope) {
18737 /**
18738 * @ngdoc object
18739 * @name expandableRowScope
18740 * @propertyOf ui.grid.expandable.api:GridOptions
18741 * @description Variables of object expandableScope will be available in the scope of the expanded subgrid
18742 * @example
18743 * <pre>
18744 * $scope.gridOptions = {
18745 * expandableRowScope: expandableScope
18746 * }
18747 * </pre>
18748 */
18749 var expandableRowScope = $scope.grid.options.expandableRowScope;
18750
18751 for (var property in expandableRowScope) {
18752 if (expandableRowScope.hasOwnProperty(property)) {
18753 $scope[property] = expandableRowScope[property];
18754 }
18755 }
18756 }
18757 var expandedRowElement = angular.element(template);
18758
18759 expandedRowElement = $compile(expandedRowElement)($scope);
18760 $elm.append(expandedRowElement);
18761 $scope.row.element = $elm;
18762 $scope.row.expandedRendered = true;
18763 });
18764 },
18765
18766 post: function ($scope, $elm) {
18767 $scope.row.element = $elm;
18768 $scope.$on('$destroy', function() {
18769 $scope.row.expandedRendered = false;
18770 });
18771 }
18772 };
18773 }
18774 };
18775 }]);
18776
18777 /**
18778 * @ngdoc directive
18779 * @name ui.grid.expandable.directive:uiGridRow
18780 * @description stacks on the uiGridRow directive to add support for expandable rows
18781 */
18782 module.directive('uiGridRow',
18783 function () {
18784 return {
18785 priority: -200,
18786 scope: false,
18787 compile: function () {
18788 return {
18789 pre: function ($scope, $elm) {
18790 if (!$scope.grid.options.enableExpandable) {
18791 return;
18792 }
18793
18794 $scope.expandableRow = {};
18795
18796 $scope.expandableRow.shouldRenderExpand = function () {
18797 return $scope.colContainer.name === 'body'
18798 && $scope.grid.options.enableExpandable !== false
18799 && $scope.row.isExpanded
18800 && (!$scope.grid.isScrollingVertically || $scope.row.expandedRendered);
18801 };
18802
18803 $scope.expandableRow.shouldRenderFiller = function () {
18804 return $scope.row.isExpanded
18805 && (
18806 $scope.colContainer.name !== 'body'
18807 || ($scope.grid.isScrollingVertically && !$scope.row.expandedRendered));
18808 };
18809
18810 if ($scope.grid.options.enableOnDblClickExpand) {
18811 $elm.on('dblclick', function (event) {
18812 // if necessary, it is possible for everyone to stop the processing of a single click OR
18813 // Inside the Config in the output agent to enter a line:
18814 // event.stopPropagation()
18815 $scope.grid.api.expandable.toggleRowExpansion($scope.row.entity, event);
18816 });
18817 }
18818 },
18819 post: function ($scope, $elm, $attrs, controllers) {}
18820 };
18821 }
18822 };
18823 });
18824
18825 /**
18826 * @ngdoc directive
18827 * @name ui.grid.expandable.directive:uiGridViewport
18828 * @description stacks on the uiGridViewport directive to append the expandable row html elements to the
18829 * default gridRow template
18830 */
18831 module.directive('uiGridViewport',
18832 ['$compile', 'gridUtil', '$templateCache',
18833 function ($compile, gridUtil, $templateCache) {
18834 return {
18835 priority: -200,
18836 scope: false,
18837 compile: function ($elm) {
18838
18839 // todo: this adds ng-if watchers to each row even if the grid is not using expandable directive
18840 // or options.enableExpandable == false
18841 // The alternative is to compile the template and append to each row in a uiGridRow directive
18842
18843 var rowRepeatDiv = angular.element($elm.children().children()[0]),
18844 expandedRowFillerElement = $templateCache.get('ui-grid/expandableScrollFiller'),
18845 expandedRowElement = $templateCache.get('ui-grid/expandableRow');
18846
18847 rowRepeatDiv.append(expandedRowElement);
18848 rowRepeatDiv.append(expandedRowFillerElement);
18849 return {
18850 pre: function ($scope, $elm, $attrs, controllers) {
18851 },
18852 post: function ($scope, $elm, $attrs, controllers) {
18853 }
18854 };
18855 }
18856 };
18857 }]);
18858
18859 })();
18860
18861 /* global ExcelBuilder */
18862 /* global console */
18863
18864 (function () {
18865 'use strict';
18866
18867 /**
18868 * @ngdoc overview
18869 * @name ui.grid.exporter
18870 * @description
18871 *
18872 * # ui.grid.exporter
18873 *
18874 * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
18875 *
18876 * This module provides the ability to export data from the grid.
18877 *
18878 * Data can be exported in a range of formats, and all data, visible
18879 * data, or selected rows can be exported, with all columns or visible
18880 * columns.
18881 *
18882 * No UI is provided, the caller should provide their own UI/buttons
18883 * as appropriate, or enable the gridMenu
18884 *
18885 * <br/>
18886 * <br/>
18887 *
18888 * <div doc-module-components="ui.grid.exporter"></div>
18889 */
18890
18891 var module = angular.module('ui.grid.exporter', ['ui.grid']);
18892
18893 /**
18894 * @ngdoc object
18895 * @name ui.grid.exporter.constant:uiGridExporterConstants
18896 *
18897 * @description constants available in exporter module
18898 */
18899 /**
18900 * @ngdoc property
18901 * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
18902 * @name ALL
18903 * @description export all data, including data not visible. Can
18904 * be set for either rowTypes or colTypes
18905 */
18906 /**
18907 * @ngdoc property
18908 * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
18909 * @name VISIBLE
18910 * @description export only visible data, including data not visible. Can
18911 * be set for either rowTypes or colTypes
18912 */
18913 /**
18914 * @ngdoc property
18915 * @propertyOf ui.grid.exporter.constant:uiGridExporterConstants
18916 * @name SELECTED
18917 * @description export all data, including data not visible. Can
18918 * be set only for rowTypes, selection of only some columns is
18919 * not supported
18920 */
18921 module.constant('uiGridExporterConstants', {
18922 featureName: 'exporter',
18923 rowHeaderColName: 'treeBaseRowHeaderCol',
18924 selectionRowHeaderColName: 'selectionRowHeaderCol',
18925 ALL: 'all',
18926 VISIBLE: 'visible',
18927 SELECTED: 'selected',
18928 CSV_CONTENT: 'CSV_CONTENT',
18929 BUTTON_LABEL: 'BUTTON_LABEL',
18930 FILE_NAME: 'FILE_NAME'
18931 });
18932
18933 /**
18934 * @ngdoc service
18935 * @name ui.grid.exporter.service:uiGridExporterService
18936 *
18937 * @description Services for exporter feature
18938 */
18939 module.service('uiGridExporterService', ['$filter', '$q', 'uiGridExporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService',
18940 function ($filter, $q, uiGridExporterConstants, gridUtil, $compile, $interval, i18nService) {
18941 var service = {
18942
18943 delay: 100,
18944
18945 initializeGrid: function (grid) {
18946
18947 // add feature namespace and any properties to grid for needed state
18948 grid.exporter = {};
18949 this.defaultGridOptions(grid.options);
18950
18951 /**
18952 * @ngdoc object
18953 * @name ui.grid.exporter.api:PublicApi
18954 *
18955 * @description Public Api for exporter feature
18956 */
18957 var publicApi = {
18958 events: {
18959 exporter: {
18960 }
18961 },
18962 methods: {
18963 exporter: {
18964 /**
18965 * @ngdoc function
18966 * @name csvExport
18967 * @methodOf ui.grid.exporter.api:PublicApi
18968 * @description Exports rows from the grid in csv format,
18969 * the data exported is selected based on the provided options
18970 * @param {string} rowTypes which rows to export, valid values are
18971 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
18972 * uiGridExporterConstants.SELECTED
18973 * @param {string} colTypes which columns to export, valid values are
18974 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
18975 */
18976 csvExport: function (rowTypes, colTypes) {
18977 service.csvExport(grid, rowTypes, colTypes);
18978 },
18979 /**
18980 * @ngdoc function
18981 * @name pdfExport
18982 * @methodOf ui.grid.exporter.api:PublicApi
18983 * @description Exports rows from the grid in pdf format,
18984 * the data exported is selected based on the provided options
18985 * Note that this function has a dependency on pdfMake, all
18986 * going well this has been installed for you.
18987 * The resulting pdf opens in a new browser window.
18988 * @param {string} rowTypes which rows to export, valid values are
18989 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
18990 * uiGridExporterConstants.SELECTED
18991 * @param {string} colTypes which columns to export, valid values are
18992 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
18993 */
18994 pdfExport: function (rowTypes, colTypes) {
18995 service.pdfExport(grid, rowTypes, colTypes);
18996 },
18997 /**
18998 * @ngdoc function
18999 * @name excelExport
19000 * @methodOf ui.grid.exporter.api:PublicApi
19001 * @description Exports rows from the grid in excel format,
19002 * the data exported is selected based on the provided options
19003 * @param {string} rowTypes which rows to export, valid values are
19004 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
19005 * uiGridExporterConstants.SELECTED
19006 * @param {string} colTypes which columns to export, valid values are
19007 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE
19008 */
19009 excelExport: function (rowTypes, colTypes) {
19010 service.excelExport(grid, rowTypes, colTypes);
19011 }
19012 }
19013 }
19014 };
19015
19016 grid.api.registerEventsFromObject(publicApi.events);
19017
19018 grid.api.registerMethodsFromObject(publicApi.methods);
19019
19020 if (grid.api.core.addToGridMenu) {
19021 service.addToMenu( grid );
19022 } else {
19023 // order of registration is not guaranteed, register in a little while
19024 $interval( function() {
19025 if (grid.api.core.addToGridMenu) {
19026 service.addToMenu( grid );
19027 }
19028 }, this.delay, 1);
19029 }
19030
19031 },
19032
19033 defaultGridOptions: function (gridOptions) {
19034 // default option to true unless it was explicitly set to false
19035 /**
19036 * @ngdoc object
19037 * @name ui.grid.exporter.api:GridOptions
19038 *
19039 * @description GridOptions for exporter feature, these are available to be
19040 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
19041 */
19042 /**
19043 * @ngdoc object
19044 * @name ui.grid.exporter.api:ColumnDef
19045 * @description ColumnDef settings for exporter
19046 */
19047 /**
19048 * @ngdoc object
19049 * @name exporterSuppressMenu
19050 * @propertyOf ui.grid.exporter.api:GridOptions
19051 * @description Don't show the export menu button, implying the user
19052 * will roll their own UI for calling the exporter
19053 * <br/>Defaults to false
19054 */
19055 gridOptions.exporterSuppressMenu = gridOptions.exporterSuppressMenu === true;
19056 /**
19057 * @ngdoc object
19058 * @name exporterMenuLabel
19059 * @propertyOf ui.grid.exporter.api:GridOptions
19060 * @description The text to show on the exporter menu button
19061 * link
19062 * <br/>Defaults to 'Export'
19063 */
19064 gridOptions.exporterMenuLabel = gridOptions.exporterMenuLabel ? gridOptions.exporterMenuLabel : 'Export';
19065 /**
19066 * @ngdoc object
19067 * @name exporterSuppressColumns
19068 * @propertyOf ui.grid.exporter.api:GridOptions
19069 * @description Columns that should not be exported. The selectionRowHeader is already automatically
19070 * suppressed, but if you had a button column or some other "system" column that shouldn't be shown in the
19071 * output then add it in this list. You should provide an array of column names.
19072 * <br/>Defaults to: []
19073 * <pre>
19074 * gridOptions.exporterSuppressColumns = [ 'buttons' ];
19075 * </pre>
19076 */
19077 gridOptions.exporterSuppressColumns = gridOptions.exporterSuppressColumns ? gridOptions.exporterSuppressColumns : [];
19078 /**
19079 * @ngdoc object
19080 * @name exporterCsvColumnSeparator
19081 * @propertyOf ui.grid.exporter.api:GridOptions
19082 * @description The character to use as column separator
19083 * link
19084 * <br/>Defaults to ','
19085 */
19086 gridOptions.exporterCsvColumnSeparator = gridOptions.exporterCsvColumnSeparator ? gridOptions.exporterCsvColumnSeparator : ',';
19087 /**
19088 * @ngdoc object
19089 * @name exporterCsvFilename
19090 * @propertyOf ui.grid.exporter.api:GridOptions
19091 * @description The default filename to use when saving the downloaded csv.
19092 * This will only work in some browsers.
19093 * <br/>Defaults to 'download.csv'
19094 */
19095 gridOptions.exporterCsvFilename = gridOptions.exporterCsvFilename ? gridOptions.exporterCsvFilename : 'download.csv';
19096 /**
19097 * @ngdoc object
19098 * @name exporterPdfFilename
19099 * @propertyOf ui.grid.exporter.api:GridOptions
19100 * @description The default filename to use when saving the downloaded pdf, only used in IE (other browsers open pdfs in a new window)
19101 * <br/>Defaults to 'download.pdf'
19102 */
19103 gridOptions.exporterPdfFilename = gridOptions.exporterPdfFilename ? gridOptions.exporterPdfFilename : 'download.pdf';
19104 /**
19105 * @ngdoc object
19106 * @name exporterExcelFilename
19107 * @propertyOf ui.grid.exporter.api:GridOptions
19108 * @description The default filename to use when saving the downloaded excel, only used in IE (other browsers open excels in a new window)
19109 * <br/>Defaults to 'download.xlsx'
19110 */
19111 gridOptions.exporterExcelFilename = gridOptions.exporterExcelFilename ? gridOptions.exporterExcelFilename : 'download.xlsx';
19112
19113 /**
19114 * @ngdoc object
19115 * @name exporterExcelSheetName
19116 * @propertyOf ui.grid.exporter.api:GridOptions
19117 * @description The default sheetname to use when saving the downloaded to excel
19118 * <br/>Defaults to 'Sheet1'
19119 */
19120 gridOptions.exporterExcelSheetName = gridOptions.exporterExcelSheetName ? gridOptions.exporterExcelSheetName : 'Sheet1';
19121
19122 /**
19123 * @ngdoc object
19124 * @name exporterOlderExcelCompatibility
19125 * @propertyOf ui.grid.exporter.api:GridOptions
19126 * @description Some versions of excel don't like the utf-16 BOM on the front, and it comes
19127 * through as  in the first column header. Setting this option to false will suppress this, at the
19128 * expense of proper utf-16 handling in applications that do recognise the BOM
19129 * <br/>Defaults to false
19130 */
19131 gridOptions.exporterOlderExcelCompatibility = gridOptions.exporterOlderExcelCompatibility === true;
19132 /**
19133 * @ngdoc object
19134 * @name exporterIsExcelCompatible
19135 * @propertyOf ui.grid.exporter.api:GridOptions
19136 * @description Separator header, used to set a custom column separator in a csv file, only works on MS Excel.
19137 * Used it on other programs will make csv content display unproperly. Setting this option to false won't add this header.
19138 * <br/>Defaults to false
19139 */
19140 gridOptions.exporterIsExcelCompatible = gridOptions.exporterIsExcelCompatible === true;
19141 /**
19142 * @ngdoc object
19143 * @name exporterMenuItemOrder
19144 * @propertyOf ui.grid.exporter.api:GridOptions
19145 * @description An option to determine the starting point for the menu items created by the exporter
19146 * <br/>Defaults to 200
19147 */
19148 gridOptions.exporterMenuItemOrder = gridOptions.exporterMenuItemOrder ? gridOptions.exporterMenuItemOrder : 200;
19149 /**
19150 * @ngdoc object
19151 * @name exporterPdfDefaultStyle
19152 * @propertyOf ui.grid.exporter.api:GridOptions
19153 * @description The default style in pdfMake format
19154 * <br/>Defaults to:
19155 * <pre>
19156 * {
19157 * fontSize: 11
19158 * }
19159 * </pre>
19160 */
19161 gridOptions.exporterPdfDefaultStyle = gridOptions.exporterPdfDefaultStyle ? gridOptions.exporterPdfDefaultStyle : { fontSize: 11 };
19162 /**
19163 * @ngdoc object
19164 * @name exporterPdfTableStyle
19165 * @propertyOf ui.grid.exporter.api:GridOptions
19166 * @description The table style in pdfMake format
19167 * <br/>Defaults to:
19168 * <pre>
19169 * {
19170 * margin: [0, 5, 0, 15]
19171 * }
19172 * </pre>
19173 */
19174 gridOptions.exporterPdfTableStyle = gridOptions.exporterPdfTableStyle ? gridOptions.exporterPdfTableStyle : { margin: [0, 5, 0, 15] };
19175 /**
19176 * @ngdoc object
19177 * @name exporterPdfTableHeaderStyle
19178 * @propertyOf ui.grid.exporter.api:GridOptions
19179 * @description The tableHeader style in pdfMake format
19180 * <br/>Defaults to:
19181 * <pre>
19182 * {
19183 * bold: true,
19184 * fontSize: 12,
19185 * color: 'black'
19186 * }
19187 * </pre>
19188 */
19189 gridOptions.exporterPdfTableHeaderStyle = gridOptions.exporterPdfTableHeaderStyle ? gridOptions.exporterPdfTableHeaderStyle : { bold: true, fontSize: 12, color: 'black' };
19190 /**
19191 * @ngdoc object
19192 * @name exporterPdfHeader
19193 * @propertyOf ui.grid.exporter.api:GridOptions
19194 * @description The header section for pdf exports. Can be
19195 * simple text:
19196 * <pre>
19197 * gridOptions.exporterPdfHeader = 'My Header';
19198 * </pre>
19199 * Can be a more complex object in pdfMake format:
19200 * <pre>
19201 * gridOptions.exporterPdfHeader = {
19202 * columns: [
19203 * 'Left part',
19204 * { text: 'Right part', alignment: 'right' }
19205 * ]
19206 * };
19207 * </pre>
19208 * Or can be a function, allowing page numbers and the like
19209 * <pre>
19210 * gridOptions.exporterPdfHeader: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
19211 * </pre>
19212 */
19213 gridOptions.exporterPdfHeader = gridOptions.exporterPdfHeader ? gridOptions.exporterPdfHeader : null;
19214 /**
19215 * @ngdoc object
19216 * @name exporterPdfFooter
19217 * @propertyOf ui.grid.exporter.api:GridOptions
19218 * @description The header section for pdf exports. Can be
19219 * simple text:
19220 * <pre>
19221 * gridOptions.exporterPdfFooter = 'My Footer';
19222 * </pre>
19223 * Can be a more complex object in pdfMake format:
19224 * <pre>
19225 * gridOptions.exporterPdfFooter = {
19226 * columns: [
19227 * 'Left part',
19228 * { text: 'Right part', alignment: 'right' }
19229 * ]
19230 * };
19231 * </pre>
19232 * Or can be a function, allowing page numbers and the like
19233 * <pre>
19234 * gridOptions.exporterPdfFooter: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };
19235 * </pre>
19236 */
19237 gridOptions.exporterPdfFooter = gridOptions.exporterPdfFooter ? gridOptions.exporterPdfFooter : null;
19238 /**
19239 * @ngdoc object
19240 * @name exporterPdfOrientation
19241 * @propertyOf ui.grid.exporter.api:GridOptions
19242 * @description The orientation, should be a valid pdfMake value,
19243 * 'landscape' or 'portrait'
19244 * <br/>Defaults to landscape
19245 */
19246 gridOptions.exporterPdfOrientation = gridOptions.exporterPdfOrientation ? gridOptions.exporterPdfOrientation : 'landscape';
19247 /**
19248 * @ngdoc object
19249 * @name exporterPdfPageSize
19250 * @propertyOf ui.grid.exporter.api:GridOptions
19251 * @description The orientation, should be a valid pdfMake
19252 * paper size, usually 'A4' or 'LETTER'
19253 * {@link https://github.com/bpampuch/pdfmake/blob/master/src/standardPageSizes.js pdfMake page sizes}
19254 * <br/>Defaults to A4
19255 */
19256 gridOptions.exporterPdfPageSize = gridOptions.exporterPdfPageSize ? gridOptions.exporterPdfPageSize : 'A4';
19257 /**
19258 * @ngdoc object
19259 * @name exporterPdfMaxGridWidth
19260 * @propertyOf ui.grid.exporter.api:GridOptions
19261 * @description The maxium grid width - the current grid width
19262 * will be scaled to match this, with any fixed width columns
19263 * being adjusted accordingly.
19264 * <br/>Defaults to 720 (for A4 landscape), use 670 for LETTER
19265 */
19266 gridOptions.exporterPdfMaxGridWidth = gridOptions.exporterPdfMaxGridWidth ? gridOptions.exporterPdfMaxGridWidth : 720;
19267 /**
19268 * @ngdoc object
19269 * @name exporterPdfTableLayout
19270 * @propertyOf ui.grid.exporter.api:GridOptions
19271 * @description A tableLayout in pdfMake format,
19272 * controls gridlines and the like. We use the default
19273 * layout usually.
19274 * <br/>Defaults to null, which means no layout
19275 */
19276
19277 /**
19278 * @ngdoc object
19279 * @name exporterMenuAllData
19280 * @propertyOf ui.grid.exporter.api:GridOptions
19281 * @description Add export all data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
19282 */
19283 gridOptions.exporterMenuAllData = gridOptions.exporterMenuAllData !== undefined ? gridOptions.exporterMenuAllData : true;
19284
19285 /**
19286 * @ngdoc object
19287 * @name exporterMenuVisibleData
19288 * @propertyOf ui.grid.exporter.api:GridOptions
19289 * @description Add export visible data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
19290 */
19291 gridOptions.exporterMenuVisibleData = gridOptions.exporterMenuVisibleData !== undefined ? gridOptions.exporterMenuVisibleData : true;
19292
19293 /**
19294 * @ngdoc object
19295 * @name exporterMenuSelectedData
19296 * @propertyOf ui.grid.exporter.api:GridOptions
19297 * @description Add export selected data as cvs/pdf menu items to the ui-grid grid menu, if it's present. Defaults to true.
19298 */
19299 gridOptions.exporterMenuSelectedData = gridOptions.exporterMenuSelectedData !== undefined ? gridOptions.exporterMenuSelectedData : true;
19300
19301 /**
19302 * @ngdoc object
19303 * @name exporterMenuCsv
19304 * @propertyOf ui.grid.exporter.api:GridOptions
19305 * @description Add csv export menu items to the ui-grid grid menu, if it's present. Defaults to true.
19306 */
19307 gridOptions.exporterMenuCsv = gridOptions.exporterMenuCsv !== undefined ? gridOptions.exporterMenuCsv : true;
19308
19309 /**
19310 * @ngdoc object
19311 * @name exporterMenuPdf
19312 * @propertyOf ui.grid.exporter.api:GridOptions
19313 * @description Add pdf export menu items to the ui-grid grid menu, if it's present. Defaults to true.
19314 */
19315 gridOptions.exporterMenuPdf = gridOptions.exporterMenuPdf !== undefined ? gridOptions.exporterMenuPdf : true;
19316
19317 /**
19318 * @ngdoc object
19319 * @name exporterMenuExcel
19320 * @propertyOf ui.grid.exporter.api:GridOptions
19321 * @description Add excel export menu items to the ui-grid grid menu, if it's present. Defaults to true.
19322 */
19323 gridOptions.exporterMenuExcel = gridOptions.exporterMenuExcel !== undefined ? gridOptions.exporterMenuExcel : true;
19324
19325 /**
19326 * @ngdoc object
19327 * @name exporterPdfCustomFormatter
19328 * @propertyOf ui.grid.exporter.api:GridOptions
19329 * @description A custom callback routine that changes the pdf document, adding any
19330 * custom styling or content that is supported by pdfMake. Takes in the complete docDefinition, and
19331 * must return an updated docDefinition ready for pdfMake.
19332 * @example
19333 * In this example we add a style to the style array, so that we can use it in our
19334 * footer definition.
19335 * <pre>
19336 * gridOptions.exporterPdfCustomFormatter = function ( docDefinition ) {
19337 * docDefinition.styles.footerStyle = { bold: true, fontSize: 10 };
19338 * return docDefinition;
19339 * }
19340 *
19341 * gridOptions.exporterPdfFooter = { text: 'My footer', style: 'footerStyle' }
19342 * </pre>
19343 */
19344 gridOptions.exporterPdfCustomFormatter = ( gridOptions.exporterPdfCustomFormatter && typeof( gridOptions.exporterPdfCustomFormatter ) === 'function' ) ? gridOptions.exporterPdfCustomFormatter : function ( docDef ) { return docDef; };
19345
19346 /**
19347 * @ngdoc object
19348 * @name exporterHeaderFilterUseName
19349 * @propertyOf ui.grid.exporter.api:GridOptions
19350 * @description Defaults to false, which leads to `displayName` being passed into the headerFilter.
19351 * If set to true, then will pass `name` instead.
19352 *
19353 *
19354 * @example
19355 * <pre>
19356 * gridOptions.exporterHeaderFilterUseName = true;
19357 * </pre>
19358 */
19359 gridOptions.exporterHeaderFilterUseName = gridOptions.exporterHeaderFilterUseName === true;
19360
19361 /**
19362 * @ngdoc object
19363 * @name exporterHeaderFilter
19364 * @propertyOf ui.grid.exporter.api:GridOptions
19365 * @description A function to apply to the header displayNames before exporting. Useful for internationalisation,
19366 * for example if you were using angular-translate you'd set this to `$translate.instant`. Note that this
19367 * call must be synchronous, it cannot be a call that returns a promise.
19368 *
19369 * Behaviour can be changed to pass in `name` instead of `displayName` through use of `exporterHeaderFilterUseName: true`.
19370 *
19371 * @example
19372 * <pre>
19373 * gridOptions.exporterHeaderFilter = function( displayName ) { return 'col: ' + name; };
19374 * </pre>
19375 * OR
19376 * <pre>
19377 * gridOptions.exporterHeaderFilter = $translate.instant;
19378 * </pre>
19379 */
19380
19381 /**
19382 * @ngdoc function
19383 * @name exporterFieldCallback
19384 * @propertyOf ui.grid.exporter.api:GridOptions
19385 * @description A function to call for each field before exporting it. Allows
19386 * massaging of raw data into a display format, for example if you have applied
19387 * filters to convert codes into decodes, or you require
19388 * a specific date format in the exported content.
19389 *
19390 * The method is called once for each field exported, and provides the grid, the
19391 * gridCol and the GridRow for you to use as context in massaging the data.
19392 *
19393 * @param {Grid} grid provides the grid in case you have need of it
19394 * @param {GridRow} row the row from which the data comes
19395 * @param {GridColumn} col the column from which the data comes
19396 * @param {object} value the value for your massaging
19397 * @returns {object} you must return the massaged value ready for exporting
19398 *
19399 * @example
19400 * <pre>
19401 * gridOptions.exporterFieldCallback = function ( grid, row, col, value ) {
19402 * if ( col.name === 'status' ) {
19403 * value = decodeStatus( value );
19404 * }
19405 * return value;
19406 * }
19407 * </pre>
19408 */
19409 gridOptions.exporterFieldCallback = gridOptions.exporterFieldCallback ? gridOptions.exporterFieldCallback : defaultExporterFieldCallback;
19410
19411 /**
19412 * @ngdoc function
19413 * @name exporterFieldFormatCallback
19414 * @propertyOf ui.grid.exporter.api:GridOptions
19415 * @description A function to call for each field before exporting it. Allows
19416 * general object to be return to modify the format of a cell in the case of
19417 * excel exports
19418 *
19419 * The method is called once for each field exported, and provides the grid, the
19420 * gridCol and the GridRow for you to use as context in massaging the data.
19421 *
19422 * @param {Grid} grid provides the grid in case you have need of it
19423 * @param {GridRow} row the row from which the data comes
19424 * @param {GridColumn} col the column from which the data comes
19425 * @param {object} value the value for your massaging
19426 * @returns {object} you must return the massaged value ready for exporting
19427 *
19428 * @example
19429 * <pre>
19430 * gridOptions.exporterFieldCallback = function ( grid, row, col, value ) {
19431 * if ( col.name === 'status' ) {
19432 * value = decodeStatus( value );
19433 * }
19434 * return value;
19435 * }
19436 * </pre>
19437 */
19438 gridOptions.exporterFieldFormatCallback = gridOptions.exporterFieldFormatCallback ? gridOptions.exporterFieldFormatCallback : function( grid, row, col, value ) { return null; };
19439
19440 /**
19441 * @ngdoc function
19442 * @name exporterExcelCustomFormatters
19443 * @propertyOf ui.grid.exporter.api:GridOptions
19444 * @description A function to call to setup formatters and store on docDefinition.
19445 *
19446 * The method is called at the start and can setup all the formatters to export to excel
19447 *
19448 * @param {Grid} grid provides the grid in case you have need of it
19449 * @param {Workbook} row the row from which the data comes
19450 * @param {docDefinition} The docDefinition that will have styles as a object to store formatters
19451 * @returns {docDefinition} Updated docDefinition with formatter styles
19452 *
19453 * @example
19454 * <pre>
19455 * gridOptions.exporterExcelCustomFormatters = function(grid, workbook, docDefinition) {
19456 * const formatters = {};
19457 * const stylesheet = workbook.getStyleSheet();
19458 * const headerFormatDefn = {
19459 * 'font': { 'size': 11, 'fontName': 'Calibri', 'bold': true },
19460 * 'alignment': { 'wrapText': false }
19461 * };
19462 *
19463 * formatters['header'] = headerFormatter;
19464 * Object.assign(docDefinition.styles , formatters);
19465 * grid.docDefinition = docDefinition;
19466 * return docDefinition;
19467 * }
19468 * </pre>
19469 */
19470 gridOptions.exporterExcelCustomFormatters = gridOptions.exporterExcelCustomFormatters ? gridOptions.exporterExcelCustomFormatters : function( grid, workbook, docDefinition ) { return docDefinition; };
19471
19472 /**
19473 * @ngdoc function
19474 * @name exporterExcelHeader
19475 * @propertyOf ui.grid.exporter.api:GridOptions
19476 * @description A function to write formatted header data to sheet.
19477 *
19478 * The method is called to provide custom header building for Excel. This data comes before the grid header
19479 *
19480 * @param {grid} grid provides the grid in case you have need of it
19481 * @param {Workbook} row the row from which the data comes
19482 * @param {Sheet} the sheet to insert data
19483 * @param {docDefinition} The docDefinition that will have styles as a object to store formatters
19484 * @returns {docDefinition} Updated docDefinition with formatter styles
19485 *
19486 * @example
19487 * <pre>
19488 * gridOptions.exporterExcelCustomFormatters = function (grid, workbook, sheet, docDefinition) {
19489 * const headerFormatter = docDefinition.styles['header'];
19490 * let cols = [];
19491 * // push data in A1 cell with metadata formatter
19492 * cols.push({ value: 'Summary Report', metadata: {style: headerFormatter.id} });
19493 * sheet.data.push(cols);
19494 * }
19495 * </pre>
19496 */
19497 gridOptions.exporterExcelHeader = gridOptions.exporterExcelHeader ? gridOptions.exporterExcelHeader : function( grid, workbook, sheet, docDefinition ) { return null; };
19498
19499
19500 /**
19501 * @ngdoc object
19502 * @name exporterColumnScaleFactor
19503 * @propertyOf ui.grid.exporter.api:GridOptions
19504 * @description A scaling factor to divide the drawnwidth of a column to convert to target excel column
19505 * format size
19506 * @example
19507 * In this example we add a number to divide the drawnwidth of a column to get the excel width.
19508 * <br/>Defaults to 3.5
19509 */
19510 gridOptions.exporterColumnScaleFactor = gridOptions.exporterColumnScaleFactor ? gridOptions.exporterColumnScaleFactor : 3.5;
19511
19512 /**
19513 * @ngdoc object
19514 * @name exporterFieldApplyFilters
19515 * @propertyOf ui.grid.exporter.api:GridOptions
19516 * @description Defaults to false, which leads to filters being evaluated on export *
19517 *
19518 * @example
19519 * <pre>
19520 * gridOptions.exporterFieldApplyFilters = true;
19521 * </pre>
19522 */
19523 gridOptions.exporterFieldApplyFilters = gridOptions.exporterFieldApplyFilters === true;
19524
19525 /**
19526 * @ngdoc function
19527 * @name exporterAllDataFn
19528 * @propertyOf ui.grid.exporter.api:GridOptions
19529 * @description This promise is needed when exporting all rows,
19530 * and the data need to be provided by server side. Default is null.
19531 * @returns {Promise} a promise to load all data from server
19532 *
19533 * @example
19534 * <pre>
19535 * gridOptions.exporterAllDataFn = function () {
19536 * return $http.get('/data/100.json')
19537 * }
19538 * </pre>
19539 */
19540 gridOptions.exporterAllDataFn = gridOptions.exporterAllDataFn ? gridOptions.exporterAllDataFn : null;
19541
19542 /**
19543 * @ngdoc function
19544 * @name exporterAllDataPromise
19545 * @propertyOf ui.grid.exporter.api:GridOptions
19546 * @description DEPRECATED - exporterAllDataFn used to be
19547 * called this, but it wasn't a promise, it was a function that returned
19548 * a promise. Deprecated, but supported for backward compatibility, use
19549 * exporterAllDataFn instead.
19550 * @returns {Promise} a promise to load all data from server
19551 *
19552 * @example
19553 * <pre>
19554 * gridOptions.exporterAllDataFn = function () {
19555 * return $http.get('/data/100.json')
19556 * }
19557 * </pre>
19558 */
19559 if ( gridOptions.exporterAllDataFn === null && gridOptions.exporterAllDataPromise ) {
19560 gridOptions.exporterAllDataFn = gridOptions.exporterAllDataPromise;
19561 }
19562 },
19563
19564
19565 /**
19566 * @ngdoc function
19567 * @name addToMenu
19568 * @methodOf ui.grid.exporter.service:uiGridExporterService
19569 * @description Adds export items to the grid menu,
19570 * allowing the user to select export options
19571 * @param {Grid} grid the grid from which data should be exported
19572 */
19573 addToMenu: function ( grid ) {
19574 grid.api.core.addToGridMenu( grid, [
19575 {
19576 title: i18nService.getSafeText('gridMenu.exporterAllAsCsv'),
19577 action: function () {
19578 grid.api.exporter.csvExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
19579 },
19580 shown: function() {
19581 return grid.options.exporterMenuCsv && grid.options.exporterMenuAllData;
19582 },
19583 order: grid.options.exporterMenuItemOrder
19584 },
19585 {
19586 title: i18nService.getSafeText('gridMenu.exporterVisibleAsCsv'),
19587 action: function () {
19588 grid.api.exporter.csvExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
19589 },
19590 shown: function() {
19591 return grid.options.exporterMenuCsv && grid.options.exporterMenuVisibleData;
19592 },
19593 order: grid.options.exporterMenuItemOrder + 1
19594 },
19595 {
19596 title: i18nService.getSafeText('gridMenu.exporterSelectedAsCsv'),
19597 action: function () {
19598 grid.api.exporter.csvExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
19599 },
19600 shown: function() {
19601 return grid.options.exporterMenuCsv && grid.options.exporterMenuSelectedData &&
19602 ( grid.api.selection && grid.api.selection.getSelectedRows().length > 0 );
19603 },
19604 order: grid.options.exporterMenuItemOrder + 2
19605 },
19606 {
19607 title: i18nService.getSafeText('gridMenu.exporterAllAsPdf'),
19608 action: function () {
19609 grid.api.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
19610 },
19611 shown: function() {
19612 return grid.options.exporterMenuPdf && grid.options.exporterMenuAllData;
19613 },
19614 order: grid.options.exporterMenuItemOrder + 3
19615 },
19616 {
19617 title: i18nService.getSafeText('gridMenu.exporterVisibleAsPdf'),
19618 action: function () {
19619 grid.api.exporter.pdfExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
19620 },
19621 shown: function() {
19622 return grid.options.exporterMenuPdf && grid.options.exporterMenuVisibleData;
19623 },
19624 order: grid.options.exporterMenuItemOrder + 4
19625 },
19626 {
19627 title: i18nService.getSafeText('gridMenu.exporterSelectedAsPdf'),
19628 action: function () {
19629 grid.api.exporter.pdfExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
19630 },
19631 shown: function() {
19632 return grid.options.exporterMenuPdf && grid.options.exporterMenuSelectedData &&
19633 ( grid.api.selection && grid.api.selection.getSelectedRows().length > 0 );
19634 },
19635 order: grid.options.exporterMenuItemOrder + 5
19636 },
19637 {
19638 title: i18nService.getSafeText('gridMenu.exporterAllAsExcel'),
19639 action: function () {
19640 grid.api.exporter.excelExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
19641 },
19642 shown: function() {
19643 return grid.options.exporterMenuExcel && grid.options.exporterMenuAllData;
19644 },
19645 order: grid.options.exporterMenuItemOrder + 6
19646 },
19647 {
19648 title: i18nService.getSafeText('gridMenu.exporterVisibleAsExcel'),
19649 action: function () {
19650 grid.api.exporter.excelExport( uiGridExporterConstants.VISIBLE, uiGridExporterConstants.VISIBLE );
19651 },
19652 shown: function() {
19653 return grid.options.exporterMenuExcel && grid.options.exporterMenuVisibleData;
19654 },
19655 order: grid.options.exporterMenuItemOrder + 7
19656 },
19657 {
19658 title: i18nService.getSafeText('gridMenu.exporterSelectedAsExcel'),
19659 action: function () {
19660 grid.api.exporter.excelExport( uiGridExporterConstants.SELECTED, uiGridExporterConstants.VISIBLE );
19661 },
19662 shown: function() {
19663 return grid.options.exporterMenuExcel && grid.options.exporterMenuSelectedData &&
19664 ( grid.api.selection && grid.api.selection.getSelectedRows().length > 0 );
19665 },
19666 order: grid.options.exporterMenuItemOrder + 8
19667 }
19668 ]);
19669 },
19670
19671
19672 /**
19673 * @ngdoc function
19674 * @name csvExport
19675 * @methodOf ui.grid.exporter.service:uiGridExporterService
19676 * @description Exports rows from the grid in csv format,
19677 * the data exported is selected based on the provided options
19678 * @param {Grid} grid the grid from which data should be exported
19679 * @param {string} rowTypes which rows to export, valid values are
19680 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
19681 * uiGridExporterConstants.SELECTED
19682 * @param {string} colTypes which columns to export, valid values are
19683 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
19684 * uiGridExporterConstants.SELECTED
19685 */
19686 csvExport: function (grid, rowTypes, colTypes) {
19687 var self = this;
19688 this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {
19689 var exportColumnHeaders = grid.options.showHeader ? self.getColumnHeaders(grid, colTypes) : [];
19690 var exportData = self.getData(grid, rowTypes, colTypes);
19691 var csvContent = self.formatAsCsv(exportColumnHeaders, exportData, grid.options.exporterCsvColumnSeparator);
19692
19693 self.downloadFile (grid.options.exporterCsvFilename, csvContent, grid.options.exporterCsvColumnSeparator, grid.options.exporterOlderExcelCompatibility, grid.options.exporterIsExcelCompatible);
19694 });
19695 },
19696
19697 /**
19698 * @ngdoc function
19699 * @name loadAllDataIfNeeded
19700 * @methodOf ui.grid.exporter.service:uiGridExporterService
19701 * @description When using server side pagination, use exporterAllDataFn to
19702 * load all data before continuing processing.
19703 * When using client side pagination, return a resolved promise so processing
19704 * continues immediately
19705 * @param {Grid} grid the grid from which data should be exported
19706 * @param {string} rowTypes which rows to export, valid values are
19707 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
19708 * uiGridExporterConstants.SELECTED
19709 * @param {string} colTypes which columns to export, valid values are
19710 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
19711 * uiGridExporterConstants.SELECTED
19712 */
19713 loadAllDataIfNeeded: function (grid, rowTypes, colTypes) {
19714 if ( rowTypes === uiGridExporterConstants.ALL && grid.rows.length !== grid.options.totalItems && grid.options.exporterAllDataFn) {
19715 return grid.options.exporterAllDataFn()
19716 .then(function(allData) {
19717 grid.modifyRows(allData);
19718 });
19719 } else {
19720 var deferred = $q.defer();
19721 deferred.resolve();
19722 return deferred.promise;
19723 }
19724 },
19725
19726 /**
19727 * @ngdoc property
19728 * @propertyOf ui.grid.exporter.api:ColumnDef
19729 * @name exporterSuppressExport
19730 * @description Suppresses export for this column. Used by selection and expandable.
19731 */
19732
19733 /**
19734 * @ngdoc function
19735 * @name getColumnHeaders
19736 * @methodOf ui.grid.exporter.service:uiGridExporterService
19737 * @description Gets the column headers from the grid to use
19738 * as a title row for the exported file, all headers have
19739 * headerCellFilters applied as appropriate.
19740 *
19741 * Column headers are an array of objects, each object has
19742 * name, displayName, width and align attributes. Only name is
19743 * used for csv, all attributes are used for pdf.
19744 *
19745 * @param {Grid} grid the grid from which data should be exported
19746 * @param {string} colTypes which columns to export, valid values are
19747 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
19748 * uiGridExporterConstants.SELECTED
19749 */
19750 getColumnHeaders: function (grid, colTypes) {
19751 var headers = [],
19752 columns;
19753
19754 if ( colTypes === uiGridExporterConstants.ALL ) {
19755 columns = grid.columns;
19756 } else {
19757 var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ) { return column.visible; } ) : [],
19758 bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ) { return column.visible; } ) : [],
19759 rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ) { return column.visible; } ) : [];
19760
19761 columns = leftColumns.concat(bodyColumns, rightColumns);
19762 }
19763
19764 columns.forEach( function( gridCol ) {
19765 // $$hashKey check since when grouping and sorting pragmatically this ends up in export. Filtering it out
19766 if ( gridCol.colDef.exporterSuppressExport !== true && gridCol.field !== '$$hashKey' &&
19767 grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ) {
19768 var headerEntry = {
19769 name: gridCol.field,
19770 displayName: getDisplayName(grid, gridCol),
19771 width: gridCol.drawnWidth ? gridCol.drawnWidth : gridCol.width,
19772 align: gridCol.colDef.align ? gridCol.colDef.align : (gridCol.colDef.type === 'number' ? 'right' : 'left')
19773 };
19774
19775 headers.push(headerEntry);
19776 }
19777 });
19778
19779 return headers;
19780 },
19781
19782 /**
19783 * @ngdoc property
19784 * @propertyOf ui.grid.exporter.api:ColumnDef
19785 * @name exporterPdfAlign
19786 * @description the alignment you'd like for this specific column when
19787 * exported into a pdf. Can be 'left', 'right', 'center' or any other
19788 * valid pdfMake alignment option.
19789 */
19790
19791 /**
19792 * @ngdoc object
19793 * @name ui.grid.exporter.api:GridRow
19794 * @description GridRow settings for exporter
19795 */
19796
19797 /**
19798 * @ngdoc object
19799 * @name exporterEnableExporting
19800 * @propertyOf ui.grid.exporter.api:GridRow
19801 * @description If set to false, then don't export this row, notwithstanding visible or
19802 * other settings
19803 * <br/>Defaults to true
19804 */
19805
19806 /**
19807 * @ngdoc function
19808 * @name getRowsFromNode
19809 * @methodOf ui.grid.exporter.service:uiGridExporterService
19810 * @description Gets rows from a node. If the node is grouped it will
19811 * recurse down into the children to get to the raw data element
19812 * which is a row without children (a leaf).
19813 * @param {Node} aNode the tree node on the grid
19814 * @returns {Array} an array of leaf nodes
19815 */
19816 getRowsFromNode: function(aNode) {
19817 var rows = [];
19818 for (var i = 0; i<aNode.children.length; i++) {
19819 if (aNode.children[i].children && aNode.children[i].children.length === 0) {
19820 rows.push(aNode.children[i]);
19821 } else {
19822 var nodeRows = this.getRowsFromNode(aNode.children[i]);
19823 rows = rows.concat(nodeRows);
19824 }
19825 }
19826 return rows;
19827 },
19828
19829 /**
19830 * @ngdoc function
19831 * @name getDataSorted
19832 * @methodOf ui.grid.exporter.service:uiGridExporterService
19833 * @description Gets rows from a node. If the node is grouped it will
19834 * recurse down into the children to get to the raw data element
19835 * which is a row without children (a leaf). If the grid is not
19836 * grouped this will return just the raw rows
19837 * @param {Grid} grid the grid from which data should be exported
19838 * @returns {Array} an array of leaf nodes
19839 */
19840 getDataSorted: function (grid) {
19841 if (!grid.treeBase || grid.treeBase.numberLevels === 0) {
19842 return grid.rows;
19843 }
19844 var rows = [];
19845
19846 for (var i = 0; i< grid.treeBase.tree.length; i++) {
19847 var nodeRows = this.getRowsFromNode(grid.treeBase.tree[i]);
19848
19849 for (var j = 0; j<nodeRows.length; j++) {
19850 rows.push(nodeRows[j].row);
19851 }
19852 }
19853 return rows;
19854 },
19855
19856 /**
19857 * @ngdoc function
19858 * @name getData
19859 * @methodOf ui.grid.exporter.service:uiGridExporterService
19860 * @description Gets data from the grid based on the provided options,
19861 * all cells have cellFilters applied as appropriate. Any rows marked
19862 * `exporterEnableExporting: false` will not be exported
19863 * @param {Grid} grid the grid from which data should be exported
19864 * @param {string} rowTypes which rows to export, valid values are
19865 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
19866 * uiGridExporterConstants.SELECTED
19867 * @param {string} colTypes which columns to export, valid values are
19868 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
19869 * uiGridExporterConstants.SELECTED
19870 * @param {boolean} applyCellFilters whether or not to get the display value or the raw value of the data
19871 */
19872 getData: function (grid, rowTypes, colTypes, applyCellFilters) {
19873 var data = [],
19874 rows,
19875 columns;
19876
19877 switch ( rowTypes ) {
19878 case uiGridExporterConstants.ALL:
19879 rows = this.getDataSorted(grid, rowTypes, colTypes, applyCellFilters);
19880 break;
19881 case uiGridExporterConstants.VISIBLE:
19882 rows = grid.getVisibleRows();
19883 break;
19884 case uiGridExporterConstants.SELECTED:
19885 if ( grid.api.selection ) {
19886 rows = grid.api.selection.getSelectedGridRows();
19887 } else {
19888 gridUtil.logError('selection feature must be enabled to allow selected rows to be exported');
19889 }
19890 break;
19891 }
19892
19893 if ( colTypes === uiGridExporterConstants.ALL ) {
19894 columns = grid.columns;
19895 } else {
19896 var leftColumns = grid.renderContainers.left ? grid.renderContainers.left.visibleColumnCache.filter( function( column ) { return column.visible; } ) : [];
19897 var bodyColumns = grid.renderContainers.body ? grid.renderContainers.body.visibleColumnCache.filter( function( column ) { return column.visible; } ) : [];
19898 var rightColumns = grid.renderContainers.right ? grid.renderContainers.right.visibleColumnCache.filter( function( column ) { return column.visible; } ) : [];
19899
19900 columns = leftColumns.concat(bodyColumns, rightColumns);
19901 }
19902
19903 rows.forEach(function( row ) {
19904 if (row.exporterEnableExporting !== false) {
19905 var extractedRow = [];
19906
19907 columns.forEach( function( gridCol ) {
19908 // $$hashKey check since when grouping and sorting programmatically this ends up in export. Filtering it out
19909 if ( (gridCol.visible || colTypes === uiGridExporterConstants.ALL ) &&
19910 gridCol.colDef.exporterSuppressExport !== true && gridCol.field !== '$$hashKey' &&
19911 grid.options.exporterSuppressColumns.indexOf( gridCol.name ) === -1 ) {
19912 var cellValue = applyCellFilters ? grid.getCellDisplayValue( row, gridCol ) : grid.getCellValue( row, gridCol ),
19913 extractedField = { value: grid.options.exporterFieldCallback( grid, row, gridCol, cellValue ) },
19914 extension = grid.options.exporterFieldFormatCallback( grid, row, gridCol, cellValue );
19915
19916 if (extension) {
19917 Object.assign(extractedField, extension);
19918 }
19919 if ( gridCol.colDef.exporterPdfAlign ) {
19920 extractedField.alignment = gridCol.colDef.exporterPdfAlign;
19921 }
19922 extractedRow.push(extractedField);
19923 }
19924 });
19925
19926 data.push(extractedRow);
19927 }
19928 });
19929
19930 return data;
19931 },
19932
19933
19934 /**
19935 * @ngdoc function
19936 * @name formatAsCsv
19937 * @methodOf ui.grid.exporter.service:uiGridExporterService
19938 * @description Formats the column headers and data as a CSV,
19939 * and sends that data to the user
19940 * @param {array} exportColumnHeaders an array of column headers,
19941 * where each header is an object with name, width and maybe alignment
19942 * @param {array} exportData an array of rows, where each row is
19943 * an array of column data
19944 * @param {string} separator a string that represents the separator to be used in the csv file
19945 * @returns {string} csv the formatted csv as a string
19946 */
19947 formatAsCsv: function (exportColumnHeaders, exportData, separator) {
19948 var self = this,
19949 bareHeaders = exportColumnHeaders.map(function(header) { return { value: header.displayName };}),
19950 csv = bareHeaders.length > 0 ? (self.formatRowAsCsv(this, separator)(bareHeaders) + '\n') : '';
19951
19952 csv += exportData.map(this.formatRowAsCsv(this, separator)).join('\n');
19953
19954 return csv;
19955 },
19956
19957 /**
19958 * @ngdoc function
19959 * @name formatRowAsCsv
19960 * @methodOf ui.grid.exporter.service:uiGridExporterService
19961 * @description Renders a single field as a csv field, including
19962 * quotes around the value
19963 * @param {exporterService} exporter pass in exporter
19964 * @param {string} separator the string to be used to join the row data
19965 * @returns {function} A function that returns a csv-ified version of the row
19966 */
19967 formatRowAsCsv: function (exporter, separator) {
19968 return function (row) {
19969 return row.map(exporter.formatFieldAsCsv).join(separator);
19970 };
19971 },
19972
19973 /**
19974 * @ngdoc function
19975 * @name formatFieldAsCsv
19976 * @methodOf ui.grid.exporter.service:uiGridExporterService
19977 * @description Renders a single field as a csv field, including
19978 * quotes around the value
19979 * @param {field} field the field to be turned into a csv string,
19980 * may be of any type
19981 * @returns {string} a csv-ified version of the field
19982 */
19983 formatFieldAsCsv: function (field) {
19984 if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
19985 return '';
19986 }
19987 if (typeof(field.value) === 'number') {
19988 return field.value;
19989 }
19990 if (typeof(field.value) === 'boolean') {
19991 return (field.value ? 'TRUE' : 'FALSE') ;
19992 }
19993 if (typeof(field.value) === 'string') {
19994 return '"' + field.value.replace(/"/g,'""') + '"';
19995 }
19996
19997 return JSON.stringify(field.value);
19998 },
19999
20000 /**
20001 * @ngdoc function
20002 * @name isIE
20003 * @methodOf ui.grid.exporter.service:uiGridExporterService
20004 * @description Checks whether current browser is IE and returns it's version if it is
20005 */
20006 isIE: function () {
20007 var match = navigator.userAgent.search(/(?:Edge|MSIE|Trident\/.*; rv:)/);
20008 var isIE = false;
20009
20010 if (match !== -1) {
20011 isIE = true;
20012 }
20013
20014 return isIE;
20015 },
20016
20017
20018 /**
20019 * @ngdoc function
20020 * @name downloadFile
20021 * @methodOf ui.grid.exporter.service:uiGridExporterService
20022 * @description Triggers download of a csv file. Logic provided
20023 * by @cssensei (from his colleagues at https://github.com/ifeelgoods) in issue #2391
20024 * @param {string} fileName the filename we'd like our file to be
20025 * given
20026 * @param {string} csvContent the csv content that we'd like to
20027 * download as a file
20028 * @param {string} columnSeparator The separator to be used by the columns
20029 * @param {boolean} exporterOlderExcelCompatibility whether or not we put a utf-16 BOM on the from (\uFEFF)
20030 * @param {boolean} exporterIsExcelCompatible whether or not we add separator header ('sep=X')
20031 */
20032 downloadFile: function (fileName, csvContent, columnSeparator, exporterOlderExcelCompatibility, exporterIsExcelCompatible) {
20033 var D = document,
20034 a = D.createElement('a'),
20035 strMimeType = 'application/octet-stream;charset=utf-8',
20036 rawFile,
20037 ieVersion = this.isIE();
20038
20039 if (exporterIsExcelCompatible) {
20040 csvContent = 'sep=' + columnSeparator + '\r\n' + csvContent;
20041 }
20042
20043 // IE10+
20044 if (navigator.msSaveBlob) {
20045 return navigator.msSaveOrOpenBlob(
20046 new Blob(
20047 [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
20048 { type: strMimeType } ),
20049 fileName
20050 );
20051 }
20052
20053 if (ieVersion) {
20054 var frame = D.createElement('iframe');
20055
20056 document.body.appendChild(frame);
20057
20058 frame.contentWindow.document.open('text/html', 'replace');
20059 frame.contentWindow.document.write(csvContent);
20060 frame.contentWindow.document.close();
20061 frame.contentWindow.focus();
20062 frame.contentWindow.document.execCommand('SaveAs', true, fileName);
20063
20064 document.body.removeChild(frame);
20065 return true;
20066 }
20067
20068 // html5 A[download]
20069 if ('download' in a) {
20070 var blob = new Blob(
20071 [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
20072 { type: strMimeType }
20073 );
20074 rawFile = URL.createObjectURL(blob);
20075 a.setAttribute('download', fileName);
20076 } else {
20077 rawFile = 'data: ' + strMimeType + ',' + encodeURIComponent(csvContent);
20078 a.setAttribute('target', '_blank');
20079 }
20080
20081 a.href = rawFile;
20082 a.setAttribute('style', 'display:none;');
20083 D.body.appendChild(a);
20084 setTimeout(function() {
20085 if (a.click) {
20086 a.click();
20087 // Workaround for Safari 5
20088 } else if (document.createEvent) {
20089 var eventObj = document.createEvent('MouseEvents');
20090 eventObj.initEvent('click', true, true);
20091 a.dispatchEvent(eventObj);
20092 }
20093 D.body.removeChild(a);
20094
20095 }, this.delay);
20096 },
20097
20098 /**
20099 * @ngdoc function
20100 * @name pdfExport
20101 * @methodOf ui.grid.exporter.service:uiGridExporterService
20102 * @description Exports rows from the grid in pdf format,
20103 * the data exported is selected based on the provided options.
20104 * Note that this function has a dependency on pdfMake, which must
20105 * be installed. The resulting pdf opens in a new
20106 * browser window.
20107 * @param {Grid} grid the grid from which data should be exported
20108 * @param {string} rowTypes which rows to export, valid values are
20109 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
20110 * uiGridExporterConstants.SELECTED
20111 * @param {string} colTypes which columns to export, valid values are
20112 * uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE,
20113 * uiGridExporterConstants.SELECTED
20114 */
20115 pdfExport: function (grid, rowTypes, colTypes) {
20116 var self = this;
20117
20118 this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function () {
20119 var exportColumnHeaders = self.getColumnHeaders(grid, colTypes),
20120 exportData = self.getData(grid, rowTypes, colTypes),
20121 docDefinition = self.prepareAsPdf(grid, exportColumnHeaders, exportData);
20122
20123 if (self.isIE() || navigator.appVersion.indexOf('Edge') !== -1) {
20124 self.downloadPDF(grid.options.exporterPdfFilename, docDefinition);
20125 } else {
20126 pdfMake.createPdf(docDefinition).open();
20127 }
20128 });
20129 },
20130
20131
20132 /**
20133 * @ngdoc function
20134 * @name downloadPdf
20135 * @methodOf ui.grid.exporter.service:uiGridExporterService
20136 * @description Generates and retrieves the pdf as a blob, then downloads
20137 * it as a file. Only used in IE, in all other browsers we use the native
20138 * pdfMake.open function to just open the PDF
20139 * @param {string} fileName the filename to give to the pdf, can be set
20140 * through exporterPdfFilename
20141 * @param {object} docDefinition a pdf docDefinition that we can generate
20142 * and get a blob from
20143 */
20144 downloadPDF: function (fileName, docDefinition) {
20145 var D = document,
20146 a = D.createElement('a'),
20147 ieVersion;
20148
20149 ieVersion = this.isIE(); // This is now a boolean value
20150 var doc = pdfMake.createPdf(docDefinition);
20151 var blob;
20152
20153 doc.getBuffer( function (buffer) {
20154 blob = new Blob([buffer]);
20155
20156 // IE10+
20157 if (navigator.msSaveBlob) {
20158 return navigator.msSaveBlob(
20159 blob, fileName
20160 );
20161 }
20162
20163 // Previously: && ieVersion < 10
20164 // ieVersion now returns a boolean for the
20165 // sake of sanity. We just check `msSaveBlob` first.
20166 if (ieVersion) {
20167 var frame = D.createElement('iframe');
20168 document.body.appendChild(frame);
20169
20170 frame.contentWindow.document.open('text/html', 'replace');
20171 frame.contentWindow.document.write(blob);
20172 frame.contentWindow.document.close();
20173 frame.contentWindow.focus();
20174 frame.contentWindow.document.execCommand('SaveAs', true, fileName);
20175
20176 document.body.removeChild(frame);
20177 return true;
20178 }
20179 });
20180 },
20181
20182
20183 /**
20184 * @ngdoc function
20185 * @name renderAsPdf
20186 * @methodOf ui.grid.exporter.service:uiGridExporterService
20187 * @description Renders the data into a pdf, and opens that pdf.
20188 *
20189 * @param {Grid} grid the grid from which data should be exported
20190 * @param {array} exportColumnHeaders an array of column headers,
20191 * where each header is an object with name, width and maybe alignment
20192 * @param {array} exportData an array of rows, where each row is
20193 * an array of column data
20194 * @returns {object} a pdfMake format document definition, ready
20195 * for generation
20196 */
20197 prepareAsPdf: function(grid, exportColumnHeaders, exportData) {
20198 var headerWidths = this.calculatePdfHeaderWidths( grid, exportColumnHeaders );
20199
20200 var headerColumns = exportColumnHeaders.map( function( header ) {
20201 return { text: header.displayName, style: 'tableHeader' };
20202 });
20203
20204 var stringData = exportData.map(this.formatRowAsPdf(this));
20205
20206 var allData = [headerColumns].concat(stringData);
20207
20208 var docDefinition = {
20209 pageOrientation: grid.options.exporterPdfOrientation,
20210 pageSize: grid.options.exporterPdfPageSize,
20211 content: [{
20212 style: 'tableStyle',
20213 table: {
20214 headerRows: 1,
20215 widths: headerWidths,
20216 body: allData
20217 }
20218 }],
20219 styles: {
20220 tableStyle: grid.options.exporterPdfTableStyle,
20221 tableHeader: grid.options.exporterPdfTableHeaderStyle
20222 },
20223 defaultStyle: grid.options.exporterPdfDefaultStyle
20224 };
20225
20226 if ( grid.options.exporterPdfLayout ) {
20227 docDefinition.layout = grid.options.exporterPdfLayout;
20228 }
20229
20230 if ( grid.options.exporterPdfHeader ) {
20231 docDefinition.header = grid.options.exporterPdfHeader;
20232 }
20233
20234 if ( grid.options.exporterPdfFooter ) {
20235 docDefinition.footer = grid.options.exporterPdfFooter;
20236 }
20237
20238 if ( grid.options.exporterPdfCustomFormatter ) {
20239 docDefinition = grid.options.exporterPdfCustomFormatter( docDefinition );
20240 }
20241 return docDefinition;
20242
20243 },
20244
20245
20246 /**
20247 * @ngdoc function
20248 * @name calculatePdfHeaderWidths
20249 * @methodOf ui.grid.exporter.service:uiGridExporterService
20250 * @description Determines the column widths base on the
20251 * widths we got from the grid. If the column is drawn
20252 * then we have a drawnWidth. If the column is not visible
20253 * then we have '*', 'x%' or a width. When columns are
20254 * not visible they don't contribute to the overall gridWidth,
20255 * so we need to adjust to allow for extra columns
20256 *
20257 * Our basic heuristic is to take the current gridWidth, plus
20258 * numeric columns and call this the base gridwidth.
20259 *
20260 * To that we add 100 for any '*' column, and x% of the base gridWidth
20261 * for any column that is a %
20262 *
20263 * @param {Grid} grid the grid from which data should be exported
20264 * @param {array} exportHeaders array of header information
20265 * @returns {object} an array of header widths
20266 */
20267 calculatePdfHeaderWidths: function ( grid, exportHeaders ) {
20268 var baseGridWidth = 0;
20269
20270 exportHeaders.forEach(function(value) {
20271 if (typeof(value.width) === 'number') {
20272 baseGridWidth += value.width;
20273 }
20274 });
20275
20276 var extraColumns = 0;
20277
20278 exportHeaders.forEach(function(value) {
20279 if (value.width === '*') {
20280 extraColumns += 100;
20281 }
20282 if (typeof(value.width) === 'string' && value.width.match(/(\d)*%/)) {
20283 var percent = parseInt(value.width.match(/(\d)*%/)[0]);
20284
20285 value.width = baseGridWidth * percent / 100;
20286 extraColumns += value.width;
20287 }
20288 });
20289
20290 var gridWidth = baseGridWidth + extraColumns;
20291
20292 return exportHeaders.map(function( header ) {
20293 return header.width === '*' ? header.width : header.width * grid.options.exporterPdfMaxGridWidth / gridWidth;
20294 });
20295 },
20296
20297 /**
20298 * @ngdoc function
20299 * @name formatRowAsPdf
20300 * @methodOf ui.grid.exporter.service:uiGridExporterService
20301 * @description Renders a row in a format consumable by PDF,
20302 * mainly meaning casting everything to a string
20303 * @param {exporterService} exporter pass in exporter
20304 * @param {array} row the row to be turned into a csv string
20305 * @returns {string} a csv-ified version of the row
20306 */
20307 formatRowAsPdf: function ( exporter ) {
20308 return function( row ) {
20309 return row.map(exporter.formatFieldAsPdfString);
20310 };
20311 },
20312
20313
20314 /**
20315 * @ngdoc function
20316 * @name formatFieldAsCsv
20317 * @methodOf ui.grid.exporter.service:uiGridExporterService
20318 * @description Renders a single field as a pdf-able field, which
20319 * is different from a csv field only in that strings don't have quotes
20320 * around them
20321 * @param {field} field the field to be turned into a pdf string,
20322 * may be of any type
20323 * @returns {string} a string-ified version of the field
20324 */
20325 formatFieldAsPdfString: function (field) {
20326 var returnVal;
20327
20328 if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
20329 returnVal = '';
20330 } else if (typeof(field.value) === 'number') {
20331 returnVal = field.value.toString();
20332 } else if (typeof(field.value) === 'boolean') {
20333 returnVal = (field.value ? 'TRUE' : 'FALSE') ;
20334 } else if (typeof(field.value) === 'string') {
20335 returnVal = field.value.replace(/"/g,'""');
20336 } else if (field.value instanceof Date) {
20337 returnVal = JSON.stringify(field.value).replace(/^"/,'').replace(/"$/,'');
20338 } else if (typeof(field.value) === 'object') {
20339 returnVal = field.value;
20340 } else {
20341 returnVal = JSON.stringify(field.value).replace(/^"/,'').replace(/"$/,'');
20342 }
20343
20344 if (field.alignment && typeof(field.alignment) === 'string' ) {
20345 returnVal = { text: returnVal, alignment: field.alignment };
20346 }
20347
20348 return returnVal;
20349 },
20350
20351 /**
20352 * @ngdoc function
20353 * @name formatAsExcel
20354 * @methodOf ui.grid.exporter.service:uiGridExporterService
20355 * @description Formats the column headers and data as a excel,
20356 * and sends that data to the user
20357 * @param {array} exportColumnHeaders an array of column headers,
20358 * where each header is an object with name, width and maybe alignment
20359 * @param {array} exportData an array of rows, where each row is
20360 * an array of column data
20361 * @param {string} separator a string that represents the separator to be used in the csv file
20362 * @returns {string} csv the formatted excel as a string
20363 */
20364 formatAsExcel: function (exportColumnHeaders, exportData, workbook, sheet, docDefinition) {
20365 var bareHeaders = exportColumnHeaders.map(function(header) {return { value: header.displayName };});
20366
20367 var sheetData = [];
20368 var headerData = [];
20369 for (var i = 0; i < bareHeaders.length; i++) {
20370 // TODO - probably need callback to determine header value and header styling
20371 var exportStyle = 'header';
20372 switch (exportColumnHeaders[i].align) {
20373 case 'center':
20374 exportStyle = 'headerCenter';
20375 break;
20376 case 'right':
20377 exportStyle = 'headerRight';
20378 break;
20379 }
20380 var metadata = (docDefinition.styles && docDefinition.styles[exportStyle]) ? {style: docDefinition.styles[exportStyle].id} : null;
20381 headerData.push({value: bareHeaders[i].value, metadata: metadata});
20382 }
20383 sheetData.push(headerData);
20384
20385 var result = exportData.map(this.formatRowAsExcel(this, workbook, sheet));
20386 for (var j = 0; j<result.length; j++) {
20387 sheetData.push(result[j]);
20388 }
20389 return sheetData;
20390 },
20391
20392 /**
20393 * @ngdoc function
20394 * @name formatRowAsExcel
20395 * @methodOf ui.grid.exporter.service:uiGridExporterService
20396 * @description Renders a single field as a csv field, including
20397 * quotes around the value
20398 * @param {exporterService} exporter pass in exporter
20399 * @param {array} row the row to be turned into a excel string
20400 * @returns {array} array of cell objects (i.e. {value: x, metadata: y})
20401 */
20402 formatRowAsExcel: function (exporter, workbook, sheet) {
20403 return function (row) {
20404 var values = [];
20405 for (var i = 0; i<row.length; i++) {
20406 var value = exporter.formatFieldAsExcel(row[i], workbook, sheet);
20407 values.push({value: value, metadata: row[i].metadata});
20408 }
20409 return values;
20410 };
20411 },
20412
20413 /**
20414 * @ngdoc function
20415 * @name formatFieldAsExcel
20416 * @methodOf ui.grid.exporter.service:uiGridExporterService
20417 * @description Renders a single field as a csv field, including
20418 * quotes around the value
20419 * @param {field} field the field to be turned into a csv string,
20420 * may be of any type
20421 * @returns {string} a excel-ified version of the field
20422 */
20423 formatFieldAsExcel: function (field, workbook, sheet, formatters) {
20424 if (field.value == null) { // we want to catch anything null-ish, hence just == not ===
20425 return '';
20426 }
20427 if (typeof(field.value) === 'number') {
20428 return field.value;
20429 }
20430 if (typeof(field.value) === 'boolean') {
20431 return (field.value ? 'TRUE' : 'FALSE') ;
20432 }
20433 if (typeof(field.value) === 'string') {
20434 return field.value.replace(/"/g,'""');
20435 }
20436
20437 return JSON.stringify(field.value);
20438 },
20439
20440 prepareAsExcel: function(grid, workbook, sheet) {
20441 var docDefinition = {
20442 styles: {
20443
20444 }
20445 };
20446
20447 if ( grid.options.exporterExcelCustomFormatters ) {
20448 docDefinition = grid.options.exporterExcelCustomFormatters( grid, workbook, docDefinition );
20449 }
20450 if ( grid.options.exporterExcelHeader ) {
20451 if (angular.isFunction( grid.options.exporterExcelHeader )) {
20452 grid.options.exporterExcelHeader(grid, workbook, sheet, docDefinition);
20453 } else {
20454 var headerText = grid.options.exporterExcelHeader.text;
20455 var style = grid.options.exporterExcelHeader.style;
20456 sheet.data.push([{value: headerText, metadata: {style: docDefinition.styles[style].id}}]);
20457 }
20458 }
20459
20460 return docDefinition;
20461 },
20462
20463 excelExport: function (grid, rowTypes, colTypes) {
20464 var self = this;
20465 this.loadAllDataIfNeeded(grid, rowTypes, colTypes).then(function() {
20466 var exportColumnHeaders = grid.options.showHeader ? self.getColumnHeaders(grid, colTypes) : [];
20467
20468 var workbook = new ExcelBuilder.Workbook();
20469 var aName = grid.options.exporterExcelSheetName ? grid.options.exporterExcelSheetName : 'Sheet1';
20470 var sheet = new ExcelBuilder.Worksheet({name: aName});
20471 workbook.addWorksheet(sheet);
20472 var docDefinition = self.prepareAsExcel(grid, workbook, sheet);
20473
20474 // The standard column width in Microsoft Excel 2000 is 8.43 characters based on fixed-width Courier font
20475 // Width of 10 in excel is 75 pixels
20476 var colWidths = [];
20477 var startDataIndex = grid.treeBase ? grid.treeBase.numberLevels : (grid.enableRowSelection ? 1 : 0);
20478 for (var i = startDataIndex; i < grid.columns.length; i++) {
20479 if (grid.columns[i].field !== uiGridExporterConstants.rowHeaderColName &&
20480 grid.columns[i].field !== uiGridExporterConstants.selectionRowHeaderColName) {
20481
20482 colWidths.push({width: (grid.columns[i].drawnWidth / grid.options.exporterColumnScaleFactor)});
20483 }
20484 }
20485 sheet.setColumns(colWidths);
20486
20487 var exportData = self.getData(grid, rowTypes, colTypes, grid.options.exporterFieldApplyFilters);
20488
20489 var excelContent = self.formatAsExcel(exportColumnHeaders, exportData, workbook, sheet, docDefinition);
20490 sheet.setData(sheet.data.concat(excelContent));
20491
20492 ExcelBuilder.Builder.createFile(workbook, {type: 'blob'}).then(function(result) {
20493 self.downloadFile (grid.options.exporterExcelFilename, result, grid.options.exporterCsvColumnSeparator,
20494 grid.options.exporterOlderExcelCompatibility);
20495 });
20496 });
20497 }
20498 };
20499
20500 function getDisplayName(grid, gridCol) {
20501 if (grid.options.exporterHeaderFilter) {
20502 return grid.options.exporterHeaderFilterUseName ?
20503 grid.options.exporterHeaderFilter(gridCol.name) :
20504 grid.options.exporterHeaderFilter(gridCol.displayName);
20505 }
20506
20507 return gridCol.headerCellFilter ?
20508 $filter(gridCol.headerCellFilter)(gridCol.displayName) :
20509 gridCol.displayName;
20510 }
20511
20512 function defaultExporterFieldCallback(grid, row, col, value) {
20513 // fix to handle cases with 'number : 1' or 'date:MM-dd-YYYY', etc.. We needed to split the string
20514 if (col.cellFilter) {
20515 var args, filter, arg1, arg2;
20516 // remove space, single/double to mantein retro-compatibility
20517 args = col.cellFilter.replace(/[\'\"\s]/g, "").split(':');
20518 filter = args[0] ? args[0] : null;
20519 arg1 = args[1] ? args[1] : null;
20520 arg2 = args[2] ? args[2] : null;
20521 return $filter(filter)(value, arg1, arg2);
20522 } else {
20523 return value;
20524 }
20525 }
20526
20527 return service;
20528 }
20529 ]);
20530
20531 /**
20532 * @ngdoc directive
20533 * @name ui.grid.exporter.directive:uiGridExporter
20534 * @element div
20535 * @restrict A
20536 *
20537 * @description Adds exporter features to grid
20538 *
20539 * @example
20540 <example module="app">
20541 <file name="app.js">
20542 var app = angular.module('app', ['ui.grid', 'ui.grid.exporter']);
20543
20544 app.controller('MainCtrl', ['$scope', function ($scope) {
20545 $scope.data = [
20546 { name: 'Bob', title: 'CEO' },
20547 { name: 'Frank', title: 'Lowly Developer' }
20548 ];
20549
20550 $scope.gridOptions = {
20551 enableGridMenu: true,
20552 exporterMenuCsv: false,
20553 columnDefs: [
20554 {name: 'name', enableCellEdit: true},
20555 {name: 'title', enableCellEdit: true}
20556 ],
20557 data: $scope.data
20558 };
20559 }]);
20560 </file>
20561 <file name="index.html">
20562 <div ng-controller="MainCtrl">
20563 <div ui-grid="gridOptions" ui-grid-exporter></div>
20564 </div>
20565 </file>
20566 </example>
20567 */
20568 module.directive('uiGridExporter', ['uiGridExporterConstants', 'uiGridExporterService', 'gridUtil', '$compile',
20569 function (uiGridExporterConstants, uiGridExporterService, gridUtil, $compile) {
20570 return {
20571 replace: true,
20572 priority: 0,
20573 require: '^uiGrid',
20574 scope: false,
20575 link: function ($scope, $elm, $attrs, uiGridCtrl) {
20576 uiGridExporterService.initializeGrid(uiGridCtrl.grid);
20577 uiGridCtrl.grid.exporter.$scope = $scope;
20578 }
20579 };
20580 }
20581 ]);
20582 })();
20583
20584 (function () {
20585 'use strict';
20586
20587 /**
20588 * @ngdoc overview
20589 * @name ui.grid.grouping
20590 * @description
20591 *
20592 * # ui.grid.grouping
20593 *
20594 * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
20595 *
20596 * This module provides grouping of rows based on the data in them, similar
20597 * in concept to excel grouping. You can group multiple columns, resulting in
20598 * nested grouping.
20599 *
20600 * In concept this feature is similar to sorting + grid footer/aggregation, it
20601 * sorts the data based on the grouped columns, then creates group rows that
20602 * reflect a break in the data. Each of those group rows can have aggregations for
20603 * the data within that group.
20604 *
20605 * This feature leverages treeBase to provide the tree functionality itself,
20606 * the key thing this feature does therefore is to set treeLevels on the rows
20607 * and insert the group headers.
20608 *
20609 * Design information:
20610 * -------------------
20611 *
20612 * Each column will get new menu items - group by, and aggregate by. Group by
20613 * will cause this column to be sorted (if not already), and will move this column
20614 * to the front of the sorted columns (i.e. grouped columns take precedence over
20615 * sorted columns). It will respect the sort order already set if there is one,
20616 * and it will allow the sorting logic to change that sort order, it just forces
20617 * the column to the front of the sorting. You can group by multiple columns, the
20618 * logic will add this column to the sorting after any already grouped columns.
20619 *
20620 * Once a grouping is defined, grouping logic is added to the rowsProcessors. This
20621 * will process the rows, identifying a break in the data value, and inserting a grouping row.
20622 * Grouping rows have specific attributes on them:
20623 *
20624 * - internalRow = true: tells us that this isn't a real row, so we can ignore it
20625 * from any processing that it looking at core data rows. This is used by the core
20626 * logic (or will be one day), as it's not grouping specific
20627 * - groupHeader = true: tells us this is a groupHeader. This is used by the grouping logic
20628 * to know if this is a groupHeader row or not
20629 *
20630 * Since the logic is baked into the rowsProcessors, it should get triggered whenever
20631 * row order or filtering or anything like that is changed. In order to avoid the row instantiation
20632 * time, and to preserve state across invocations, we hold a cache of the rows that we created
20633 * last time, and we use them again this time if we can.
20634 *
20635 * By default rows are collapsed, which means all data rows have their visible property
20636 * set to false, and only level 0 group rows are set to visible.
20637 *
20638 * <br/>
20639 * <br/>
20640 *
20641 * <div doc-module-components="ui.grid.grouping"></div>
20642 */
20643
20644 var module = angular.module('ui.grid.grouping', ['ui.grid', 'ui.grid.treeBase']);
20645
20646 /**
20647 * @ngdoc object
20648 * @name ui.grid.grouping.constant:uiGridGroupingConstants
20649 *
20650 * @description constants available in grouping module, this includes
20651 * all the constants declared in the treeBase module (these are manually copied
20652 * as there isn't an easy way to include constants in another constants file, and
20653 * we don't want to make users include treeBase)
20654 *
20655 */
20656 module.constant('uiGridGroupingConstants', {
20657 featureName: "grouping",
20658 rowHeaderColName: 'treeBaseRowHeaderCol',
20659 EXPANDED: 'expanded',
20660 COLLAPSED: 'collapsed',
20661 aggregation: {
20662 COUNT: 'count',
20663 SUM: 'sum',
20664 MAX: 'max',
20665 MIN: 'min',
20666 AVG: 'avg'
20667 }
20668 });
20669
20670 /**
20671 * @ngdoc service
20672 * @name ui.grid.grouping.service:uiGridGroupingService
20673 *
20674 * @description Services for grouping features
20675 */
20676 module.service('uiGridGroupingService', ['$q', 'uiGridGroupingConstants', 'gridUtil', 'rowSorter', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'uiGridTreeBaseService',
20677 function ($q, uiGridGroupingConstants, gridUtil, rowSorter, GridRow, gridClassFactory, i18nService, uiGridConstants, uiGridTreeBaseService) {
20678 var service = {
20679 initializeGrid: function (grid, $scope) {
20680 uiGridTreeBaseService.initializeGrid( grid, $scope );
20681
20682 // add feature namespace and any properties to grid for needed
20683 /**
20684 * @ngdoc object
20685 * @name ui.grid.grouping.grid:grouping
20686 *
20687 * @description Grid properties and functions added for grouping
20688 */
20689 grid.grouping = {};
20690
20691 /**
20692 * @ngdoc property
20693 * @propertyOf ui.grid.grouping.grid:grouping
20694 * @name groupHeaderCache
20695 *
20696 * @description Cache that holds the group header rows we created last time, we'll
20697 * reuse these next time, not least because they hold our expanded states.
20698 *
20699 * We need to take care with these that they don't become a memory leak, we
20700 * create a new cache each time using the values from the old cache. This works
20701 * so long as we're creating group rows for invisible rows as well.
20702 *
20703 * The cache is a nested hash, indexed on the value we grouped by. So if we
20704 * grouped by gender then age, we'd maybe have something like:
20705 * ```
20706 * {
20707 * male: {
20708 * row: <pointer to the old row>,
20709 * children: {
20710 * 22: { row: <pointer to the old row> },
20711 * 31: { row: <pointer to the old row> }
20712 * },
20713 * female: {
20714 * row: <pointer to the old row>,
20715 * children: {
20716 * 28: { row: <pointer to the old row> },
20717 * 55: { row: <pointer to the old row> }
20718 * }
20719 * }
20720 * ```
20721 *
20722 * We create new rows for any missing rows, this means that they come in as collapsed.
20723 *
20724 */
20725 grid.grouping.groupHeaderCache = {};
20726
20727 service.defaultGridOptions(grid.options);
20728
20729 grid.registerRowsProcessor(service.groupRows, 400);
20730
20731 grid.registerColumnBuilder( service.groupingColumnBuilder);
20732
20733 grid.registerColumnsProcessor(service.groupingColumnProcessor, 400);
20734
20735 /**
20736 * @ngdoc object
20737 * @name ui.grid.grouping.api:PublicApi
20738 *
20739 * @description Public Api for grouping feature
20740 */
20741 var publicApi = {
20742 events: {
20743 grouping: {
20744 /**
20745 * @ngdoc event
20746 * @eventOf ui.grid.grouping.api:PublicApi
20747 * @name aggregationChanged
20748 * @description raised whenever aggregation is changed, added or removed from a column
20749 *
20750 * <pre>
20751 * gridApi.grouping.on.aggregationChanged(scope,function(col) {})
20752 * </pre>
20753 * @param {GridColumn} col the column which on which aggregation changed. The aggregation
20754 * type is available as `col.treeAggregation.type`
20755 */
20756 aggregationChanged: {},
20757 /**
20758 * @ngdoc event
20759 * @eventOf ui.grid.grouping.api:PublicApi
20760 * @name groupingChanged
20761 * @description raised whenever the grouped columns changes
20762 *
20763 * <pre>
20764 * gridApi.grouping.on.groupingChanged(scope,function(col) {})
20765 * </pre>
20766 * @param {GridColumn} col the column which on which grouping changed. The new grouping is
20767 * available as `col.grouping`
20768 */
20769 groupingChanged: {}
20770 }
20771 },
20772 methods: {
20773 grouping: {
20774 /**
20775 * @ngdoc function
20776 * @name getGrouping
20777 * @methodOf ui.grid.grouping.api:PublicApi
20778 * @description Get the grouping configuration for this grid,
20779 * used by the saveState feature. Adds expandedState to the information
20780 * provided by the internal getGrouping, and removes any aggregations that have a source
20781 * of grouping (i.e. will be automatically reapplied when we regroup the column)
20782 * Returned grouping is an object
20783 * `{ grouping: groupArray, treeAggregations: aggregateArray, expandedState: hash }`
20784 * where grouping contains an array of objects:
20785 * `{ field: column.field, colName: column.name, groupPriority: column.grouping.groupPriority }`
20786 * and aggregations contains an array of objects:
20787 * `{ field: column.field, colName: column.name, aggregation: column.grouping.aggregation }`
20788 * and expandedState is a hash of the currently expanded nodes
20789 *
20790 * The groupArray will be sorted by groupPriority.
20791 *
20792 * @param {boolean} getExpanded whether or not to return the expanded state
20793 * @returns {object} grouping configuration
20794 */
20795 getGrouping: function ( getExpanded ) {
20796 var grouping = service.getGrouping(grid);
20797
20798 grouping.grouping.forEach( function( group ) {
20799 group.colName = group.col.name;
20800 delete group.col;
20801 });
20802
20803 grouping.aggregations.forEach( function( aggregation ) {
20804 aggregation.colName = aggregation.col.name;
20805 delete aggregation.col;
20806 });
20807
20808 grouping.aggregations = grouping.aggregations.filter( function( aggregation ) {
20809 return !aggregation.aggregation.source || aggregation.aggregation.source !== 'grouping';
20810 });
20811
20812 if ( getExpanded ) {
20813 grouping.rowExpandedStates = service.getRowExpandedStates( grid.grouping.groupingHeaderCache );
20814 }
20815
20816 return grouping;
20817 },
20818
20819 /**
20820 * @ngdoc function
20821 * @name setGrouping
20822 * @methodOf ui.grid.grouping.api:PublicApi
20823 * @description Set the grouping configuration for this grid,
20824 * used by the saveState feature, but can also be used by any
20825 * user to specify a combined grouping and aggregation configuration
20826 * @param {object} config the config you want to apply, in the format
20827 * provided out by getGrouping
20828 */
20829 setGrouping: function ( config ) {
20830 service.setGrouping(grid, config);
20831 },
20832
20833 /**
20834 * @ngdoc function
20835 * @name groupColumn
20836 * @methodOf ui.grid.grouping.api:PublicApi
20837 * @description Adds this column to the existing grouping, at the end of the priority order.
20838 * If the column doesn't have a sort, adds one, by default ASC
20839 *
20840 * This column will move to the left of any non-group columns, the
20841 * move is handled in a columnProcessor, so gets called as part of refresh
20842 *
20843 * @param {string} columnName the name of the column we want to group
20844 */
20845 groupColumn: function(columnName) {
20846 var column = grid.getColumn(columnName);
20847
20848 service.groupColumn(grid, column);
20849 },
20850
20851 /**
20852 * @ngdoc function
20853 * @name ungroupColumn
20854 * @methodOf ui.grid.grouping.api:PublicApi
20855 * @description Removes the groupPriority from this column. If the
20856 * column was previously aggregated the aggregation will come back.
20857 * The sort will remain.
20858 *
20859 * This column will move to the right of any other group columns, the
20860 * move is handled in a columnProcessor, so gets called as part of refresh
20861 *
20862 * @param {string} columnName the name of the column we want to ungroup
20863 */
20864 ungroupColumn: function(columnName) {
20865 var column = grid.getColumn(columnName);
20866
20867 service.ungroupColumn(grid, column);
20868 },
20869
20870 /**
20871 * @ngdoc function
20872 * @name clearGrouping
20873 * @methodOf ui.grid.grouping.api:PublicApi
20874 * @description Clear any grouped columns and any aggregations. Doesn't remove sorting,
20875 * as we don't know whether that sorting was added by grouping or was there beforehand
20876 *
20877 */
20878 clearGrouping: function() {
20879 service.clearGrouping(grid);
20880 },
20881
20882 /**
20883 * @ngdoc function
20884 * @name aggregateColumn
20885 * @methodOf ui.grid.grouping.api:PublicApi
20886 * @description Sets the aggregation type on a column, if the
20887 * column is currently grouped then it removes the grouping first.
20888 * If the aggregationDef is null then will result in the aggregation
20889 * being removed
20890 *
20891 * @param {string} columnName the column we want to aggregate
20892 * @param {string|function} aggregationDef one of the recognised types
20893 * from uiGridGroupingConstants or a custom aggregation function.
20894 * @param {string} aggregationLabel (optional) The label to use for this aggregation.
20895 */
20896 aggregateColumn: function(columnName, aggregationDef, aggregationLabel) {
20897 var column = grid.getColumn(columnName);
20898
20899 service.aggregateColumn(grid, column, aggregationDef, aggregationLabel);
20900 }
20901 }
20902 }
20903 };
20904
20905 grid.api.registerEventsFromObject(publicApi.events);
20906
20907 grid.api.registerMethodsFromObject(publicApi.methods);
20908
20909 grid.api.core.on.sortChanged($scope, service.tidyPriorities);
20910 },
20911
20912 defaultGridOptions: function (gridOptions) {
20913 // default option to true unless it was explicitly set to false
20914 /**
20915 * @ngdoc object
20916 * @name ui.grid.grouping.api:GridOptions
20917 *
20918 * @description GridOptions for grouping feature, these are available to be
20919 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
20920 */
20921
20922 /**
20923 * @ngdoc object
20924 * @name enableGrouping
20925 * @propertyOf ui.grid.grouping.api:GridOptions
20926 * @description Enable row grouping for entire grid.
20927 * <br/>Defaults to true
20928 */
20929 gridOptions.enableGrouping = gridOptions.enableGrouping !== false;
20930
20931 /**
20932 * @ngdoc object
20933 * @name groupingShowCounts
20934 * @propertyOf ui.grid.grouping.api:GridOptions
20935 * @description shows counts on the groupHeader rows. Not that if you are using a cellFilter or a
20936 * sortingAlgorithm which relies on a specific format or data type, showing counts may cause that
20937 * to break, since the group header rows will always be a string with groupingShowCounts enabled.
20938 * <br/>Defaults to true except on columns of types 'date' and 'object'
20939 */
20940 gridOptions.groupingShowCounts = gridOptions.groupingShowCounts !== false;
20941
20942 /**
20943 * @ngdoc object
20944 * @name groupingNullLabel
20945 * @propertyOf ui.grid.grouping.api:GridOptions
20946 * @description The string to use for the grouping header row label on rows which contain a null or undefined value in the grouped column.
20947 * <br/>Defaults to "Null"
20948 */
20949 gridOptions.groupingNullLabel = typeof(gridOptions.groupingNullLabel) === 'undefined' ? 'Null' : gridOptions.groupingNullLabel;
20950
20951 /**
20952 * @ngdoc object
20953 * @name enableGroupHeaderSelection
20954 * @propertyOf ui.grid.grouping.api:GridOptions
20955 * @description Allows group header rows to be selected.
20956 * <br/>Defaults to false
20957 */
20958 gridOptions.enableGroupHeaderSelection = gridOptions.enableGroupHeaderSelection === true;
20959 },
20960
20961
20962 /**
20963 * @ngdoc function
20964 * @name groupingColumnBuilder
20965 * @methodOf ui.grid.grouping.service:uiGridGroupingService
20966 * @description Sets the grouping defaults based on the columnDefs
20967 *
20968 * @param {object} colDef columnDef we're basing on
20969 * @param {GridColumn} col the column we're to update
20970 * @param {object} gridOptions the options we should use
20971 * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved
20972 */
20973 groupingColumnBuilder: function (colDef, col, gridOptions) {
20974 /**
20975 * @ngdoc object
20976 * @name ui.grid.grouping.api:ColumnDef
20977 *
20978 * @description ColumnDef for grouping feature, these are available to be
20979 * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
20980 */
20981
20982 /**
20983 * @ngdoc object
20984 * @name enableGrouping
20985 * @propertyOf ui.grid.grouping.api:ColumnDef
20986 * @description Enable grouping on this column
20987 * <br/>Defaults to true.
20988 */
20989 if (colDef.enableGrouping === false) {
20990 return;
20991 }
20992
20993 /**
20994 * @ngdoc object
20995 * @name grouping
20996 * @propertyOf ui.grid.grouping.api:ColumnDef
20997 * @description Set the grouping for a column. Format is:
20998 * ```
20999 * {
21000 * groupPriority: <number, starts at 0, if less than 0 or undefined then we're aggregating in this column>
21001 * }
21002 * ```
21003 *
21004 * **Note that aggregation used to be included in grouping, but is now separately set on the column via treeAggregation
21005 * setting in treeBase**
21006 *
21007 * We group in the priority order given, this will also put these columns to the high order of the sort irrespective
21008 * of the sort priority given them. If there is no sort defined then we sort ascending, if there is a sort defined then
21009 * we use that sort.
21010 *
21011 * If the groupPriority is undefined or less than 0, then we expect to be aggregating, and we look at the
21012 * aggregation types to determine what sort of aggregation we can do. Values are in the constants file, but
21013 * include SUM, COUNT, MAX, MIN
21014 *
21015 * groupPriorities should generally be sequential, if they're not then the next time getGrouping is called
21016 * we'll renumber them to be sequential.
21017 * <br/>Defaults to undefined.
21018 */
21019
21020 if ( typeof(col.grouping) === 'undefined' && typeof(colDef.grouping) !== 'undefined') {
21021 col.grouping = angular.copy(colDef.grouping);
21022 if ( typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority > -1 ) {
21023 col.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;
21024 col.treeAggregationFinalizerFn = service.groupedFinalizerFn;
21025 }
21026 } else if (typeof(col.grouping) === 'undefined') {
21027 col.grouping = {};
21028 }
21029
21030 if (typeof(col.grouping) !== 'undefined' && typeof(col.grouping.groupPriority) !== 'undefined' && col.grouping.groupPriority >= 0) {
21031 col.suppressRemoveSort = true;
21032 }
21033
21034 var groupColumn = {
21035 name: 'ui.grid.grouping.group',
21036 title: i18nService.get().grouping.group,
21037 icon: 'ui-grid-icon-indent-right',
21038 shown: function () {
21039 return typeof(this.context.col.grouping) === 'undefined' ||
21040 typeof(this.context.col.grouping.groupPriority) === 'undefined' ||
21041 this.context.col.grouping.groupPriority < 0;
21042 },
21043 action: function () {
21044 service.groupColumn( this.context.col.grid, this.context.col );
21045 }
21046 };
21047
21048 var ungroupColumn = {
21049 name: 'ui.grid.grouping.ungroup',
21050 title: i18nService.get().grouping.ungroup,
21051 icon: 'ui-grid-icon-indent-left',
21052 shown: function () {
21053 return typeof(this.context.col.grouping) !== 'undefined' &&
21054 typeof(this.context.col.grouping.groupPriority) !== 'undefined' &&
21055 this.context.col.grouping.groupPriority >= 0;
21056 },
21057 action: function () {
21058 service.ungroupColumn( this.context.col.grid, this.context.col );
21059 }
21060 };
21061
21062 var aggregateRemove = {
21063 name: 'ui.grid.grouping.aggregateRemove',
21064 title: i18nService.get().grouping.aggregate_remove,
21065 shown: function () {
21066 return typeof(this.context.col.treeAggregationFn) !== 'undefined';
21067 },
21068 action: function () {
21069 service.aggregateColumn( this.context.col.grid, this.context.col, null);
21070 }
21071 };
21072
21073 // generic adder for the aggregation menus, which follow a pattern
21074 var addAggregationMenu = function(type, title) {
21075 title = title || i18nService.get().grouping['aggregate_' + type] || type;
21076 var menuItem = {
21077 name: 'ui.grid.grouping.aggregate' + type,
21078 title: title,
21079 shown: function () {
21080 return typeof(this.context.col.treeAggregation) === 'undefined' ||
21081 typeof(this.context.col.treeAggregation.type) === 'undefined' ||
21082 this.context.col.treeAggregation.type !== type;
21083 },
21084 action: function () {
21085 service.aggregateColumn( this.context.col.grid, this.context.col, type);
21086 }
21087 };
21088
21089 if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregate' + type)) {
21090 col.menuItems.push(menuItem);
21091 }
21092 };
21093
21094 /**
21095 * @ngdoc object
21096 * @name groupingShowGroupingMenu
21097 * @propertyOf ui.grid.grouping.api:ColumnDef
21098 * @description Show the grouping (group and ungroup items) menu on this column
21099 * <br/>Defaults to true.
21100 */
21101 if ( col.colDef.groupingShowGroupingMenu !== false ) {
21102 if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.group')) {
21103 col.menuItems.push(groupColumn);
21104 }
21105
21106 if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.ungroup')) {
21107 col.menuItems.push(ungroupColumn);
21108 }
21109 }
21110
21111
21112 /**
21113 * @ngdoc object
21114 * @name groupingShowAggregationMenu
21115 * @propertyOf ui.grid.grouping.api:ColumnDef
21116 * @description Show the aggregation menu on this column
21117 * <br/>Defaults to true.
21118 */
21119 if ( col.colDef.groupingShowAggregationMenu !== false ) {
21120 angular.forEach(uiGridTreeBaseService.nativeAggregations(), function(aggregationDef, name) {
21121 addAggregationMenu(name);
21122 });
21123 angular.forEach(gridOptions.treeCustomAggregations, function(aggregationDef, name) {
21124 addAggregationMenu(name, aggregationDef.menuTitle);
21125 });
21126
21127 if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.grouping.aggregateRemove')) {
21128 col.menuItems.push(aggregateRemove);
21129 }
21130 }
21131 },
21132
21133
21134
21135
21136 /**
21137 * @ngdoc function
21138 * @name groupingColumnProcessor
21139 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21140 * @description Moves the columns around based on which are grouped
21141 *
21142 * @param {array} columns the columns to consider rendering
21143 * @param {array} rows the grid rows, which we don't use but are passed to us
21144 * @returns {array} updated columns array
21145 */
21146 groupingColumnProcessor: function( columns, rows ) {
21147 columns = service.moveGroupColumns(this, columns, rows);
21148 return columns;
21149 },
21150
21151 /**
21152 * @ngdoc function
21153 * @name groupedFinalizerFn
21154 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21155 * @description Used on group columns to display the rendered value and optionally
21156 * display the count of rows.
21157 *
21158 * @param {aggregation} aggregation The aggregation entity for a grouped column
21159 */
21160 groupedFinalizerFn: function( aggregation ) {
21161 var col = this;
21162
21163 if ( typeof(aggregation.groupVal) !== 'undefined') {
21164 aggregation.rendered = aggregation.groupVal;
21165 if ( col.grid.options.groupingShowCounts && col.colDef.type !== 'date' && col.colDef.type !== 'object' ) {
21166 aggregation.rendered += (' (' + aggregation.value + ')');
21167 }
21168 } else {
21169 aggregation.rendered = null;
21170 }
21171 },
21172
21173 /**
21174 * @ngdoc function
21175 * @name moveGroupColumns
21176 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21177 * @description Moves the column order so that the grouped columns are lined up
21178 * to the left (well, unless you're RTL, then it's the right). By doing this in
21179 * the columnsProcessor, we make it transient - when the column is ungrouped it'll
21180 * go back to where it was.
21181 *
21182 * Does nothing if the option `moveGroupColumns` is set to false.
21183 *
21184 * @param {Grid} grid grid object
21185 * @param {array} columns the columns that we should process/move
21186 * @returns {array} updated columns
21187 */
21188 moveGroupColumns: function( grid, columns ) {
21189 if ( grid.options.moveGroupColumns === false) {
21190 return columns;
21191 }
21192
21193 columns.forEach(function(column, index) {
21194 // position used to make stable sort in moveGroupColumns
21195 column.groupingPosition = index;
21196 });
21197
21198 columns.sort(function(a, b) {
21199 var a_group, b_group;
21200
21201 if (a.isRowHeader) {
21202 a_group = a.headerPriority;
21203 }
21204 else if ( typeof(a.grouping) === 'undefined' || typeof(a.grouping.groupPriority) === 'undefined' || a.grouping.groupPriority < 0) {
21205 a_group = null;
21206 }
21207 else {
21208 a_group = a.grouping.groupPriority;
21209 }
21210
21211 if (b.isRowHeader) {
21212 b_group = b.headerPriority;
21213 }
21214 else if ( typeof(b.grouping) === 'undefined' || typeof(b.grouping.groupPriority) === 'undefined' || b.grouping.groupPriority < 0) {
21215 b_group = null;
21216 }
21217 else {
21218 b_group = b.grouping.groupPriority;
21219 }
21220
21221 // groups get sorted to the top
21222 if ( a_group !== null && b_group === null) { return -1; }
21223 if ( b_group !== null && a_group === null) { return 1; }
21224 if ( a_group !== null && b_group !== null) {return a_group - b_group; }
21225
21226 return a.groupingPosition - b.groupingPosition;
21227 });
21228
21229 columns.forEach( function(column) {
21230 delete column.groupingPosition;
21231 });
21232
21233 return columns;
21234 },
21235
21236
21237 /**
21238 * @ngdoc function
21239 * @name groupColumn
21240 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21241 * @description Adds this column to the existing grouping, at the end of the priority order.
21242 * If the column doesn't have a sort, adds one, by default ASC
21243 *
21244 * This column will move to the left of any non-group columns, the
21245 * move is handled in a columnProcessor, so gets called as part of refresh
21246 *
21247 * @param {Grid} grid grid object
21248 * @param {GridColumn} column the column we want to group
21249 */
21250 groupColumn: function( grid, column) {
21251 if ( typeof(column.grouping) === 'undefined' ) {
21252 column.grouping = {};
21253 }
21254
21255 // set the group priority to the next number in the hierarchy
21256 var existingGrouping = service.getGrouping( grid );
21257 column.grouping.groupPriority = existingGrouping.grouping.length;
21258
21259 // save sort in order to restore it when column is ungrouped
21260 column.previousSort = angular.copy(column.sort);
21261
21262 // add sort if not present
21263 if ( !column.sort ) {
21264 column.sort = { direction: uiGridConstants.ASC };
21265 } else if ( typeof(column.sort.direction) === 'undefined' || column.sort.direction === null ) {
21266 column.sort.direction = uiGridConstants.ASC;
21267 }
21268
21269 column.treeAggregation = { type: uiGridGroupingConstants.aggregation.COUNT, source: 'grouping' };
21270 column.treeAggregationFn = uiGridTreeBaseService.nativeAggregations()[uiGridGroupingConstants.aggregation.COUNT].aggregationFn;
21271 column.treeAggregationFinalizerFn = service.groupedFinalizerFn;
21272
21273 grid.api.grouping.raise.groupingChanged(column);
21274 // This indirectly calls service.tidyPriorities( grid );
21275 grid.api.core.raise.sortChanged(grid, grid.getColumnSorting());
21276
21277 grid.queueGridRefresh();
21278 },
21279
21280
21281 /**
21282 * @ngdoc function
21283 * @name ungroupColumn
21284 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21285 * @description Removes the groupPriority from this column. If the
21286 * column was previously aggregated the aggregation will come back.
21287 * The sort will remain.
21288 *
21289 * This column will move to the right of any other group columns, the
21290 * move is handled in a columnProcessor, so gets called as part of refresh
21291 *
21292 * @param {Grid} grid grid object
21293 * @param {GridColumn} column the column we want to ungroup
21294 */
21295 ungroupColumn: function( grid, column) {
21296 if ( typeof(column.grouping) === 'undefined' ) {
21297 return;
21298 }
21299
21300 delete column.grouping.groupPriority;
21301 delete column.treeAggregation;
21302 delete column.customTreeAggregationFinalizer;
21303
21304 if (column.previousSort) {
21305 column.sort = column.previousSort;
21306 delete column.previousSort;
21307 }
21308
21309 service.tidyPriorities( grid );
21310
21311 grid.api.grouping.raise.groupingChanged(column);
21312 grid.api.core.raise.sortChanged(grid, grid.getColumnSorting());
21313
21314 grid.queueGridRefresh();
21315 },
21316
21317 /**
21318 * @ngdoc function
21319 * @name aggregateColumn
21320 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21321 * @description Sets the aggregation type on a column, if the
21322 * column is currently grouped then it removes the grouping first.
21323 *
21324 * @param {Grid} grid grid object
21325 * @param {GridColumn} column the column we want to aggregate
21326 * @param {string} aggregationType of the recognised types from uiGridGroupingConstants or one of the custom aggregations from gridOptions
21327 */
21328 aggregateColumn: function( grid, column, aggregationType) {
21329 if (typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0) {
21330 service.ungroupColumn( grid, column );
21331 }
21332
21333 var aggregationDef = {};
21334
21335 if ( typeof(grid.options.treeCustomAggregations[aggregationType]) !== 'undefined' ) {
21336 aggregationDef = grid.options.treeCustomAggregations[aggregationType];
21337 } else if ( typeof(uiGridTreeBaseService.nativeAggregations()[aggregationType]) !== 'undefined' ) {
21338 aggregationDef = uiGridTreeBaseService.nativeAggregations()[aggregationType];
21339 }
21340
21341 column.treeAggregation = { type: aggregationType, label: i18nService.get().aggregation[aggregationDef.label] || aggregationDef.label };
21342 column.treeAggregationFn = aggregationDef.aggregationFn;
21343 column.treeAggregationFinalizerFn = aggregationDef.finalizerFn;
21344
21345 grid.api.grouping.raise.aggregationChanged(column);
21346
21347 grid.queueGridRefresh();
21348 },
21349
21350
21351 /**
21352 * @ngdoc function
21353 * @name setGrouping
21354 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21355 * @description Set the grouping based on a config object, used by the save state feature
21356 * (more specifically, by the restore function in that feature )
21357 *
21358 * @param {Grid} grid grid object
21359 * @param {object} config the config we want to set, same format as that returned by getGrouping
21360 */
21361 setGrouping: function ( grid, config ) {
21362 if ( typeof(config) === 'undefined' ) {
21363 return;
21364 }
21365
21366 // first remove any existing grouping
21367 service.clearGrouping(grid);
21368
21369 if ( config.grouping && config.grouping.length && config.grouping.length > 0 ) {
21370 config.grouping.forEach( function( group ) {
21371 var col = grid.getColumn(group.colName);
21372
21373 if ( col ) {
21374 service.groupColumn( grid, col );
21375 }
21376 });
21377 }
21378
21379 if ( config.aggregations && config.aggregations.length ) {
21380 config.aggregations.forEach( function( aggregation ) {
21381 var col = grid.getColumn(aggregation.colName);
21382
21383 if ( col ) {
21384 service.aggregateColumn( grid, col, aggregation.aggregation.type );
21385 }
21386 });
21387 }
21388
21389 if ( config.rowExpandedStates ) {
21390 service.applyRowExpandedStates( grid.grouping.groupingHeaderCache, config.rowExpandedStates );
21391 }
21392 },
21393
21394
21395 /**
21396 * @ngdoc function
21397 * @name clearGrouping
21398 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21399 * @description Clear any grouped columns and any aggregations. Doesn't remove sorting,
21400 * as we don't know whether that sorting was added by grouping or was there beforehand
21401 *
21402 * @param {Grid} grid grid object
21403 */
21404 clearGrouping: function( grid ) {
21405 var currentGrouping = service.getGrouping(grid);
21406
21407 if ( currentGrouping.grouping.length > 0 ) {
21408 currentGrouping.grouping.forEach( function( group ) {
21409 if (!group.col) {
21410 // should have a group.colName if there's no col
21411 group.col = grid.getColumn(group.colName);
21412 }
21413 service.ungroupColumn(grid, group.col);
21414 });
21415 }
21416
21417 if ( currentGrouping.aggregations.length > 0 ) {
21418 currentGrouping.aggregations.forEach( function( aggregation ) {
21419 if (!aggregation.col) {
21420 // should have a group.colName if there's no col
21421 aggregation.col = grid.getColumn(aggregation.colName);
21422 }
21423 service.aggregateColumn(grid, aggregation.col, null);
21424 });
21425 }
21426 },
21427
21428
21429 /**
21430 * @ngdoc function
21431 * @name tidyPriorities
21432 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21433 * @description Renumbers groupPriority and sortPriority such that
21434 * groupPriority is contiguous, and sortPriority either matches
21435 * groupPriority (for group columns), and otherwise is contiguous and
21436 * higher than groupPriority.
21437 *
21438 * @param {Grid} grid grid object
21439 */
21440 tidyPriorities: function( grid ) {
21441 // if we're called from sortChanged, grid is in this, not passed as param, the param can be a column or undefined
21442 if ( ( typeof(grid) === 'undefined' || typeof(grid.grid) !== 'undefined' ) && typeof(this.grid) !== 'undefined' ) {
21443 grid = this.grid;
21444 }
21445
21446 var groupArray = [],
21447 sortArray = [];
21448
21449 grid.columns.forEach( function(column, index) {
21450 if ( typeof(column.grouping) !== 'undefined' && typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0) {
21451 groupArray.push(column);
21452 }
21453 else if ( typeof(column.sort) !== 'undefined' && typeof(column.sort.priority) !== 'undefined' && column.sort.priority >= 0) {
21454 sortArray.push(column);
21455 }
21456 });
21457
21458 groupArray.sort(function(a, b) { return a.grouping.groupPriority - b.grouping.groupPriority; });
21459 groupArray.forEach( function(column, index) {
21460 column.grouping.groupPriority = index;
21461 column.suppressRemoveSort = true;
21462 if ( typeof(column.sort) === 'undefined') {
21463 column.sort = {};
21464 }
21465 column.sort.priority = index;
21466 });
21467
21468 var i = groupArray.length;
21469
21470 sortArray.sort(function(a, b) { return a.sort.priority - b.sort.priority; });
21471 sortArray.forEach(function(column) {
21472 column.sort.priority = i;
21473 column.suppressRemoveSort = column.colDef.suppressRemoveSort;
21474 i++;
21475 });
21476 },
21477
21478 /**
21479 * @ngdoc function
21480 * @name groupRows
21481 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21482 * @description The rowProcessor that creates the groupHeaders (i.e. does
21483 * the actual grouping).
21484 *
21485 * Assumes it is always called after the sorting processor, guaranteed by the priority setting
21486 *
21487 * Processes all the rows in order, inserting a groupHeader row whenever there is a change
21488 * in value of a grouped row, based on the sortAlgorithm used for the column. The group header row
21489 * is looked up in the groupHeaderCache, and used from there if there is one. The entity is reset
21490 * to {} if one is found.
21491 *
21492 * As it processes it maintains a `processingState` array. This records, for each level of grouping we're
21493 * working with, the following information:
21494 * ```
21495 * {
21496 * fieldName: name,
21497 * col: col,
21498 * initialised: boolean,
21499 * currentValue: value,
21500 * currentRow: gridRow,
21501 * }
21502 * ```
21503 * We look for changes in the currentValue at any of the levels. Where we find a change we:
21504 *
21505 * - create a new groupHeader row in the array
21506 *
21507 * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor
21508 * @returns {array} the updated rows, including our new group rows
21509 */
21510 groupRows: function( renderableRows ) {
21511 if (renderableRows.length === 0) {
21512 return renderableRows;
21513 }
21514
21515 var grid = this;
21516 grid.grouping.oldGroupingHeaderCache = grid.grouping.groupingHeaderCache || {};
21517 grid.grouping.groupingHeaderCache = {};
21518
21519 var processingState = service.initialiseProcessingState( grid );
21520
21521 // processes each of the fields we are grouping by, checks if the value has changed and inserts a groupHeader
21522 // Broken out as shouldn't create functions in a loop.
21523 var updateProcessingState = function( groupFieldState, stateIndex ) {
21524 var fieldValue = grid.getCellValue(row, groupFieldState.col);
21525
21526 // look for change of value - and insert a header
21527 if ( !groupFieldState.initialised || rowSorter.getSortFn(grid, groupFieldState.col, renderableRows)(fieldValue, groupFieldState.currentValue) !== 0 ) {
21528 service.insertGroupHeader( grid, renderableRows, i, processingState, stateIndex );
21529 i++;
21530 }
21531 };
21532
21533 // use a for loop because it's tolerant of the array length changing whilst we go - we can
21534 // manipulate the iterator when we insert groupHeader rows
21535 for (var i = 0; i < renderableRows.length; i++ ) {
21536 var row = renderableRows[i];
21537
21538 if ( row.visible ) {
21539 processingState.forEach( updateProcessingState );
21540 }
21541 }
21542
21543 delete grid.grouping.oldGroupingHeaderCache;
21544 return renderableRows;
21545 },
21546
21547
21548 /**
21549 * @ngdoc function
21550 * @name initialiseProcessingState
21551 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21552 * @description Creates the processing state array that is used
21553 * for groupRows.
21554 *
21555 * @param {Grid} grid grid object
21556 * @returns {array} an array in the format described in the groupRows method,
21557 * initialised with blank values
21558 */
21559 initialiseProcessingState: function( grid ) {
21560 var processingState = [];
21561 var columnSettings = service.getGrouping( grid );
21562
21563 columnSettings.grouping.forEach( function( groupItem, index) {
21564 processingState.push({
21565 fieldName: groupItem.field,
21566 col: groupItem.col,
21567 initialised: false,
21568 currentValue: null,
21569 currentRow: null
21570 });
21571 });
21572
21573 return processingState;
21574 },
21575
21576
21577 /**
21578 * @ngdoc function
21579 * @name getGrouping
21580 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21581 * @description Get the grouping settings from the columns. As a side effect
21582 * this always renumbers the grouping starting at 0
21583 * @param {Grid} grid grid object
21584 * @returns {array} an array of the group fields, in order of priority
21585 */
21586 getGrouping: function( grid ) {
21587 var groupArray = [],
21588 aggregateArray = [];
21589
21590 // get all the grouping
21591 grid.columns.forEach(function(column) {
21592 if ( column.grouping ) {
21593 if ( typeof(column.grouping.groupPriority) !== 'undefined' && column.grouping.groupPriority >= 0) {
21594 groupArray.push({ field: column.field, col: column, groupPriority: column.grouping.groupPriority, grouping: column.grouping });
21595 }
21596 }
21597 if ( column.treeAggregation && column.treeAggregation.type ) {
21598 aggregateArray.push({ field: column.field, col: column, aggregation: column.treeAggregation });
21599 }
21600 });
21601
21602 // sort grouping into priority order
21603 groupArray.sort( function(a, b) {
21604 return a.groupPriority - b.groupPriority;
21605 });
21606
21607 // renumber the priority in case it was somewhat messed up, then remove the grouping reference
21608 groupArray.forEach( function( group, index) {
21609 group.grouping.groupPriority = index;
21610 group.groupPriority = index;
21611 delete group.grouping;
21612 });
21613
21614 return { grouping: groupArray, aggregations: aggregateArray };
21615 },
21616
21617
21618 /**
21619 * @ngdoc function
21620 * @name insertGroupHeader
21621 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21622 * @description Create a group header row, and link it to the various configuration
21623 * items that we use.
21624 *
21625 * Look for the row in the oldGroupingHeaderCache, write the row into the new groupingHeaderCache.
21626 *
21627 * @param {Grid} grid grid object
21628 * @param {array} renderableRows the rows that we are processing
21629 * @param {number} rowIndex the row we were up to processing
21630 * @param {array} processingState the current processing state
21631 * @param {number} stateIndex the processing state item that we were on when we triggered a new group header -
21632 * i.e. the column that we want to create a header for
21633 */
21634 insertGroupHeader: function( grid, renderableRows, rowIndex, processingState, stateIndex ) {
21635 // set the value that caused the end of a group into the header row and the processing state
21636 var col = processingState[stateIndex].col,
21637 newValue = grid.getCellValue(renderableRows[rowIndex], col),
21638 newDisplayValue = newValue;
21639
21640 if ( typeof(newValue) === 'undefined' || newValue === null ) {
21641 newDisplayValue = grid.options.groupingNullLabel;
21642 }
21643
21644 function getKeyAsValueForCacheMap(key) {
21645 return angular.isObject(key) ? JSON.stringify(key) : key;
21646 }
21647
21648 var cacheItem = grid.grouping.oldGroupingHeaderCache;
21649
21650 for ( var i = 0; i < stateIndex; i++ ) {
21651 if ( cacheItem && cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)] ) {
21652 cacheItem = cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)].children;
21653 }
21654 }
21655
21656 var headerRow;
21657
21658 if ( cacheItem && cacheItem[getKeyAsValueForCacheMap(newValue)]) {
21659 headerRow = cacheItem[getKeyAsValueForCacheMap(newValue)].row;
21660 headerRow.entity = {};
21661 } else {
21662 headerRow = new GridRow( {}, null, grid );
21663 gridClassFactory.rowTemplateAssigner.call(grid, headerRow);
21664 }
21665
21666 headerRow.entity['$$' + processingState[stateIndex].col.uid] = { groupVal: newDisplayValue };
21667 headerRow.treeLevel = stateIndex;
21668 headerRow.groupHeader = true;
21669 headerRow.internalRow = true;
21670 headerRow.enableCellEdit = false;
21671 headerRow.enableSelection = grid.options.enableGroupHeaderSelection;
21672 processingState[stateIndex].initialised = true;
21673 processingState[stateIndex].currentValue = newValue;
21674 processingState[stateIndex].currentRow = headerRow;
21675
21676 // set all processing states below this one to not be initialised - change of this state
21677 // means all those need to start again
21678 service.finaliseProcessingState( processingState, stateIndex + 1);
21679
21680 // insert our new header row
21681 renderableRows.splice(rowIndex, 0, headerRow);
21682
21683 // add our new header row to the cache
21684 cacheItem = grid.grouping.groupingHeaderCache;
21685 for ( i = 0; i < stateIndex; i++ ) {
21686 cacheItem = cacheItem[getKeyAsValueForCacheMap(processingState[i].currentValue)].children;
21687 }
21688 cacheItem[getKeyAsValueForCacheMap(newValue)] = { row: headerRow, children: {} };
21689 },
21690
21691
21692 /**
21693 * @ngdoc function
21694 * @name finaliseProcessingState
21695 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21696 * @description Set all processing states lower than the one that had a break in value to
21697 * no longer be initialised. Render the counts into the entity ready for display.
21698 *
21699 * @param {array} processingState the current processing state
21700 * @param {number} stateIndex the processing state item that we were on when we triggered a new group header, all
21701 * processing states after this need to be finalised
21702 */
21703 finaliseProcessingState: function( processingState, stateIndex ) {
21704 for ( var i = stateIndex; i < processingState.length; i++) {
21705 processingState[i].initialised = false;
21706 processingState[i].currentRow = null;
21707 processingState[i].currentValue = null;
21708 }
21709 },
21710
21711
21712 /**
21713 * @ngdoc function
21714 * @name getRowExpandedStates
21715 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21716 * @description Extract the groupHeaderCache hash, pulling out only the states.
21717 *
21718 * The example below shows a grid that is grouped by gender then age
21719 *
21720 * <pre>
21721 * {
21722 * male: {
21723 * state: 'expanded',
21724 * children: {
21725 * 22: { state: 'expanded' },
21726 * 30: { state: 'collapsed' }
21727 * }
21728 * },
21729 * female: {
21730 * state: 'expanded',
21731 * children: {
21732 * 28: { state: 'expanded' },
21733 * 55: { state: 'collapsed' }
21734 * }
21735 * }
21736 * }
21737 * </pre>
21738 *
21739 * @param {object} treeChildren The tree children elements object
21740 * @returns {object} the expanded states as an object
21741 */
21742 getRowExpandedStates: function(treeChildren) {
21743 if ( typeof(treeChildren) === 'undefined' ) {
21744 return {};
21745 }
21746
21747 var newChildren = {};
21748
21749 angular.forEach( treeChildren, function( value, key ) {
21750 newChildren[key] = { state: value.row.treeNode.state };
21751 if ( value.children ) {
21752 newChildren[key].children = service.getRowExpandedStates( value.children );
21753 } else {
21754 newChildren[key].children = {};
21755 }
21756 });
21757
21758 return newChildren;
21759 },
21760
21761
21762 /**
21763 * @ngdoc function
21764 * @name applyRowExpandedStates
21765 * @methodOf ui.grid.grouping.service:uiGridGroupingService
21766 * @description Take a hash in the format as created by getRowExpandedStates,
21767 * and apply it to the grid.grouping.groupHeaderCache.
21768 *
21769 * Takes a treeSubset, and applies to a treeSubset - so can be called
21770 * recursively.
21771 *
21772 * @param {object} currentNode can be grid.grouping.groupHeaderCache, or any of
21773 * the children of that hash
21774 * @param {object} expandedStates can be the full expanded states, or children
21775 * of that expanded states (which hopefully matches the subset of the groupHeaderCache)
21776 */
21777 applyRowExpandedStates: function( currentNode, expandedStates ) {
21778 if ( typeof(expandedStates) === 'undefined' ) {
21779 return;
21780 }
21781
21782 angular.forEach(expandedStates, function( value, key ) {
21783 if ( currentNode[key] ) {
21784 currentNode[key].row.treeNode.state = value.state;
21785
21786 if (value.children && currentNode[key].children) {
21787 service.applyRowExpandedStates( currentNode[key].children, value.children );
21788 }
21789 }
21790 });
21791 }
21792
21793
21794 };
21795
21796 return service;
21797
21798 }]);
21799
21800
21801 /**
21802 * @ngdoc directive
21803 * @name ui.grid.grouping.directive:uiGridGrouping
21804 * @element div
21805 * @restrict A
21806 *
21807 * @description Adds grouping features to grid
21808 *
21809 * @example
21810 <example module="app">
21811 <file name="app.js">
21812 var app = angular.module('app', ['ui.grid', 'ui.grid.grouping']);
21813
21814 app.controller('MainCtrl', ['$scope', function ($scope) {
21815 $scope.data = [
21816 { name: 'Bob', title: 'CEO' },
21817 { name: 'Frank', title: 'Lowly Developer' }
21818 ];
21819
21820 $scope.columnDefs = [
21821 {name: 'name', enableCellEdit: true},
21822 {name: 'title', enableCellEdit: true}
21823 ];
21824
21825 $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };
21826 }]);
21827 </file>
21828 <file name="index.html">
21829 <div ng-controller="MainCtrl">
21830 <div ui-grid="gridOptions" ui-grid-grouping></div>
21831 </div>
21832 </file>
21833 </example>
21834 */
21835 module.directive('uiGridGrouping', ['uiGridGroupingConstants', 'uiGridGroupingService',
21836 function (uiGridGroupingConstants, uiGridGroupingService) {
21837 return {
21838 replace: true,
21839 priority: 0,
21840 require: '^uiGrid',
21841 scope: false,
21842 compile: function () {
21843 return {
21844 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
21845 if (uiGridCtrl.grid.options.enableGrouping !== false) {
21846 uiGridGroupingService.initializeGrid(uiGridCtrl.grid, $scope);
21847 }
21848 },
21849 post: function ($scope, $elm, $attrs, uiGridCtrl) {
21850 }
21851 };
21852 }
21853 };
21854 }]);
21855
21856 })();
21857
21858 (function () {
21859 'use strict';
21860
21861 /**
21862 * @ngdoc overview
21863 * @name ui.grid.importer
21864 * @description
21865 *
21866 * # ui.grid.importer
21867 *
21868 * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
21869 *
21870 * This module provides the ability to import data into the grid. It
21871 * uses the column defs to work out which data belongs in which column,
21872 * and creates entities from a configured class (typically a $resource).
21873 *
21874 * If the rowEdit feature is enabled, it also calls save on those newly
21875 * created objects, and then displays any errors in the imported data.
21876 *
21877 * Currently the importer imports only CSV and json files, although provision has been
21878 * made to process other file formats, and these can be added over time.
21879 *
21880 * For json files, the properties within each object in the json must match the column names
21881 * (to put it another way, the importer doesn't process the json, it just copies the objects
21882 * within the json into a new instance of the specified object type)
21883 *
21884 * For CSV import, the default column identification relies on each column in the
21885 * header row matching a column.name or column.displayName. Optionally, a column identification
21886 * callback can be used. This allows matching using other attributes, which is particularly
21887 * useful if your application has internationalised column headings (i.e. the headings that
21888 * the user sees don't match the column names).
21889 *
21890 * The importer makes use of the grid menu as the UI for requesting an
21891 * import.
21892 *
21893 * <div ui-grid-importer></div>
21894 */
21895
21896 var module = angular.module('ui.grid.importer', ['ui.grid']);
21897
21898 /**
21899 * @ngdoc object
21900 * @name ui.grid.importer.constant:uiGridImporterConstants
21901 *
21902 * @description constants available in importer module
21903 */
21904
21905 module.constant('uiGridImporterConstants', {
21906 featureName: 'importer'
21907 });
21908
21909 /**
21910 * @ngdoc service
21911 * @name ui.grid.importer.service:uiGridImporterService
21912 *
21913 * @description Services for importer feature
21914 */
21915 module.service('uiGridImporterService', ['$q', 'uiGridConstants', 'uiGridImporterConstants', 'gridUtil', '$compile', '$interval', 'i18nService', '$window',
21916 function ($q, uiGridConstants, uiGridImporterConstants, gridUtil, $compile, $interval, i18nService, $window) {
21917
21918 var service = {
21919
21920 initializeGrid: function ($scope, grid) {
21921
21922 // add feature namespace and any properties to grid for needed state
21923 grid.importer = {
21924 $scope: $scope
21925 };
21926
21927 this.defaultGridOptions(grid.options);
21928
21929 /**
21930 * @ngdoc object
21931 * @name ui.grid.importer.api:PublicApi
21932 *
21933 * @description Public Api for importer feature
21934 */
21935 var publicApi = {
21936 events: {
21937 importer: {
21938 }
21939 },
21940 methods: {
21941 importer: {
21942 /**
21943 * @ngdoc function
21944 * @name importFile
21945 * @methodOf ui.grid.importer.api:PublicApi
21946 * @description Imports a file into the grid using the file object
21947 * provided. Bypasses the grid menu
21948 * @param {File} fileObject the file we want to import, as a javascript
21949 * File object
21950 */
21951 importFile: function ( fileObject ) {
21952 service.importThisFile( grid, fileObject );
21953 }
21954 }
21955 }
21956 };
21957
21958 grid.api.registerEventsFromObject(publicApi.events);
21959
21960 grid.api.registerMethodsFromObject(publicApi.methods);
21961
21962 if ( grid.options.enableImporter && grid.options.importerShowMenu ) {
21963 if ( grid.api.core.addToGridMenu ) {
21964 service.addToMenu( grid );
21965 } else {
21966 // order of registration is not guaranteed, register in a little while
21967 $interval( function() {
21968 if (grid.api.core.addToGridMenu) {
21969 service.addToMenu( grid );
21970 }
21971 }, 100, 1);
21972 }
21973 }
21974 },
21975
21976
21977 defaultGridOptions: function (gridOptions) {
21978 // default option to true unless it was explicitly set to false
21979 /**
21980 * @ngdoc object
21981 * @name ui.grid.importer.api:GridOptions
21982 *
21983 * @description GridOptions for importer feature, these are available to be
21984 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
21985 */
21986
21987 /**
21988 * @ngdoc property
21989 * @propertyOf ui.grid.importer.api:GridOptions
21990 * @name enableImporter
21991 * @description Whether or not importer is enabled. Automatically set
21992 * to false if the user's browser does not support the required fileApi.
21993 * Otherwise defaults to true.
21994 *
21995 */
21996 if (gridOptions.enableImporter || gridOptions.enableImporter === undefined) {
21997 if ( !($window.hasOwnProperty('File') && $window.hasOwnProperty('FileReader') && $window.hasOwnProperty('FileList') && $window.hasOwnProperty('Blob')) ) {
21998 gridUtil.logError('The File APIs are not fully supported in this browser, grid importer cannot be used.');
21999 gridOptions.enableImporter = false;
22000 } else {
22001 gridOptions.enableImporter = true;
22002 }
22003 } else {
22004 gridOptions.enableImporter = false;
22005 }
22006
22007 /**
22008 * @ngdoc method
22009 * @name importerProcessHeaders
22010 * @methodOf ui.grid.importer.api:GridOptions
22011 * @description A callback function that will process headers using custom
22012 * logic. Set this callback function if the headers that your user will provide in their
22013 * import file don't necessarily match the grid header or field names. This might commonly
22014 * occur where your application is internationalised, and therefore the field names
22015 * that the user recognises are in a different language than the field names that
22016 * ui-grid knows about.
22017 *
22018 * Defaults to the internal `processHeaders` method, which seeks to match using both
22019 * displayName and column.name. Any non-matching columns are discarded.
22020 *
22021 * Your callback routine should respond by processing the header array, and returning an array
22022 * of matching column names. A null value in any given position means "don't import this column"
22023 *
22024 * <pre>
22025 * gridOptions.importerProcessHeaders: function( grid, headerArray ) {
22026 * var myHeaderColumns = [];
22027 * var thisCol;
22028 * headerArray.forEach( function( value, index ) {
22029 * thisCol = mySpecialLookupFunction( value );
22030 * myHeaderColumns.push( thisCol.name );
22031 * });
22032 *
22033 * return myHeaderCols;
22034 * })
22035 * </pre>
22036 * @param {Grid} grid the grid we're importing into
22037 * @param {array} headerArray an array of the text from the first row of the csv file,
22038 * which you need to match to column.names
22039 * @returns {array} array of matching column names, in the same order as the headerArray
22040 *
22041 */
22042 gridOptions.importerProcessHeaders = gridOptions.importerProcessHeaders || service.processHeaders;
22043
22044 /**
22045 * @ngdoc method
22046 * @name importerHeaderFilter
22047 * @methodOf ui.grid.importer.api:GridOptions
22048 * @description A callback function that will filter (usually translate) a single
22049 * header. Used when you want to match the passed in column names to the column
22050 * displayName after the header filter.
22051 *
22052 * Your callback routine needs to return the filtered header value.
22053 * <pre>
22054 * gridOptions.importerHeaderFilter: function( displayName ) {
22055 * return $translate.instant( displayName );
22056 * })
22057 * </pre>
22058 *
22059 * or:
22060 * <pre>
22061 * gridOptions.importerHeaderFilter: $translate.instant
22062 * </pre>
22063 * @param {string} displayName the displayName that we'd like to translate
22064 * @returns {string} the translated name
22065 *
22066 */
22067 gridOptions.importerHeaderFilter = gridOptions.importerHeaderFilter || function( displayName ) { return displayName; };
22068
22069 /**
22070 * @ngdoc method
22071 * @name importerErrorCallback
22072 * @methodOf ui.grid.importer.api:GridOptions
22073 * @description A callback function that provides custom error handling, rather
22074 * than the standard grid behaviour of an alert box and a console message. You
22075 * might use this to internationalise the console log messages, or to write to a
22076 * custom logging routine that returned errors to the server.
22077 *
22078 * <pre>
22079 * gridOptions.importerErrorCallback: function( grid, errorKey, consoleMessage, context ) {
22080 * myUserDisplayRoutine( errorKey );
22081 * myLoggingRoutine( consoleMessage, context );
22082 * })
22083 * </pre>
22084 * @param {Grid} grid the grid we're importing into, may be useful if you're positioning messages
22085 * in some way
22086 * @param {string} errorKey one of the i18n keys the importer can return - importer.noHeaders,
22087 * importer.noObjects, importer.invalidCsv, importer.invalidJson, importer.jsonNotArray
22088 * @param {string} consoleMessage the English console message that importer would have written
22089 * @param {object} context the context data that importer would have appended to that console message,
22090 * often the file content itself or the element that is in error
22091 *
22092 */
22093 if ( !gridOptions.importerErrorCallback || typeof(gridOptions.importerErrorCallback) !== 'function' ) {
22094 delete gridOptions.importerErrorCallback;
22095 }
22096
22097 /**
22098 * @ngdoc method
22099 * @name importerDataAddCallback
22100 * @methodOf ui.grid.importer.api:GridOptions
22101 * @description A mandatory callback function that adds data to the source data array. The grid
22102 * generally doesn't add rows to the source data array, it is tidier to handle this through a user
22103 * callback.
22104 *
22105 * <pre>
22106 * gridOptions.importerDataAddCallback: function( grid, newObjects ) {
22107 * $scope.myData = $scope.myData.concat( newObjects );
22108 * })
22109 * </pre>
22110 * @param {Grid} grid the grid we're importing into, may be useful in some way
22111 * @param {array} newObjects an array of new objects that you should add to your data
22112 *
22113 */
22114 if ( gridOptions.enableImporter === true && !gridOptions.importerDataAddCallback ) {
22115 gridUtil.logError("You have not set an importerDataAddCallback, importer is disabled");
22116 gridOptions.enableImporter = false;
22117 }
22118
22119 /**
22120 * @ngdoc object
22121 * @name importerNewObject
22122 * @propertyOf ui.grid.importer.api:GridOptions
22123 * @description An object on which we call `new` to create each new row before inserting it into
22124 * the data array. Typically this would be a $resource entity, which means that if you're using
22125 * the rowEdit feature, you can directly call save on this entity when the save event is triggered.
22126 *
22127 * Defaults to a vanilla javascript object
22128 *
22129 * @example
22130 * <pre>
22131 * gridOptions.importerNewObject = MyRes;
22132 * </pre>
22133 *
22134 */
22135
22136 /**
22137 * @ngdoc property
22138 * @propertyOf ui.grid.importer.api:GridOptions
22139 * @name importerShowMenu
22140 * @description Whether or not to show an item in the grid menu. Defaults to true.
22141 *
22142 */
22143 gridOptions.importerShowMenu = gridOptions.importerShowMenu !== false;
22144
22145 /**
22146 * @ngdoc method
22147 * @methodOf ui.grid.importer.api:GridOptions
22148 * @name importerObjectCallback
22149 * @description A callback that massages the data for each object. For example,
22150 * you might have data stored as a code value, but display the decode. This callback
22151 * can be used to change the decoded value back into a code. Defaults to doing nothing.
22152 * @param {Grid} grid in case you need it
22153 * @param {object} newObject the new object as importer has created it, modify it
22154 * then return the modified version
22155 * @returns {object} the modified object
22156 * @example
22157 * <pre>
22158 * gridOptions.importerObjectCallback = function ( grid, newObject ) {
22159 * switch newObject.status {
22160 * case 'Active':
22161 * newObject.status = 1;
22162 * break;
22163 * case 'Inactive':
22164 * newObject.status = 2;
22165 * break;
22166 * }
22167 * return newObject;
22168 * };
22169 * </pre>
22170 */
22171 gridOptions.importerObjectCallback = gridOptions.importerObjectCallback || function( grid, newObject ) { return newObject; };
22172 },
22173
22174
22175 /**
22176 * @ngdoc function
22177 * @name addToMenu
22178 * @methodOf ui.grid.importer.service:uiGridImporterService
22179 * @description Adds import menu item to the grid menu,
22180 * allowing the user to request import of a file
22181 * @param {Grid} grid the grid into which data should be imported
22182 */
22183 addToMenu: function ( grid ) {
22184 grid.api.core.addToGridMenu( grid, [
22185 {
22186 title: i18nService.getSafeText('gridMenu.importerTitle'),
22187 order: 150
22188 },
22189 {
22190 templateUrl: 'ui-grid/importerMenuItemContainer',
22191 action: function () {
22192 this.grid.api.importer.importAFile( grid );
22193 },
22194 order: 151
22195 }
22196 ]);
22197 },
22198
22199
22200 /**
22201 * @ngdoc function
22202 * @name importThisFile
22203 * @methodOf ui.grid.importer.service:uiGridImporterService
22204 * @description Imports the provided file into the grid using the file object
22205 * provided. Bypasses the grid menu
22206 * @param {Grid} grid the grid we're importing into
22207 * @param {File} fileObject the file we want to import, as returned from the File
22208 * javascript object
22209 */
22210 importThisFile: function ( grid, fileObject ) {
22211 if (!fileObject) {
22212 gridUtil.logError( 'No file object provided to importThisFile, should be impossible, aborting');
22213 return;
22214 }
22215
22216 var reader = new FileReader();
22217
22218 switch ( fileObject.type ) {
22219 case 'application/json':
22220 reader.onload = service.importJsonClosure( grid );
22221 break;
22222 default:
22223 reader.onload = service.importCsvClosure( grid );
22224 break;
22225 }
22226
22227 reader.readAsText( fileObject );
22228 },
22229
22230
22231 /**
22232 * @ngdoc function
22233 * @name importJson
22234 * @methodOf ui.grid.importer.service:uiGridImporterService
22235 * @description Creates a function that imports a json file into the grid.
22236 * The json data is imported into new objects of type `gridOptions.importerNewObject`,
22237 * and if the rowEdit feature is enabled the rows are marked as dirty
22238 * @param {Grid} grid the grid we want to import into
22239 * @return {function} Function that receives the file that we want to import, as
22240 * a FileObject as an argument
22241 */
22242 importJsonClosure: function( grid ) {
22243 return function( importFile ) {
22244 var newObjects = [],
22245 newObject,
22246 importArray = service.parseJson( grid, importFile );
22247
22248 if (importArray === null) {
22249 return;
22250 }
22251 importArray.forEach( function( value ) {
22252 newObject = service.newObject( grid );
22253 angular.extend( newObject, value );
22254 newObject = grid.options.importerObjectCallback( grid, newObject );
22255 newObjects.push( newObject );
22256 });
22257
22258 service.addObjects( grid, newObjects );
22259 };
22260 },
22261
22262
22263 /**
22264 * @ngdoc function
22265 * @name parseJson
22266 * @methodOf ui.grid.importer.service:uiGridImporterService
22267 * @description Parses a json file, returns the parsed data.
22268 * Displays an error if file doesn't parse
22269 * @param {Grid} grid the grid that we want to import into
22270 * @param {FileObject} importFile the file that we want to import, as
22271 * a FileObject
22272 * @returns {array} array of objects from the imported json
22273 */
22274 parseJson: function( grid, importFile ) {
22275 var loadedObjects;
22276
22277 try {
22278 loadedObjects = JSON.parse( importFile.target.result );
22279 } catch (e) {
22280 service.alertError( grid, 'importer.invalidJson', 'File could not be processed, is it valid json? Content was: ', importFile.target.result );
22281 return;
22282 }
22283
22284 if ( !Array.isArray( loadedObjects ) ) {
22285 service.alertError( grid, 'importer.jsonNotarray', 'Import failed, file is not an array, file was: ', importFile.target.result );
22286 return [];
22287 } else {
22288 return loadedObjects;
22289 }
22290 },
22291
22292
22293
22294 /**
22295 * @ngdoc function
22296 * @name importCsvClosure
22297 * @methodOf ui.grid.importer.service:uiGridImporterService
22298 * @description Creates a function that imports a csv file into the grid
22299 * (allowing it to be used in the reader.onload event)
22300 * @param {Grid} grid the grid that we want to import into
22301 * @return {function} Function that receives the file that we want to import, as
22302 * a file object
22303 */
22304 importCsvClosure: function( grid ) {
22305 return function( importFile ) {
22306 var importArray = service.parseCsv( importFile );
22307
22308 if ( !importArray || importArray.length < 1 ) {
22309 service.alertError( grid, 'importer.invalidCsv', 'File could not be processed, is it valid csv? Content was: ', importFile.target.result );
22310 return;
22311 }
22312
22313 var newObjects = service.createCsvObjects( grid, importArray );
22314
22315 if ( !newObjects || newObjects.length === 0 ) {
22316 service.alertError( grid, 'importer.noObjects', 'Objects were not able to be derived, content was: ', importFile.target.result );
22317 return;
22318 }
22319
22320 service.addObjects( grid, newObjects );
22321 };
22322 },
22323
22324
22325 /**
22326 * @ngdoc function
22327 * @name parseCsv
22328 * @methodOf ui.grid.importer.service:uiGridImporterService
22329 * @description Parses a csv file into an array of arrays, with the first
22330 * array being the headers, and the remaining arrays being the data.
22331 * The logic for this comes from https://github.com/thetalecrafter/excel.js/blob/master/src/csv.js,
22332 * which is noted as being under the MIT license. The code is modified to pass the jscs yoda condition
22333 * checker
22334 * @param {FileObject} importFile the file that we want to import, as a
22335 * file object
22336 */
22337 parseCsv: function( importFile ) {
22338 var csv = importFile.target.result;
22339
22340 // use the CSV-JS library to parse
22341 return CSV.parse(csv);
22342 },
22343
22344
22345 /**
22346 * @ngdoc function
22347 * @name createCsvObjects
22348 * @methodOf ui.grid.importer.service:uiGridImporterService
22349 * @description Converts an array of arrays (representing the csv file)
22350 * into a set of objects. Uses the provided `gridOptions.importerNewObject`
22351 * to create the objects, and maps the header row into the individual columns
22352 * using either `gridOptions.importerProcessHeaders`, or by using a native method
22353 * of matching to either the displayName, column name or column field of
22354 * the columns in the column defs. The resulting objects will have attributes
22355 * that are named based on the column.field or column.name, in that order.
22356 * @param {Grid} grid the grid that we want to import into
22357 * @param {Array} importArray the data that we want to import, as an array
22358 */
22359 createCsvObjects: function( grid, importArray ) {
22360 // pull off header row and turn into headers
22361 var headerMapping = grid.options.importerProcessHeaders( grid, importArray.shift() );
22362
22363 if ( !headerMapping || headerMapping.length === 0 ) {
22364 service.alertError( grid, 'importer.noHeaders', 'Column names could not be derived, content was: ', importArray );
22365 return [];
22366 }
22367
22368 var newObjects = [],
22369 newObject;
22370
22371 importArray.forEach( function( row ) {
22372 newObject = service.newObject( grid );
22373 if ( row !== null ) {
22374 row.forEach( function( field, index ) {
22375 if ( headerMapping[index] !== null ) {
22376 newObject[ headerMapping[index] ] = field;
22377 }
22378 });
22379 }
22380 newObject = grid.options.importerObjectCallback( grid, newObject );
22381 newObjects.push( newObject );
22382 });
22383
22384 return newObjects;
22385 },
22386
22387
22388 /**
22389 * @ngdoc function
22390 * @name processHeaders
22391 * @methodOf ui.grid.importer.service:uiGridImporterService
22392 * @description Determines the columns that the header row from
22393 * a csv (or other) file represents.
22394 * @param {Grid} grid the grid we're importing into
22395 * @param {array} headerRow the header row that we wish to match against
22396 * the column definitions
22397 * @returns {array} an array of the attribute names that should be used
22398 * for that column, based on matching the headers or creating the headers
22399 *
22400 */
22401 processHeaders: function( grid, headerRow ) {
22402 var headers = [];
22403
22404 if ( !grid.options.columnDefs || grid.options.columnDefs.length === 0 ) {
22405 // we are going to create new columnDefs for all these columns, so just remove
22406 // spaces from the names to create fields
22407 headerRow.forEach( function( value ) {
22408 headers.push( value.replace( /[^0-9a-zA-Z\-_]/g, '_' ) );
22409 });
22410 return headers;
22411 }
22412 else {
22413 var lookupHash = service.flattenColumnDefs( grid, grid.options.columnDefs );
22414 headerRow.forEach( function( value ) {
22415 if ( lookupHash[value] ) {
22416 headers.push( lookupHash[value] );
22417 }
22418 else if ( lookupHash[ value.toLowerCase() ] ) {
22419 headers.push( lookupHash[ value.toLowerCase() ] );
22420 }
22421 else {
22422 headers.push( null );
22423 }
22424 });
22425 return headers;
22426 }
22427 },
22428
22429
22430 /**
22431 * @name flattenColumnDefs
22432 * @methodOf ui.grid.importer.service:uiGridImporterService
22433 * @description Runs through the column defs and creates a hash of
22434 * the displayName, name and field, and of each of those values forced to lower case,
22435 * with each pointing to the field or name
22436 * (whichever is present). Used to lookup column headers and decide what
22437 * attribute name to give to the resulting field.
22438 * @param {Grid} grid the grid we're importing into
22439 * @param {array} columnDefs the columnDefs that we should flatten
22440 * @returns {hash} the flattened version of the column def information, allowing
22441 * us to look up a value by `flattenedHash[ headerValue ]`
22442 */
22443 flattenColumnDefs: function( grid, columnDefs ) {
22444 var flattenedHash = {};
22445
22446 columnDefs.forEach( function( columnDef) {
22447 if ( columnDef.name ) {
22448 flattenedHash[ columnDef.name ] = columnDef.field || columnDef.name;
22449 flattenedHash[ columnDef.name.toLowerCase() ] = columnDef.field || columnDef.name;
22450 }
22451
22452 if ( columnDef.field ) {
22453 flattenedHash[ columnDef.field ] = columnDef.field || columnDef.name;
22454 flattenedHash[ columnDef.field.toLowerCase() ] = columnDef.field || columnDef.name;
22455 }
22456
22457 if ( columnDef.displayName ) {
22458 flattenedHash[ columnDef.displayName ] = columnDef.field || columnDef.name;
22459 flattenedHash[ columnDef.displayName.toLowerCase() ] = columnDef.field || columnDef.name;
22460 }
22461
22462 if ( columnDef.displayName && grid.options.importerHeaderFilter ) {
22463 flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName) ] = columnDef.field || columnDef.name;
22464 flattenedHash[ grid.options.importerHeaderFilter(columnDef.displayName).toLowerCase() ] = columnDef.field || columnDef.name;
22465 }
22466 });
22467
22468 return flattenedHash;
22469 },
22470
22471
22472 /**
22473 * @ngdoc function
22474 * @name addObjects
22475 * @methodOf ui.grid.importer.service:uiGridImporterService
22476 * @description Inserts our new objects into the grid data, and
22477 * sets the rows to dirty if the rowEdit feature is being used
22478 *
22479 * Does this by registering a watch on dataChanges, which essentially
22480 * is waiting on the result of the grid data watch, and downstream processing.
22481 *
22482 * When the callback is called, it deregisters itself - we don't want to run
22483 * again next time data is added.
22484 *
22485 * If we never get called, we deregister on destroy.
22486 *
22487 * @param {Grid} grid the grid we're importing into
22488 * @param {array} newObjects the objects we want to insert into the grid data
22489 * @returns {object} the new object
22490 */
22491 addObjects: function( grid, newObjects ) {
22492 if ( grid.api.rowEdit ) {
22493 var dataChangeDereg = grid.registerDataChangeCallback( function() {
22494 grid.api.rowEdit.setRowsDirty( newObjects );
22495 dataChangeDereg();
22496 }, [uiGridConstants.dataChange.ROW] );
22497
22498 grid.importer.$scope.$on( '$destroy', dataChangeDereg );
22499 }
22500
22501 grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );
22502
22503 },
22504
22505
22506 /**
22507 * @ngdoc function
22508 * @name newObject
22509 * @methodOf ui.grid.importer.service:uiGridImporterService
22510 * @description Makes a new object based on `gridOptions.importerNewObject`,
22511 * or based on an empty object if not present
22512 * @param {Grid} grid the grid we're importing into
22513 * @returns {object} the new object
22514 */
22515 newObject: function( grid ) {
22516 if ( typeof(grid.options) !== "undefined" && typeof(grid.options.importerNewObject) !== "undefined" ) {
22517 return new grid.options.importerNewObject();
22518 }
22519 else {
22520 return {};
22521 }
22522 },
22523
22524
22525 /**
22526 * @ngdoc function
22527 * @name alertError
22528 * @methodOf ui.grid.importer.service:uiGridImporterService
22529 * @description Provides an internationalised user alert for the failure,
22530 * and logs a console message including diagnostic content.
22531 * Optionally, if the the `gridOptions.importerErrorCallback` routine
22532 * is defined, then calls that instead, allowing user specified error routines
22533 * @param {Grid} grid the grid we're importing into
22534 * @param {array} headerRow the header row that we wish to match against
22535 * the column definitions
22536 */
22537 alertError: function( grid, alertI18nToken, consoleMessage, context ) {
22538 if ( grid.options.importerErrorCallback ) {
22539 grid.options.importerErrorCallback( grid, alertI18nToken, consoleMessage, context );
22540 }
22541 else {
22542 $window.alert(i18nService.getSafeText( alertI18nToken ));
22543 gridUtil.logError(consoleMessage + context );
22544 }
22545 }
22546 };
22547
22548 return service;
22549
22550 }
22551 ]);
22552
22553 /**
22554 * @ngdoc directive
22555 * @name ui.grid.importer.directive:uiGridImporter
22556 * @element div
22557 * @restrict A
22558 *
22559 * @description Adds importer features to grid
22560 *
22561 */
22562 module.directive('uiGridImporter', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',
22563 function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {
22564 return {
22565 replace: true,
22566 priority: 0,
22567 require: '^uiGrid',
22568 scope: false,
22569 link: function ($scope, $elm, $attrs, uiGridCtrl) {
22570 uiGridImporterService.initializeGrid($scope, uiGridCtrl.grid);
22571 }
22572 };
22573 }
22574 ]);
22575
22576 /**
22577 * @ngdoc directive
22578 * @name ui.grid.importer.directive:uiGridImporterMenuItem
22579 * @element div
22580 * @restrict A
22581 *
22582 * @description Handles the processing from the importer menu item - once a file is
22583 * selected
22584 *
22585 */
22586 module.directive('uiGridImporterMenuItem', ['uiGridImporterConstants', 'uiGridImporterService', 'gridUtil', '$compile',
22587 function (uiGridImporterConstants, uiGridImporterService, gridUtil, $compile) {
22588 return {
22589 replace: true,
22590 priority: 0,
22591 require: '?^uiGrid',
22592 scope: false,
22593 templateUrl: 'ui-grid/importerMenuItem',
22594 link: function ($scope, $elm, $attrs, uiGridCtrl) {
22595 var grid;
22596
22597 function handleFileSelect(event) {
22598 var target = event.srcElement || event.target;
22599
22600 if (target && target.files && target.files.length === 1) {
22601 var fileObject = target.files[0];
22602
22603 // Define grid if the uiGrid controller is present
22604 if (typeof(uiGridCtrl) !== 'undefined' && uiGridCtrl) {
22605 grid = uiGridCtrl.grid;
22606
22607 uiGridImporterService.importThisFile( grid, fileObject );
22608 target.form.reset();
22609 }
22610 else {
22611 gridUtil.logError('Could not import file because UI Grid was not found.');
22612 }
22613 }
22614 }
22615
22616 var fileChooser = $elm[0].querySelectorAll('.ui-grid-importer-file-chooser');
22617
22618 if ( fileChooser.length !== 1 ) {
22619 gridUtil.logError('Found > 1 or < 1 file choosers within the menu item, error, cannot continue');
22620 }
22621 else {
22622 fileChooser[0].addEventListener('change', handleFileSelect, false);
22623 }
22624 }
22625 };
22626 }
22627 ]);
22628 })();
22629
22630 (function() {
22631 'use strict';
22632 /**
22633 * @ngdoc overview
22634 * @name ui.grid.infiniteScroll
22635 *
22636 * @description
22637 *
22638 * #ui.grid.infiniteScroll
22639 *
22640 * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
22641 *
22642 * This module provides infinite scroll functionality to ui-grid
22643 *
22644 */
22645 var module = angular.module('ui.grid.infiniteScroll', ['ui.grid']);
22646 /**
22647 * @ngdoc service
22648 * @name ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
22649 *
22650 * @description Service for infinite scroll features
22651 */
22652 module.service('uiGridInfiniteScrollService', ['gridUtil', '$compile', '$rootScope', 'uiGridConstants', 'ScrollEvent', '$q', function (gridUtil, $compile, $rootScope, uiGridConstants, ScrollEvent, $q) {
22653 var service = {
22654
22655 /**
22656 * @ngdoc function
22657 * @name initializeGrid
22658 * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
22659 * @description This method register events and methods into grid public API
22660 */
22661
22662 initializeGrid: function(grid, $scope) {
22663 service.defaultGridOptions(grid.options);
22664
22665 if (!grid.options.enableInfiniteScroll) {
22666 return;
22667 }
22668
22669 grid.infiniteScroll = { dataLoading: false };
22670 service.setScrollDirections( grid, grid.options.infiniteScrollUp, grid.options.infiniteScrollDown );
22671 grid.api.core.on.scrollEnd($scope, service.handleScroll);
22672
22673 /**
22674 * @ngdoc object
22675 * @name ui.grid.infiniteScroll.api:PublicAPI
22676 *
22677 * @description Public API for infinite scroll feature
22678 */
22679 var publicApi = {
22680 events: {
22681 infiniteScroll: {
22682
22683 /**
22684 * @ngdoc event
22685 * @name needLoadMoreData
22686 * @eventOf ui.grid.infiniteScroll.api:PublicAPI
22687 * @description This event fires when scroll reaches bottom percentage of grid
22688 * and needs to load data
22689 */
22690
22691 needLoadMoreData: function ($scope, fn) {
22692 },
22693
22694 /**
22695 * @ngdoc event
22696 * @name needLoadMoreDataTop
22697 * @eventOf ui.grid.infiniteScroll.api:PublicAPI
22698 * @description This event fires when scroll reaches top percentage of grid
22699 * and needs to load data
22700 */
22701
22702 needLoadMoreDataTop: function ($scope, fn) {
22703 }
22704 }
22705 },
22706 methods: {
22707 infiniteScroll: {
22708
22709 /**
22710 * @ngdoc function
22711 * @name dataLoaded
22712 * @methodOf ui.grid.infiniteScroll.api:PublicAPI
22713 * @description Call this function when you have loaded the additional data
22714 * requested. You should set scrollUp and scrollDown to indicate
22715 * whether there are still more pages in each direction.
22716 *
22717 * If you call dataLoaded without first calling `saveScrollPercentage` then we will
22718 * scroll the user to the start of the newly loaded data, which usually gives a smooth scroll
22719 * experience, but can give a jumpy experience with large `infiniteScrollRowsFromEnd` values, and
22720 * on variable speed internet connections. Using `saveScrollPercentage` as demonstrated in the tutorial
22721 * should give a smoother scrolling experience for users.
22722 *
22723 * See infinite_scroll tutorial for example of usage
22724 * @param {boolean} scrollUp if set to false flags that there are no more pages upwards, so don't fire
22725 * any more infinite scroll events upward
22726 * @param {boolean} scrollDown if set to false flags that there are no more pages downwards, so don't
22727 * fire any more infinite scroll events downward
22728 * @returns {promise} a promise that is resolved when the grid scrolling is fully adjusted. If you're
22729 * planning to remove pages, you should wait on this promise first, or you'll break the scroll positioning
22730 */
22731 dataLoaded: function( scrollUp, scrollDown ) {
22732 service.setScrollDirections(grid, scrollUp, scrollDown);
22733
22734 return service.adjustScroll(grid).then(function() {
22735 grid.infiniteScroll.dataLoading = false;
22736 });
22737 },
22738
22739 /**
22740 * @ngdoc function
22741 * @name resetScroll
22742 * @methodOf ui.grid.infiniteScroll.api:PublicAPI
22743 * @description Call this function when you have taken some action that makes the current
22744 * scroll position invalid. For example, if you're using external sorting and you've resorted
22745 * then you might reset the scroll, or if you've otherwise substantially changed the data, perhaps
22746 * you've reused an existing grid for a new data set
22747 *
22748 * You must tell us whether there is data upwards or downwards after the reset
22749 *
22750 * @param {boolean} scrollUp flag that there are pages upwards, fire
22751 * infinite scroll events upward
22752 * @param {boolean} scrollDown flag that there are pages downwards, so
22753 * fire infinite scroll events downward
22754 */
22755 resetScroll: function( scrollUp, scrollDown ) {
22756 service.setScrollDirections( grid, scrollUp, scrollDown);
22757
22758 service.adjustInfiniteScrollPosition(grid, 0);
22759 },
22760
22761
22762 /**
22763 * @ngdoc function
22764 * @name saveScrollPercentage
22765 * @methodOf ui.grid.infiniteScroll.api:PublicAPI
22766 * @description Saves the scroll percentage and number of visible rows before you adjust the data,
22767 * used if you're subsequently going to call `dataRemovedTop` or `dataRemovedBottom`
22768 */
22769 saveScrollPercentage: function() {
22770 grid.infiniteScroll.prevScrollTop = grid.renderContainers.body.prevScrollTop;
22771 grid.infiniteScroll.previousVisibleRows = grid.getVisibleRowCount();
22772 },
22773
22774
22775 /**
22776 * @ngdoc function
22777 * @name dataRemovedTop
22778 * @methodOf ui.grid.infiniteScroll.api:PublicAPI
22779 * @description Adjusts the scroll position after you've removed data at the top
22780 * @param {boolean} scrollUp flag that there are pages upwards, fire
22781 * infinite scroll events upward
22782 * @param {boolean} scrollDown flag that there are pages downwards, so
22783 * fire infinite scroll events downward
22784 */
22785 dataRemovedTop: function( scrollUp, scrollDown ) {
22786 service.dataRemovedTop( grid, scrollUp, scrollDown );
22787 },
22788
22789 /**
22790 * @ngdoc function
22791 * @name dataRemovedBottom
22792 * @methodOf ui.grid.infiniteScroll.api:PublicAPI
22793 * @description Adjusts the scroll position after you've removed data at the bottom
22794 * @param {boolean} scrollUp flag that there are pages upwards, fire
22795 * infinite scroll events upward
22796 * @param {boolean} scrollDown flag that there are pages downwards, so
22797 * fire infinite scroll events downward
22798 */
22799 dataRemovedBottom: function( scrollUp, scrollDown ) {
22800 service.dataRemovedBottom( grid, scrollUp, scrollDown );
22801 },
22802
22803 /**
22804 * @ngdoc function
22805 * @name setScrollDirections
22806 * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
22807 * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,
22808 * and also sets the grid.suppressParentScroll
22809 * @param {boolean} scrollUp whether there are pages available up - defaults to false
22810 * @param {boolean} scrollDown whether there are pages available down - defaults to true
22811 */
22812 setScrollDirections: function ( scrollUp, scrollDown ) {
22813 service.setScrollDirections( grid, scrollUp, scrollDown );
22814 }
22815
22816 }
22817 }
22818 };
22819 grid.api.registerEventsFromObject(publicApi.events);
22820 grid.api.registerMethodsFromObject(publicApi.methods);
22821 },
22822
22823
22824 defaultGridOptions: function (gridOptions) {
22825 // default option to true unless it was explicitly set to false
22826 /**
22827 * @ngdoc object
22828 * @name ui.grid.infiniteScroll.api:GridOptions
22829 *
22830 * @description GridOptions for infinite scroll feature, these are available to be
22831 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
22832 */
22833
22834 /**
22835 * @ngdoc object
22836 * @name enableInfiniteScroll
22837 * @propertyOf ui.grid.infiniteScroll.api:GridOptions
22838 * @description Enable infinite scrolling for this grid
22839 * <br/>Defaults to true
22840 */
22841 gridOptions.enableInfiniteScroll = gridOptions.enableInfiniteScroll !== false;
22842
22843 /**
22844 * @ngdoc property
22845 * @name infiniteScrollRowsFromEnd
22846 * @propertyOf ui.grid.class:GridOptions
22847 * @description This setting controls how close to the end of the dataset a user gets before
22848 * more data is requested by the infinite scroll, whether scrolling up or down. This allows you to
22849 * 'prefetch' rows before the user actually runs out of scrolling.
22850 *
22851 * Note that if you set this value too high it may give jumpy scrolling behaviour, if you're getting
22852 * this behaviour you could use the `saveScrollPercentageMethod` right before loading your data, and we'll
22853 * preserve that scroll position
22854 *
22855 * <br> Defaults to 20
22856 */
22857 gridOptions.infiniteScrollRowsFromEnd = gridOptions.infiniteScrollRowsFromEnd || 20;
22858
22859 /**
22860 * @ngdoc property
22861 * @name infiniteScrollUp
22862 * @propertyOf ui.grid.class:GridOptions
22863 * @description Whether you allow infinite scroll up, implying that the first page of data
22864 * you have displayed is in the middle of your data set. If set to true then we trigger the
22865 * needMoreDataTop event when the user hits the top of the scrollbar.
22866 * <br> Defaults to false
22867 */
22868 gridOptions.infiniteScrollUp = gridOptions.infiniteScrollUp === true;
22869
22870 /**
22871 * @ngdoc property
22872 * @name infiniteScrollDown
22873 * @propertyOf ui.grid.class:GridOptions
22874 * @description Whether you allow infinite scroll down, implying that the first page of data
22875 * you have displayed is in the middle of your data set. If set to true then we trigger the
22876 * needMoreData event when the user hits the bottom of the scrollbar.
22877 * <br> Defaults to true
22878 */
22879 gridOptions.infiniteScrollDown = gridOptions.infiniteScrollDown !== false;
22880 },
22881
22882
22883 /**
22884 * @ngdoc function
22885 * @name setScrollDirections
22886 * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
22887 * @description Sets the scrollUp and scrollDown flags, handling nulls and undefined,
22888 * and also sets the grid.suppressParentScroll
22889 * @param {grid} grid the grid we're operating on
22890 * @param {boolean} scrollUp whether there are pages available up - defaults to false
22891 * @param {boolean} scrollDown whether there are pages available down - defaults to true
22892 */
22893 setScrollDirections: function ( grid, scrollUp, scrollDown ) {
22894 grid.infiniteScroll.scrollUp = ( scrollUp === true );
22895 grid.suppressParentScrollUp = ( scrollUp === true );
22896
22897 grid.infiniteScroll.scrollDown = ( scrollDown !== false);
22898 grid.suppressParentScrollDown = ( scrollDown !== false);
22899 },
22900
22901
22902 /**
22903 * @ngdoc function
22904 * @name handleScroll
22905 * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
22906 * @description Called whenever the grid scrolls, determines whether the scroll should
22907 * trigger an infinite scroll request for more data
22908 * @param {object} args the args from the event
22909 */
22910 handleScroll: function (args) {
22911 // don't request data if already waiting for data, or if source is coming from ui.grid.adjustInfiniteScrollPosition() function
22912 if ( args.grid.infiniteScroll && args.grid.infiniteScroll.dataLoading || args.source === 'ui.grid.adjustInfiniteScrollPosition' ) {
22913 return;
22914 }
22915
22916 if (args.y) {
22917
22918 // If the user is scrolling very quickly all the way to the top/bottom, the scroll handler can get confused
22919 // about the direction. First we check if they've gone all the way, and data always is loaded in this case.
22920 if (args.y.percentage === 0) {
22921 args.grid.scrollDirection = uiGridConstants.scrollDirection.UP;
22922 service.loadData(args.grid);
22923 }
22924 else if (args.y.percentage === 1) {
22925 args.grid.scrollDirection = uiGridConstants.scrollDirection.DOWN;
22926 service.loadData(args.grid);
22927 }
22928 else { // Scroll position is somewhere in between top/bottom, so determine whether it's far enough to load more data.
22929 var percentage,
22930 targetPercentage = args.grid.options.infiniteScrollRowsFromEnd / args.grid.renderContainers.body.visibleRowCache.length;
22931
22932 if (args.grid.scrollDirection === uiGridConstants.scrollDirection.UP ) {
22933 percentage = args.y.percentage;
22934 if (percentage <= targetPercentage) {
22935 service.loadData(args.grid);
22936 }
22937 }
22938 else if (args.grid.scrollDirection === uiGridConstants.scrollDirection.DOWN) {
22939 percentage = 1 - args.y.percentage;
22940 if (percentage <= targetPercentage) {
22941 service.loadData(args.grid);
22942 }
22943 }
22944 }
22945 }
22946 },
22947
22948
22949 /**
22950 * @ngdoc function
22951 * @name loadData
22952 * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
22953 * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection
22954 * and whether there are more pages upwards or downwards. It also stores the number of rows that we had previously,
22955 * and clears out any saved scroll position so that we know whether or not the user calls `saveScrollPercentage`
22956 * @param {Grid} grid the grid we're working on
22957 */
22958 loadData: function (grid) {
22959 // save number of currently visible rows to calculate new scroll position later - we know that we want
22960 // to be at approximately the row we're currently at
22961 grid.infiniteScroll.previousVisibleRows = grid.renderContainers.body.visibleRowCache.length;
22962 grid.infiniteScroll.direction = grid.scrollDirection;
22963 delete grid.infiniteScroll.prevScrollTop;
22964
22965 if (grid.scrollDirection === uiGridConstants.scrollDirection.UP && grid.infiniteScroll.scrollUp ) {
22966 grid.infiniteScroll.dataLoading = true;
22967 grid.api.infiniteScroll.raise.needLoadMoreDataTop();
22968 }
22969 else if (grid.scrollDirection === uiGridConstants.scrollDirection.DOWN && grid.infiniteScroll.scrollDown ) {
22970 grid.infiniteScroll.dataLoading = true;
22971 grid.api.infiniteScroll.raise.needLoadMoreData();
22972 }
22973 },
22974
22975
22976 /**
22977 * @ngdoc function
22978 * @name adjustScroll
22979 * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
22980 * @description Once we are informed that data has been loaded, adjust the scroll position to account for that
22981 * addition and to make things look clean.
22982 *
22983 * If we're scrolling up we scroll to the first row of the old data set -
22984 * so we're assuming that you would have gotten to the top of the grid (from the 20% need more data trigger) by
22985 * the time the data comes back. If we're scrolling down we scroll to the last row of the old data set - so we're
22986 * assuming that you would have gotten to the bottom of the grid (from the 80% need more data trigger) by the time
22987 * the data comes back.
22988 *
22989 * Neither of these are good assumptions, but making this a smoother experience really requires
22990 * that trigger to not be a percentage, and to be much closer to the end of the data (say, 5 rows off the end). Even then
22991 * it'd be better still to actually run into the end. But if the data takes a while to come back, they may have scrolled
22992 * somewhere else in the mean-time, in which case they'll get a jump back to the new data. Anyway, this will do for
22993 * now, until someone wants to do better.
22994 * @param {Grid} grid the grid we're working on
22995 * @returns {promise} a promise that is resolved when scrolling has finished
22996 */
22997 adjustScroll: function(grid) {
22998 var promise = $q.defer();
22999 $rootScope.$applyAsync(function () {
23000 var viewportHeight, rowHeight, newVisibleRows, oldTop, newTop;
23001
23002 viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight;
23003 rowHeight = grid.options.rowHeight;
23004
23005 if ( grid.infiniteScroll.direction === undefined ) {
23006 // called from initialize, tweak our scroll up a little
23007 service.adjustInfiniteScrollPosition(grid, 0);
23008 }
23009
23010 newVisibleRows = grid.getVisibleRowCount();
23011
23012 // in case not enough data is loaded to enable scroller - load more data
23013 var canvasHeight = rowHeight * newVisibleRows;
23014 if (grid.infiniteScroll.scrollDown && (viewportHeight > canvasHeight)) {
23015 grid.api.infiniteScroll.raise.needLoadMoreData();
23016 }
23017
23018 if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.UP ) {
23019 oldTop = grid.infiniteScroll.prevScrollTop || 0;
23020 newTop = oldTop + (newVisibleRows - grid.infiniteScroll.previousVisibleRows)*rowHeight;
23021 service.adjustInfiniteScrollPosition(grid, newTop);
23022 $rootScope.$applyAsync( function() {
23023 promise.resolve();
23024 });
23025 }
23026
23027 if ( grid.infiniteScroll.direction === uiGridConstants.scrollDirection.DOWN ) {
23028 newTop = grid.infiniteScroll.prevScrollTop || (grid.infiniteScroll.previousVisibleRows*rowHeight - viewportHeight);
23029 service.adjustInfiniteScrollPosition(grid, newTop);
23030 $rootScope.$applyAsync( function() {
23031 promise.resolve();
23032 });
23033 }
23034 }, 0);
23035
23036 return promise.promise;
23037 },
23038
23039
23040 /**
23041 * @ngdoc function
23042 * @name adjustInfiniteScrollPosition
23043 * @methodOf ui.grid.infiniteScroll.service:uiGridInfiniteScrollService
23044 * @description This function fires 'needLoadMoreData' or 'needLoadMoreDataTop' event based on scrollDirection
23045 * @param {Grid} grid the grid we're working on
23046 * @param {number} scrollTop the position through the grid that we want to scroll to
23047 */
23048 adjustInfiniteScrollPosition: function (grid, scrollTop) {
23049 var scrollEvent = new ScrollEvent(grid, null, null, 'ui.grid.adjustInfiniteScrollPosition'),
23050 visibleRows = grid.getVisibleRowCount(),
23051 viewportHeight = grid.getViewportHeight() + grid.headerHeight - grid.renderContainers.body.headerHeight - grid.scrollbarHeight,
23052 rowHeight = grid.options.rowHeight,
23053 scrollHeight = visibleRows*rowHeight-viewportHeight;
23054
23055 // for infinite scroll, if there are pages upwards then never allow it to be at the zero position so the up button can be active
23056 if (scrollTop === 0 && grid.infiniteScroll.scrollUp) {
23057 // using pixels results in a relative scroll, hence we have to use percentage
23058 scrollEvent.y = {percentage: 1/scrollHeight};
23059 }
23060 else {
23061 scrollEvent.y = {percentage: scrollTop/scrollHeight};
23062 }
23063 grid.scrollContainers('', scrollEvent);
23064 },
23065
23066
23067 /**
23068 * @ngdoc function
23069 * @name dataRemovedTop
23070 * @methodOf ui.grid.infiniteScroll.api:PublicAPI
23071 * @description Adjusts the scroll position after you've removed data at the top. You should
23072 * have called `saveScrollPercentage` before you remove the data, and if you're doing this in
23073 * response to a `needMoreData` you should wait until the promise from `loadData` has resolved
23074 * before you start removing data
23075 * @param {Grid} grid the grid we're working on
23076 * @param {boolean} scrollUp flag that there are pages upwards, fire
23077 * infinite scroll events upward
23078 * @param {boolean} scrollDown flag that there are pages downwards, so
23079 * fire infinite scroll events downward
23080 */
23081 dataRemovedTop: function( grid, scrollUp, scrollDown ) {
23082 var newVisibleRows, oldTop, newTop, rowHeight;
23083 service.setScrollDirections( grid, scrollUp, scrollDown );
23084
23085 newVisibleRows = grid.renderContainers.body.visibleRowCache.length;
23086 oldTop = grid.infiniteScroll.prevScrollTop;
23087 rowHeight = grid.options.rowHeight;
23088
23089 // since we removed from the top, our new scroll row will be the old scroll row less the number
23090 // of rows removed
23091 newTop = oldTop - ( grid.infiniteScroll.previousVisibleRows - newVisibleRows )*rowHeight;
23092
23093 service.adjustInfiniteScrollPosition( grid, newTop );
23094 },
23095
23096 /**
23097 * @ngdoc function
23098 * @name dataRemovedBottom
23099 * @methodOf ui.grid.infiniteScroll.api:PublicAPI
23100 * @description Adjusts the scroll position after you've removed data at the bottom. You should
23101 * have called `saveScrollPercentage` before you remove the data, and if you're doing this in
23102 * response to a `needMoreData` you should wait until the promise from `loadData` has resolved
23103 * before you start removing data
23104 * @param {Grid} grid the grid we're working on
23105 * @param {boolean} scrollUp flag that there are pages upwards, fire
23106 * infinite scroll events upward
23107 * @param {boolean} scrollDown flag that there are pages downwards, so
23108 * fire infinite scroll events downward
23109 */
23110 dataRemovedBottom: function( grid, scrollUp, scrollDown ) {
23111 var newTop;
23112
23113 service.setScrollDirections( grid, scrollUp, scrollDown );
23114
23115 newTop = grid.infiniteScroll.prevScrollTop;
23116
23117 service.adjustInfiniteScrollPosition( grid, newTop );
23118 }
23119 };
23120 return service;
23121 }]);
23122 /**
23123 * @ngdoc directive
23124 * @name ui.grid.infiniteScroll.directive:uiGridInfiniteScroll
23125 * @element div
23126 * @restrict A
23127 *
23128 * @description Adds infinite scroll features to grid
23129 *
23130 * @example
23131 <example module="app">
23132 <file name="app.js">
23133 var app = angular.module('app', ['ui.grid', 'ui.grid.infiniteScroll']);
23134
23135 app.controller('MainCtrl', ['$scope', function ($scope) {
23136 $scope.data = [
23137 { name: 'Alex', car: 'Toyota' },
23138 { name: 'Sam', car: 'Lexus' }
23139 ];
23140
23141 $scope.columnDefs = [
23142 {name: 'name'},
23143 {name: 'car'}
23144 ];
23145 }]);
23146 </file>
23147 <file name="index.html">
23148 <div ng-controller="MainCtrl">
23149 <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-infinite-scroll="20"></div>
23150 </div>
23151 </file>
23152 </example>
23153 */
23154
23155 module.directive('uiGridInfiniteScroll', ['uiGridInfiniteScrollService',
23156 function (uiGridInfiniteScrollService) {
23157 return {
23158 priority: -200,
23159 scope: false,
23160 require: '^uiGrid',
23161 compile: function() {
23162 return {
23163 pre: function($scope, $elm, $attr, uiGridCtrl) {
23164 uiGridInfiniteScrollService.initializeGrid(uiGridCtrl.grid, $scope);
23165 },
23166 post: function($scope, $elm, $attr) {
23167 }
23168 };
23169 }
23170 };
23171 }]);
23172 })();
23173
23174 (function () {
23175 'use strict';
23176
23177 /**
23178 * @ngdoc overview
23179 * @name ui.grid.moveColumns
23180 * @description
23181 *
23182 * # ui.grid.moveColumns
23183 *
23184 * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
23185 *
23186 * This module provides column moving capability to ui.grid. It enables to change the position of columns.
23187 * <div doc-module-components="ui.grid.moveColumns"></div>
23188 */
23189 var module = angular.module('ui.grid.moveColumns', ['ui.grid']);
23190
23191 /**
23192 * @ngdoc service
23193 * @name ui.grid.moveColumns.service:uiGridMoveColumnService
23194 * @description Service for column moving feature.
23195 */
23196 module.service('uiGridMoveColumnService', ['$q', '$rootScope', '$log', 'ScrollEvent', 'uiGridConstants', 'gridUtil', function ($q, $rootScope, $log, ScrollEvent, uiGridConstants, gridUtil) {
23197 var service = {
23198 initializeGrid: function (grid) {
23199 var self = this;
23200 this.registerPublicApi(grid);
23201 this.defaultGridOptions(grid.options);
23202 grid.moveColumns = {orderCache: []}; // Used to cache the order before columns are rebuilt
23203 grid.registerColumnBuilder(self.movableColumnBuilder);
23204 grid.registerDataChangeCallback(self.verifyColumnOrder, [uiGridConstants.dataChange.COLUMN]);
23205 },
23206 registerPublicApi: function (grid) {
23207 var self = this;
23208 /**
23209 * @ngdoc object
23210 * @name ui.grid.moveColumns.api:PublicApi
23211 * @description Public Api for column moving feature.
23212 */
23213 var publicApi = {
23214 events: {
23215 /**
23216 * @ngdoc event
23217 * @name columnPositionChanged
23218 * @eventOf ui.grid.moveColumns.api:PublicApi
23219 * @description raised when column is moved
23220 * <pre>
23221 * gridApi.colMovable.on.columnPositionChanged(scope,function(colDef, originalPosition, newPosition) {})
23222 * </pre>
23223 * @param {object} colDef the column that was moved
23224 * @param {integer} originalPosition of the column
23225 * @param {integer} finalPosition of the column
23226 */
23227 colMovable: {
23228 columnPositionChanged: function (colDef, originalPosition, newPosition) {
23229 }
23230 }
23231 },
23232 methods: {
23233 /**
23234 * @ngdoc method
23235 * @name moveColumn
23236 * @methodOf ui.grid.moveColumns.api:PublicApi
23237 * @description Method can be used to change column position.
23238 * <pre>
23239 * gridApi.colMovable.moveColumn(oldPosition, newPosition)
23240 * </pre>
23241 * @param {integer} originalPosition of the column
23242 * @param {integer} finalPosition of the column
23243 */
23244 colMovable: {
23245 moveColumn: function (originalPosition, finalPosition) {
23246 var columns = grid.columns;
23247 if (!angular.isNumber(originalPosition) || !angular.isNumber(finalPosition)) {
23248 gridUtil.logError('MoveColumn: Please provide valid values for originalPosition and finalPosition');
23249 return;
23250 }
23251 var nonMovableColumns = 0;
23252 for (var i = 0; i < columns.length; i++) {
23253 if ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true) {
23254 nonMovableColumns++;
23255 }
23256 }
23257 if (originalPosition >= (columns.length - nonMovableColumns) || finalPosition >= (columns.length - nonMovableColumns)) {
23258 gridUtil.logError('MoveColumn: Invalid values for originalPosition, finalPosition');
23259 return;
23260 }
23261 var findPositionForRenderIndex = function (index) {
23262 var position = index;
23263 for (var i = 0; i <= position; i++) {
23264 if (angular.isDefined(columns[i]) && ((angular.isDefined(columns[i].colDef.visible) && columns[i].colDef.visible === false) || columns[i].isRowHeader === true)) {
23265 position++;
23266 }
23267 }
23268 return position;
23269 };
23270 self.redrawColumnAtPosition(grid, findPositionForRenderIndex(originalPosition), findPositionForRenderIndex(finalPosition));
23271 }
23272 }
23273 }
23274 };
23275 grid.api.registerEventsFromObject(publicApi.events);
23276 grid.api.registerMethodsFromObject(publicApi.methods);
23277 },
23278 defaultGridOptions: function (gridOptions) {
23279 /**
23280 * @ngdoc object
23281 * @name ui.grid.moveColumns.api:GridOptions
23282 *
23283 * @description Options for configuring the move column feature, these are available to be
23284 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
23285 */
23286 /**
23287 * @ngdoc object
23288 * @name enableColumnMoving
23289 * @propertyOf ui.grid.moveColumns.api:GridOptions
23290 * @description If defined, sets the default value for the colMovable flag on each individual colDefs
23291 * if their individual enableColumnMoving configuration is not defined. Defaults to true.
23292 */
23293 gridOptions.enableColumnMoving = gridOptions.enableColumnMoving !== false;
23294 },
23295 movableColumnBuilder: function (colDef, col, gridOptions) {
23296 var promises = [];
23297 /**
23298 * @ngdoc object
23299 * @name ui.grid.moveColumns.api:ColumnDef
23300 *
23301 * @description Column Definition for move column feature, these are available to be
23302 * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
23303 */
23304 /**
23305 * @ngdoc object
23306 * @name enableColumnMoving
23307 * @propertyOf ui.grid.moveColumns.api:ColumnDef
23308 * @description Enable column moving for the column.
23309 */
23310 colDef.enableColumnMoving = colDef.enableColumnMoving === undefined ? gridOptions.enableColumnMoving
23311 : colDef.enableColumnMoving;
23312 return $q.all(promises);
23313 },
23314 /**
23315 * @ngdoc method
23316 * @name updateColumnCache
23317 * @methodOf ui.grid.moveColumns
23318 * @description Cache the current order of columns, so we can restore them after new columnDefs are defined
23319 */
23320 updateColumnCache: function(grid) {
23321 grid.moveColumns.orderCache = grid.getOnlyDataColumns();
23322 },
23323 /**
23324 * @ngdoc method
23325 * @name verifyColumnOrder
23326 * @methodOf ui.grid.moveColumns
23327 * @description dataChangeCallback which uses the cached column order to restore the column order
23328 * when it is reset by altering the columnDefs array.
23329 */
23330 verifyColumnOrder: function(grid) {
23331 var headerRowOffset = grid.rowHeaderColumns.length;
23332 var newIndex;
23333
23334 angular.forEach(grid.moveColumns.orderCache, function(cacheCol, cacheIndex) {
23335 newIndex = grid.columns.indexOf(cacheCol);
23336 if ( newIndex !== -1 && newIndex - headerRowOffset !== cacheIndex ) {
23337 var column = grid.columns.splice(newIndex, 1)[0];
23338 grid.columns.splice(cacheIndex + headerRowOffset, 0, column);
23339 }
23340 });
23341 },
23342 redrawColumnAtPosition: function (grid, originalPosition, newPosition) {
23343 var columns = grid.columns;
23344
23345 if (originalPosition === newPosition) {
23346 return;
23347 }
23348
23349 // check columns in between move-range to make sure they are visible columns
23350 var pos = (originalPosition < newPosition) ? originalPosition + 1 : originalPosition - 1;
23351 var i0 = Math.min(pos, newPosition);
23352 for (i0; i0 <= Math.max(pos, newPosition); i0++) {
23353 if (columns[i0].visible) {
23354 break;
23355 }
23356 }
23357 if (i0 > Math.max(pos, newPosition)) {
23358 // no visible column found, column did not visibly move
23359 return;
23360 }
23361
23362 var originalColumn = columns[originalPosition];
23363 if (originalColumn.colDef.enableColumnMoving) {
23364 if (originalPosition > newPosition) {
23365 for (var i1 = originalPosition; i1 > newPosition; i1--) {
23366 columns[i1] = columns[i1 - 1];
23367 }
23368 }
23369 else if (newPosition > originalPosition) {
23370 for (var i2 = originalPosition; i2 < newPosition; i2++) {
23371 columns[i2] = columns[i2 + 1];
23372 }
23373 }
23374 columns[newPosition] = originalColumn;
23375 service.updateColumnCache(grid);
23376 grid.queueGridRefresh();
23377 $rootScope.$applyAsync(function () {
23378 grid.api.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
23379 grid.api.colMovable.raise.columnPositionChanged(originalColumn.colDef, originalPosition, newPosition);
23380 });
23381 }
23382 }
23383 };
23384 return service;
23385 }]);
23386
23387 /**
23388 * @ngdoc directive
23389 * @name ui.grid.moveColumns.directive:uiGridMoveColumns
23390 * @element div
23391 * @restrict A
23392 * @description Adds column moving features to the ui-grid directive.
23393 * @example
23394 <example module="app">
23395 <file name="app.js">
23396 var app = angular.module('app', ['ui.grid', 'ui.grid.moveColumns']);
23397 app.controller('MainCtrl', ['$scope', function ($scope) {
23398 $scope.data = [
23399 { name: 'Bob', title: 'CEO', age: 45 },
23400 { name: 'Frank', title: 'Lowly Developer', age: 25 },
23401 { name: 'Jenny', title: 'Highly Developer', age: 35 }
23402 ];
23403 $scope.columnDefs = [
23404 {name: 'name'},
23405 {name: 'title'},
23406 {name: 'age'}
23407 ];
23408 }]);
23409 </file>
23410 <file name="main.css">
23411 .grid {
23412 width: 100%;
23413 height: 150px;
23414 }
23415 </file>
23416 <file name="index.html">
23417 <div ng-controller="MainCtrl">
23418 <div class="grid" ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-move-columns></div>
23419 </div>
23420 </file>
23421 </example>
23422 */
23423 module.directive('uiGridMoveColumns', ['uiGridMoveColumnService', function (uiGridMoveColumnService) {
23424 return {
23425 replace: true,
23426 priority: 0,
23427 require: '^uiGrid',
23428 scope: false,
23429 compile: function () {
23430 return {
23431 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
23432 uiGridMoveColumnService.initializeGrid(uiGridCtrl.grid);
23433 },
23434 post: function ($scope, $elm, $attrs, uiGridCtrl) {
23435 }
23436 };
23437 }
23438 };
23439 }]);
23440
23441 /**
23442 * @ngdoc directive
23443 * @name ui.grid.moveColumns.directive:uiGridHeaderCell
23444 * @element div
23445 * @restrict A
23446 *
23447 * @description Stacks on top of ui.grid.uiGridHeaderCell to provide capability to be able to move it to reposition column.
23448 *
23449 * On receiving mouseDown event headerCell is cloned, now as the mouse moves the cloned header cell also moved in the grid.
23450 * In case the moving cloned header cell reaches the left or right extreme of grid, grid scrolling is triggered (if horizontal scroll exists).
23451 * On mouseUp event column is repositioned at position where mouse is released and cloned header cell is removed.
23452 *
23453 * Events that invoke cloning of header cell:
23454 * - mousedown
23455 *
23456 * Events that invoke movement of cloned header cell:
23457 * - mousemove
23458 *
23459 * Events that invoke repositioning of column:
23460 * - mouseup
23461 */
23462 module.directive('uiGridHeaderCell', ['$q', 'gridUtil', 'uiGridMoveColumnService', '$document', '$log', 'uiGridConstants', 'ScrollEvent',
23463 function ($q, gridUtil, uiGridMoveColumnService, $document, $log, uiGridConstants, ScrollEvent) {
23464 return {
23465 priority: -10,
23466 require: '^uiGrid',
23467 compile: function () {
23468 return {
23469 post: function ($scope, $elm, $attrs, uiGridCtrl) {
23470
23471 if ($scope.col.colDef.enableColumnMoving) {
23472
23473 /*
23474 * Our general approach to column move is that we listen to a touchstart or mousedown
23475 * event over the column header. When we hear one, then we wait for a move of the same type
23476 * - if we are a touchstart then we listen for a touchmove, if we are a mousedown we listen for
23477 * a mousemove (i.e. a drag) before we decide that there's a move underway. If there's never a move,
23478 * and we instead get a mouseup or a touchend, then we just drop out again and do nothing.
23479 *
23480 */
23481 var $contentsElm = angular.element( $elm[0].querySelectorAll('.ui-grid-cell-contents') );
23482
23483 var gridLeft;
23484 var previousMouseX;
23485 var totalMouseMovement;
23486 var rightMoveLimit;
23487 var elmCloned = false;
23488 var movingElm;
23489 var reducedWidth;
23490 var moveOccurred = false;
23491
23492 var downFn = function( event ) {
23493 // Setting some variables required for calculations.
23494 gridLeft = $scope.grid.element[0].getBoundingClientRect().left;
23495 if ( $scope.grid.hasLeftContainer() ) {
23496 gridLeft += $scope.grid.renderContainers.left.header[0].getBoundingClientRect().width;
23497 }
23498
23499 previousMouseX = event.pageX || (event.originalEvent ? event.originalEvent.pageX : 0);
23500 totalMouseMovement = 0;
23501 rightMoveLimit = gridLeft + $scope.grid.getViewportWidth();
23502
23503 if ( event.type === 'mousedown' ) {
23504 $document.on('mousemove', moveFn);
23505 $document.on('mouseup', upFn);
23506 }
23507 else if ( event.type === 'touchstart' ) {
23508 $document.on('touchmove', moveFn);
23509 $document.on('touchend', upFn);
23510 }
23511 };
23512
23513 var moveFn = function( event ) {
23514 var pageX = event.pageX || (event.originalEvent ? event.originalEvent.pageX : 0);
23515 var changeValue = pageX - previousMouseX;
23516 if ( changeValue === 0 ) { return; }
23517 // Disable text selection in Chrome during column move
23518 document.onselectstart = function() { return false; };
23519
23520 moveOccurred = true;
23521
23522 if (!elmCloned) {
23523 cloneElement();
23524 }
23525 else if (elmCloned) {
23526 moveElement(changeValue);
23527 previousMouseX = pageX;
23528 }
23529 };
23530
23531 var upFn = function( event ) {
23532 // Re-enable text selection after column move
23533 document.onselectstart = null;
23534
23535 // Remove the cloned element on mouse up.
23536 if (movingElm) {
23537 movingElm.remove();
23538 elmCloned = false;
23539 }
23540
23541 offAllEvents();
23542 onDownEvents();
23543
23544 if (!moveOccurred) {
23545 return;
23546 }
23547
23548 var columns = $scope.grid.columns;
23549 var columnIndex = 0;
23550 for (var i = 0; i < columns.length; i++) {
23551 if (columns[i].colDef.name !== $scope.col.colDef.name) {
23552 columnIndex++;
23553 }
23554 else {
23555 break;
23556 }
23557 }
23558
23559 var targetIndex;
23560
23561 // Case where column should be moved to a position on its left
23562 if (totalMouseMovement < 0) {
23563 var totalColumnsLeftWidth = 0;
23564 var il;
23565 if ( $scope.grid.isRTL() ) {
23566 for (il = columnIndex + 1; il < columns.length; il++) {
23567 if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
23568 totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
23569 if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {
23570 uiGridMoveColumnService.redrawColumnAtPosition
23571 ($scope.grid, columnIndex, il - 1);
23572 break;
23573 }
23574 }
23575 }
23576 }
23577 else {
23578 for (il = columnIndex - 1; il >= 0; il--) {
23579 if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
23580 totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
23581 if (totalColumnsLeftWidth > Math.abs(totalMouseMovement)) {
23582 uiGridMoveColumnService.redrawColumnAtPosition
23583 ($scope.grid, columnIndex, il + 1);
23584 break;
23585 }
23586 }
23587 }
23588 }
23589
23590 // Case where column should be moved to beginning (or end in RTL) of the grid.
23591 if (totalColumnsLeftWidth < Math.abs(totalMouseMovement)) {
23592 targetIndex = 0;
23593 if ( $scope.grid.isRTL() ) {
23594 targetIndex = columns.length - 1;
23595 }
23596 uiGridMoveColumnService.redrawColumnAtPosition
23597 ($scope.grid, columnIndex, targetIndex);
23598 }
23599 }
23600
23601 // Case where column should be moved to a position on its right
23602 else if (totalMouseMovement > 0) {
23603 var totalColumnsRightWidth = 0;
23604 var ir;
23605 if ( $scope.grid.isRTL() ) {
23606 for (ir = columnIndex - 1; ir > 0; ir--) {
23607 if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {
23608 totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;
23609 if (totalColumnsRightWidth > totalMouseMovement) {
23610 uiGridMoveColumnService.redrawColumnAtPosition
23611 ($scope.grid, columnIndex, ir);
23612 break;
23613 }
23614 }
23615 }
23616 }
23617 else {
23618 for (ir = columnIndex + 1; ir < columns.length; ir++) {
23619 if (angular.isUndefined(columns[ir].colDef.visible) || columns[ir].colDef.visible === true) {
23620 totalColumnsRightWidth += columns[ir].drawnWidth || columns[ir].width || columns[ir].colDef.width;
23621 if (totalColumnsRightWidth > totalMouseMovement) {
23622 uiGridMoveColumnService.redrawColumnAtPosition
23623 ($scope.grid, columnIndex, ir - 1);
23624 break;
23625 }
23626 }
23627 }
23628 }
23629
23630
23631 // Case where column should be moved to end (or beginning in RTL) of the grid.
23632 if (totalColumnsRightWidth < totalMouseMovement) {
23633 targetIndex = columns.length - 1;
23634 if ( $scope.grid.isRTL() ) {
23635 targetIndex = 0;
23636 }
23637 uiGridMoveColumnService.redrawColumnAtPosition
23638 ($scope.grid, columnIndex, targetIndex);
23639 }
23640 }
23641
23642
23643
23644 };
23645
23646 var onDownEvents = function() {
23647 $contentsElm.on('touchstart', downFn);
23648 $contentsElm.on('mousedown', downFn);
23649 };
23650
23651 var offAllEvents = function() {
23652 $contentsElm.off('touchstart', downFn);
23653 $contentsElm.off('mousedown', downFn);
23654
23655 $document.off('mousemove', moveFn);
23656 $document.off('touchmove', moveFn);
23657
23658 $document.off('mouseup', upFn);
23659 $document.off('touchend', upFn);
23660 };
23661
23662 onDownEvents();
23663
23664
23665 var cloneElement = function () {
23666 elmCloned = true;
23667
23668 // Cloning header cell and appending to current header cell.
23669 movingElm = $elm.clone();
23670 $elm.parent().append(movingElm);
23671
23672 // Left of cloned element should be aligned to original header cell.
23673 movingElm.addClass('movingColumn');
23674 var movingElementStyles = {};
23675 movingElementStyles.left = $elm[0].offsetLeft + 'px';
23676 var gridRight = $scope.grid.element[0].getBoundingClientRect().right;
23677 var elmRight = $elm[0].getBoundingClientRect().right;
23678 if (elmRight > gridRight) {
23679 reducedWidth = $scope.col.drawnWidth + (gridRight - elmRight);
23680 movingElementStyles.width = reducedWidth + 'px';
23681 }
23682 movingElm.css(movingElementStyles);
23683 };
23684
23685 var moveElement = function (changeValue) {
23686 // Calculate total column width
23687 var columns = $scope.grid.columns;
23688 var totalColumnWidth = 0;
23689 for (var i = 0; i < columns.length; i++) {
23690 if (angular.isUndefined(columns[i].colDef.visible) || columns[i].colDef.visible === true) {
23691 totalColumnWidth += columns[i].drawnWidth || columns[i].width || columns[i].colDef.width;
23692 }
23693 }
23694
23695 // Calculate new position of left of column
23696 var currentElmLeft = movingElm[0].getBoundingClientRect().left - 1;
23697 var currentElmRight = movingElm[0].getBoundingClientRect().right;
23698 var newElementLeft;
23699
23700 newElementLeft = currentElmLeft - gridLeft + changeValue;
23701 newElementLeft = newElementLeft < rightMoveLimit ? newElementLeft : rightMoveLimit;
23702
23703 // Update css of moving column to adjust to new left value or fire scroll in case column has reached edge of grid
23704 if ((currentElmLeft >= gridLeft || changeValue > 0) && (currentElmRight <= rightMoveLimit || changeValue < 0)) {
23705 movingElm.css({visibility: 'visible', 'left': (movingElm[0].offsetLeft +
23706 (newElementLeft < rightMoveLimit ? changeValue : (rightMoveLimit - currentElmLeft))) + 'px'});
23707 }
23708 else if (totalColumnWidth > Math.ceil(uiGridCtrl.grid.gridWidth)) {
23709 changeValue *= 8;
23710 var scrollEvent = new ScrollEvent($scope.col.grid, null, null, 'uiGridHeaderCell.moveElement');
23711 scrollEvent.x = {pixels: changeValue};
23712 scrollEvent.grid.scrollContainers('',scrollEvent);
23713 }
23714
23715 // Calculate total width of columns on the left of the moving column and the mouse movement
23716 var totalColumnsLeftWidth = 0;
23717 for (var il = 0; il < columns.length; il++) {
23718 if (angular.isUndefined(columns[il].colDef.visible) || columns[il].colDef.visible === true) {
23719 if (columns[il].colDef.name !== $scope.col.colDef.name) {
23720 totalColumnsLeftWidth += columns[il].drawnWidth || columns[il].width || columns[il].colDef.width;
23721 }
23722 else {
23723 break;
23724 }
23725 }
23726 }
23727 if ($scope.newScrollLeft === undefined) {
23728 totalMouseMovement += changeValue;
23729 }
23730 else {
23731 totalMouseMovement = $scope.newScrollLeft + newElementLeft - totalColumnsLeftWidth;
23732 }
23733
23734 // Increase width of moving column, in case the rightmost column was moved and its width was
23735 // decreased because of overflow
23736 if (reducedWidth < $scope.col.drawnWidth) {
23737 reducedWidth += Math.abs(changeValue);
23738 movingElm.css({'width': reducedWidth + 'px'});
23739 }
23740 };
23741
23742 $scope.$on('$destroy', offAllEvents);
23743 }
23744 }
23745 };
23746 }
23747 };
23748 }]);
23749 })();
23750
23751 (function() {
23752 'use strict';
23753
23754 /**
23755 * @ngdoc overview
23756 * @name ui.grid.pagination
23757 *
23758 * @description
23759 *
23760 * # ui.grid.pagination
23761 *
23762 * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
23763 *
23764 * This module provides pagination support to ui-grid
23765 */
23766 var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);
23767
23768 /**
23769 * @ngdoc service
23770 * @name ui.grid.pagination.service:uiGridPaginationService
23771 *
23772 * @description Service for the pagination feature
23773 */
23774 module.service('uiGridPaginationService', ['gridUtil',
23775 function (gridUtil) {
23776 var service = {
23777 /**
23778 * @ngdoc method
23779 * @name initializeGrid
23780 * @methodOf ui.grid.pagination.service:uiGridPaginationService
23781 * @description Attaches the service to a certain grid
23782 * @param {Grid} grid The grid we want to work with
23783 */
23784 initializeGrid: function (grid) {
23785 service.defaultGridOptions(grid.options);
23786
23787 /**
23788 * @ngdoc object
23789 * @name ui.grid.pagination.api:PublicAPI
23790 *
23791 * @description Public API for the pagination feature
23792 */
23793 var publicApi = {
23794 events: {
23795 pagination: {
23796 /**
23797 * @ngdoc event
23798 * @name paginationChanged
23799 * @eventOf ui.grid.pagination.api:PublicAPI
23800 * @description This event fires when the pageSize or currentPage changes
23801 * @param {int} currentPage requested page number
23802 * @param {int} pageSize requested page size
23803 */
23804 paginationChanged: function (currentPage, pageSize) { }
23805 }
23806 },
23807 methods: {
23808 pagination: {
23809 /**
23810 * @ngdoc method
23811 * @name getPage
23812 * @methodOf ui.grid.pagination.api:PublicAPI
23813 * @description Returns the number of the current page
23814 */
23815 getPage: function () {
23816 return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;
23817 },
23818 /**
23819 * @ngdoc method
23820 * @name getFirstRowIndex
23821 * @methodOf ui.grid.pagination.api:PublicAPI
23822 * @description Returns the index of the first row of the current page.
23823 */
23824 getFirstRowIndex: function () {
23825 if (grid.options.useCustomPagination) {
23826 return grid.options.paginationPageSizes.reduce(function(result, size, index) {
23827 return index < grid.options.paginationCurrentPage - 1 ? result + size : result;
23828 }, 0);
23829 }
23830 return ((grid.options.paginationCurrentPage - 1) * grid.options.paginationPageSize);
23831 },
23832 /**
23833 * @ngdoc method
23834 * @name getLastRowIndex
23835 * @methodOf ui.grid.pagination.api:PublicAPI
23836 * @description Returns the index of the last row of the current page.
23837 */
23838 getLastRowIndex: function () {
23839 if (grid.options.useCustomPagination) {
23840 return publicApi.methods.pagination.getFirstRowIndex() + grid.options.paginationPageSizes[grid.options.paginationCurrentPage - 1] - 1;
23841 }
23842 return Math.min(grid.options.paginationCurrentPage * grid.options.paginationPageSize, grid.options.totalItems) - 1;
23843 },
23844 /**
23845 * @ngdoc method
23846 * @name getTotalPages
23847 * @methodOf ui.grid.pagination.api:PublicAPI
23848 * @description Returns the total number of pages
23849 */
23850 getTotalPages: function () {
23851 if (!grid.options.enablePagination) {
23852 return null;
23853 }
23854
23855 if (grid.options.useCustomPagination) {
23856 return grid.options.paginationPageSizes.length;
23857 }
23858
23859 return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);
23860 },
23861 /**
23862 * @ngdoc method
23863 * @name nextPage
23864 * @methodOf ui.grid.pagination.api:PublicAPI
23865 * @description Moves to the next page, if possible
23866 */
23867 nextPage: function () {
23868 if (!grid.options.enablePagination) {
23869 return;
23870 }
23871
23872 if (grid.options.totalItems > 0) {
23873 grid.options.paginationCurrentPage = Math.min(
23874 grid.options.paginationCurrentPage + 1,
23875 publicApi.methods.pagination.getTotalPages()
23876 );
23877 }
23878 else {
23879 grid.options.paginationCurrentPage++;
23880 }
23881 },
23882 /**
23883 * @ngdoc method
23884 * @name previousPage
23885 * @methodOf ui.grid.pagination.api:PublicAPI
23886 * @description Moves to the previous page, if we're not on the first page
23887 */
23888 previousPage: function () {
23889 if (!grid.options.enablePagination) {
23890 return;
23891 }
23892
23893 grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);
23894 },
23895 /**
23896 * @ngdoc method
23897 * @name seek
23898 * @methodOf ui.grid.pagination.api:PublicAPI
23899 * @description Moves to the requested page
23900 * @param {int} page The number of the page that should be displayed
23901 */
23902 seek: function (page) {
23903 if (!grid.options.enablePagination) {
23904 return;
23905 }
23906 if (!angular.isNumber(page) || page < 1) {
23907 throw 'Invalid page number: ' + page;
23908 }
23909
23910 grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());
23911 }
23912 }
23913 }
23914 };
23915
23916 grid.api.registerEventsFromObject(publicApi.events);
23917 grid.api.registerMethodsFromObject(publicApi.methods);
23918
23919 var processPagination = function( renderableRows ) {
23920 if (grid.options.useExternalPagination || !grid.options.enablePagination) {
23921 return renderableRows;
23922 }
23923 // client side pagination
23924 var pageSize = parseInt(grid.options.paginationPageSize, 10);
23925 var currentPage = parseInt(grid.options.paginationCurrentPage, 10);
23926
23927 var visibleRows = renderableRows.filter(function (row) { return row.visible; });
23928 grid.options.totalItems = visibleRows.length;
23929
23930 var firstRow = publicApi.methods.pagination.getFirstRowIndex();
23931 var lastRow = publicApi.methods.pagination.getLastRowIndex();
23932
23933 if (firstRow > visibleRows.length) {
23934 currentPage = grid.options.paginationCurrentPage = 1;
23935 firstRow = (currentPage - 1) * pageSize;
23936 }
23937 return visibleRows.slice(firstRow, lastRow + 1);
23938 };
23939
23940 grid.registerRowsProcessor(processPagination, 900 );
23941
23942 },
23943 defaultGridOptions: function (gridOptions) {
23944 /**
23945 * @ngdoc object
23946 * @name ui.grid.pagination.api:GridOptions
23947 *
23948 * @description GridOptions for the pagination feature, these are available to be
23949 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
23950 */
23951
23952 /**
23953 * @ngdoc property
23954 * @name enablePagination
23955 * @propertyOf ui.grid.pagination.api:GridOptions
23956 * @description Enables pagination. Defaults to true.
23957 */
23958 gridOptions.enablePagination = gridOptions.enablePagination !== false;
23959 /**
23960 * @ngdoc property
23961 * @name enablePaginationControls
23962 * @propertyOf ui.grid.pagination.api:GridOptions
23963 * @description Enables the paginator at the bottom of the grid. Turn this off if you want to implement your
23964 * own controls outside the grid.
23965 */
23966 gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;
23967 /**
23968 * @ngdoc property
23969 * @name useExternalPagination
23970 * @propertyOf ui.grid.pagination.api:GridOptions
23971 * @description Disables client side pagination. When true, handle the paginationChanged event and set data
23972 * and totalItems. Defaults to `false`
23973 */
23974 gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;
23975
23976 /**
23977 * @ngdoc property
23978 * @name useCustomPagination
23979 * @propertyOf ui.grid.pagination.api:GridOptions
23980 * @description Disables client-side pagination. When true, handle the `paginationChanged` event and set `data`,
23981 * `firstRowIndex`, `lastRowIndex`, and `totalItems`. Defaults to `false`.
23982 */
23983 gridOptions.useCustomPagination = gridOptions.useCustomPagination === true;
23984
23985 /**
23986 * @ngdoc property
23987 * @name totalItems
23988 * @propertyOf ui.grid.pagination.api:GridOptions
23989 * @description Total number of items, set automatically when using client side pagination, but needs set by user
23990 * for server side pagination
23991 */
23992 if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {
23993 gridOptions.totalItems = 0;
23994 }
23995 /**
23996 * @ngdoc property
23997 * @name paginationPageSizes
23998 * @propertyOf ui.grid.pagination.api:GridOptions
23999 * @description Array of page sizes, defaults to `[250, 500, 1000]`
24000 */
24001 if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {
24002 gridOptions.paginationPageSizes = [250, 500, 1000];
24003 }
24004 /**
24005 * @ngdoc property
24006 * @name paginationPageSize
24007 * @propertyOf ui.grid.pagination.api:GridOptions
24008 * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty
24009 */
24010 if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {
24011 if (gridOptions.paginationPageSizes.length > 0) {
24012 gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];
24013 }
24014 else {
24015 gridOptions.paginationPageSize = 0;
24016 }
24017 }
24018 /**
24019 * @ngdoc property
24020 * @name paginationCurrentPage
24021 * @propertyOf ui.grid.pagination.api:GridOptions
24022 * @description Current page number, defaults to 1
24023 */
24024 if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {
24025 gridOptions.paginationCurrentPage = 1;
24026 }
24027
24028 /**
24029 * @ngdoc property
24030 * @name paginationTemplate
24031 * @propertyOf ui.grid.pagination.api:GridOptions
24032 * @description A custom template for the pager, defaults to `ui-grid/pagination`
24033 */
24034 if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {
24035 gridOptions.paginationTemplate = 'ui-grid/pagination';
24036 }
24037 },
24038 /**
24039 * @ngdoc method
24040 * @methodOf ui.grid.pagination.service:uiGridPaginationService
24041 * @name uiGridPaginationService
24042 * @description Raises paginationChanged and calls refresh for client side pagination
24043 * @param {Grid} grid the grid for which the pagination changed
24044 * @param {int} currentPage requested page number
24045 * @param {int} pageSize requested page size
24046 */
24047 onPaginationChanged: function (grid, currentPage, pageSize) {
24048 grid.api.pagination.raise.paginationChanged(currentPage, pageSize);
24049 if (!grid.options.useExternalPagination) {
24050 grid.queueGridRefresh(); // client side pagination
24051 }
24052 }
24053 };
24054
24055 return service;
24056 }
24057 ]);
24058 /**
24059 * @ngdoc directive
24060 * @name ui.grid.pagination.directive:uiGridPagination
24061 * @element div
24062 * @restrict A
24063 *
24064 * @description Adds pagination features to grid
24065 * @example
24066 <example module="app">
24067 <file name="app.js">
24068 var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);
24069
24070 app.controller('MainCtrl', ['$scope', function ($scope) {
24071 $scope.data = [
24072 { name: 'Alex', car: 'Toyota' },
24073 { name: 'Sam', car: 'Lexus' },
24074 { name: 'Joe', car: 'Dodge' },
24075 { name: 'Bob', car: 'Buick' },
24076 { name: 'Cindy', car: 'Ford' },
24077 { name: 'Brian', car: 'Audi' },
24078 { name: 'Malcom', car: 'Mercedes Benz' },
24079 { name: 'Dave', car: 'Ford' },
24080 { name: 'Stacey', car: 'Audi' },
24081 { name: 'Amy', car: 'Acura' },
24082 { name: 'Scott', car: 'Toyota' },
24083 { name: 'Ryan', car: 'BMW' },
24084 ];
24085
24086 $scope.gridOptions = {
24087 data: 'data',
24088 paginationPageSizes: [5, 10, 25],
24089 paginationPageSize: 5,
24090 columnDefs: [
24091 {name: 'name'},
24092 {name: 'car'}
24093 ]
24094 }
24095 }]);
24096 </file>
24097 <file name="index.html">
24098 <div ng-controller="MainCtrl">
24099 <div ui-grid="gridOptions" ui-grid-pagination></div>
24100 </div>
24101 </file>
24102 </example>
24103 */
24104 module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',
24105 function (gridUtil, uiGridPaginationService) {
24106 return {
24107 priority: -200,
24108 scope: false,
24109 require: 'uiGrid',
24110 link: {
24111 pre: function ($scope, $elm, $attr, uiGridCtrl) {
24112 uiGridPaginationService.initializeGrid(uiGridCtrl.grid);
24113
24114 gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)
24115 .then(function (contents) {
24116 var template = angular.element(contents);
24117
24118 $elm.append(template);
24119 uiGridCtrl.innerCompile(template);
24120 });
24121 }
24122 }
24123 };
24124 }
24125 ]);
24126
24127 /**
24128 * @ngdoc directive
24129 * @name ui.grid.pagination.directive:uiGridPager
24130 * @element div
24131 *
24132 * @description Panel for handling pagination
24133 */
24134 module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService', 'i18nConstants',
24135 function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService, i18nConstants) {
24136 return {
24137 priority: -200,
24138 scope: true,
24139 require: '^uiGrid',
24140 link: function ($scope, $elm, $attr, uiGridCtrl) {
24141 var defaultFocusElementSelector = '.ui-grid-pager-control-input';
24142
24143 $scope.aria = i18nService.getSafeText('pagination.aria'); // Returns an object with all of the aria labels
24144
24145 var updateLabels = function() {
24146 $scope.paginationApi = uiGridCtrl.grid.api.pagination;
24147 $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');
24148 $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');
24149 $scope.paginationOf = i18nService.getSafeText('pagination.of');
24150 $scope.paginationThrough = i18nService.getSafeText('pagination.through');
24151 };
24152
24153 updateLabels();
24154
24155 $scope.$on(i18nConstants.UPDATE_EVENT, updateLabels);
24156
24157 var options = uiGridCtrl.grid.options;
24158
24159 uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
24160 if (options.enablePaginationControls) {
24161 adjustment.height = adjustment.height - gridUtil.elementHeight($elm, "padding");
24162 }
24163 return adjustment;
24164 });
24165
24166 var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {
24167 if (!grid.options.useExternalPagination) {
24168 grid.options.totalItems = grid.rows.length;
24169 }
24170 }, [uiGridConstants.dataChange.ROW]);
24171
24172 $scope.$on('$destroy', dataChangeDereg);
24173
24174 var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {
24175 if (newValues === oldValues || oldValues === undefined) {
24176 return;
24177 }
24178
24179 if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {
24180 options.paginationCurrentPage = 1;
24181 return;
24182 }
24183
24184 if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {
24185 options.paginationCurrentPage = $scope.paginationApi.getTotalPages();
24186 return;
24187 }
24188
24189 uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);
24190 });
24191
24192 $scope.$on('$destroy', function() {
24193 deregP();
24194 });
24195
24196 $scope.cantPageForward = function () {
24197 if ($scope.paginationApi.getTotalPages()) {
24198 return $scope.cantPageToLast();
24199 }
24200 else {
24201 return options.data.length < 1;
24202 }
24203 };
24204
24205 $scope.cantPageToLast = function () {
24206 var totalPages = $scope.paginationApi.getTotalPages();
24207
24208 return !totalPages || options.paginationCurrentPage >= totalPages;
24209 };
24210
24211 $scope.cantPageBackward = function () {
24212 return options.paginationCurrentPage <= 1;
24213 };
24214
24215 var focusToInputIf = function(condition) {
24216 if (condition) {
24217 gridUtil.focus.bySelector($elm, defaultFocusElementSelector);
24218 }
24219 };
24220
24221 // Takes care of setting focus to the middle element when focus is lost
24222 $scope.pageFirstPageClick = function () {
24223 $scope.paginationApi.seek(1);
24224 focusToInputIf($scope.cantPageBackward());
24225 };
24226
24227 $scope.pagePreviousPageClick = function () {
24228 $scope.paginationApi.previousPage();
24229 focusToInputIf($scope.cantPageBackward());
24230 };
24231
24232 $scope.pageNextPageClick = function () {
24233 $scope.paginationApi.nextPage();
24234 focusToInputIf($scope.cantPageForward());
24235 };
24236
24237 $scope.pageLastPageClick = function () {
24238 $scope.paginationApi.seek($scope.paginationApi.getTotalPages());
24239 focusToInputIf($scope.cantPageToLast());
24240 };
24241 }
24242 };
24243 }
24244 ]);
24245 })();
24246
24247 (function () {
24248 'use strict';
24249
24250 /**
24251 * @ngdoc overview
24252 * @name ui.grid.pinning
24253 * @description
24254 *
24255 * # ui.grid.pinning
24256 *
24257 * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
24258 *
24259 * This module provides column pinning to the end user via menu options in the column header
24260 *
24261 * <div doc-module-components="ui.grid.pinning"></div>
24262 */
24263
24264 var module = angular.module('ui.grid.pinning', ['ui.grid']);
24265
24266 module.constant('uiGridPinningConstants', {
24267 container: {
24268 LEFT: 'left',
24269 RIGHT: 'right',
24270 NONE: ''
24271 }
24272 });
24273
24274 module.service('uiGridPinningService', ['gridUtil', 'GridRenderContainer', 'i18nService', 'uiGridPinningConstants', function (gridUtil, GridRenderContainer, i18nService, uiGridPinningConstants) {
24275 var service = {
24276
24277 initializeGrid: function (grid) {
24278 service.defaultGridOptions(grid.options);
24279
24280 // Register a column builder to add new menu items for pinning left and right
24281 grid.registerColumnBuilder(service.pinningColumnBuilder);
24282
24283 /**
24284 * @ngdoc object
24285 * @name ui.grid.pinning.api:PublicApi
24286 *
24287 * @description Public Api for pinning feature
24288 */
24289 var publicApi = {
24290 events: {
24291 pinning: {
24292 /**
24293 * @ngdoc event
24294 * @name columnPinned
24295 * @eventOf ui.grid.pinning.api:PublicApi
24296 * @description raised when column pin state has changed
24297 * <pre>
24298 * gridApi.pinning.on.columnPinned(scope, function(colDef){})
24299 * </pre>
24300 * @param {object} colDef the column that was changed
24301 * @param {string} container the render container the column is in ('left', 'right', '')
24302 */
24303 columnPinned: function(colDef, container) {
24304 }
24305 }
24306 },
24307 methods: {
24308 pinning: {
24309 /**
24310 * @ngdoc function
24311 * @name pinColumn
24312 * @methodOf ui.grid.pinning.api:PublicApi
24313 * @description pin column left, right, or none
24314 * <pre>
24315 * gridApi.pinning.pinColumn(col, uiGridPinningConstants.container.LEFT)
24316 * </pre>
24317 * @param {gridColumn} col the column being pinned
24318 * @param {string} container one of the recognised types
24319 * from uiGridPinningConstants
24320 */
24321 pinColumn: function(col, container) {
24322 service.pinColumn(grid, col, container);
24323 }
24324 }
24325 }
24326 };
24327
24328 grid.api.registerEventsFromObject(publicApi.events);
24329 grid.api.registerMethodsFromObject(publicApi.methods);
24330 },
24331
24332 defaultGridOptions: function (gridOptions) {
24333 // default option to true unless it was explicitly set to false
24334 /**
24335 * @ngdoc object
24336 * @name ui.grid.pinning.api:GridOptions
24337 *
24338 * @description GridOptions for pinning feature, these are available to be
24339 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
24340 */
24341
24342 /**
24343 * @ngdoc object
24344 * @name enablePinning
24345 * @propertyOf ui.grid.pinning.api:GridOptions
24346 * @description Enable pinning for the entire grid.
24347 * <br/>Defaults to true
24348 */
24349 gridOptions.enablePinning = gridOptions.enablePinning !== false;
24350 /**
24351 * @ngdoc object
24352 * @name hidePinLeft
24353 * @propertyOf ui.grid.pinning.api:GridOptions
24354 * @description Hide Pin Left for the entire grid.
24355 * <br/>Defaults to false
24356 */
24357 gridOptions.hidePinLeft = gridOptions.enablePinning && gridOptions.hidePinLeft;
24358 /**
24359 * @ngdoc object
24360 * @name hidePinRight
24361 * @propertyOf ui.grid.pinning.api:GridOptions
24362 * @description Hide Pin Right pinning for the entire grid.
24363 * <br/>Defaults to false
24364 */
24365 gridOptions.hidePinRight = gridOptions.enablePinning && gridOptions.hidePinRight;
24366 },
24367
24368 pinningColumnBuilder: function (colDef, col, gridOptions) {
24369 // default to true unless gridOptions or colDef is explicitly false
24370
24371 /**
24372 * @ngdoc object
24373 * @name ui.grid.pinning.api:ColumnDef
24374 *
24375 * @description ColumnDef for pinning feature, these are available to be
24376 * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
24377 */
24378
24379 /**
24380 * @ngdoc object
24381 * @name enablePinning
24382 * @propertyOf ui.grid.pinning.api:ColumnDef
24383 * @description Enable pinning for the individual column.
24384 * <br/>Defaults to true
24385 */
24386 colDef.enablePinning = colDef.enablePinning === undefined ? gridOptions.enablePinning : colDef.enablePinning;
24387 /**
24388 * @ngdoc object
24389 * @name hidePinLeft
24390 * @propertyOf ui.grid.pinning.api:ColumnDef
24391 * @description Hide Pin Left for the individual column.
24392 * <br/>Defaults to false
24393 */
24394 colDef.hidePinLeft = colDef.hidePinLeft === undefined ? gridOptions.hidePinLeft : colDef.hidePinLeft;
24395 /**
24396 * @ngdoc object
24397 * @name hidePinRight
24398 * @propertyOf ui.grid.pinning.api:ColumnDef
24399 * @description Hide Pin Right for the individual column.
24400 * <br/>Defaults to false
24401 */
24402 colDef.hidePinRight = colDef.hidePinRight === undefined ? gridOptions.hidePinRight : colDef.hidePinRight;
24403
24404 /**
24405 * @ngdoc object
24406 * @name pinnedLeft
24407 * @propertyOf ui.grid.pinning.api:ColumnDef
24408 * @description Column is pinned left when grid is rendered
24409 * <br/>Defaults to false
24410 */
24411
24412 /**
24413 * @ngdoc object
24414 * @name pinnedRight
24415 * @propertyOf ui.grid.pinning.api:ColumnDef
24416 * @description Column is pinned right when grid is rendered
24417 * <br/>Defaults to false
24418 */
24419 if (colDef.pinnedLeft) {
24420 col.renderContainer = 'left';
24421 col.grid.createLeftContainer();
24422 }
24423 else if (colDef.pinnedRight) {
24424 col.renderContainer = 'right';
24425 col.grid.createRightContainer();
24426 }
24427
24428 if (!colDef.enablePinning) {
24429 return;
24430 }
24431
24432 var pinColumnLeftAction = {
24433 name: 'ui.grid.pinning.pinLeft',
24434 title: i18nService.get().pinning.pinLeft,
24435 icon: 'ui-grid-icon-left-open',
24436 shown: function () {
24437 return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'left';
24438 },
24439 action: function () {
24440 service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.LEFT);
24441 }
24442 };
24443
24444 var pinColumnRightAction = {
24445 name: 'ui.grid.pinning.pinRight',
24446 title: i18nService.get().pinning.pinRight,
24447 icon: 'ui-grid-icon-right-open',
24448 shown: function () {
24449 return typeof(this.context.col.renderContainer) === 'undefined' || !this.context.col.renderContainer || this.context.col.renderContainer !== 'right';
24450 },
24451 action: function () {
24452 service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.RIGHT);
24453 }
24454 };
24455
24456 var removePinAction = {
24457 name: 'ui.grid.pinning.unpin',
24458 title: i18nService.get().pinning.unpin,
24459 icon: 'ui-grid-icon-cancel',
24460 shown: function () {
24461 return typeof(this.context.col.renderContainer) !== 'undefined' && this.context.col.renderContainer !== null && this.context.col.renderContainer !== 'body';
24462 },
24463 action: function () {
24464 service.pinColumn(this.context.col.grid, this.context.col, uiGridPinningConstants.container.NONE);
24465 }
24466 };
24467
24468 // Skip from menu if hidePinLeft or hidePinRight is true
24469 if (!colDef.hidePinLeft && !gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinLeft')) {
24470 col.menuItems.push(pinColumnLeftAction);
24471 }
24472 if (!colDef.hidePinRight && !gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.pinRight')) {
24473 col.menuItems.push(pinColumnRightAction);
24474 }
24475 if (!gridUtil.arrayContainsObjectWithProperty(col.menuItems, 'name', 'ui.grid.pinning.unpin')) {
24476 col.menuItems.push(removePinAction);
24477 }
24478 },
24479
24480 pinColumn: function(grid, col, container) {
24481 if (container === uiGridPinningConstants.container.NONE) {
24482 col.renderContainer = null;
24483 col.colDef.pinnedLeft = col.colDef.pinnedRight = false;
24484 }
24485 else {
24486 col.renderContainer = container;
24487 if (container === uiGridPinningConstants.container.LEFT) {
24488 grid.createLeftContainer();
24489 }
24490 else if (container === uiGridPinningConstants.container.RIGHT) {
24491 grid.createRightContainer();
24492 }
24493 }
24494
24495 grid.refresh()
24496 .then(function() {
24497 grid.api.pinning.raise.columnPinned( col.colDef, container );
24498 });
24499 }
24500 };
24501
24502 return service;
24503 }]);
24504
24505 module.directive('uiGridPinning', ['gridUtil', 'uiGridPinningService',
24506 function (gridUtil, uiGridPinningService) {
24507 return {
24508 require: 'uiGrid',
24509 scope: false,
24510 compile: function () {
24511 return {
24512 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
24513 uiGridPinningService.initializeGrid(uiGridCtrl.grid);
24514 },
24515 post: function ($scope, $elm, $attrs, uiGridCtrl) {
24516 }
24517 };
24518 }
24519 };
24520 }]);
24521 })();
24522
24523 (function() {
24524 'use strict';
24525
24526 /**
24527 * @ngdoc overview
24528 * @name ui.grid.resizeColumns
24529 * @description
24530 *
24531 * # ui.grid.resizeColumns
24532 *
24533 * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
24534 *
24535 * This module allows columns to be resized.
24536 */
24537 var module = angular.module('ui.grid.resizeColumns', ['ui.grid']);
24538
24539 module.service('uiGridResizeColumnsService', ['gridUtil', '$q', '$rootScope',
24540 function (gridUtil, $q, $rootScope) {
24541 return {
24542 defaultGridOptions: function(gridOptions) {
24543 // default option to true unless it was explicitly set to false
24544 /**
24545 * @ngdoc object
24546 * @name ui.grid.resizeColumns.api:GridOptions
24547 *
24548 * @description GridOptions for resizeColumns feature, these are available to be
24549 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
24550 */
24551
24552 /**
24553 * @ngdoc object
24554 * @name enableColumnResizing
24555 * @propertyOf ui.grid.resizeColumns.api:GridOptions
24556 * @description Enable column resizing on the entire grid
24557 * <br/>Defaults to true
24558 */
24559 gridOptions.enableColumnResizing = gridOptions.enableColumnResizing !== false;
24560
24561 // legacy support
24562 // use old name if it is explicitly false
24563 if (gridOptions.enableColumnResize === false) {
24564 gridOptions.enableColumnResizing = false;
24565 }
24566 },
24567
24568 colResizerColumnBuilder: function (colDef, col, gridOptions) {
24569 var promises = [];
24570
24571 /**
24572 * @ngdoc object
24573 * @name ui.grid.resizeColumns.api:ColumnDef
24574 *
24575 * @description ColumnDef for resizeColumns feature, these are available to be
24576 * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
24577 */
24578
24579 /**
24580 * @ngdoc object
24581 * @name enableColumnResizing
24582 * @propertyOf ui.grid.resizeColumns.api:ColumnDef
24583 * @description Enable column resizing on an individual column
24584 * <br/>Defaults to GridOptions.enableColumnResizing
24585 */
24586 // default to true unless gridOptions or colDef is explicitly false
24587 colDef.enableColumnResizing = colDef.enableColumnResizing === undefined ? gridOptions.enableColumnResizing : colDef.enableColumnResizing;
24588
24589
24590 // legacy support of old option name
24591 if (colDef.enableColumnResize === false) {
24592 colDef.enableColumnResizing = false;
24593 }
24594
24595 return $q.all(promises);
24596 },
24597
24598 registerPublicApi: function (grid) {
24599 /**
24600 * @ngdoc object
24601 * @name ui.grid.resizeColumns.api:PublicApi
24602 * @description Public Api for column resize feature.
24603 */
24604 var publicApi = {
24605 events: {
24606 /**
24607 * @ngdoc event
24608 * @name columnSizeChanged
24609 * @eventOf ui.grid.resizeColumns.api:PublicApi
24610 * @description raised when column is resized
24611 * <pre>
24612 * gridApi.colResizable.on.columnSizeChanged(scope,function(colDef, deltaChange) {})
24613 * </pre>
24614 * @param {object} colDef the column that was resized
24615 * @param {integer} delta of the column size change
24616 */
24617 colResizable: {
24618 columnSizeChanged: function (colDef, deltaChange) {
24619 }
24620 }
24621 }
24622 };
24623 grid.api.registerEventsFromObject(publicApi.events);
24624 },
24625
24626 fireColumnSizeChanged: function (grid, colDef, deltaChange) {
24627 $rootScope.$applyAsync(function () {
24628 if ( grid.api.colResizable ) {
24629 grid.api.colResizable.raise.columnSizeChanged(colDef, deltaChange);
24630 } else {
24631 gridUtil.logError("The resizeable api is not registered, this may indicate that you've included the module but not added the 'ui-grid-resize-columns' directive to your grid definition. Cannot raise any events.");
24632 }
24633 });
24634 },
24635
24636 // get either this column, or the column next to this column, to resize,
24637 // returns the column we're going to resize
24638 findTargetCol: function(col, position, rtlMultiplier) {
24639 var renderContainer = col.getRenderContainer();
24640
24641 if (position === 'left') {
24642 // Get the column to the left of this one
24643 var colIndex = renderContainer.visibleColumnCache.indexOf(col);
24644 return renderContainer.visibleColumnCache[colIndex - 1 * rtlMultiplier];
24645 } else {
24646 return col;
24647 }
24648 }
24649 };
24650 }]);
24651
24652
24653 /**
24654 * @ngdoc directive
24655 * @name ui.grid.resizeColumns.directive:uiGridResizeColumns
24656 * @element div
24657 * @restrict A
24658 * @description
24659 * Enables resizing for all columns on the grid. If, for some reason, you want to use the ui-grid-resize-columns directive, but not allow column resizing, you can explicitly set the
24660 * option to false. This prevents resizing for the entire grid, regardless of individual columnDef options.
24661 *
24662 * @example
24663 <doc:example module="app">
24664 <doc:source>
24665 <script>
24666 var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);
24667
24668 app.controller('MainCtrl', ['$scope', function ($scope) {
24669 $scope.gridOpts = {
24670 data: [
24671 { "name": "Ethel Price", "gender": "female", "company": "Enersol" },
24672 { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" },
24673 { "name": "Beryl Rice", "gender": "female", "company": "Velity" },
24674 { "name": "Wilder Gonzales", "gender": "male", "company": "Geekko" }
24675 ]
24676 };
24677 }]);
24678 </script>
24679
24680 <div ng-controller="MainCtrl">
24681 <div class="testGrid" ui-grid="gridOpts" ui-grid-resize-columns ></div>
24682 </div>
24683 </doc:source>
24684 <doc:scenario>
24685
24686 </doc:scenario>
24687 </doc:example>
24688 */
24689 module.directive('uiGridResizeColumns', ['gridUtil', 'uiGridResizeColumnsService', function (gridUtil, uiGridResizeColumnsService) {
24690 return {
24691 replace: true,
24692 priority: 0,
24693 require: '^uiGrid',
24694 scope: false,
24695 compile: function () {
24696 return {
24697 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
24698 uiGridResizeColumnsService.defaultGridOptions(uiGridCtrl.grid.options);
24699 uiGridCtrl.grid.registerColumnBuilder( uiGridResizeColumnsService.colResizerColumnBuilder);
24700 uiGridResizeColumnsService.registerPublicApi(uiGridCtrl.grid);
24701 },
24702 post: function ($scope, $elm, $attrs, uiGridCtrl) {
24703 }
24704 };
24705 }
24706 };
24707 }]);
24708
24709 // Extend the uiGridHeaderCell directive
24710 module.directive('uiGridHeaderCell', ['gridUtil', '$templateCache', '$compile', '$q', 'uiGridResizeColumnsService', 'uiGridConstants', function (gridUtil, $templateCache, $compile, $q, uiGridResizeColumnsService, uiGridConstants) {
24711 return {
24712 // Run after the original uiGridHeaderCell
24713 priority: -10,
24714 require: '^uiGrid',
24715 // scope: false,
24716 compile: function() {
24717 return {
24718 post: function ($scope, $elm, $attrs, uiGridCtrl) {
24719 var grid = uiGridCtrl.grid;
24720
24721 if (grid.options.enableColumnResizing) {
24722 var columnResizerElm = $templateCache.get('ui-grid/columnResizer');
24723
24724 var rtlMultiplier = 1;
24725 // when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
24726 if (grid.isRTL()) {
24727 $scope.position = 'left';
24728 rtlMultiplier = -1;
24729 }
24730
24731 var displayResizers = function() {
24732
24733 // remove any existing resizers.
24734 var resizers = $elm[0].getElementsByClassName('ui-grid-column-resizer');
24735 for ( var i = 0; i < resizers.length; i++ ) {
24736 angular.element(resizers[i]).remove();
24737 }
24738
24739 // get the target column for the left resizer
24740 var otherCol = uiGridResizeColumnsService.findTargetCol($scope.col, 'left', rtlMultiplier);
24741 var renderContainer = $scope.col.getRenderContainer();
24742
24743 // Don't append the left resizer if this is the first column or the column to the left of this one has resizing disabled
24744 if (otherCol && renderContainer.visibleColumnCache.indexOf($scope.col) !== 0 && otherCol.colDef.enableColumnResizing !== false) {
24745 var resizerLeft = angular.element(columnResizerElm).clone();
24746 resizerLeft.attr('position', 'left');
24747
24748 $elm.prepend(resizerLeft);
24749 $compile(resizerLeft)($scope);
24750 }
24751
24752 // Don't append the right resizer if this column has resizing disabled
24753 if ($scope.col.colDef.enableColumnResizing !== false) {
24754 var resizerRight = angular.element(columnResizerElm).clone();
24755 resizerRight.attr('position', 'right');
24756
24757 $elm.append(resizerRight);
24758 $compile(resizerRight)($scope);
24759 }
24760 };
24761
24762 displayResizers();
24763
24764 var waitDisplay = function() {
24765 $scope.$applyAsync(displayResizers);
24766 };
24767
24768 var dataChangeDereg = grid.registerDataChangeCallback( waitDisplay, [uiGridConstants.dataChange.COLUMN] );
24769
24770 $scope.$on( '$destroy', dataChangeDereg );
24771 }
24772 }
24773 };
24774 }
24775 };
24776 }]);
24777
24778
24779
24780 /**
24781 * @ngdoc directive
24782 * @name ui.grid.resizeColumns.directive:uiGridColumnResizer
24783 * @element div
24784 * @restrict A
24785 *
24786 * @description
24787 * Draggable handle that controls column resizing.
24788 *
24789 * @example
24790 <doc:example module="app">
24791 <doc:source>
24792 <script>
24793 var app = angular.module('app', ['ui.grid', 'ui.grid.resizeColumns']);
24794
24795 app.controller('MainCtrl', ['$scope', function ($scope) {
24796 $scope.gridOpts = {
24797 enableColumnResizing: true,
24798 data: [
24799 { "name": "Ethel Price", "gender": "female", "company": "Enersol" },
24800 { "name": "Claudine Neal", "gender": "female", "company": "Sealoud" },
24801 { "name": "Beryl Rice", "gender": "female", "company": "Velity" },
24802 { "name": "Wilder Gonzales", "gender": "male", "company": "Geekko" }
24803 ]
24804 };
24805 }]);
24806 </script>
24807
24808 <div ng-controller="MainCtrl">
24809 <div class="testGrid" ui-grid="gridOpts"></div>
24810 </div>
24811 </doc:source>
24812 <doc:scenario>
24813 // TODO: e2e specs?
24814
24815 // TODO: post-resize a horizontal scroll event should be fired
24816 </doc:scenario>
24817 </doc:example>
24818 */
24819 module.directive('uiGridColumnResizer', ['$document', 'gridUtil', 'uiGridConstants', 'uiGridResizeColumnsService', function ($document, gridUtil, uiGridConstants, uiGridResizeColumnsService) {
24820 var resizeOverlay = angular.element('<div class="ui-grid-resize-overlay"></div>');
24821
24822 return {
24823 priority: 0,
24824 scope: {
24825 col: '=',
24826 position: '@',
24827 renderIndex: '='
24828 },
24829 require: '?^uiGrid',
24830 link: function ($scope, $elm, $attrs, uiGridCtrl) {
24831 var startX = 0,
24832 x = 0,
24833 gridLeft = 0,
24834 rtlMultiplier = 1;
24835
24836 // when in RTL mode reverse the direction using the rtlMultiplier and change the position to left
24837 if (uiGridCtrl.grid.isRTL()) {
24838 $scope.position = 'left';
24839 rtlMultiplier = -1;
24840 }
24841
24842 if ($scope.position === 'left') {
24843 $elm.addClass('left');
24844 }
24845 else if ($scope.position === 'right') {
24846 $elm.addClass('right');
24847 }
24848
24849 // Refresh the grid canvas
24850 // takes an argument representing the diff along the X-axis that the resize had
24851 function refreshCanvas(xDiff) {
24852 // Then refresh the grid canvas, rebuilding the styles so that the scrollbar updates its size
24853 uiGridCtrl.grid.refreshCanvas(true).then( function() {
24854 uiGridCtrl.grid.queueGridRefresh();
24855 });
24856 }
24857
24858 // Check that the requested width isn't wider than the maxWidth, or narrower than the minWidth
24859 // Returns the new recommended with, after constraints applied
24860 function constrainWidth(col, width) {
24861 var newWidth = width;
24862
24863 // If the new width would be less than the column's allowably minimum width, don't allow it
24864 if (col.minWidth && newWidth < col.minWidth) {
24865 newWidth = col.minWidth;
24866 }
24867 else if (col.maxWidth && newWidth > col.maxWidth) {
24868 newWidth = col.maxWidth;
24869 }
24870
24871 return newWidth;
24872 }
24873
24874
24875 /*
24876 * Our approach to event handling aims to deal with both touch devices and mouse devices
24877 * We register down handlers on both touch and mouse. When a touchstart or mousedown event
24878 * occurs, we register the corresponding touchmove/touchend, or mousemove/mouseend events.
24879 *
24880 * This way we can listen for both without worrying about the fact many touch devices also emulate
24881 * mouse events - basically whichever one we hear first is what we'll go with.
24882 */
24883 function moveFunction(event, args) {
24884 if (event.originalEvent) { event = event.originalEvent; }
24885 event.preventDefault();
24886
24887 x = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;
24888
24889 if (x < 0) { x = 0; }
24890 else if (x > uiGridCtrl.grid.gridWidth) { x = uiGridCtrl.grid.gridWidth; }
24891
24892 var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
24893
24894 // Don't resize if it's disabled on this column
24895 if (col.colDef.enableColumnResizing === false) {
24896 return;
24897 }
24898
24899 if (!uiGridCtrl.grid.element.hasClass('column-resizing')) {
24900 uiGridCtrl.grid.element.addClass('column-resizing');
24901 }
24902
24903 // Get the diff along the X axis
24904 var xDiff = x - startX;
24905
24906 // Get the width that this mouse would give the column
24907 var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);
24908
24909 // check we're not outside the allowable bounds for this column
24910 x = x + ( constrainWidth(col, newWidth) - newWidth ) * rtlMultiplier;
24911
24912 resizeOverlay.css({ left: x + 'px' });
24913
24914 uiGridCtrl.fireEvent(uiGridConstants.events.ITEM_DRAGGING);
24915 }
24916
24917
24918 function upFunction(event) {
24919 if (event.originalEvent) { event = event.originalEvent; }
24920 event.preventDefault();
24921
24922 uiGridCtrl.grid.element.removeClass('column-resizing');
24923
24924 resizeOverlay.remove();
24925
24926 // Resize the column
24927 x = (event.changedTouches ? event.changedTouches[0] : event).clientX - gridLeft;
24928 var xDiff = x - startX;
24929
24930 if (xDiff === 0) {
24931 // no movement, so just reset event handlers, including turning back on both
24932 // down events - we turned one off when this event started
24933 offAllEvents();
24934 onDownEvents();
24935 return;
24936 }
24937
24938 var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
24939
24940 // Don't resize if it's disabled on this column
24941 if (col.colDef.enableColumnResizing === false) {
24942 return;
24943 }
24944
24945 // Get the new width
24946 var newWidth = parseInt(col.drawnWidth + xDiff * rtlMultiplier, 10);
24947
24948 // check we're not outside the allowable bounds for this column
24949 col.width = constrainWidth(col, newWidth);
24950 col.hasCustomWidth = true;
24951
24952 refreshCanvas(xDiff);
24953
24954 uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff);
24955
24956 // stop listening of up and move events - wait for next down
24957 // reset the down events - we will have turned one off when this event started
24958 offAllEvents();
24959 onDownEvents();
24960 }
24961
24962
24963 var downFunction = function(event, args) {
24964 if (event.originalEvent) { event = event.originalEvent; }
24965 event.stopPropagation();
24966
24967 // Get the left offset of the grid
24968 // gridLeft = uiGridCtrl.grid.element[0].offsetLeft;
24969 gridLeft = uiGridCtrl.grid.element[0].getBoundingClientRect().left;
24970
24971 // Get the starting X position, which is the X coordinate of the click minus the grid's offset
24972 startX = (event.targetTouches ? event.targetTouches[0] : event).clientX - gridLeft;
24973
24974 // Append the resizer overlay
24975 uiGridCtrl.grid.element.append(resizeOverlay);
24976
24977 // Place the resizer overlay at the start position
24978 resizeOverlay.css({ left: startX });
24979
24980 // Add handlers for move and up events - if we were mousedown then we listen for mousemove and mouseup, if
24981 // we were touchdown then we listen for touchmove and touchup. Also remove the handler for the equivalent
24982 // down event - so if we're touchdown, then remove the mousedown handler until this event is over, if we're
24983 // mousedown then remove the touchdown handler until this event is over, this avoids processing duplicate events
24984 if ( event.type === 'touchstart' ) {
24985 $document.on('touchend', upFunction);
24986 $document.on('touchmove', moveFunction);
24987 $elm.off('mousedown', downFunction);
24988 }
24989 else {
24990 $document.on('mouseup', upFunction);
24991 $document.on('mousemove', moveFunction);
24992 $elm.off('touchstart', downFunction);
24993 }
24994 };
24995
24996 var onDownEvents = function() {
24997 $elm.on('mousedown', downFunction);
24998 $elm.on('touchstart', downFunction);
24999 };
25000
25001 var offAllEvents = function() {
25002 $document.off('mouseup', upFunction);
25003 $document.off('touchend', upFunction);
25004 $document.off('mousemove', moveFunction);
25005 $document.off('touchmove', moveFunction);
25006 $elm.off('mousedown', downFunction);
25007 $elm.off('touchstart', downFunction);
25008 };
25009
25010 onDownEvents();
25011
25012
25013 // On doubleclick, resize to fit all rendered cells
25014 var dblClickFn = function(event, args) {
25015 event.stopPropagation();
25016
25017 var col = uiGridResizeColumnsService.findTargetCol($scope.col, $scope.position, rtlMultiplier);
25018
25019 // Don't resize if it's disabled on this column
25020 if (col.colDef.enableColumnResizing === false) {
25021 return;
25022 }
25023
25024 // Go through the rendered rows and find out the max size for the data in this column
25025 var maxWidth = 0;
25026
25027 // Get the parent render container element
25028 var renderContainerElm = gridUtil.closestElm($elm, '.ui-grid-render-container');
25029
25030 // Get the cell contents so we measure correctly. For the header cell we have to account for the sort icon and the menu buttons, if present
25031 var cells = renderContainerElm.querySelectorAll('.' + uiGridConstants.COL_CLASS_PREFIX + col.uid + ' .ui-grid-cell-contents');
25032 Array.prototype.forEach.call(cells, function (cell) {
25033 // Get the cell width
25034 // gridUtil.logDebug('width', gridUtil.elementWidth(cell));
25035
25036 // Account for the menu button if it exists
25037 var menuButton;
25038 if (angular.element(cell).parent().hasClass('ui-grid-header-cell')) {
25039 menuButton = angular.element(cell).parent()[0].querySelectorAll('.ui-grid-column-menu-button');
25040 }
25041
25042 gridUtil.fakeElement(cell, {}, function(newElm) {
25043 // Make the element float since it's a div and can expand to fill its container
25044 var e = angular.element(newElm);
25045 e.attr('style', 'float: left');
25046
25047 var width = gridUtil.elementWidth(e);
25048
25049 if (menuButton) {
25050 var menuButtonWidth = gridUtil.elementWidth(menuButton);
25051 width = width + menuButtonWidth;
25052 }
25053
25054 if (width > maxWidth) {
25055 maxWidth = width;
25056 }
25057 });
25058 });
25059
25060 // check we're not outside the allowable bounds for this column
25061 var newWidth = constrainWidth(col, maxWidth);
25062 var xDiff = newWidth - col.drawnWidth;
25063 col.width = newWidth;
25064 col.hasCustomWidth = true;
25065
25066 refreshCanvas(xDiff);
25067
25068 uiGridResizeColumnsService.fireColumnSizeChanged(uiGridCtrl.grid, col.colDef, xDiff); };
25069 $elm.on('dblclick', dblClickFn);
25070
25071 $elm.on('$destroy', function() {
25072 $elm.off('dblclick', dblClickFn);
25073 offAllEvents();
25074 });
25075 }
25076 };
25077 }]);
25078 })();
25079
25080 (function () {
25081 'use strict';
25082
25083 /**
25084 * @ngdoc overview
25085 * @name ui.grid.rowEdit
25086 * @description
25087 *
25088 * # ui.grid.rowEdit
25089 *
25090 * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
25091 *
25092 * This module extends the edit feature to provide tracking and saving of rows
25093 * of data. The tutorial provides more information on how this feature is best
25094 * used {@link tutorial/205_row_editable here}.
25095 * <br/>
25096 * This feature depends on usage of the ui-grid-edit feature, and also benefits
25097 * from use of ui-grid-cellNav to provide the full spreadsheet-like editing
25098 * experience
25099 *
25100 */
25101
25102 var module = angular.module('ui.grid.rowEdit', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);
25103
25104 /**
25105 * @ngdoc object
25106 * @name ui.grid.rowEdit.constant:uiGridRowEditConstants
25107 *
25108 * @description constants available in row edit module
25109 */
25110 module.constant('uiGridRowEditConstants', {
25111 });
25112
25113 /**
25114 * @ngdoc service
25115 * @name ui.grid.rowEdit.service:uiGridRowEditService
25116 *
25117 * @description Services for row editing features
25118 */
25119 module.service('uiGridRowEditService', ['$interval', '$q', 'uiGridConstants', 'uiGridRowEditConstants', 'gridUtil',
25120 function ($interval, $q, uiGridConstants, uiGridRowEditConstants, gridUtil) {
25121
25122 var service = {
25123
25124 initializeGrid: function (scope, grid) {
25125 /**
25126 * @ngdoc object
25127 * @name ui.grid.rowEdit.api:PublicApi
25128 *
25129 * @description Public Api for rowEdit feature
25130 */
25131
25132 grid.rowEdit = {};
25133
25134 var publicApi = {
25135 events: {
25136 rowEdit: {
25137 /**
25138 * @ngdoc event
25139 * @eventOf ui.grid.rowEdit.api:PublicApi
25140 * @name saveRow
25141 * @description raised when a row is ready for saving. Once your
25142 * row has saved you may need to use angular.extend to update the
25143 * data entity with any changed data from your save (for example,
25144 * lock version information if you're using optimistic locking,
25145 * or last update time/user information).
25146 *
25147 * Your method should call setSavePromise somewhere in the body before
25148 * returning control. The feature will then wait, with the gridRow greyed out
25149 * whilst this promise is being resolved.
25150 *
25151 * <pre>
25152 * gridApi.rowEdit.on.saveRow(scope,function(rowEntity) {})
25153 * </pre>
25154 * and somewhere within the event handler:
25155 * <pre>
25156 * gridApi.rowEdit.setSavePromise( rowEntity, savePromise)
25157 * </pre>
25158 * @param {object} rowEntity the options.data element that was edited
25159 * @returns {promise} Your saveRow method should return a promise, the
25160 * promise should either be resolved (implying successful save), or
25161 * rejected (implying an error).
25162 */
25163 saveRow: function (rowEntity) {
25164 }
25165 }
25166 },
25167 methods: {
25168 rowEdit: {
25169 /**
25170 * @ngdoc method
25171 * @methodOf ui.grid.rowEdit.api:PublicApi
25172 * @name setSavePromise
25173 * @description Sets the promise associated with the row save, mandatory that
25174 * the saveRow event handler calls this method somewhere before returning.
25175 * <pre>
25176 * gridApi.rowEdit.setSavePromise(rowEntity, savePromise)
25177 * </pre>
25178 * @param {object} rowEntity a data row from the grid for which a save has
25179 * been initiated
25180 * @param {promise} savePromise the promise that will be resolved when the
25181 * save is successful, or rejected if the save fails
25182 *
25183 */
25184 setSavePromise: function ( rowEntity, savePromise) {
25185 service.setSavePromise(grid, rowEntity, savePromise);
25186 },
25187 /**
25188 * @ngdoc method
25189 * @methodOf ui.grid.rowEdit.api:PublicApi
25190 * @name getDirtyRows
25191 * @description Returns all currently dirty rows
25192 * <pre>
25193 * gridApi.rowEdit.getDirtyRows(grid)
25194 * </pre>
25195 * @returns {array} An array of gridRows that are currently dirty
25196 *
25197 */
25198 getDirtyRows: function () {
25199 return grid.rowEdit.dirtyRows ? grid.rowEdit.dirtyRows : [];
25200 },
25201 /**
25202 * @ngdoc method
25203 * @methodOf ui.grid.rowEdit.api:PublicApi
25204 * @name getErrorRows
25205 * @description Returns all currently errored rows
25206 * <pre>
25207 * gridApi.rowEdit.getErrorRows(grid)
25208 * </pre>
25209 * @returns {array} An array of gridRows that are currently in error
25210 *
25211 */
25212 getErrorRows: function () {
25213 return grid.rowEdit.errorRows ? grid.rowEdit.errorRows : [];
25214 },
25215 /**
25216 * @ngdoc method
25217 * @methodOf ui.grid.rowEdit.api:PublicApi
25218 * @name flushDirtyRows
25219 * @description Triggers a save event for all currently dirty rows, could
25220 * be used where user presses a save button or navigates away from the page
25221 * <pre>
25222 * gridApi.rowEdit.flushDirtyRows(grid)
25223 * </pre>
25224 * @returns {promise} a promise that represents the aggregate of all
25225 * of the individual save promises - i.e. it will be resolved when all
25226 * the individual save promises have been resolved.
25227 *
25228 */
25229 flushDirtyRows: function () {
25230 return service.flushDirtyRows(grid);
25231 },
25232
25233 /**
25234 * @ngdoc method
25235 * @methodOf ui.grid.rowEdit.api:PublicApi
25236 * @name setRowsDirty
25237 * @description Sets each of the rows passed in dataRows
25238 * to be dirty. Note that if you have only just inserted the
25239 * rows into your data you will need to wait for a $digest cycle
25240 * before the gridRows are present - so often you would wrap this
25241 * call in a $interval or $timeout. Also, you must pass row.entity
25242 * into this function rather than row objects themselves.
25243 * <pre>
25244 * $interval( function() {
25245 * gridApi.rowEdit.setRowsDirty(myDataRows);
25246 * }, 0, 1);
25247 * </pre>
25248 * @param {array} dataRows the data entities for which the gridRows
25249 * should be set dirty.
25250 *
25251 */
25252 setRowsDirty: function ( dataRows) {
25253 service.setRowsDirty(grid, dataRows);
25254 },
25255
25256 /**
25257 * @ngdoc method
25258 * @methodOf ui.grid.rowEdit.api:PublicApi
25259 * @name setRowsClean
25260 * @description Sets each of the rows passed in dataRows
25261 * to be clean, removing them from the dirty cache and the error cache,
25262 * and clearing the error flag and the dirty flag
25263 * <pre>
25264 * var gridRows = $scope.gridApi.rowEdit.getDirtyRows();
25265 * var dataRows = gridRows.map( function( gridRow ) { return gridRow.entity; });
25266 * $scope.gridApi.rowEdit.setRowsClean( dataRows );
25267 * </pre>
25268 * @param {array} dataRows the data entities for which the gridRows
25269 * should be set clean.
25270 *
25271 */
25272 setRowsClean: function ( dataRows) {
25273 service.setRowsClean(grid, dataRows);
25274 }
25275 }
25276 }
25277 };
25278
25279 grid.api.registerEventsFromObject(publicApi.events);
25280 grid.api.registerMethodsFromObject(publicApi.methods);
25281
25282 grid.api.core.on.renderingComplete( scope, function ( gridApi ) {
25283 grid.api.edit.on.afterCellEdit( scope, service.endEditCell );
25284 grid.api.edit.on.beginCellEdit( scope, service.beginEditCell );
25285 grid.api.edit.on.cancelCellEdit( scope, service.cancelEditCell );
25286
25287 if ( grid.api.cellNav ) {
25288 grid.api.cellNav.on.navigate( scope, service.navigate );
25289 }
25290 });
25291
25292 },
25293
25294 defaultGridOptions: function (gridOptions) {
25295
25296 /**
25297 * @ngdoc object
25298 * @name ui.grid.rowEdit.api:GridOptions
25299 *
25300 * @description Options for configuring the rowEdit feature, these are available to be
25301 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
25302 */
25303
25304 },
25305
25306
25307 /**
25308 * @ngdoc method
25309 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25310 * @name saveRow
25311 * @description Returns a function that saves the specified row from the grid,
25312 * and returns a promise
25313 * @param {object} grid the grid for which dirty rows should be flushed
25314 * @param {GridRow} gridRow the row that should be saved
25315 * @returns {function} the saveRow function returns a function. That function
25316 * in turn, when called, returns a promise relating to the save callback
25317 */
25318 saveRow: function ( grid, gridRow ) {
25319 var self = this;
25320
25321 return function() {
25322 gridRow.isSaving = true;
25323
25324 if ( gridRow.rowEditSavePromise ) {
25325 // don't save the row again if it's already saving - that causes stale object exceptions
25326 return gridRow.rowEditSavePromise;
25327 }
25328
25329 var promise = grid.api.rowEdit.raise.saveRow( gridRow.entity );
25330
25331 if ( gridRow.rowEditSavePromise ) {
25332 gridRow.rowEditSavePromise.then( self.processSuccessPromise( grid, gridRow ), self.processErrorPromise( grid, gridRow ));
25333 } else {
25334 gridUtil.logError( 'A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise' );
25335 }
25336 return promise;
25337 };
25338 },
25339
25340
25341 /**
25342 * @ngdoc method
25343 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25344 * @name setSavePromise
25345 * @description Sets the promise associated with the row save, mandatory that
25346 * the saveRow event handler calls this method somewhere before returning.
25347 * <pre>
25348 * gridApi.rowEdit.setSavePromise(grid, rowEntity)
25349 * </pre>
25350 * @param {object} grid the grid for which dirty rows should be returned
25351 * @param {object} rowEntity a data row from the grid for which a save has
25352 * been initiated
25353 * @param {promise} savePromise the promise that will be resolved when the
25354 * save is successful, or rejected if the save fails
25355 *
25356 */
25357 setSavePromise: function (grid, rowEntity, savePromise) {
25358 var gridRow = grid.getRow( rowEntity );
25359 gridRow.rowEditSavePromise = savePromise;
25360 },
25361
25362
25363 /**
25364 * @ngdoc method
25365 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25366 * @name processSuccessPromise
25367 * @description Returns a function that processes the successful
25368 * resolution of a save promise
25369 * @param {object} grid the grid for which the promise should be processed
25370 * @param {GridRow} gridRow the row that has been saved
25371 * @returns {function} the success handling function
25372 */
25373 processSuccessPromise: function ( grid, gridRow ) {
25374 var self = this;
25375
25376 return function() {
25377 delete gridRow.isSaving;
25378 delete gridRow.isDirty;
25379 delete gridRow.isError;
25380 delete gridRow.rowEditSaveTimer;
25381 delete gridRow.rowEditSavePromise;
25382 self.removeRow( grid.rowEdit.errorRows, gridRow );
25383 self.removeRow( grid.rowEdit.dirtyRows, gridRow );
25384 };
25385 },
25386
25387
25388 /**
25389 * @ngdoc method
25390 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25391 * @name processErrorPromise
25392 * @description Returns a function that processes the failed
25393 * resolution of a save promise
25394 * @param {object} grid the grid for which the promise should be processed
25395 * @param {GridRow} gridRow the row that is now in error
25396 * @returns {function} the error handling function
25397 */
25398 processErrorPromise: function ( grid, gridRow ) {
25399 return function() {
25400 delete gridRow.isSaving;
25401 delete gridRow.rowEditSaveTimer;
25402 delete gridRow.rowEditSavePromise;
25403
25404 gridRow.isError = true;
25405
25406 if (!grid.rowEdit.errorRows) {
25407 grid.rowEdit.errorRows = [];
25408 }
25409 if (!service.isRowPresent( grid.rowEdit.errorRows, gridRow ) ) {
25410 grid.rowEdit.errorRows.push( gridRow );
25411 }
25412 };
25413 },
25414
25415
25416 /**
25417 * @ngdoc method
25418 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25419 * @name removeRow
25420 * @description Removes a row from a cache of rows - either
25421 * grid.rowEdit.errorRows or grid.rowEdit.dirtyRows. If the row
25422 * is not present silently does nothing.
25423 * @param {array} rowArray the array from which to remove the row
25424 * @param {GridRow} gridRow the row that should be removed
25425 */
25426 removeRow: function( rowArray, removeGridRow ) {
25427 if (typeof(rowArray) === 'undefined' || rowArray === null) {
25428 return;
25429 }
25430
25431 rowArray.forEach( function( gridRow, index ) {
25432 if ( gridRow.uid === removeGridRow.uid ) {
25433 rowArray.splice( index, 1);
25434 }
25435 });
25436 },
25437
25438
25439 /**
25440 * @ngdoc method
25441 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25442 * @name isRowPresent
25443 * @description Checks whether a row is already present
25444 * in the given array
25445 * @param {array} rowArray the array in which to look for the row
25446 * @param {GridRow} gridRow the row that should be looked for
25447 */
25448 isRowPresent: function( rowArray, removeGridRow ) {
25449 var present = false;
25450 rowArray.forEach( function( gridRow, index ) {
25451 if ( gridRow.uid === removeGridRow.uid ) {
25452 present = true;
25453 }
25454 });
25455 return present;
25456 },
25457
25458
25459 /**
25460 * @ngdoc method
25461 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25462 * @name flushDirtyRows
25463 * @description Triggers a save event for all currently dirty rows, could
25464 * be used where user presses a save button or navigates away from the page
25465 * <pre>
25466 * gridApi.rowEdit.flushDirtyRows(grid)
25467 * </pre>
25468 * @param {object} grid the grid for which dirty rows should be flushed
25469 * @returns {promise} a promise that represents the aggregate of all
25470 * of the individual save promises - i.e. it will be resolved when all
25471 * the individual save promises have been resolved.
25472 *
25473 */
25474 flushDirtyRows: function(grid) {
25475 var promises = [];
25476 grid.api.rowEdit.getDirtyRows().forEach( function( gridRow ) {
25477 service.cancelTimer( grid, gridRow );
25478 service.saveRow( grid, gridRow )();
25479 promises.push( gridRow.rowEditSavePromise );
25480 });
25481
25482 return $q.all( promises );
25483 },
25484
25485
25486 /**
25487 * @ngdoc method
25488 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25489 * @name endEditCell
25490 * @description Receives an afterCellEdit event from the edit function,
25491 * and sets flags as appropriate. Only the rowEntity parameter
25492 * is processed, although other params are available. Grid
25493 * is automatically provided by the gridApi.
25494 * @param {object} rowEntity the data entity for which the cell
25495 * was edited
25496 */
25497 endEditCell: function( rowEntity, colDef, newValue, previousValue ) {
25498 var grid = this.grid;
25499 var gridRow = grid.getRow( rowEntity );
25500 if ( !gridRow ) { gridUtil.logError( 'Unable to find rowEntity in grid data, dirty flag cannot be set' ); return; }
25501
25502 if ( newValue !== previousValue || gridRow.isDirty ) {
25503 if ( !grid.rowEdit.dirtyRows ) {
25504 grid.rowEdit.dirtyRows = [];
25505 }
25506
25507 if ( !gridRow.isDirty ) {
25508 gridRow.isDirty = true;
25509 grid.rowEdit.dirtyRows.push( gridRow );
25510 }
25511
25512 delete gridRow.isError;
25513
25514 service.considerSetTimer( grid, gridRow );
25515 }
25516 },
25517
25518
25519 /**
25520 * @ngdoc method
25521 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25522 * @name beginEditCell
25523 * @description Receives a beginCellEdit event from the edit function,
25524 * and cancels any rowEditSaveTimers if present, as the user is still editing
25525 * this row. Only the rowEntity parameter
25526 * is processed, although other params are available. Grid
25527 * is automatically provided by the gridApi.
25528 * @param {object} rowEntity the data entity for which the cell
25529 * editing has commenced
25530 */
25531 beginEditCell: function( rowEntity, colDef ) {
25532 var grid = this.grid;
25533 var gridRow = grid.getRow( rowEntity );
25534 if ( !gridRow ) { gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be cancelled' ); return; }
25535
25536 service.cancelTimer( grid, gridRow );
25537 },
25538
25539
25540 /**
25541 * @ngdoc method
25542 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25543 * @name cancelEditCell
25544 * @description Receives a cancelCellEdit event from the edit function,
25545 * and if the row was already dirty, restarts the save timer. If the row
25546 * was not already dirty, then it's not dirty now either and does nothing.
25547 *
25548 * Only the rowEntity parameter
25549 * is processed, although other params are available. Grid
25550 * is automatically provided by the gridApi.
25551 *
25552 * @param {object} rowEntity the data entity for which the cell
25553 * editing was cancelled
25554 */
25555 cancelEditCell: function( rowEntity, colDef ) {
25556 var grid = this.grid;
25557 var gridRow = grid.getRow( rowEntity );
25558 if ( !gridRow ) { gridUtil.logError( 'Unable to find rowEntity in grid data, timer cannot be set' ); return; }
25559
25560 service.considerSetTimer( grid, gridRow );
25561 },
25562
25563
25564 /**
25565 * @ngdoc method
25566 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25567 * @name navigate
25568 * @description cellNav tells us that the selected cell has changed. If
25569 * the new row had a timer running, then stop it similar to in a beginCellEdit
25570 * call. If the old row is dirty and not the same as the new row, then
25571 * start a timer on it.
25572 * @param {object} newRowCol the row and column that were selected
25573 * @param {object} oldRowCol the row and column that was left
25574 *
25575 */
25576 navigate: function( newRowCol, oldRowCol ) {
25577 var grid = this.grid;
25578 if ( newRowCol.row.rowEditSaveTimer ) {
25579 service.cancelTimer( grid, newRowCol.row );
25580 }
25581
25582 if ( oldRowCol && oldRowCol.row && oldRowCol.row !== newRowCol.row ) {
25583 service.considerSetTimer( grid, oldRowCol.row );
25584 }
25585 },
25586
25587
25588 /**
25589 * @ngdoc property
25590 * @propertyOf ui.grid.rowEdit.api:GridOptions
25591 * @name rowEditWaitInterval
25592 * @description How long the grid should wait for another change on this row
25593 * before triggering a save (in milliseconds). If set to -1, then saves are
25594 * never triggered by timer (implying that the user will call flushDirtyRows()
25595 * manually)
25596 *
25597 * @example
25598 * Setting the wait interval to 4 seconds
25599 * <pre>
25600 * $scope.gridOptions = { rowEditWaitInterval: 4000 }
25601 * </pre>
25602 *
25603 */
25604 /**
25605 * @ngdoc method
25606 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25607 * @name considerSetTimer
25608 * @description Consider setting a timer on this row (if it is dirty). if there is a timer running
25609 * on the row and the row isn't currently saving, cancel it, using cancelTimer, then if the row is
25610 * dirty and not currently saving then set a new timer
25611 * @param {object} grid the grid for which we are processing
25612 * @param {GridRow} gridRow the row for which the timer should be adjusted
25613 *
25614 */
25615 considerSetTimer: function( grid, gridRow ) {
25616 service.cancelTimer( grid, gridRow );
25617
25618 if ( gridRow.isDirty && !gridRow.isSaving ) {
25619 if ( grid.options.rowEditWaitInterval !== -1 ) {
25620 var waitTime = grid.options.rowEditWaitInterval ? grid.options.rowEditWaitInterval : 2000;
25621 gridRow.rowEditSaveTimer = $interval( service.saveRow( grid, gridRow ), waitTime, 1);
25622 }
25623 }
25624 },
25625
25626
25627 /**
25628 * @ngdoc method
25629 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25630 * @name cancelTimer
25631 * @description cancel the $interval for any timer running on this row
25632 * then delete the timer itself
25633 * @param {object} grid the grid for which we are processing
25634 * @param {GridRow} gridRow the row for which the timer should be adjusted
25635 *
25636 */
25637 cancelTimer: function( grid, gridRow ) {
25638 if ( gridRow.rowEditSaveTimer && !gridRow.isSaving ) {
25639 $interval.cancel(gridRow.rowEditSaveTimer);
25640 delete gridRow.rowEditSaveTimer;
25641 }
25642 },
25643
25644
25645 /**
25646 * @ngdoc method
25647 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25648 * @name setRowsDirty
25649 * @description Sets each of the rows passed in dataRows
25650 * to be dirty. note that if you have only just inserted the
25651 * rows into your data you will need to wait for a $digest cycle
25652 * before the gridRows are present - so often you would wrap this
25653 * call in a $interval or $timeout
25654 * <pre>
25655 * $interval( function() {
25656 * gridApi.rowEdit.setRowsDirty( myDataRows);
25657 * }, 0, 1);
25658 * </pre>
25659 * @param {object} grid the grid for which rows should be set dirty
25660 * @param {array} dataRows the data entities for which the gridRows
25661 * should be set dirty.
25662 *
25663 */
25664 setRowsDirty: function( grid, myDataRows ) {
25665 var gridRow;
25666 myDataRows.forEach( function( value, index ) {
25667 gridRow = grid.getRow( value );
25668 if ( gridRow ) {
25669 if ( !grid.rowEdit.dirtyRows ) {
25670 grid.rowEdit.dirtyRows = [];
25671 }
25672
25673 if ( !gridRow.isDirty ) {
25674 gridRow.isDirty = true;
25675 grid.rowEdit.dirtyRows.push( gridRow );
25676 }
25677
25678 delete gridRow.isError;
25679
25680 service.considerSetTimer( grid, gridRow );
25681 } else {
25682 gridUtil.logError( "requested row not found in rowEdit.setRowsDirty, row was: " + value );
25683 }
25684 });
25685 },
25686
25687
25688 /**
25689 * @ngdoc method
25690 * @methodOf ui.grid.rowEdit.service:uiGridRowEditService
25691 * @name setRowsClean
25692 * @description Sets each of the rows passed in dataRows
25693 * to be clean, clearing the dirty flag and the error flag, and removing
25694 * the rows from the dirty and error caches.
25695 * @param {object} grid the grid for which rows should be set clean
25696 * @param {array} dataRows the data entities for which the gridRows
25697 * should be set clean.
25698 *
25699 */
25700 setRowsClean: function( grid, myDataRows ) {
25701 var gridRow;
25702
25703 myDataRows.forEach( function( value, index ) {
25704 gridRow = grid.getRow( value );
25705 if ( gridRow ) {
25706 delete gridRow.isDirty;
25707 service.removeRow( grid.rowEdit.dirtyRows, gridRow );
25708 service.cancelTimer( grid, gridRow );
25709
25710 delete gridRow.isError;
25711 service.removeRow( grid.rowEdit.errorRows, gridRow );
25712 } else {
25713 gridUtil.logError( "requested row not found in rowEdit.setRowsClean, row was: " + value );
25714 }
25715 });
25716 }
25717
25718 };
25719
25720 return service;
25721
25722 }]);
25723
25724 /**
25725 * @ngdoc directive
25726 * @name ui.grid.rowEdit.directive:uiGridEdit
25727 * @element div
25728 * @restrict A
25729 *
25730 * @description Adds row editing features to the ui-grid-edit directive.
25731 *
25732 */
25733 module.directive('uiGridRowEdit', ['gridUtil', 'uiGridRowEditService', 'uiGridEditConstants',
25734 function (gridUtil, uiGridRowEditService, uiGridEditConstants) {
25735 return {
25736 replace: true,
25737 priority: 0,
25738 require: '^uiGrid',
25739 scope: false,
25740 compile: function () {
25741 return {
25742 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
25743 uiGridRowEditService.initializeGrid($scope, uiGridCtrl.grid);
25744 },
25745 post: function ($scope, $elm, $attrs, uiGridCtrl) {
25746 }
25747 };
25748 }
25749 };
25750 }]);
25751
25752
25753 /**
25754 * @ngdoc directive
25755 * @name ui.grid.rowEdit.directive:uiGridViewport
25756 * @element div
25757 *
25758 * @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
25759 * for the grid row to allow coloring of saving and error rows
25760 */
25761 module.directive('uiGridViewport',
25762 ['$compile', 'uiGridConstants', 'gridUtil', '$parse',
25763 function ($compile, uiGridConstants, gridUtil, $parse) {
25764 return {
25765 priority: -200, // run after default directive
25766 scope: false,
25767 compile: function ($elm, $attrs) {
25768 var rowRepeatDiv = angular.element($elm.children().children()[0]);
25769
25770 var existingNgClass = rowRepeatDiv.attr("ng-class");
25771 var newNgClass = '';
25772 if ( existingNgClass ) {
25773 newNgClass = existingNgClass.slice(0, -1) + ", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}";
25774 } else {
25775 newNgClass = "{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}";
25776 }
25777 rowRepeatDiv.attr("ng-class", newNgClass);
25778
25779 return {
25780 pre: function ($scope, $elm, $attrs, controllers) {
25781
25782 },
25783 post: function ($scope, $elm, $attrs, controllers) {
25784 }
25785 };
25786 }
25787 };
25788 }]);
25789
25790 })();
25791
25792 (function () {
25793 'use strict';
25794
25795 /**
25796 * @ngdoc overview
25797 * @name ui.grid.saveState
25798 * @description
25799 *
25800 * # ui.grid.saveState
25801 *
25802 * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
25803 *
25804 * This module provides the ability to save the grid state, and restore
25805 * it when the user returns to the page.
25806 *
25807 * No UI is provided, the caller should provide their own UI/buttons
25808 * as appropriate. Usually the navigate events would be used to save
25809 * the grid state and restore it.
25810 *
25811 * <br/>
25812 * <br/>
25813 *
25814 * <div doc-module-components="ui.grid.save-state"></div>
25815 */
25816
25817 var module = angular.module('ui.grid.saveState', ['ui.grid', 'ui.grid.selection', 'ui.grid.cellNav', 'ui.grid.grouping', 'ui.grid.pinning', 'ui.grid.treeView']);
25818
25819 /**
25820 * @ngdoc object
25821 * @name ui.grid.saveState.constant:uiGridSaveStateConstants
25822 *
25823 * @description constants available in save state module
25824 */
25825
25826 module.constant('uiGridSaveStateConstants', {
25827 featureName: 'saveState'
25828 });
25829
25830 /**
25831 * @ngdoc service
25832 * @name ui.grid.saveState.service:uiGridSaveStateService
25833 *
25834 * @description Services for saveState feature
25835 */
25836 module.service('uiGridSaveStateService',
25837 function () {
25838 var service = {
25839
25840 initializeGrid: function (grid) {
25841
25842 // add feature namespace and any properties to grid for needed state
25843 grid.saveState = {};
25844 this.defaultGridOptions(grid.options);
25845
25846 /**
25847 * @ngdoc object
25848 * @name ui.grid.saveState.api:PublicApi
25849 *
25850 * @description Public Api for saveState feature
25851 */
25852 var publicApi = {
25853 events: {
25854 saveState: {
25855 }
25856 },
25857 methods: {
25858 saveState: {
25859 /**
25860 * @ngdoc function
25861 * @name save
25862 * @methodOf ui.grid.saveState.api:PublicApi
25863 * @description Packages the current state of the grid into
25864 * an object, and provides it to the user for saving
25865 * @returns {object} the state as a javascript object that can be saved
25866 */
25867 save: function () {
25868 return service.save(grid);
25869 },
25870 /**
25871 * @ngdoc function
25872 * @name restore
25873 * @methodOf ui.grid.saveState.api:PublicApi
25874 * @description Restores the provided state into the grid
25875 * @param {scope} $scope a scope that we can broadcast on
25876 * @param {object} state the state that should be restored into the grid
25877 * @returns {object} the promise created by refresh
25878 */
25879 restore: function ( $scope, state) {
25880 return service.restore(grid, $scope, state);
25881 }
25882 }
25883 }
25884 };
25885
25886 grid.api.registerEventsFromObject(publicApi.events);
25887
25888 grid.api.registerMethodsFromObject(publicApi.methods);
25889 },
25890
25891 defaultGridOptions: function (gridOptions) {
25892 // default option to true unless it was explicitly set to false
25893 /**
25894 * @ngdoc object
25895 * @name ui.grid.saveState.api:GridOptions
25896 *
25897 * @description GridOptions for saveState feature, these are available to be
25898 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
25899 */
25900 /**
25901 * @ngdoc object
25902 * @name saveWidths
25903 * @propertyOf ui.grid.saveState.api:GridOptions
25904 * @description Save the current column widths. Note that unless
25905 * you've provided the user with some way to resize their columns (say
25906 * the resize columns feature), then this makes little sense.
25907 * <br/>Defaults to true
25908 */
25909 gridOptions.saveWidths = gridOptions.saveWidths !== false;
25910 /**
25911 * @ngdoc object
25912 * @name saveOrder
25913 * @propertyOf ui.grid.saveState.api:GridOptions
25914 * @description Restore the current column order. Note that unless
25915 * you've provided the user with some way to reorder their columns (for
25916 * example the move columns feature), this makes little sense.
25917 * <br/>Defaults to true
25918 */
25919 gridOptions.saveOrder = gridOptions.saveOrder !== false;
25920 /**
25921 * @ngdoc object
25922 * @name saveScroll
25923 * @propertyOf ui.grid.saveState.api:GridOptions
25924 * @description Save the current scroll position. Note that this
25925 * is saved as the percentage of the grid scrolled - so if your
25926 * user returns to a grid with a significantly different number of
25927 * rows (perhaps some data has been deleted) then the scroll won't
25928 * actually show the same rows as before. If you want to scroll to
25929 * a specific row then you should instead use the saveFocus option, which
25930 * is the default.
25931 *
25932 * Note that this element will only be saved if the cellNav feature is
25933 * enabled
25934 * <br/>Defaults to false
25935 */
25936 gridOptions.saveScroll = gridOptions.saveScroll === true;
25937 /**
25938 * @ngdoc object
25939 * @name saveFocus
25940 * @propertyOf ui.grid.saveState.api:GridOptions
25941 * @description Save the current focused cell. On returning
25942 * to this focused cell we'll also scroll. This option is
25943 * preferred to the saveScroll option, so is set to true by
25944 * default. If saveScroll is set to true then this option will
25945 * be disabled.
25946 *
25947 * By default this option saves the current row number and column
25948 * number, and returns to that row and column. However, if you define
25949 * a saveRowIdentity function, then it will return you to the currently
25950 * selected column within that row (in a business sense - so if some
25951 * rows have been deleted, it will still find the same data, presuming it
25952 * still exists in the list. If it isn't in the list then it will instead
25953 * return to the same row number - i.e. scroll percentage)
25954 *
25955 * Note that this option will do nothing if the cellNav
25956 * feature is not enabled.
25957 *
25958 * <br/>Defaults to true (unless saveScroll is true)
25959 */
25960 gridOptions.saveFocus = gridOptions.saveScroll !== true && gridOptions.saveFocus !== false;
25961 /**
25962 * @ngdoc object
25963 * @name saveRowIdentity
25964 * @propertyOf ui.grid.saveState.api:GridOptions
25965 * @description A function that can be called, passing in a rowEntity,
25966 * and that will return a unique id for that row. This might simply
25967 * return the `id` field from that row (if you have one), or it might
25968 * concatenate some fields within the row to make a unique value.
25969 *
25970 * This value will be used to find the same row again and set the focus
25971 * to it, if it exists when we return.
25972 *
25973 * <br/>Defaults to undefined
25974 */
25975 /**
25976 * @ngdoc object
25977 * @name saveVisible
25978 * @propertyOf ui.grid.saveState.api:GridOptions
25979 * @description Save whether or not columns are visible.
25980 *
25981 * <br/>Defaults to true
25982 */
25983 gridOptions.saveVisible = gridOptions.saveVisible !== false;
25984 /**
25985 * @ngdoc object
25986 * @name saveSort
25987 * @propertyOf ui.grid.saveState.api:GridOptions
25988 * @description Save the current sort state for each column
25989 *
25990 * <br/>Defaults to true
25991 */
25992 gridOptions.saveSort = gridOptions.saveSort !== false;
25993 /**
25994 * @ngdoc object
25995 * @name saveFilter
25996 * @propertyOf ui.grid.saveState.api:GridOptions
25997 * @description Save the current filter state for each column
25998 *
25999 * <br/>Defaults to true
26000 */
26001 gridOptions.saveFilter = gridOptions.saveFilter !== false;
26002 /**
26003 * @ngdoc object
26004 * @name saveSelection
26005 * @propertyOf ui.grid.saveState.api:GridOptions
26006 * @description Save the currently selected rows. If the `saveRowIdentity` callback
26007 * is defined, then it will save the id of the row and select that. If not, then
26008 * it will attempt to select the rows by row number, which will give the wrong results
26009 * if the data set has changed in the mean-time.
26010 *
26011 * Note that this option only does anything
26012 * if the selection feature is enabled.
26013 *
26014 * <br/>Defaults to true
26015 */
26016 gridOptions.saveSelection = gridOptions.saveSelection !== false;
26017 /**
26018 * @ngdoc object
26019 * @name saveGrouping
26020 * @propertyOf ui.grid.saveState.api:GridOptions
26021 * @description Save the grouping configuration. If set to true and the
26022 * grouping feature is not enabled then does nothing.
26023 *
26024 * <br/>Defaults to true
26025 */
26026 gridOptions.saveGrouping = gridOptions.saveGrouping !== false;
26027 /**
26028 * @ngdoc object
26029 * @name saveGroupingExpandedStates
26030 * @propertyOf ui.grid.saveState.api:GridOptions
26031 * @description Save the grouping row expanded states. If set to true and the
26032 * grouping feature is not enabled then does nothing.
26033 *
26034 * This can be quite a bit of data, in many cases you wouldn't want to save this
26035 * information.
26036 *
26037 * <br/>Defaults to false
26038 */
26039 gridOptions.saveGroupingExpandedStates = gridOptions.saveGroupingExpandedStates === true;
26040 /**
26041 * @ngdoc object
26042 * @name savePinning
26043 * @propertyOf ui.grid.saveState.api:GridOptions
26044 * @description Save pinning state for columns.
26045 *
26046 * <br/>Defaults to true
26047 */
26048 gridOptions.savePinning = gridOptions.savePinning !== false;
26049 /**
26050 * @ngdoc object
26051 * @name saveTreeView
26052 * @propertyOf ui.grid.saveState.api:GridOptions
26053 * @description Save the treeView configuration. If set to true and the
26054 * treeView feature is not enabled then does nothing.
26055 *
26056 * <br/>Defaults to true
26057 */
26058 gridOptions.saveTreeView = gridOptions.saveTreeView !== false;
26059 },
26060
26061 /**
26062 * @ngdoc function
26063 * @name save
26064 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26065 * @description Saves the current grid state into an object, and
26066 * passes that object back to the caller
26067 * @param {Grid} grid the grid whose state we'd like to save
26068 * @returns {object} the state ready to be saved
26069 */
26070 save: function (grid) {
26071 var savedState = {};
26072
26073 savedState.columns = service.saveColumns( grid );
26074 savedState.scrollFocus = service.saveScrollFocus( grid );
26075 savedState.selection = service.saveSelection( grid );
26076 savedState.grouping = service.saveGrouping( grid );
26077 savedState.treeView = service.saveTreeView( grid );
26078 savedState.pagination = service.savePagination( grid );
26079
26080 return savedState;
26081 },
26082
26083
26084 /**
26085 * @ngdoc function
26086 * @name restore
26087 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26088 * @description Applies the provided state to the grid
26089 *
26090 * @param {Grid} grid the grid whose state we'd like to restore
26091 * @param {scope} $scope a scope that we can broadcast on
26092 * @param {object} state the state we'd like to restore
26093 * @returns {object} the promise created by refresh
26094 */
26095 restore: function( grid, $scope, state ) {
26096 if ( state.columns ) {
26097 service.restoreColumns( grid, state.columns );
26098 }
26099
26100 if ( state.scrollFocus ) {
26101 service.restoreScrollFocus( grid, $scope, state.scrollFocus );
26102 }
26103
26104 if ( state.selection ) {
26105 service.restoreSelection( grid, state.selection );
26106 }
26107
26108 if ( state.grouping ) {
26109 service.restoreGrouping( grid, state.grouping );
26110 }
26111
26112 if ( state.treeView ) {
26113 service.restoreTreeView( grid, state.treeView );
26114 }
26115
26116 if ( state.pagination ) {
26117 service.restorePagination( grid, state.pagination );
26118 }
26119
26120 return grid.refresh();
26121 },
26122
26123
26124 /**
26125 * @ngdoc function
26126 * @name saveColumns
26127 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26128 * @description Saves the column setup, including sort, filters, ordering,
26129 * pinning and column widths.
26130 *
26131 * Works through the current columns, storing them in order. Stores the
26132 * column name, then the visible flag, width, sort and filters for each column.
26133 *
26134 * @param {Grid} grid the grid whose state we'd like to save
26135 * @returns {array} the columns state ready to be saved
26136 */
26137 saveColumns: function( grid ) {
26138 var columns = [];
26139
26140 grid.getOnlyDataColumns().forEach( function( column ) {
26141 var savedColumn = {};
26142 savedColumn.name = column.name;
26143
26144 if ( grid.options.saveVisible ) {
26145 savedColumn.visible = column.visible;
26146 }
26147
26148 if ( grid.options.saveWidths ) {
26149 savedColumn.width = column.width;
26150 }
26151
26152 // these two must be copied, not just pointed too - otherwise our saved state is pointing to the same object as current state
26153 if ( grid.options.saveSort ) {
26154 savedColumn.sort = angular.copy( column.sort );
26155 }
26156
26157 if ( grid.options.saveFilter ) {
26158 savedColumn.filters = [];
26159 column.filters.forEach( function( filter ) {
26160 var copiedFilter = {};
26161 angular.forEach( filter, function( value, key) {
26162 if ( key !== 'condition' && key !== '$$hashKey' && key !== 'placeholder') {
26163 copiedFilter[key] = value;
26164 }
26165 });
26166 savedColumn.filters.push(copiedFilter);
26167 });
26168 }
26169
26170 if ( !!grid.api.pinning && grid.options.savePinning ) {
26171 savedColumn.pinned = column.renderContainer ? column.renderContainer : '';
26172 }
26173
26174 columns.push( savedColumn );
26175 });
26176
26177 return columns;
26178 },
26179
26180
26181 /**
26182 * @ngdoc function
26183 * @name saveScrollFocus
26184 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26185 * @description Saves the currently scroll or focus.
26186 *
26187 * If cellNav isn't present then does nothing - we can't return
26188 * to the scroll position without cellNav anyway.
26189 *
26190 * If the cellNav module is present, and saveFocus is true, then
26191 * it saves the currently focused cell. If rowIdentity is present
26192 * then saves using rowIdentity, otherwise saves visibleRowNum.
26193 *
26194 * If the cellNav module is not present, and saveScroll is true, then
26195 * it approximates the current scroll row and column, and saves that.
26196 *
26197 * @param {Grid} grid the grid whose state we'd like to save
26198 * @returns {object} the selection state ready to be saved
26199 */
26200 saveScrollFocus: function( grid ) {
26201 if ( !grid.api.cellNav ) {
26202 return {};
26203 }
26204
26205 var scrollFocus = {};
26206 if ( grid.options.saveFocus ) {
26207 scrollFocus.focus = true;
26208 var rowCol = grid.api.cellNav.getFocusedCell();
26209 if ( rowCol !== null ) {
26210 if ( rowCol.col !== null ) {
26211 scrollFocus.colName = rowCol.col.colDef.name;
26212 }
26213 if ( rowCol.row !== null ) {
26214 scrollFocus.rowVal = service.getRowVal( grid, rowCol.row );
26215 }
26216 }
26217 }
26218
26219 if ( grid.options.saveScroll || grid.options.saveFocus && !scrollFocus.colName && !scrollFocus.rowVal ) {
26220 scrollFocus.focus = false;
26221 if ( grid.renderContainers.body.prevRowScrollIndex ) {
26222 scrollFocus.rowVal = service.getRowVal( grid, grid.renderContainers.body.visibleRowCache[ grid.renderContainers.body.prevRowScrollIndex ]);
26223 }
26224
26225 if ( grid.renderContainers.body.prevColScrollIndex ) {
26226 scrollFocus.colName = grid.renderContainers.body.visibleColumnCache[ grid.renderContainers.body.prevColScrollIndex ].name;
26227 }
26228 }
26229
26230 return scrollFocus;
26231 },
26232
26233
26234 /**
26235 * @ngdoc function
26236 * @name saveSelection
26237 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26238 * @description Saves the currently selected rows, if the selection feature is enabled
26239 * @param {Grid} grid the grid whose state we'd like to save
26240 * @returns {array} the selection state ready to be saved
26241 */
26242 saveSelection: function( grid ) {
26243 if ( !grid.api.selection || !grid.options.saveSelection ) {
26244 return [];
26245 }
26246
26247 return grid.api.selection.getSelectedGridRows().map( function( gridRow ) {
26248 return service.getRowVal( grid, gridRow );
26249 });
26250 },
26251
26252
26253 /**
26254 * @ngdoc function
26255 * @name saveGrouping
26256 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26257 * @description Saves the grouping state, if the grouping feature is enabled
26258 * @param {Grid} grid the grid whose state we'd like to save
26259 * @returns {object} the grouping state ready to be saved
26260 */
26261 saveGrouping: function( grid ) {
26262 if ( !grid.api.grouping || !grid.options.saveGrouping ) {
26263 return {};
26264 }
26265
26266 return grid.api.grouping.getGrouping( grid.options.saveGroupingExpandedStates );
26267 },
26268
26269
26270 /**
26271 * @ngdoc function
26272 * @name savePagination
26273 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26274 * @description Saves the pagination state, if the pagination feature is enabled
26275 * @param {Grid} grid the grid whose state we'd like to save
26276 * @returns {object} the pagination state ready to be saved
26277 */
26278 savePagination: function( grid ) {
26279 if ( !grid.api.pagination || !grid.options.paginationPageSize ) {
26280 return {};
26281 }
26282
26283 return {
26284 paginationCurrentPage: grid.options.paginationCurrentPage,
26285 paginationPageSize: grid.options.paginationPageSize
26286 };
26287 },
26288
26289
26290 /**
26291 * @ngdoc function
26292 * @name saveTreeView
26293 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26294 * @description Saves the tree view state, if the tree feature is enabled
26295 * @param {Grid} grid the grid whose state we'd like to save
26296 * @returns {object} the tree view state ready to be saved
26297 */
26298 saveTreeView: function( grid ) {
26299 if ( !grid.api.treeView || !grid.options.saveTreeView ) {
26300 return {};
26301 }
26302
26303 return grid.api.treeView.getTreeView();
26304 },
26305
26306
26307 /**
26308 * @ngdoc function
26309 * @name getRowVal
26310 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26311 * @description Helper function that gets either the rowNum or
26312 * the saveRowIdentity, given a gridRow
26313 * @param {Grid} grid the grid the row is in
26314 * @param {GridRow} gridRow the row we want the rowNum for
26315 * @returns {object} an object containing { identity: true/false, row: rowNumber/rowIdentity }
26316 *
26317 */
26318 getRowVal: function( grid, gridRow ) {
26319 if ( !gridRow ) {
26320 return null;
26321 }
26322
26323 var rowVal = {};
26324 if ( grid.options.saveRowIdentity ) {
26325 rowVal.identity = true;
26326 rowVal.row = grid.options.saveRowIdentity( gridRow.entity );
26327 }
26328 else {
26329 rowVal.identity = false;
26330 rowVal.row = grid.renderContainers.body.visibleRowCache.indexOf( gridRow );
26331 }
26332 return rowVal;
26333 },
26334
26335
26336 /**
26337 * @ngdoc function
26338 * @name restoreColumns
26339 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26340 * @description Restores the columns, including order, visible, width,
26341 * pinning, sort and filters.
26342 *
26343 * @param {Grid} grid the grid whose state we'd like to restore
26344 * @param {object} columnsState the list of columns we had before, with their state
26345 */
26346 restoreColumns: function( grid, columnsState ) {
26347 var isSortChanged = false;
26348
26349 columnsState.forEach( function( columnState, index ) {
26350 var currentCol = grid.getColumn( columnState.name );
26351
26352 if ( currentCol && !grid.isRowHeaderColumn(currentCol) ) {
26353 if ( grid.options.saveVisible &&
26354 ( currentCol.visible !== columnState.visible ||
26355 currentCol.colDef.visible !== columnState.visible ) ) {
26356 currentCol.visible = columnState.visible;
26357 currentCol.colDef.visible = columnState.visible;
26358 grid.api.core.raise.columnVisibilityChanged(currentCol);
26359 }
26360
26361 if ( grid.options.saveWidths && currentCol.width !== columnState.width) {
26362 currentCol.width = columnState.width;
26363 currentCol.hasCustomWidth = true;
26364 }
26365
26366 if ( grid.options.saveSort &&
26367 !angular.equals(currentCol.sort, columnState.sort) &&
26368 !( currentCol.sort === undefined && angular.isEmpty(columnState.sort) ) ) {
26369 currentCol.sort = angular.copy( columnState.sort );
26370 isSortChanged = true;
26371 }
26372
26373 if ( grid.options.saveFilter &&
26374 !angular.equals(currentCol.filters, columnState.filters ) ) {
26375 columnState.filters.forEach( function( filter, index ) {
26376 angular.extend( currentCol.filters[index], filter );
26377 if ( typeof(filter.term) === 'undefined' || filter.term === null ) {
26378 delete currentCol.filters[index].term;
26379 }
26380 });
26381 grid.api.core.raise.filterChanged();
26382 }
26383
26384 if ( !!grid.api.pinning && grid.options.savePinning && currentCol.renderContainer !== columnState.pinned ) {
26385 grid.api.pinning.pinColumn(currentCol, columnState.pinned);
26386 }
26387
26388 var currentIndex = grid.getOnlyDataColumns().indexOf( currentCol );
26389 if (currentIndex !== -1) {
26390 if (grid.options.saveOrder && currentIndex !== index) {
26391 var column = grid.columns.splice(currentIndex + grid.rowHeaderColumns.length, 1)[0];
26392 grid.columns.splice(index + grid.rowHeaderColumns.length, 0, column);
26393 }
26394 }
26395 }
26396 });
26397
26398 if ( isSortChanged ) {
26399 grid.api.core.raise.sortChanged( grid, grid.getColumnSorting() );
26400 }
26401 },
26402
26403
26404 /**
26405 * @ngdoc function
26406 * @name restoreScrollFocus
26407 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26408 * @description Scrolls to the position that was saved. If focus is true, then
26409 * sets focus to the specified row/col. If focus is false, then scrolls to the
26410 * specified row/col.
26411 *
26412 * @param {Grid} grid the grid whose state we'd like to restore
26413 * @param {scope} $scope a scope that we can broadcast on
26414 * @param {object} scrollFocusState the scroll/focus state ready to be restored
26415 */
26416 restoreScrollFocus: function( grid, $scope, scrollFocusState ) {
26417 if ( !grid.api.cellNav ) {
26418 return;
26419 }
26420
26421 var colDef, row;
26422 if ( scrollFocusState.colName ) {
26423 var colDefs = grid.options.columnDefs.filter( function( colDef ) { return colDef.name === scrollFocusState.colName; });
26424 if ( colDefs.length > 0 ) {
26425 colDef = colDefs[0];
26426 }
26427 }
26428
26429 if ( scrollFocusState.rowVal && scrollFocusState.rowVal.row ) {
26430 if ( scrollFocusState.rowVal.identity ) {
26431 row = service.findRowByIdentity( grid, scrollFocusState.rowVal );
26432 }
26433 else {
26434 row = grid.renderContainers.body.visibleRowCache[ scrollFocusState.rowVal.row ];
26435 }
26436 }
26437
26438 var entity = row && row.entity ? row.entity : null ;
26439
26440 if ( colDef || entity ) {
26441 if (scrollFocusState.focus ) {
26442 grid.api.cellNav.scrollToFocus( entity, colDef );
26443 }
26444 else {
26445 grid.scrollTo( entity, colDef );
26446 }
26447 }
26448 },
26449
26450
26451 /**
26452 * @ngdoc function
26453 * @name restoreSelection
26454 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26455 * @description Selects the rows that are provided in the selection
26456 * state. If you are using `saveRowIdentity` and more than one row matches the identity
26457 * function then only the first is selected.
26458 * @param {Grid} grid the grid whose state we'd like to restore
26459 * @param {object} selectionState the selection state ready to be restored
26460 */
26461 restoreSelection: function( grid, selectionState ) {
26462 if ( !grid.api.selection ) {
26463 return;
26464 }
26465
26466 grid.api.selection.clearSelectedRows();
26467
26468 selectionState.forEach(function( rowVal ) {
26469 if ( rowVal.identity ) {
26470 var foundRow = service.findRowByIdentity( grid, rowVal );
26471
26472 if ( foundRow ) {
26473 grid.api.selection.selectRow( foundRow.entity );
26474 }
26475
26476 }
26477 else {
26478 grid.api.selection.selectRowByVisibleIndex( rowVal.row );
26479 }
26480 });
26481 },
26482
26483
26484 /**
26485 * @ngdoc function
26486 * @name restoreGrouping
26487 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26488 * @description Restores the grouping configuration, if the grouping feature
26489 * is enabled.
26490 * @param {Grid} grid the grid whose state we'd like to restore
26491 * @param {object} groupingState the grouping state ready to be restored
26492 */
26493 restoreGrouping: function( grid, groupingState ) {
26494 if ( !grid.api.grouping || typeof(groupingState) === 'undefined' || groupingState === null || angular.equals(groupingState, {}) ) {
26495 return;
26496 }
26497
26498 grid.api.grouping.setGrouping( groupingState );
26499 },
26500
26501 /**
26502 * @ngdoc function
26503 * @name restoreTreeView
26504 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26505 * @description Restores the tree view configuration, if the tree view feature
26506 * is enabled.
26507 * @param {Grid} grid the grid whose state we'd like to restore
26508 * @param {object} treeViewState the tree view state ready to be restored
26509 */
26510 restoreTreeView: function( grid, treeViewState ) {
26511 if ( !grid.api.treeView || typeof(treeViewState) === 'undefined' || treeViewState === null || angular.equals(treeViewState, {}) ) {
26512 return;
26513 }
26514
26515 grid.api.treeView.setTreeView( treeViewState );
26516 },
26517
26518 /**
26519 * @ngdoc function
26520 * @name restorePagination
26521 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26522 * @description Restores the pagination information, if pagination is enabled.
26523 * @param {Grid} grid the grid whose state we'd like to restore
26524 * @param {object} pagination the pagination object to be restored
26525 * @param {number} pagination.paginationCurrentPage the page number to restore
26526 * @param {number} pagination.paginationPageSize the number of items displayed per page
26527 */
26528 restorePagination: function( grid, pagination ) {
26529 if ( !grid.api.pagination || !grid.options.paginationPageSize ) {
26530 return;
26531 }
26532
26533 grid.options.paginationCurrentPage = pagination.paginationCurrentPage;
26534 grid.options.paginationPageSize = pagination.paginationPageSize;
26535 },
26536
26537 /**
26538 * @ngdoc function
26539 * @name findRowByIdentity
26540 * @methodOf ui.grid.saveState.service:uiGridSaveStateService
26541 * @description Finds a row given it's identity value, returns the first found row
26542 * if any are found, otherwise returns null if no rows are found.
26543 * @param {Grid} grid the grid whose state we'd like to restore
26544 * @param {object} rowVal the row we'd like to find
26545 * @returns {gridRow} the found row, or null if none found
26546 */
26547 findRowByIdentity: function( grid, rowVal ) {
26548 if ( !grid.options.saveRowIdentity ) {
26549 return null;
26550 }
26551
26552 var filteredRows = grid.rows.filter( function( gridRow ) {
26553 return ( grid.options.saveRowIdentity( gridRow.entity ) === rowVal.row );
26554 });
26555
26556 if ( filteredRows.length > 0 ) {
26557 return filteredRows[0];
26558 } else {
26559 return null;
26560 }
26561 }
26562 };
26563
26564 return service;
26565 }
26566 );
26567
26568 /**
26569 * @ngdoc directive
26570 * @name ui.grid.saveState.directive:uiGridSaveState
26571 * @element div
26572 * @restrict A
26573 *
26574 * @description Adds saveState features to grid
26575 *
26576 * @example
26577 <example module="app">
26578 <file name="app.js">
26579 var app = angular.module('app', ['ui.grid', 'ui.grid.saveState']);
26580
26581 app.controller('MainCtrl', ['$scope', function ($scope) {
26582 $scope.data = [
26583 { name: 'Bob', title: 'CEO' },
26584 { name: 'Frank', title: 'Lowly Developer' }
26585 ];
26586
26587 $scope.gridOptions = {
26588 columnDefs: [
26589 {name: 'name'},
26590 {name: 'title', enableCellEdit: true}
26591 ],
26592 data: $scope.data
26593 };
26594 }]);
26595 </file>
26596 <file name="index.html">
26597 <div ng-controller="MainCtrl">
26598 <div ui-grid="gridOptions" ui-grid-save-state></div>
26599 </div>
26600 </file>
26601 </example>
26602 */
26603 module.directive('uiGridSaveState', ['uiGridSaveStateConstants', 'uiGridSaveStateService', 'gridUtil', '$compile',
26604 function (uiGridSaveStateConstants, uiGridSaveStateService, gridUtil, $compile) {
26605 return {
26606 replace: true,
26607 priority: 0,
26608 require: '^uiGrid',
26609 scope: false,
26610 link: function ($scope, $elm, $attrs, uiGridCtrl) {
26611 uiGridSaveStateService.initializeGrid(uiGridCtrl.grid);
26612 }
26613 };
26614 }
26615 ]);
26616 })();
26617
26618 (function () {
26619 'use strict';
26620
26621 /**
26622 * @ngdoc overview
26623 * @name ui.grid.selection
26624 * @description
26625 *
26626 * # ui.grid.selection
26627 * This module provides row selection
26628 *
26629 * <div class="alert alert-success" role="alert"><strong>Stable</strong> This feature is stable. There should no longer be breaking api changes without a deprecation warning.</div>
26630 *
26631 * <div doc-module-components="ui.grid.selection"></div>
26632 */
26633
26634 var module = angular.module('ui.grid.selection', ['ui.grid']);
26635
26636 /**
26637 * @ngdoc object
26638 * @name ui.grid.selection.constant:uiGridSelectionConstants
26639 *
26640 * @description constants available in selection module
26641 */
26642 module.constant('uiGridSelectionConstants', {
26643 featureName: 'selection',
26644 selectionRowHeaderColName: 'selectionRowHeaderCol'
26645 });
26646
26647 // add methods to GridRow
26648 angular.module('ui.grid').config(['$provide', function ($provide) {
26649 $provide.decorator('GridRow', ['$delegate', function ($delegate) {
26650
26651 /**
26652 * @ngdoc object
26653 * @name ui.grid.selection.api:GridRow
26654 *
26655 * @description GridRow prototype functions added for selection
26656 */
26657
26658 /**
26659 * @ngdoc object
26660 * @name enableSelection
26661 * @propertyOf ui.grid.selection.api:GridRow
26662 * @description Enable row selection for this row, only settable by internal code.
26663 *
26664 * The grouping feature, for example, might set group header rows to not be selectable.
26665 * <br/>Defaults to true
26666 */
26667
26668 /**
26669 * @ngdoc object
26670 * @name isSelected
26671 * @propertyOf ui.grid.selection.api:GridRow
26672 * @description Selected state of row. Should be readonly. Make any changes to selected state using setSelected().
26673 * <br/>Defaults to false
26674 */
26675
26676 /**
26677 * @ngdoc object
26678 * @name isFocused
26679 * @propertyOf ui.grid.selection.api:GridRow
26680 * @description Focused state of row. Should be readonly. Make any changes to focused state using setFocused().
26681 * <br/>Defaults to false
26682 */
26683
26684 /**
26685 * @ngdoc function
26686 * @name setSelected
26687 * @methodOf ui.grid.selection.api:GridRow
26688 * @description Sets the isSelected property and updates the selectedCount
26689 * Changes to isSelected state should only be made via this function
26690 * @param {Boolean} selected value to set
26691 */
26692 $delegate.prototype.setSelected = function (selected) {
26693 if (selected !== this.isSelected) {
26694 this.isSelected = selected;
26695 this.grid.selection.selectedCount += selected ? 1 : -1;
26696 }
26697 };
26698
26699 /**
26700 * @ngdoc function
26701 * @name setFocused
26702 * @methodOf ui.grid.selection.api:GridRow
26703 * @description Sets the isFocused property
26704 * Changes to isFocused state should only be made via this function
26705 * @param {Boolean} val value to set
26706 */
26707 $delegate.prototype.setFocused = function(val) {
26708 if (val !== this.isFocused) {
26709 this.grid.selection.focusedRow && (this.grid.selection.focusedRow.isFocused = false);
26710 this.grid.selection.focusedRow = val ? this : null;
26711 this.isFocused = val;
26712 }
26713 };
26714
26715 return $delegate;
26716 }]);
26717 }]);
26718
26719 /**
26720 * @ngdoc service
26721 * @name ui.grid.selection.service:uiGridSelectionService
26722 *
26723 * @description Services for selection features
26724 */
26725 module.service('uiGridSelectionService',
26726 function () {
26727 var service = {
26728
26729 initializeGrid: function (grid) {
26730
26731 // add feature namespace and any properties to grid for needed
26732 /**
26733 * @ngdoc object
26734 * @name ui.grid.selection.grid:selection
26735 *
26736 * @description Grid properties and functions added for selection
26737 */
26738 grid.selection = {
26739 lastSelectedRow: null,
26740 /**
26741 * @ngdoc object
26742 * @name focusedRow
26743 * @propertyOf ui.grid.selection.grid:selection
26744 * @description Focused row.
26745 */
26746 focusedRow: null,
26747 selectAll: false
26748 };
26749
26750
26751 /**
26752 * @ngdoc object
26753 * @name selectedCount
26754 * @propertyOf ui.grid.selection.grid:selection
26755 * @description Current count of selected rows
26756 * @example
26757 * var count = grid.selection.selectedCount
26758 */
26759 grid.selection.selectedCount = 0;
26760
26761 service.defaultGridOptions(grid.options);
26762
26763 /**
26764 * @ngdoc object
26765 * @name ui.grid.selection.api:PublicApi
26766 *
26767 * @description Public Api for selection feature
26768 */
26769 var publicApi = {
26770 events: {
26771 selection: {
26772 /**
26773 * @ngdoc event
26774 * @name rowFocusChanged
26775 * @eventOf ui.grid.selection.api:PublicApi
26776 * @description is raised after the row.isFocused state is changed
26777 * @param {object} scope the scope associated with the grid
26778 * @param {GridRow} row the row that was focused/unfocused
26779 * @param {Event} evt object if raised from an event
26780 */
26781 rowFocusChanged: function (scope, row, evt) {},
26782 /**
26783 * @ngdoc event
26784 * @name rowSelectionChanged
26785 * @eventOf ui.grid.selection.api:PublicApi
26786 * @description is raised after the row.isSelected state is changed
26787 * @param {object} scope the scope associated with the grid
26788 * @param {GridRow} row the row that was selected/deselected
26789 * @param {Event} evt object if raised from an event
26790 */
26791 rowSelectionChanged: function (scope, row, evt) {
26792 },
26793 /**
26794 * @ngdoc event
26795 * @name rowSelectionChangedBatch
26796 * @eventOf ui.grid.selection.api:PublicApi
26797 * @description is raised after the row.isSelected state is changed
26798 * in bulk, if the `enableSelectionBatchEvent` option is set to true
26799 * (which it is by default). This allows more efficient processing
26800 * of bulk events.
26801 * @param {object} scope the scope associated with the grid
26802 * @param {array} rows the rows that were selected/deselected
26803 * @param {Event} evt object if raised from an event
26804 */
26805 rowSelectionChangedBatch: function (scope, rows, evt) {
26806 }
26807 }
26808 },
26809 methods: {
26810 selection: {
26811 /**
26812 * @ngdoc function
26813 * @name toggleRowSelection
26814 * @methodOf ui.grid.selection.api:PublicApi
26815 * @description Toggles data row as selected or unselected
26816 * @param {object} rowEntity gridOptions.data[] array instance
26817 * @param {Event} evt object if raised from an event
26818 */
26819 toggleRowSelection: function (rowEntity, evt) {
26820 var row = grid.getRow(rowEntity);
26821 if (row !== null) {
26822 service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
26823 }
26824 },
26825 /**
26826 * @ngdoc function
26827 * @name selectRow
26828 * @methodOf ui.grid.selection.api:PublicApi
26829 * @description Select the data row
26830 * @param {object} rowEntity gridOptions.data[] array instance
26831 * @param {Event} evt object if raised from an event
26832 */
26833 selectRow: function (rowEntity, evt) {
26834 var row = grid.getRow(rowEntity);
26835 if (row !== null && !row.isSelected) {
26836 service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
26837 }
26838 },
26839 /**
26840 * @ngdoc function
26841 * @name selectRowByVisibleIndex
26842 * @methodOf ui.grid.selection.api:PublicApi
26843 * @description Select the specified row by visible index (i.e. if you
26844 * specify row 0 you'll get the first visible row selected). In this context
26845 * visible means of those rows that are theoretically visible (i.e. not filtered),
26846 * rather than rows currently rendered on the screen.
26847 * @param {number} rowNum index within the rowsVisible array
26848 * @param {Event} evt object if raised from an event
26849 */
26850 selectRowByVisibleIndex: function (rowNum, evt) {
26851 var row = grid.renderContainers.body.visibleRowCache[rowNum];
26852 if (row !== null && typeof (row) !== 'undefined' && !row.isSelected) {
26853 service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
26854 }
26855 },
26856 /**
26857 * @ngdoc function
26858 * @name unSelectRow
26859 * @methodOf ui.grid.selection.api:PublicApi
26860 * @description UnSelect the data row
26861 * @param {object} rowEntity gridOptions.data[] array instance
26862 * @param {Event} evt object if raised from an event
26863 */
26864 unSelectRow: function (rowEntity, evt) {
26865 var row = grid.getRow(rowEntity);
26866 if (row !== null && row.isSelected) {
26867 service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
26868 }
26869 },
26870 /**
26871 * @ngdoc function
26872 * @name unSelectRowByVisibleIndex
26873 * @methodOf ui.grid.selection.api:PublicApi
26874 * @description Unselect the specified row by visible index (i.e. if you
26875 * specify row 0 you'll get the first visible row unselected). In this context
26876 * visible means of those rows that are theoretically visible (i.e. not filtered),
26877 * rather than rows currently rendered on the screen.
26878 * @param {number} rowNum index within the rowsVisible array
26879 * @param {Event} evt object if raised from an event
26880 */
26881 unSelectRowByVisibleIndex: function (rowNum, evt) {
26882 var row = grid.renderContainers.body.visibleRowCache[rowNum];
26883 if (row !== null && typeof (row) !== 'undefined' && row.isSelected) {
26884 service.toggleRowSelection(grid, row, evt, grid.options.multiSelect, grid.options.noUnselect);
26885 }
26886 },
26887 /**
26888 * @ngdoc function
26889 * @name selectAllRows
26890 * @methodOf ui.grid.selection.api:PublicApi
26891 * @description Selects all rows. Does nothing if multiSelect = false
26892 * @param {Event} evt object if raised from an event
26893 */
26894 selectAllRows: function (evt) {
26895 if (grid.options.multiSelect !== false) {
26896 var changedRows = [];
26897 grid.rows.forEach(function (row) {
26898 if (!row.isSelected && row.enableSelection !== false && grid.options.isRowSelectable(row) !== false) {
26899 row.setSelected(true);
26900 service.decideRaiseSelectionEvent(grid, row, changedRows, evt);
26901 }
26902 });
26903 grid.selection.selectAll = true;
26904 service.decideRaiseSelectionBatchEvent(grid, changedRows, evt);
26905 }
26906 },
26907 /**
26908 * @ngdoc function
26909 * @name selectAllVisibleRows
26910 * @methodOf ui.grid.selection.api:PublicApi
26911 * @description Selects all visible rows. Does nothing if multiSelect = false
26912 * @param {Event} evt object if raised from an event
26913 */
26914 selectAllVisibleRows: function (evt) {
26915 if (grid.options.multiSelect !== false) {
26916 var changedRows = [];
26917 grid.rows.forEach(function(row) {
26918 if (row.visible) {
26919 if (!row.isSelected && row.enableSelection !== false && grid.options.isRowSelectable(row) !== false) {
26920 row.setSelected(true);
26921 service.decideRaiseSelectionEvent(grid, row, changedRows, evt);
26922 }
26923 } else if (row.isSelected) {
26924 row.setSelected(false);
26925 service.decideRaiseSelectionEvent(grid, row, changedRows, evt);
26926 }
26927 });
26928 grid.selection.selectAll = true;
26929 service.decideRaiseSelectionBatchEvent(grid, changedRows, evt);
26930 }
26931 },
26932 /**
26933 * @ngdoc function
26934 * @name clearSelectedRows
26935 * @methodOf ui.grid.selection.api:PublicApi
26936 * @description Unselects all rows
26937 * @param {Event} evt object if raised from an event
26938 */
26939 clearSelectedRows: function (evt) {
26940 service.clearSelectedRows(grid, evt);
26941 },
26942 /**
26943 * @ngdoc function
26944 * @name getSelectedRows
26945 * @methodOf ui.grid.selection.api:PublicApi
26946 * @description returns all selectedRow's entity references
26947 */
26948 getSelectedRows: function () {
26949 return service.getSelectedRows(grid).map(function (gridRow) {
26950 return gridRow.entity;
26951 }).filter(function (entity) {
26952 return entity.hasOwnProperty('$$hashKey') || !angular.isObject(entity);
26953 });
26954 },
26955 /**
26956 * @ngdoc function
26957 * @name getSelectedGridRows
26958 * @methodOf ui.grid.selection.api:PublicApi
26959 * @description returns all selectedRow's as gridRows
26960 */
26961 getSelectedGridRows: function () {
26962 return service.getSelectedRows(grid);
26963 },
26964 /**
26965 * @ngdoc function
26966 * @name getSelectedCount
26967 * @methodOf ui.grid.selection.api:PublicApi
26968 * @description returns the number of rows selected
26969 */
26970 getSelectedCount: function () {
26971 return grid.selection.selectedCount;
26972 },
26973 /**
26974 * @ngdoc function
26975 * @name setMultiSelect
26976 * @methodOf ui.grid.selection.api:PublicApi
26977 * @description Sets the current gridOption.multiSelect to true or false
26978 * @param {bool} multiSelect true to allow multiple rows
26979 */
26980 setMultiSelect: function (multiSelect) {
26981 grid.options.multiSelect = multiSelect;
26982 },
26983 /**
26984 * @ngdoc function
26985 * @name setModifierKeysToMultiSelect
26986 * @methodOf ui.grid.selection.api:PublicApi
26987 * @description Sets the current gridOption.modifierKeysToMultiSelect to true or false
26988 * @param {bool} modifierKeysToMultiSelect true to only allow multiple rows when using ctrlKey or shiftKey is used
26989 */
26990 setModifierKeysToMultiSelect: function (modifierKeysToMultiSelect) {
26991 grid.options.modifierKeysToMultiSelect = modifierKeysToMultiSelect;
26992 },
26993 /**
26994 * @ngdoc function
26995 * @name getSelectAllState
26996 * @methodOf ui.grid.selection.api:PublicApi
26997 * @description Returns whether or not the selectAll checkbox is currently ticked. The
26998 * grid doesn't automatically select rows when you add extra data - so when you add data
26999 * you need to explicitly check whether the selectAll is set, and then call setVisible rows
27000 * if it is
27001 */
27002 getSelectAllState: function () {
27003 return grid.selection.selectAll;
27004 }
27005
27006 }
27007 }
27008 };
27009
27010 grid.api.registerEventsFromObject(publicApi.events);
27011
27012 grid.api.registerMethodsFromObject(publicApi.methods);
27013
27014 },
27015
27016 defaultGridOptions: function (gridOptions) {
27017 // default option to true unless it was explicitly set to false
27018 /**
27019 * @ngdoc object
27020 * @name ui.grid.selection.api:GridOptions
27021 *
27022 * @description GridOptions for selection feature, these are available to be
27023 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
27024 */
27025
27026 /**
27027 * @ngdoc object
27028 * @name enableRowSelection
27029 * @propertyOf ui.grid.selection.api:GridOptions
27030 * @description Enable row selection for entire grid.
27031 * <br/>Defaults to true
27032 */
27033 gridOptions.enableRowSelection = gridOptions.enableRowSelection !== false;
27034 /**
27035 * @ngdoc object
27036 * @name multiSelect
27037 * @propertyOf ui.grid.selection.api:GridOptions
27038 * @description Enable multiple row selection for entire grid
27039 * <br/>Defaults to true
27040 */
27041 gridOptions.multiSelect = gridOptions.multiSelect !== false;
27042 /**
27043 * @ngdoc object
27044 * @name noUnselect
27045 * @propertyOf ui.grid.selection.api:GridOptions
27046 * @description Prevent a row from being unselected. Works in conjunction
27047 * with `multiselect = false` and `gridApi.selection.selectRow()` to allow
27048 * you to create a single selection only grid - a row is always selected, you
27049 * can only select different rows, you can't unselect the row.
27050 * <br/>Defaults to false
27051 */
27052 gridOptions.noUnselect = gridOptions.noUnselect === true;
27053 /**
27054 * @ngdoc object
27055 * @name modifierKeysToMultiSelect
27056 * @propertyOf ui.grid.selection.api:GridOptions
27057 * @description Enable multiple row selection only when using the ctrlKey or shiftKey. Requires multiSelect to be true.
27058 * <br/>Defaults to false
27059 */
27060 gridOptions.modifierKeysToMultiSelect = gridOptions.modifierKeysToMultiSelect === true;
27061 /**
27062 * @ngdoc object
27063 * @name enableRowHeaderSelection
27064 * @propertyOf ui.grid.selection.api:GridOptions
27065 * @description Enable a row header to be used for selection
27066 * <br/>Defaults to true
27067 */
27068 gridOptions.enableRowHeaderSelection = gridOptions.enableRowHeaderSelection !== false;
27069 /**
27070 * @ngdoc object
27071 * @name enableFullRowSelection
27072 * @propertyOf ui.grid.selection.api:GridOptions
27073 * @description Enable selection by clicking anywhere on the row. Defaults to
27074 * false if `enableRowHeaderSelection` is true, otherwise defaults to true.
27075 */
27076 if (typeof (gridOptions.enableFullRowSelection) === 'undefined') {
27077 gridOptions.enableFullRowSelection = !gridOptions.enableRowHeaderSelection;
27078 }
27079 /**
27080 * @ngdoc object
27081 * @name enableFocusRowOnRowHeaderClick
27082 * @propertyOf ui.grid.selection.api:GridOptions
27083 * @description Enable focuse row by clicking on the row header. Defaults to
27084 * true if `enableRowHeaderSelection` is true, otherwise defaults to false.
27085 */
27086 gridOptions.enableFocusRowOnRowHeaderClick = (gridOptions.enableFocusRowOnRowHeaderClick !== false)
27087 || !gridOptions.enableRowHeaderSelection;
27088 /**
27089 * @ngdoc object
27090 * @name enableSelectRowOnFocus
27091 * @propertyOf ui.grid.selection.api:GridOptions
27092 * @description Enable focuse row by clicking on the row anywhere. Defaults true.
27093 */
27094 gridOptions.enableSelectRowOnFocus = (gridOptions.enableSelectRowOnFocus !== false);
27095 /**
27096 * @ngdoc object
27097 * @name enableSelectAll
27098 * @propertyOf ui.grid.selection.api:GridOptions
27099 * @description Enable the select all checkbox at the top of the selectionRowHeader
27100 * <br/>Defaults to true
27101 */
27102 gridOptions.enableSelectAll = gridOptions.enableSelectAll !== false;
27103 /**
27104 * @ngdoc object
27105 * @name enableSelectionBatchEvent
27106 * @propertyOf ui.grid.selection.api:GridOptions
27107 * @description If selected rows are changed in bulk, either via the API or
27108 * via the selectAll checkbox, then a separate event is fired. Setting this
27109 * option to false will cause the rowSelectionChanged event to be called multiple times
27110 * instead
27111 * <br/>Defaults to true
27112 */
27113 gridOptions.enableSelectionBatchEvent = gridOptions.enableSelectionBatchEvent !== false;
27114 /**
27115 * @ngdoc object
27116 * @name selectionRowHeaderWidth
27117 * @propertyOf ui.grid.selection.api:GridOptions
27118 * @description can be used to set a custom width for the row header selection column
27119 * <br/>Defaults to 30px
27120 */
27121 gridOptions.selectionRowHeaderWidth = angular.isDefined(gridOptions.selectionRowHeaderWidth) ? gridOptions.selectionRowHeaderWidth : 30;
27122 /**
27123 * @ngdoc object
27124 * @name enableFooterTotalSelected
27125 * @propertyOf ui.grid.selection.api:GridOptions
27126 * @description Shows the total number of selected items in footer if true.
27127 * <br/>Defaults to true.
27128 * <br/>GridOptions.showGridFooter must also be set to true.
27129 */
27130 gridOptions.enableFooterTotalSelected = gridOptions.enableFooterTotalSelected !== false;
27131
27132 /**
27133 * @ngdoc object
27134 * @name isRowSelectable
27135 * @propertyOf ui.grid.selection.api:GridOptions
27136 * @description Makes it possible to specify a method that evaluates for each row and sets its "enableSelection" property.
27137 */
27138 gridOptions.isRowSelectable = angular.isDefined(gridOptions.isRowSelectable) ? gridOptions.isRowSelectable : angular.noop;
27139 },
27140
27141 /**
27142 * @ngdoc function
27143 * @name toggleRowSelection
27144 * @methodOf ui.grid.selection.service:uiGridSelectionService
27145 * @description Toggles row as selected or unselected
27146 * @param {Grid} grid grid object
27147 * @param {GridRow} row row to select or deselect
27148 * @param {Event} evt object if resulting from event
27149 * @param {bool} multiSelect if false, only one row at time can be selected
27150 * @param {bool} noUnselect if true then rows cannot be unselected
27151 */
27152 toggleRowSelection: function (grid, row, evt, multiSelect, noUnselect) {
27153 if ( row.enableSelection === false ) {
27154 return;
27155 }
27156
27157 var selected = row.isSelected,
27158 selectedRows;
27159
27160 if (!multiSelect) {
27161 if (!selected) {
27162 service.clearSelectedRows(grid, evt);
27163 }
27164 else {
27165 selectedRows = service.getSelectedRows(grid);
27166 if (selectedRows.length > 1) {
27167 selected = false; // Enable reselect of the row
27168 service.clearSelectedRows(grid, evt);
27169 }
27170 }
27171 }
27172
27173 // only select row in this case
27174 if (!(selected && noUnselect)) {
27175 row.setSelected(!selected);
27176 if (row.isSelected === true) {
27177 grid.selection.lastSelectedRow = row;
27178 }
27179
27180 selectedRows = service.getSelectedRows(grid);
27181 grid.selection.selectAll = grid.rows.length === selectedRows.length;
27182
27183 grid.api.selection.raise.rowSelectionChanged(row, evt);
27184 }
27185 },
27186 /**
27187 * @ngdoc function
27188 * @name shiftSelect
27189 * @methodOf ui.grid.selection.service:uiGridSelectionService
27190 * @description selects a group of rows from the last selected row using the shift key
27191 * @param {Grid} grid grid object
27192 * @param {GridRow} row clicked row
27193 * @param {Event} evt object if raised from an event
27194 * @param {bool} multiSelect if false, does nothing this is for multiSelect only
27195 */
27196 shiftSelect: function (grid, row, evt, multiSelect) {
27197 if (!multiSelect) {
27198 return;
27199 }
27200 var selectedRows = service.getSelectedRows(grid);
27201 var fromRow = selectedRows.length > 0 ? grid.renderContainers.body.visibleRowCache.indexOf(grid.selection.lastSelectedRow) : 0;
27202 var toRow = grid.renderContainers.body.visibleRowCache.indexOf(row);
27203 // reverse select direction
27204 if (fromRow > toRow) {
27205 var tmp = fromRow;
27206 fromRow = toRow;
27207 toRow = tmp;
27208 }
27209
27210 var changedRows = [];
27211 for (var i = fromRow; i <= toRow; i++) {
27212 var rowToSelect = grid.renderContainers.body.visibleRowCache[i];
27213 if (rowToSelect) {
27214 if (!rowToSelect.isSelected && rowToSelect.enableSelection !== false) {
27215 rowToSelect.setSelected(true);
27216 grid.selection.lastSelectedRow = rowToSelect;
27217 service.decideRaiseSelectionEvent(grid, rowToSelect, changedRows, evt);
27218 }
27219 }
27220 }
27221 service.decideRaiseSelectionBatchEvent(grid, changedRows, evt);
27222 },
27223 /**
27224 * @ngdoc function
27225 * @name getSelectedRows
27226 * @methodOf ui.grid.selection.service:uiGridSelectionService
27227 * @description Returns all the selected rows
27228 * @param {Grid} grid grid object
27229 */
27230 getSelectedRows: function (grid) {
27231 return grid.rows.filter(function (row) {
27232 return row.isSelected;
27233 });
27234 },
27235
27236 /**
27237 * @ngdoc function
27238 * @name clearSelectedRows
27239 * @methodOf ui.grid.selection.service:uiGridSelectionService
27240 * @description Clears all selected rows
27241 * @param {Grid} grid grid object
27242 * @param {Event} evt object if raised from an event
27243 */
27244 clearSelectedRows: function (grid, evt) {
27245 var changedRows = [];
27246 service.getSelectedRows(grid).forEach(function (row) {
27247 if (row.isSelected) {
27248 row.setSelected(false);
27249 service.decideRaiseSelectionEvent(grid, row, changedRows, evt);
27250 }
27251 });
27252 grid.selection.selectAll = false;
27253 grid.selection.selectedCount = 0;
27254 service.decideRaiseSelectionBatchEvent(grid, changedRows, evt);
27255 },
27256
27257 /**
27258 * @ngdoc function
27259 * @name decideRaiseSelectionEvent
27260 * @methodOf ui.grid.selection.service:uiGridSelectionService
27261 * @description Decides whether to raise a single event or a batch event
27262 * @param {Grid} grid grid object
27263 * @param {GridRow} row row that has changed
27264 * @param {array} changedRows an array to which we can append the changed
27265 * @param {Event} evt object if raised from an event
27266 * row if we're doing batch events
27267 */
27268 decideRaiseSelectionEvent: function (grid, row, changedRows, evt) {
27269 if (!grid.options.enableSelectionBatchEvent) {
27270 grid.api.selection.raise.rowSelectionChanged(row, evt);
27271 }
27272 else {
27273 changedRows.push(row);
27274 }
27275 },
27276
27277 /**
27278 * @ngdoc function
27279 * @name raiseSelectionEvent
27280 * @methodOf ui.grid.selection.service:uiGridSelectionService
27281 * @description Decides whether we need to raise a batch event, and
27282 * raises it if we do.
27283 * @param {Grid} grid grid object
27284 * @param {array} changedRows an array of changed rows, only populated
27285 * @param {Event} evt object if raised from an event
27286 * if we're doing batch events
27287 */
27288 decideRaiseSelectionBatchEvent: function (grid, changedRows, evt) {
27289 if (changedRows.length > 0) {
27290 grid.api.selection.raise.rowSelectionChangedBatch(changedRows, evt);
27291 }
27292 }
27293 };
27294
27295 return service;
27296 });
27297
27298 /**
27299 * @ngdoc directive
27300 * @name ui.grid.selection.directive:uiGridSelection
27301 * @element div
27302 * @restrict A
27303 *
27304 * @description Adds selection features to grid
27305 *
27306 * @example
27307 <example module="app">
27308 <file name="app.js">
27309 var app = angular.module('app', ['ui.grid', 'ui.grid.selection']);
27310
27311 app.controller('MainCtrl', ['$scope', function ($scope) {
27312 $scope.data = [
27313 { name: 'Bob', title: 'CEO' },
27314 { name: 'Frank', title: 'Lowly Developer' }
27315 ];
27316
27317 $scope.columnDefs = [
27318 {name: 'name', enableCellEdit: true},
27319 {name: 'title', enableCellEdit: true}
27320 ];
27321 }]);
27322 </file>
27323 <file name="index.html">
27324 <div ng-controller="MainCtrl">
27325 <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-selection></div>
27326 </div>
27327 </file>
27328 </example>
27329 */
27330 module.directive('uiGridSelection', ['uiGridSelectionConstants', 'uiGridSelectionService', 'uiGridConstants',
27331 function (uiGridSelectionConstants, uiGridSelectionService, uiGridConstants) {
27332 return {
27333 replace: true,
27334 priority: 0,
27335 require: '^uiGrid',
27336 scope: false,
27337 compile: function () {
27338 return {
27339 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
27340 uiGridSelectionService.initializeGrid(uiGridCtrl.grid);
27341 if (uiGridCtrl.grid.options.enableRowHeaderSelection) {
27342 var selectionRowHeaderDef = {
27343 name: uiGridSelectionConstants.selectionRowHeaderColName,
27344 displayName: '',
27345 width: uiGridCtrl.grid.options.selectionRowHeaderWidth,
27346 minWidth: 10,
27347 cellTemplate: 'ui-grid/selectionRowHeader',
27348 headerCellTemplate: 'ui-grid/selectionHeaderCell',
27349 enableColumnResizing: false,
27350 enableColumnMenu: false,
27351 exporterSuppressExport: true,
27352 allowCellFocus: true
27353 };
27354
27355 uiGridCtrl.grid.addRowHeaderColumn(selectionRowHeaderDef, 0);
27356 }
27357
27358 var processorSet = false;
27359
27360 var processSelectableRows = function (rows) {
27361 rows.forEach(function (row) {
27362 row.enableSelection = uiGridCtrl.grid.options.isRowSelectable(row);
27363 });
27364 return rows;
27365 };
27366
27367 var updateOptions = function () {
27368 if (uiGridCtrl.grid.options.isRowSelectable !== angular.noop && processorSet !== true) {
27369 uiGridCtrl.grid.registerRowsProcessor(processSelectableRows, 500);
27370 processorSet = true;
27371 }
27372 };
27373
27374 updateOptions();
27375
27376 var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(updateOptions, [uiGridConstants.dataChange.OPTIONS]);
27377
27378 $scope.$on('$destroy', dataChangeDereg);
27379 },
27380 post: function ($scope, $elm, $attrs, uiGridCtrl) {
27381
27382 }
27383 };
27384 }
27385 };
27386 }]);
27387
27388 module.directive('uiGridSelectionRowHeaderButtons', ['$templateCache', 'uiGridSelectionService', 'gridUtil',
27389 function ($templateCache, uiGridSelectionService, gridUtil) {
27390 return {
27391 replace: true,
27392 restrict: 'E',
27393 template: $templateCache.get('ui-grid/selectionRowHeaderButtons'),
27394 scope: true,
27395 require: '^uiGrid',
27396 link: function ($scope, $elm, $attrs, uiGridCtrl) {
27397 var self = uiGridCtrl.grid;
27398 $scope.selectButtonClick = selectButtonClick;
27399 $scope.selectButtonKeyDown = selectButtonKeyDown;
27400
27401 // On IE, prevent mousedowns on the select button from starting a selection.
27402 // If this is not done and you shift+click on another row, the browser will select a big chunk of text
27403 if (gridUtil.detectBrowser() === 'ie') {
27404 $elm.on('mousedown', selectButtonMouseDown);
27405 }
27406
27407 function selectButtonKeyDown(row, evt) {
27408 if (evt.keyCode === 32) {
27409 evt.preventDefault();
27410 selectButtonClick(row, evt);
27411 }
27412 }
27413
27414 function selectButtonClick(row, evt) {
27415 evt.stopPropagation();
27416
27417 if (evt.shiftKey) {
27418 uiGridSelectionService.shiftSelect(self, row, evt, self.options.multiSelect);
27419 }
27420 else if (evt.ctrlKey || evt.metaKey) {
27421 uiGridSelectionService.toggleRowSelection(self, row, evt,
27422 self.options.multiSelect, self.options.noUnselect);
27423 }
27424 else if (row.groupHeader) {
27425 uiGridSelectionService.toggleRowSelection(self, row, evt, self.options.multiSelect, self.options.noUnselect);
27426 for (var i = 0; i < row.treeNode.children.length; i++) {
27427 uiGridSelectionService.toggleRowSelection(self, row.treeNode.children[i].row, evt, self.options.multiSelect, self.options.noUnselect);
27428 }
27429 }
27430 else {
27431 uiGridSelectionService.toggleRowSelection(self, row, evt,
27432 (self.options.multiSelect && !self.options.modifierKeysToMultiSelect), self.options.noUnselect);
27433 }
27434 self.options.enableFocusRowOnRowHeaderClick && row.setFocused(!row.isFocused) && self.api.selection.raise.rowFocusChanged(row, evt);
27435 }
27436
27437 function selectButtonMouseDown(evt) {
27438 if (evt.ctrlKey || evt.shiftKey) {
27439 evt.target.onselectstart = function () { return false; };
27440 window.setTimeout(function () { evt.target.onselectstart = null; }, 0);
27441 }
27442 }
27443
27444 $scope.$on('$destroy', function unbindEvents() {
27445 $elm.off();
27446 });
27447 }
27448 };
27449 }]);
27450
27451 module.directive('uiGridSelectionSelectAllButtons', ['$templateCache', 'uiGridSelectionService',
27452 function ($templateCache, uiGridSelectionService) {
27453 return {
27454 replace: true,
27455 restrict: 'E',
27456 template: $templateCache.get('ui-grid/selectionSelectAllButtons'),
27457 scope: false,
27458 link: function ($scope) {
27459 var self = $scope.col.grid;
27460
27461 $scope.headerButtonKeyDown = function (evt) {
27462 if (evt.keyCode === 32 || evt.keyCode === 13) {
27463 evt.preventDefault();
27464 $scope.headerButtonClick(evt);
27465 }
27466 };
27467
27468 $scope.headerButtonClick = function (evt) {
27469 if (self.selection.selectAll) {
27470 uiGridSelectionService.clearSelectedRows(self, evt);
27471 if (self.options.noUnselect) {
27472 self.api.selection.selectRowByVisibleIndex(0, evt);
27473 }
27474 self.selection.selectAll = false;
27475 }
27476 else if (self.options.multiSelect) {
27477 self.api.selection.selectAllVisibleRows(evt);
27478 self.selection.selectAll = true;
27479 }
27480 };
27481 }
27482 };
27483 }]);
27484
27485 /**
27486 * @ngdoc directive
27487 * @name ui.grid.selection.directive:uiGridViewport
27488 * @element div
27489 *
27490 * @description Stacks on top of ui.grid.uiGridViewport to alter the attributes used
27491 * for the grid row
27492 */
27493 module.directive('uiGridViewport',
27494 function () {
27495 return {
27496 priority: -200, // run after default directive
27497 scope: false,
27498 compile: function ($elm) {
27499 var rowRepeatDiv = angular.element($elm[0].querySelector('.ui-grid-canvas:not(.ui-grid-empty-base-layer-container)').children[0]),
27500 newNgClass = "'ui-grid-row-selected': row.isSelected, 'ui-grid-row-focused': row.isFocused}",
27501 existingNgClass = rowRepeatDiv.attr('ng-class');
27502
27503 if (existingNgClass) {
27504 newNgClass = existingNgClass.slice(0, -1) + ',' + newNgClass;
27505 } else {
27506 newNgClass = '{' + newNgClass;
27507 }
27508 rowRepeatDiv.attr('ng-class', newNgClass);
27509
27510 return {
27511 pre: function ($scope, $elm, $attrs, controllers) {},
27512 post: function ($scope, $elm, $attrs, controllers) {}
27513 };
27514 }
27515 };
27516 });
27517
27518 /**
27519 * @ngdoc directive
27520 * @name ui.grid.selection.directive:uiGridCell
27521 * @element div
27522 * @restrict A
27523 *
27524 * @description Stacks on top of ui.grid.uiGridCell to provide selection feature
27525 */
27526 module.directive('uiGridCell',
27527 ['uiGridConstants', 'uiGridSelectionService',
27528 function (uiGridConstants, uiGridSelectionService) {
27529 return {
27530 priority: -200, // run after default uiGridCell directive
27531 restrict: 'A',
27532 require: '?^uiGrid',
27533 scope: false,
27534 link: function ($scope, $elm, $attrs, uiGridCtrl) {
27535 var touchStartTime = 0,
27536 touchTimeout = 300;
27537
27538 // Bind to keydown events in the render container
27539 if (uiGridCtrl.grid.api.cellNav) {
27540 uiGridCtrl.grid.api.cellNav.on.viewPortKeyDown($scope, function (evt, rowCol) {
27541 if (rowCol === null ||
27542 rowCol.row !== $scope.row ||
27543 rowCol.col !== $scope.col) {
27544 return;
27545 }
27546
27547 if (evt.keyCode === uiGridConstants.keymap.SPACE && $scope.col.colDef.name === 'selectionRowHeaderCol') {
27548 evt.preventDefault();
27549 uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
27550 ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect),
27551 $scope.grid.options.noUnselect);
27552 $scope.$apply();
27553 }
27554 });
27555 }
27556
27557 var selectCells = function (evt) {
27558 // if you click on expandable icon doesn't trigger selection
27559 if (evt.target.className === "ui-grid-icon-minus-squared" || evt.target.className === "ui-grid-icon-plus-squared") {
27560 return;
27561 }
27562
27563 // if we get a click, then stop listening for touchend
27564 $elm.off('touchend', touchEnd);
27565
27566 if (evt.shiftKey) {
27567 uiGridSelectionService.shiftSelect($scope.grid, $scope.row, evt, $scope.grid.options.multiSelect);
27568 }
27569 else if (evt.ctrlKey || evt.metaKey) {
27570 uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
27571 $scope.grid.options.multiSelect, $scope.grid.options.noUnselect);
27572 }
27573 else if ($scope.grid.options.enableSelectRowOnFocus) {
27574 uiGridSelectionService.toggleRowSelection($scope.grid, $scope.row, evt,
27575 ($scope.grid.options.multiSelect && !$scope.grid.options.modifierKeysToMultiSelect),
27576 $scope.grid.options.noUnselect);
27577 }
27578 $scope.row.setFocused(!$scope.row.isFocused);
27579 $scope.grid.api.selection.raise.rowFocusChanged($scope.row, evt);
27580 $scope.$apply();
27581
27582 // don't re-enable the touchend handler for a little while - some devices generate both, and it will
27583 // take a little while to move your hand from the mouse to the screen if you have both modes of input
27584 window.setTimeout(function () {
27585 $elm.on('touchend', touchEnd);
27586 }, touchTimeout);
27587 };
27588
27589 var touchStart = function () {
27590 touchStartTime = (new Date()).getTime();
27591
27592 // if we get a touch event, then stop listening for click
27593 $elm.off('click', selectCells);
27594 };
27595
27596 var touchEnd = function (evt) {
27597 var touchEndTime = (new Date()).getTime();
27598 var touchTime = touchEndTime - touchStartTime;
27599
27600 if (touchTime < touchTimeout) {
27601 // short touch
27602 selectCells(evt);
27603 }
27604
27605 // don't re-enable the click handler for a little while - some devices generate both, and it will
27606 // take a little while to move your hand from the screen to the mouse if you have both modes of input
27607 window.setTimeout(function () {
27608 $elm.on('click', selectCells);
27609 }, touchTimeout);
27610 };
27611
27612 function registerRowSelectionEvents() {
27613 if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection && $scope.col.colDef.name !== 'selectionRowHeaderCol') {
27614 $elm.addClass('ui-grid-disable-selection');
27615 $elm.on('touchstart', touchStart);
27616 $elm.on('touchend', touchEnd);
27617 $elm.on('click', selectCells);
27618
27619 $scope.registered = true;
27620 }
27621 }
27622
27623 function unregisterRowSelectionEvents() {
27624 if ($scope.registered) {
27625 $elm.removeClass('ui-grid-disable-selection');
27626 $elm.off('touchstart', touchStart);
27627 $elm.off('touchend', touchEnd);
27628 $elm.off('click', selectCells);
27629
27630 $scope.registered = false;
27631 }
27632 }
27633
27634 registerRowSelectionEvents();
27635
27636 // register a dataChange callback so that we can change the selection configuration dynamically
27637 // if the user changes the options
27638 var dataChangeUnreg = $scope.grid.registerDataChangeCallback(function () {
27639 if ($scope.grid.options.enableRowSelection && $scope.grid.options.enableFullRowSelection &&
27640 !$scope.registered) {
27641 registerRowSelectionEvents();
27642 }
27643 else if ((!$scope.grid.options.enableRowSelection || !$scope.grid.options.enableFullRowSelection) &&
27644 $scope.registered) {
27645 unregisterRowSelectionEvents();
27646 }
27647 }, [uiGridConstants.dataChange.OPTIONS]);
27648
27649 $elm.on('$destroy', dataChangeUnreg);
27650 }
27651 };
27652 }]);
27653
27654 module.directive('uiGridGridFooter', ['$compile', 'gridUtil', function ($compile, gridUtil) {
27655 return {
27656 restrict: 'EA',
27657 replace: true,
27658 priority: -1000,
27659 require: '^uiGrid',
27660 scope: true,
27661 compile: function () {
27662 return {
27663 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
27664 if (!uiGridCtrl.grid.options.showGridFooter) {
27665 return;
27666 }
27667
27668 gridUtil.getTemplate('ui-grid/gridFooterSelectedItems')
27669 .then(function (contents) {
27670 var template = angular.element(contents);
27671
27672 var newElm = $compile(template)($scope);
27673
27674 angular.element($elm[0].getElementsByClassName('ui-grid-grid-footer')[0]).append(newElm);
27675 });
27676 },
27677 post: function ($scope, $elm, $attrs, controllers) {
27678
27679 }
27680 };
27681 }
27682 };
27683 }]);
27684 })();
27685
27686 (function () {
27687 'use strict';
27688
27689 /**
27690 * @ngdoc overview
27691 * @name ui.grid.treeBase
27692 * @description
27693 *
27694 * # ui.grid.treeBase
27695 *
27696 * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
27697 *
27698 * This module provides base tree handling functions that are shared by other features, notably grouping
27699 * and treeView. It provides a tree view of the data, with nodes in that
27700 * tree and leaves.
27701 *
27702 * Design information:
27703 * -------------------
27704 *
27705 * The raw data that is provided must come with a $$treeLevel on any non-leaf node. Grouping will create
27706 * these on all the group header rows, treeView will expect these to be set in the raw data by the user.
27707 * TreeBase will run a rowsProcessor that:
27708 * - builds `treeBase.tree` out of the provided rows
27709 * - permits a recursive sort of the tree
27710 * - maintains the expand/collapse state of each node
27711 * - provides the expand/collapse all button and the expand/collapse buttons
27712 * - maintains the count of children for each node
27713 *
27714 * Each row is updated with a link to the tree node that represents it. Refer {@link ui.grid.treeBase.grid:treeBase.tree tree documentation}
27715 * for information.
27716 *
27717 * TreeBase adds information to the rows
27718 * - treeLevel: if present and > -1 tells us the level (level 0 is the top level)
27719 * - treeNode: pointer to the node in the grid.treeBase.tree that refers
27720 * to this row, allowing us to manipulate the state
27721 *
27722 * Since the logic is baked into the rowsProcessors, it should get triggered whenever
27723 * row order or filtering or anything like that is changed. We recall the expanded state
27724 * across invocations of the rowsProcessors by the reference to the treeNode on the individual
27725 * rows. We rebuild the tree itself quite frequently, when we do this we use the saved treeNodes to
27726 * get the state, but we overwrite the other data in that treeNode.
27727 *
27728 * By default rows are collapsed, which means all data rows have their visible property
27729 * set to false, and only level 0 group rows are set to visible.
27730 *
27731 * We rely on the rowsProcessors to do the actual expanding and collapsing, so we set the flags we want into
27732 * grid.treeBase.tree, then call refresh. This is because we can't easily change the visible
27733 * row cache without calling the processors, and once we've built the logic into the rowProcessors we may as
27734 * well use it all the time.
27735 *
27736 * Tree base provides sorting (on non-grouped columns).
27737 *
27738 * Sorting works in two passes. The standard sorting is performed for any columns that are important to building
27739 * the tree (for example, any grouped columns). Then after the tree is built, a recursive tree sort is performed
27740 * for the remaining sort columns (including the original sort) - these columns are sorted within each tree level
27741 * (so all the level 1 nodes are sorted, then all the level 2 nodes within each level 1 node etc).
27742 *
27743 * To achieve this we make use of the `ignoreSort` property on the sort configuration. The parent feature (treeView or grouping)
27744 * must provide a rowsProcessor that runs with very low priority (typically in the 60-65 range), and that sets
27745 * the `ignoreSort`on any sort that it wants to run on the tree. TreeBase will clear the ignoreSort on all sorts - so it
27746 * will turn on any sorts that haven't run. It will then call a recursive sort on the tree.
27747 *
27748 * Tree base provides treeAggregation. It checks the treeAggregation configuration on each column, and aggregates based on
27749 * the logic provided as it builds the tree. Footer aggregation from the uiGrid core should not be used with treeBase aggregation,
27750 * since it operates on all visible rows, as opposed to to leaf nodes only. Setting `showColumnFooter: true` will show the
27751 * treeAggregations in the column footer. Aggregation information will be collected in the format:
27752 *
27753 * ```
27754 * {
27755 * type: 'count',
27756 * value: 4,
27757 * label: 'count: ',
27758 * rendered: 'count: 4'
27759 * }
27760 * ```
27761 *
27762 * A callback is provided to format the value once it is finalised (aka a valueFilter).
27763 *
27764 * <br/>
27765 * <br/>
27766 *
27767 * <div doc-module-components="ui.grid.treeBase"></div>
27768 */
27769
27770 var module = angular.module('ui.grid.treeBase', ['ui.grid']);
27771
27772 /**
27773 * @ngdoc object
27774 * @name ui.grid.treeBase.constant:uiGridTreeBaseConstants
27775 *
27776 * @description constants available in treeBase module.
27777 *
27778 * These constants are manually copied into grouping and treeView,
27779 * as I haven't found a way to simply include them, and it's not worth
27780 * investing time in for something that changes very infrequently.
27781 *
27782 */
27783 module.constant('uiGridTreeBaseConstants', {
27784 featureName: "treeBase",
27785 rowHeaderColName: 'treeBaseRowHeaderCol',
27786 EXPANDED: 'expanded',
27787 COLLAPSED: 'collapsed',
27788 aggregation: {
27789 COUNT: 'count',
27790 SUM: 'sum',
27791 MAX: 'max',
27792 MIN: 'min',
27793 AVG: 'avg'
27794 }
27795 });
27796
27797 /**
27798 * @ngdoc service
27799 * @name ui.grid.treeBase.service:uiGridTreeBaseService
27800 *
27801 * @description Services for treeBase feature
27802 */
27803 /**
27804 * @ngdoc object
27805 * @name ui.grid.treeBase.api:ColumnDef
27806 *
27807 * @description ColumnDef for tree feature, these are available to be
27808 * set using the ui-grid {@link ui.grid.class:GridOptions.columnDef gridOptions.columnDefs}
27809 */
27810
27811 module.service('uiGridTreeBaseService', ['$q', 'uiGridTreeBaseConstants', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants', 'rowSorter',
27812 function ($q, uiGridTreeBaseConstants, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants, rowSorter) {
27813
27814 var service = {
27815
27816 initializeGrid: function (grid) {
27817
27818 // add feature namespace and any properties to grid for needed
27819 /**
27820 * @ngdoc object
27821 * @name ui.grid.treeBase.grid:treeBase
27822 *
27823 * @description Grid properties and functions added for treeBase
27824 */
27825 grid.treeBase = {};
27826
27827 /**
27828 * @ngdoc property
27829 * @propertyOf ui.grid.treeBase.grid:treeBase
27830 * @name numberLevels
27831 *
27832 * @description Total number of tree levels currently used, calculated by the rowsProcessor by
27833 * retaining the highest tree level it sees
27834 */
27835 grid.treeBase.numberLevels = 0;
27836
27837 /**
27838 * @ngdoc property
27839 * @propertyOf ui.grid.treeBase.grid:treeBase
27840 * @name expandAll
27841 *
27842 * @description Whether or not the expandAll box is selected
27843 */
27844 grid.treeBase.expandAll = false;
27845
27846 /**
27847 * @ngdoc property
27848 * @propertyOf ui.grid.treeBase.grid:treeBase
27849 * @name tree
27850 *
27851 * @description Tree represented as a nested array that holds the state of each node, along with a
27852 * pointer to the row. The array order is material - we will display the children in the order
27853 * they are stored in the array
27854 *
27855 * Each node stores:
27856 *
27857 * - the state of this node
27858 * - an array of children of this node
27859 * - a pointer to the parent of this node (reverse pointer, allowing us to walk up the tree)
27860 * - the number of children of this node
27861 * - aggregation information calculated from the nodes
27862 *
27863 * ```
27864 * [{
27865 * state: 'expanded',
27866 * row: <reference to row>,
27867 * parentRow: null,
27868 * aggregations: [{
27869 * type: 'count',
27870 * col: <gridCol>,
27871 * value: 2,
27872 * label: 'count: ',
27873 * rendered: 'count: 2'
27874 * }],
27875 * children: [
27876 * {
27877 * state: 'expanded',
27878 * row: <reference to row>,
27879 * parentRow: <reference to row>,
27880 * aggregations: [{
27881 * type: 'count',
27882 * col: '<gridCol>,
27883 * value: 4,
27884 * label: 'count: ',
27885 * rendered: 'count: 4'
27886 * }],
27887 * children: [
27888 * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
27889 * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },
27890 * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
27891 * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> }
27892 * ]
27893 * },
27894 * {
27895 * state: 'collapsed',
27896 * row: <reference to row>,
27897 * parentRow: <reference to row>,
27898 * aggregations: [{
27899 * type: 'count',
27900 * col: <gridCol>,
27901 * value: 3,
27902 * label: 'count: ',
27903 * rendered: 'count: 3'
27904 * }],
27905 * children: [
27906 * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> },
27907 * { state: 'collapsed', row: <reference to row>, parentRow: <reference to row> },
27908 * { state: 'expanded', row: <reference to row>, parentRow: <reference to row> }
27909 * ]
27910 * }
27911 * ]
27912 * }, {<another level 0 node maybe>} ]
27913 * ```
27914 * Missing state values are false - meaning they aren't expanded.
27915 *
27916 * This is used because the rowProcessors run every time the grid is refreshed, so
27917 * we'd lose the expanded state every time the grid was refreshed. This instead gives
27918 * us a reliable lookup that persists across rowProcessors.
27919 *
27920 * This tree is rebuilt every time we run the rowsProcessors. Since each row holds a pointer
27921 * to it's tree node we can persist expand/collapse state across calls to rowsProcessor, we discard
27922 * all transient information on the tree (children, childCount) and recalculate it
27923 *
27924 */
27925 grid.treeBase.tree = [];
27926
27927 service.defaultGridOptions(grid.options);
27928
27929 grid.registerRowsProcessor(service.treeRows, 410);
27930
27931 grid.registerColumnBuilder( service.treeBaseColumnBuilder );
27932
27933 service.createRowHeader( grid );
27934
27935 /**
27936 * @ngdoc object
27937 * @name ui.grid.treeBase.api:PublicApi
27938 *
27939 * @description Public Api for treeBase feature
27940 */
27941 var publicApi = {
27942 events: {
27943 treeBase: {
27944 /**
27945 * @ngdoc event
27946 * @eventOf ui.grid.treeBase.api:PublicApi
27947 * @name rowExpanded
27948 * @description raised whenever a row is expanded. If you are dynamically
27949 * rendering your tree you can listen to this event, and then retrieve
27950 * the children of this row and load them into the grid data.
27951 *
27952 * When the data is loaded the grid will automatically refresh to show these new rows
27953 *
27954 * <pre>
27955 * gridApi.treeBase.on.rowExpanded(scope,function(row) {})
27956 * </pre>
27957 * @param {gridRow} row the row that was expanded. You can also
27958 * retrieve the grid from this row with row.grid
27959 */
27960 rowExpanded: {},
27961
27962 /**
27963 * @ngdoc event
27964 * @eventOf ui.grid.treeBase.api:PublicApi
27965 * @name rowCollapsed
27966 * @description raised whenever a row is collapsed. Doesn't really have
27967 * a purpose at the moment, included for symmetry
27968 *
27969 * <pre>
27970 * gridApi.treeBase.on.rowCollapsed(scope,function(row) {})
27971 * </pre>
27972 * @param {gridRow} row the row that was collapsed. You can also
27973 * retrieve the grid from this row with row.grid
27974 */
27975 rowCollapsed: {}
27976 }
27977 },
27978
27979 methods: {
27980 treeBase: {
27981 /**
27982 * @ngdoc function
27983 * @name expandAllRows
27984 * @methodOf ui.grid.treeBase.api:PublicApi
27985 * @description Expands all tree rows
27986 */
27987 expandAllRows: function () {
27988 service.expandAllRows(grid);
27989 },
27990
27991 /**
27992 * @ngdoc function
27993 * @name collapseAllRows
27994 * @methodOf ui.grid.treeBase.api:PublicApi
27995 * @description collapse all tree rows
27996 */
27997 collapseAllRows: function () {
27998 service.collapseAllRows(grid);
27999 },
28000
28001 /**
28002 * @ngdoc function
28003 * @name toggleRowTreeState
28004 * @methodOf ui.grid.treeBase.api:PublicApi
28005 * @description call expand if the row is collapsed, collapse if it is expanded
28006 * @param {gridRow} row the row you wish to toggle
28007 */
28008 toggleRowTreeState: function (row) {
28009 service.toggleRowTreeState(grid, row);
28010 },
28011
28012 /**
28013 * @ngdoc function
28014 * @name expandRow
28015 * @methodOf ui.grid.treeBase.api:PublicApi
28016 * @description expand the immediate children of the specified row
28017 * @param {gridRow} row the row you wish to expand
28018 * @param {boolean} recursive true if you wish to expand the row's ancients
28019 */
28020 expandRow: function (row, recursive) {
28021 service.expandRow(grid, row, recursive);
28022 },
28023
28024 /**
28025 * @ngdoc function
28026 * @name expandRowChildren
28027 * @methodOf ui.grid.treeBase.api:PublicApi
28028 * @description expand all children of the specified row
28029 * @param {gridRow} row the row you wish to expand
28030 */
28031 expandRowChildren: function (row) {
28032 service.expandRowChildren(grid, row);
28033 },
28034
28035 /**
28036 * @ngdoc function
28037 * @name collapseRow
28038 * @methodOf ui.grid.treeBase.api:PublicApi
28039 * @description collapse the specified row. When
28040 * you expand the row again, all grandchildren will retain their state
28041 * @param {gridRow} row the row you wish to collapse
28042 */
28043 collapseRow: function ( row ) {
28044 service.collapseRow(grid, row);
28045 },
28046
28047 /**
28048 * @ngdoc function
28049 * @name collapseRowChildren
28050 * @methodOf ui.grid.treeBase.api:PublicApi
28051 * @description collapse all children of the specified row. When
28052 * you expand the row again, all grandchildren will be collapsed
28053 * @param {gridRow} row the row you wish to collapse children for
28054 */
28055 collapseRowChildren: function ( row ) {
28056 service.collapseRowChildren(grid, row);
28057 },
28058
28059 /**
28060 * @ngdoc function
28061 * @name getTreeState
28062 * @methodOf ui.grid.treeBase.api:PublicApi
28063 * @description Get the tree state for this grid,
28064 * used by the saveState feature
28065 * Returned treeState as an object
28066 * `{ expandedState: { uid: 'expanded', uid: 'collapsed' } }`
28067 * where expandedState is a hash of row uid and the current expanded state
28068 *
28069 * @returns {object} tree state
28070 *
28071 * TODO - this needs work - we need an identifier that persists across instantiations,
28072 * not uid. This really means we need a row identity defined, but that won't work for
28073 * grouping. Perhaps this needs to be moved up to treeView and grouping, rather than
28074 * being in base.
28075 */
28076 getTreeExpandedState: function () {
28077 return { expandedState: service.getTreeState(grid) };
28078 },
28079
28080 /**
28081 * @ngdoc function
28082 * @name setTreeState
28083 * @methodOf ui.grid.treeBase.api:PublicApi
28084 * @description Set the expanded states of the tree
28085 * @param {object} config the config you want to apply, in the format
28086 * provided by getTreeState
28087 */
28088 setTreeState: function ( config ) {
28089 service.setTreeState( grid, config );
28090 },
28091
28092 /**
28093 * @ngdoc function
28094 * @name getRowChildren
28095 * @methodOf ui.grid.treeBase.api:PublicApi
28096 * @description Get the children of the specified row
28097 * @param {GridRow} row the row you want the children of
28098 * @returns {Array} array of children of this row, the children
28099 * are all gridRows
28100 */
28101 getRowChildren: function ( row ) {
28102 return row.treeNode.children.map( function( childNode ) {
28103 return childNode.row;
28104 });
28105 }
28106 }
28107 }
28108 };
28109
28110 grid.api.registerEventsFromObject(publicApi.events);
28111
28112 grid.api.registerMethodsFromObject(publicApi.methods);
28113 },
28114
28115
28116 defaultGridOptions: function (gridOptions) {
28117 // default option to true unless it was explicitly set to false
28118 /**
28119 * @ngdoc object
28120 * @name ui.grid.treeBase.api:GridOptions
28121 *
28122 * @description GridOptions for treeBase feature, these are available to be
28123 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
28124 */
28125
28126 /**
28127 * @ngdoc object
28128 * @name treeRowHeaderBaseWidth
28129 * @propertyOf ui.grid.treeBase.api:GridOptions
28130 * @description Base width of the tree header, provides for a single level of tree. This
28131 * is incremented by `treeIndent` for each extra level
28132 * <br/>Defaults to 30
28133 */
28134 gridOptions.treeRowHeaderBaseWidth = gridOptions.treeRowHeaderBaseWidth || 30;
28135
28136 /**
28137 * @ngdoc object
28138 * @name treeIndent
28139 * @propertyOf ui.grid.treeBase.api:GridOptions
28140 * @description Number of pixels of indent for the icon at each tree level, wider indents are visually more pleasing,
28141 * but will make the tree row header wider
28142 * <br/>Defaults to 10
28143 */
28144 gridOptions.treeIndent = (gridOptions.treeIndent != null) ? gridOptions.treeIndent : 10;
28145
28146 /**
28147 * @ngdoc object
28148 * @name showTreeRowHeader
28149 * @propertyOf ui.grid.treeBase.api:GridOptions
28150 * @description If set to false, don't create the row header. You'll need to programmatically control the expand
28151 * states
28152 * <br/>Defaults to true
28153 */
28154 gridOptions.showTreeRowHeader = gridOptions.showTreeRowHeader !== false;
28155
28156 /**
28157 * @ngdoc object
28158 * @name showTreeExpandNoChildren
28159 * @propertyOf ui.grid.treeBase.api:GridOptions
28160 * @description If set to true, show the expand/collapse button even if there are no
28161 * children of a node. You'd use this if you're planning to dynamically load the children
28162 *
28163 * <br/>Defaults to true, grouping overrides to false
28164 */
28165 gridOptions.showTreeExpandNoChildren = gridOptions.showTreeExpandNoChildren !== false;
28166
28167 /**
28168 * @ngdoc object
28169 * @name treeRowHeaderAlwaysVisible
28170 * @propertyOf ui.grid.treeBase.api:GridOptions
28171 * @description If set to true, row header even if there are no tree nodes
28172 *
28173 * <br/>Defaults to true
28174 */
28175 gridOptions.treeRowHeaderAlwaysVisible = gridOptions.treeRowHeaderAlwaysVisible !== false;
28176
28177 /**
28178 * @ngdoc object
28179 * @name treeCustomAggregations
28180 * @propertyOf ui.grid.treeBase.api:GridOptions
28181 * @description Define custom aggregation functions. The properties of this object will be
28182 * aggregation types available for use on columnDef with {@link ui.grid.treeBase.api:ColumnDef treeAggregationType} or through the column menu.
28183 * If a function defined here uses the same name as one of the native aggregations, this one will take precedence.
28184 * The object format is:
28185 *
28186 * <pre>
28187 * {
28188 * aggregationName: {
28189 * label: (optional) string,
28190 * aggregationFn: function( aggregation, fieldValue, numValue, row ) {...},
28191 * finalizerFn: (optional) function( aggregation ) {...}
28192 * },
28193 * mean: {
28194 * label: 'mean',
28195 * aggregationFn: function( aggregation, fieldValue, numValue ) {
28196 * aggregation.count = (aggregation.count || 1) + 1;
28197 * aggregation.sum = (aggregation.sum || 0) + numValue;
28198 * },
28199 * finalizerFn: function( aggregation ) {
28200 * aggregation.value = aggregation.sum / aggregation.count
28201 * }
28202 * }
28203 * }
28204 * </pre>
28205 *
28206 * <br/>The `finalizerFn` may be used to manipulate the value before rendering, or to
28207 * apply a custom rendered value. If `aggregation.rendered` is left undefined, the value will be
28208 * rendered. Note that the native aggregation functions use an `finalizerFn` to concatenate
28209 * the label and the value.
28210 *
28211 * <br/>Defaults to {}
28212 */
28213 gridOptions.treeCustomAggregations = gridOptions.treeCustomAggregations || {};
28214
28215 /**
28216 * @ngdoc object
28217 * @name enableExpandAll
28218 * @propertyOf ui.grid.treeBase.api:GridOptions
28219 * @description Enable the expand all button at the top of the row header
28220 *
28221 * <br/>Defaults to true
28222 */
28223 gridOptions.enableExpandAll = gridOptions.enableExpandAll !== false;
28224 },
28225
28226
28227 /**
28228 * @ngdoc function
28229 * @name treeBaseColumnBuilder
28230 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28231 * @description Sets the tree defaults based on the columnDefs
28232 *
28233 * @param {object} colDef columnDef we're basing on
28234 * @param {GridColumn} col the column we're to update
28235 * @param {object} gridOptions the options we should use
28236 * @returns {promise} promise for the builder - actually we do it all inline so it's immediately resolved
28237 */
28238 treeBaseColumnBuilder: function (colDef, col, gridOptions) {
28239
28240
28241 /**
28242 * @ngdoc object
28243 * @name customTreeAggregationFn
28244 * @propertyOf ui.grid.treeBase.api:ColumnDef
28245 * @description A custom function that aggregates rows into some form of
28246 * total. Aggregations run row-by-row, the function needs to be capable of
28247 * creating a running total.
28248 *
28249 * The function will be provided the aggregation item (in which you can store running
28250 * totals), the row value that is to be aggregated, and that same row value converted to
28251 * a number (most aggregations work on numbers)
28252 * @example
28253 * <pre>
28254 * customTreeAggregationFn = function ( aggregation, fieldValue, numValue, row ) {
28255 * // calculates the average of the squares of the values
28256 * if ( typeof(aggregation.count) === 'undefined' ) {
28257 * aggregation.count = 0;
28258 * }
28259 * aggregation.count++;
28260 *
28261 * if ( !isNaN(numValue) ) {
28262 * if ( typeof(aggregation.total) === 'undefined' ) {
28263 * aggregation.total = 0;
28264 * }
28265 * aggregation.total = aggregation.total + numValue * numValue;
28266 * }
28267 *
28268 * aggregation.value = aggregation.total / aggregation.count;
28269 * }
28270 * </pre>
28271 * <br/>Defaults to undefined. May be overwritten by treeAggregationType, the two options should not be used together.
28272 */
28273 if ( typeof(colDef.customTreeAggregationFn) !== 'undefined' ) {
28274 col.treeAggregationFn = colDef.customTreeAggregationFn;
28275 }
28276
28277 /**
28278 * @ngdoc object
28279 * @name treeAggregationType
28280 * @propertyOf ui.grid.treeBase.api:ColumnDef
28281 * @description Use one of the native or grid-level aggregation methods for calculating aggregations on this column.
28282 * Native method are in the constants file and include: SUM, COUNT, MIN, MAX, AVG. This may also be the property the
28283 * name of an aggregation function defined with {@link ui.grid.treeBase.api:GridOptions treeCustomAggregations}.
28284 *
28285 * <pre>
28286 * treeAggregationType = uiGridTreeBaseConstants.aggregation.SUM,
28287 * }
28288 * </pre>
28289 *
28290 * If you are using aggregations you should either:
28291 *
28292 * - also use grouping, in which case the aggregations are displayed in the group header, OR
28293 * - use treeView, in which case you can set `treeAggregationUpdateEntity: true` in the colDef, and
28294 * treeBase will store the aggregation information in the entity, or you can set `treeAggregationUpdateEntity: false`
28295 * in the colDef, and you need to manual retrieve the calculated aggregations from the row.treeNode.aggregations
28296 *
28297 * <br/>Takes precendence over a treeAggregationFn, the two options should not be used together.
28298 * <br/>Defaults to undefined.
28299 */
28300 if ( typeof(colDef.treeAggregationType) !== 'undefined' ) {
28301 col.treeAggregation = { type: colDef.treeAggregationType };
28302 if ( typeof(gridOptions.treeCustomAggregations[colDef.treeAggregationType]) !== 'undefined' ) {
28303 col.treeAggregationFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].aggregationFn;
28304 col.treeAggregationFinalizerFn = gridOptions.treeCustomAggregations[colDef.treeAggregationType].finalizerFn;
28305 col.treeAggregation.label = gridOptions.treeCustomAggregations[colDef.treeAggregationType].label;
28306 }
28307 else if ( typeof(service.nativeAggregations()[colDef.treeAggregationType]) !== 'undefined' ) {
28308 col.treeAggregationFn = service.nativeAggregations()[colDef.treeAggregationType].aggregationFn;
28309 col.treeAggregation.label = service.nativeAggregations()[colDef.treeAggregationType].label;
28310 }
28311 }
28312
28313 /**
28314 * @ngdoc object
28315 * @name treeAggregationLabel
28316 * @propertyOf ui.grid.treeBase.api:ColumnDef
28317 * @description A custom label to use for this aggregation. If provided we don't use native i18n.
28318 */
28319 if ( typeof(colDef.treeAggregationLabel) !== 'undefined' ) {
28320 if (typeof(col.treeAggregation) === 'undefined' ) {
28321 col.treeAggregation = {};
28322 }
28323 col.treeAggregation.label = colDef.treeAggregationLabel;
28324 }
28325
28326 /**
28327 * @ngdoc object
28328 * @name treeAggregationUpdateEntity
28329 * @propertyOf ui.grid.treeBase.api:ColumnDef
28330 * @description Store calculated aggregations into the entity, allowing them
28331 * to be displayed in the grid using a standard cellTemplate. This defaults to true,
28332 * if you are using grouping then you shouldn't set it to false, as then the aggregations won't
28333 * display.
28334 *
28335 * If you are using treeView in most cases you'll want to set this to true. This will result in
28336 * getCellValue returning the aggregation rather than whatever was stored in the cell attribute on
28337 * the entity. If you want to render the underlying entity value (and do something else with the aggregation)
28338 * then you could use a custom cellTemplate to display `row.entity.myAttribute`, rather than using getCellValue.
28339 *
28340 * <br/>Defaults to true
28341 *
28342 * @example
28343 * <pre>
28344 * gridOptions.columns = [{
28345 * name: 'myCol',
28346 * treeAggregation: { type: uiGridTreeBaseConstants.aggregation.SUM },
28347 * treeAggregationUpdateEntity: true
28348 * cellTemplate: '<div>{{row.entity.myCol + " " + row.treeNode.aggregations[0].rendered}}</div>'
28349 * }];
28350 * </pre>
28351 */
28352 col.treeAggregationUpdateEntity = colDef.treeAggregationUpdateEntity !== false;
28353
28354 /**
28355 * @ngdoc object
28356 * @name customTreeAggregationFinalizerFn
28357 * @propertyOf ui.grid.treeBase.api:ColumnDef
28358 * @description A custom function that populates aggregation.rendered, this is called when
28359 * a particular aggregation has been fully calculated, and we want to render the value.
28360 *
28361 * With the native aggregation options we just concatenate `aggregation.label` and
28362 * `aggregation.value`, but if you wanted to apply a filter or otherwise manipulate the label
28363 * or the value, you can do so with this function. This function will be called after the
28364 * the default `finalizerFn`.
28365 *
28366 * @example
28367 * <pre>
28368 * customTreeAggregationFinalizerFn = function ( aggregation ) {
28369 * aggregation.rendered = aggregation.label + aggregation.value / 100 + '%';
28370 * }
28371 * </pre>
28372 * <br/>Defaults to undefined.
28373 */
28374 if ( typeof(col.customTreeAggregationFinalizerFn) === 'undefined' ) {
28375 col.customTreeAggregationFinalizerFn = colDef.customTreeAggregationFinalizerFn;
28376 }
28377
28378 },
28379
28380
28381 /**
28382 * @ngdoc function
28383 * @name createRowHeader
28384 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28385 * @description Create the rowHeader. If treeRowHeaderAlwaysVisible then
28386 * set it to visible, otherwise set it to invisible
28387 *
28388 * @param {Grid} grid grid object
28389 */
28390 createRowHeader: function( grid ) {
28391 var rowHeaderColumnDef = {
28392 name: uiGridTreeBaseConstants.rowHeaderColName,
28393 displayName: '',
28394 width: grid.options.treeRowHeaderBaseWidth,
28395 minWidth: 10,
28396 cellTemplate: 'ui-grid/treeBaseRowHeader',
28397 headerCellTemplate: 'ui-grid/treeBaseHeaderCell',
28398 enableColumnResizing: false,
28399 enableColumnMenu: false,
28400 exporterSuppressExport: true,
28401 allowCellFocus: true
28402 };
28403
28404 rowHeaderColumnDef.visible = grid.options.treeRowHeaderAlwaysVisible;
28405 grid.addRowHeaderColumn(rowHeaderColumnDef, -100);
28406 },
28407
28408
28409 /**
28410 * @ngdoc function
28411 * @name expandAllRows
28412 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28413 * @description Expands all nodes in the tree
28414 *
28415 * @param {Grid} grid grid object
28416 */
28417 expandAllRows: function (grid) {
28418 grid.treeBase.tree.forEach( function( node ) {
28419 service.setAllNodes( grid, node, uiGridTreeBaseConstants.EXPANDED);
28420 });
28421 grid.treeBase.expandAll = true;
28422 grid.queueGridRefresh();
28423 },
28424
28425
28426 /**
28427 * @ngdoc function
28428 * @name collapseAllRows
28429 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28430 * @description Collapses all nodes in the tree
28431 *
28432 * @param {Grid} grid grid object
28433 */
28434 collapseAllRows: function (grid) {
28435 grid.treeBase.tree.forEach( function( node ) {
28436 service.setAllNodes( grid, node, uiGridTreeBaseConstants.COLLAPSED);
28437 });
28438 grid.treeBase.expandAll = false;
28439 grid.queueGridRefresh();
28440 },
28441
28442
28443 /**
28444 * @ngdoc function
28445 * @name setAllNodes
28446 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28447 * @description Works through a subset of grid.treeBase.rowExpandedStates, setting
28448 * all child nodes (and their descendents) of the provided node to the given state.
28449 *
28450 * Calls itself recursively on all nodes so as to achieve this.
28451 *
28452 * @param {Grid} grid the grid we're operating on (so we can raise events)
28453 * @param {object} treeNode a node in the tree that we want to update
28454 * @param {string} targetState the state we want to set it to
28455 */
28456 setAllNodes: function (grid, treeNode, targetState) {
28457 if ( typeof(treeNode.state) !== 'undefined' && treeNode.state !== targetState ) {
28458 treeNode.state = targetState;
28459
28460 if ( targetState === uiGridTreeBaseConstants.EXPANDED ) {
28461 grid.api.treeBase.raise.rowExpanded(treeNode.row);
28462 }
28463 else {
28464 grid.api.treeBase.raise.rowCollapsed(treeNode.row);
28465 }
28466 }
28467
28468 // set all child nodes
28469 if ( treeNode.children ) {
28470 treeNode.children.forEach(function( childNode ) {
28471 service.setAllNodes(grid, childNode, targetState);
28472 });
28473 }
28474 },
28475
28476
28477 /**
28478 * @ngdoc function
28479 * @name toggleRowTreeState
28480 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28481 * @description Toggles the expand or collapse state of this grouped row, if
28482 * it's a parent row
28483 *
28484 * @param {Grid} grid grid object
28485 * @param {GridRow} row the row we want to toggle
28486 */
28487 toggleRowTreeState: function ( grid, row ) {
28488 if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) {
28489 return;
28490 }
28491
28492 if (row.treeNode.state === uiGridTreeBaseConstants.EXPANDED) {
28493 service.collapseRow(grid, row);
28494 }
28495 else {
28496 service.expandRow(grid, row, false);
28497 }
28498
28499 grid.queueGridRefresh();
28500 },
28501
28502
28503 /**
28504 * @ngdoc function
28505 * @name expandRow
28506 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28507 * @description Expands this specific row, showing only immediate children.
28508 *
28509 * @param {Grid} grid grid object
28510 * @param {GridRow} row the row we want to expand
28511 * @param {boolean} recursive true if you wish to expand the row's ancients
28512 */
28513 expandRow: function ( grid, row, recursive ) {
28514 if ( recursive ) {
28515 var parents = [];
28516 while ( row && typeof(row.treeLevel) !== 'undefined' && row.treeLevel !== null && row.treeLevel >= 0 && row.treeNode.state !== uiGridTreeBaseConstants.EXPANDED ) {
28517 parents.push(row);
28518 row = row.treeNode.parentRow;
28519 }
28520
28521 if ( parents.length > 0 ) {
28522 row = parents.pop();
28523 while ( row ) {
28524 row.treeNode.state = uiGridTreeBaseConstants.EXPANDED;
28525 grid.api.treeBase.raise.rowExpanded(row);
28526 row = parents.pop();
28527 }
28528
28529 grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
28530 grid.queueGridRefresh();
28531 }
28532 }
28533 else {
28534 if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) {
28535 return;
28536 }
28537
28538 if ( row.treeNode.state !== uiGridTreeBaseConstants.EXPANDED ) {
28539 row.treeNode.state = uiGridTreeBaseConstants.EXPANDED;
28540 grid.api.treeBase.raise.rowExpanded(row);
28541 grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
28542 grid.queueGridRefresh();
28543 }
28544 }
28545 },
28546
28547
28548 /**
28549 * @ngdoc function
28550 * @name expandRowChildren
28551 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28552 * @description Expands this specific row, showing all children.
28553 *
28554 * @param {Grid} grid grid object
28555 * @param {GridRow} row the row we want to expand
28556 */
28557 expandRowChildren: function ( grid, row ) {
28558 if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) {
28559 return;
28560 }
28561
28562 service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.EXPANDED);
28563 grid.treeBase.expandAll = service.allExpanded(grid.treeBase.tree);
28564 grid.queueGridRefresh();
28565 },
28566
28567
28568 /**
28569 * @ngdoc function
28570 * @name collapseRow
28571 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28572 * @description Collapses this specific row
28573 *
28574 * @param {Grid} grid grid object
28575 * @param {GridRow} row the row we want to collapse
28576 */
28577 collapseRow: function( grid, row ) {
28578 if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) {
28579 return;
28580 }
28581
28582 if ( row.treeNode.state !== uiGridTreeBaseConstants.COLLAPSED ) {
28583 row.treeNode.state = uiGridTreeBaseConstants.COLLAPSED;
28584 grid.treeBase.expandAll = false;
28585 grid.api.treeBase.raise.rowCollapsed(row);
28586 grid.queueGridRefresh();
28587 }
28588 },
28589
28590
28591 /**
28592 * @ngdoc function
28593 * @name collapseRowChildren
28594 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28595 * @description Collapses this specific row and all children
28596 *
28597 * @param {Grid} grid grid object
28598 * @param {GridRow} row the row we want to collapse
28599 */
28600 collapseRowChildren: function( grid, row ) {
28601 if ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) {
28602 return;
28603 }
28604
28605 service.setAllNodes(grid, row.treeNode, uiGridTreeBaseConstants.COLLAPSED);
28606 grid.treeBase.expandAll = false;
28607 grid.queueGridRefresh();
28608 },
28609
28610
28611 /**
28612 * @ngdoc function
28613 * @name allExpanded
28614 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28615 * @description Returns true if all rows are expanded, false
28616 * if they're not. Walks the tree to determine this. Used
28617 * to set the expandAll state.
28618 *
28619 * If the node has no children, then return true (it's immaterial
28620 * whether it is expanded). If the node has children, then return
28621 * false if this node is collapsed, or if any child node is not all expanded
28622 *
28623 * @param {object} tree the grid to check
28624 * @returns {boolean} whether or not the tree is all expanded
28625 */
28626 allExpanded: function( tree ) {
28627 var allExpanded = true;
28628
28629 tree.forEach(function( node ) {
28630 if ( !service.allExpandedInternal( node ) ) {
28631 allExpanded = false;
28632 }
28633 });
28634 return allExpanded;
28635 },
28636
28637 allExpandedInternal: function( treeNode ) {
28638 if ( treeNode.children && treeNode.children.length > 0 ) {
28639 if ( treeNode.state === uiGridTreeBaseConstants.COLLAPSED ) {
28640 return false;
28641 }
28642 var allExpanded = true;
28643 treeNode.children.forEach( function( node ) {
28644 if ( !service.allExpandedInternal( node ) ) {
28645 allExpanded = false;
28646 }
28647 });
28648 return allExpanded;
28649 }
28650 else {
28651 return true;
28652 }
28653 },
28654
28655
28656 /**
28657 * @ngdoc function
28658 * @name treeRows
28659 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28660 * @description The rowProcessor that adds the nodes to the tree, and sets the visible
28661 * state of each row based on it's parent state
28662 *
28663 * Assumes it is always called after the sorting processor, and the grouping processor if there is one.
28664 * Performs any tree sorts itself after having built the tree
28665 *
28666 * Processes all the rows in order, setting the group level based on the $$treeLevel in the associated
28667 * entity, and setting the visible state based on the parent's state.
28668 *
28669 * Calculates the deepest level of tree whilst it goes, and updates that so that the header column can be correctly
28670 * sized.
28671 *
28672 * Aggregates if necessary along the way.
28673 *
28674 * @param {array} renderableRows the rows we want to process, usually the output from the previous rowProcessor
28675 * @returns {array} the updated rows
28676 */
28677 treeRows: function( renderableRows ) {
28678 var grid = this;
28679
28680 if (renderableRows.length === 0) {
28681 service.updateRowHeaderWidth( grid );
28682 return renderableRows;
28683 }
28684
28685 grid.treeBase.tree = service.createTree( grid, renderableRows );
28686 service.updateRowHeaderWidth( grid );
28687
28688 service.sortTree( grid );
28689 service.fixFilter( grid );
28690
28691 return service.renderTree( grid.treeBase.tree );
28692 },
28693
28694
28695 /**
28696 * @ngdoc function
28697 * @name createOrUpdateRowHeaderWidth
28698 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28699 * @description Calculates the rowHeader width.
28700 *
28701 * If rowHeader is always present, updates the width.
28702 *
28703 * If rowHeader is only sometimes present (`treeRowHeaderAlwaysVisible: false`), determines whether there
28704 * should be one, then creates or removes it as appropriate, with the created rowHeader having the
28705 * right width.
28706 *
28707 * If there's never a rowHeader then never creates one: `showTreeRowHeader: false`
28708 *
28709 * @param {Grid} grid the grid we want to set the row header on
28710 */
28711 updateRowHeaderWidth: function( grid ) {
28712 var rowHeader = grid.getColumn(uiGridTreeBaseConstants.rowHeaderColName),
28713 newWidth = grid.options.treeRowHeaderBaseWidth + grid.options.treeIndent * Math.max(grid.treeBase.numberLevels - 1, 0);
28714
28715 if ( rowHeader && newWidth !== rowHeader.width ) {
28716 rowHeader.width = newWidth;
28717 grid.queueRefresh();
28718 }
28719
28720 var newVisibility = true;
28721
28722 if ( grid.options.showTreeRowHeader === false ) {
28723 newVisibility = false;
28724 }
28725 if ( grid.options.treeRowHeaderAlwaysVisible === false && grid.treeBase.numberLevels <= 0 ) {
28726 newVisibility = false;
28727 }
28728 if ( rowHeader && rowHeader.visible !== newVisibility ) {
28729 rowHeader.visible = newVisibility;
28730 rowHeader.colDef.visible = newVisibility;
28731 grid.queueGridRefresh();
28732 }
28733 },
28734
28735
28736 /**
28737 * @ngdoc function
28738 * @name renderTree
28739 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28740 * @description Creates an array of rows based on the tree, exporting only
28741 * the visible nodes and leaves
28742 *
28743 * @param {array} nodeList The list of nodes - can be grid.treeBase.tree, or can be node.children when
28744 * we're calling recursively
28745 * @returns {array} renderable rows
28746 */
28747 renderTree: function( nodeList ) {
28748 var renderableRows = [];
28749
28750 nodeList.forEach( function ( node ) {
28751 if ( node.row.visible ) {
28752 renderableRows.push( node.row );
28753 }
28754 if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ) {
28755 renderableRows = renderableRows.concat( service.renderTree( node.children ) );
28756 }
28757 });
28758 return renderableRows;
28759 },
28760
28761
28762 /**
28763 * @ngdoc function
28764 * @name createTree
28765 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28766 * @description Creates a tree from the renderableRows
28767 *
28768 * @param {Grid} grid The grid
28769 * @param {array} renderableRows The rows we want to create a tree from
28770 * @returns {object} The tree we've build
28771 */
28772 createTree: function( grid, renderableRows ) {
28773 var currentLevel = -1,
28774 parents = [],
28775 currentState;
28776
28777 grid.treeBase.tree = [];
28778 grid.treeBase.numberLevels = 0;
28779
28780 var aggregations = service.getAggregations( grid );
28781
28782 function createNode( row ) {
28783 if ( typeof(row.entity.$$treeLevel) !== 'undefined' && row.treeLevel !== row.entity.$$treeLevel ) {
28784 row.treeLevel = row.entity.$$treeLevel;
28785 }
28786
28787 if ( row.treeLevel <= currentLevel ) {
28788 // pop any levels that aren't parents of this level, formatting the aggregation at the same time
28789 while ( row.treeLevel <= currentLevel ) {
28790 var lastParent = parents.pop();
28791 service.finaliseAggregations( lastParent );
28792 currentLevel--;
28793 }
28794
28795 // reset our current state based on the new parent, set to expanded if this is a level 0 node
28796 if ( parents.length > 0 ) {
28797 currentState = service.setCurrentState(parents);
28798 }
28799 else {
28800 currentState = uiGridTreeBaseConstants.EXPANDED;
28801 }
28802 }
28803
28804 // aggregate if this is a leaf node
28805 if ( ( typeof(row.treeLevel) === 'undefined' || row.treeLevel === null || row.treeLevel < 0 ) && row.visible ) {
28806 service.aggregate( grid, row, parents );
28807 }
28808
28809 // add this node to the tree
28810 service.addOrUseNode(grid, row, parents, aggregations);
28811
28812 if ( typeof(row.treeLevel) !== 'undefined' && row.treeLevel !== null && row.treeLevel >= 0 ) {
28813 parents.push(row);
28814 currentLevel++;
28815 currentState = service.setCurrentState(parents);
28816 }
28817
28818 // update the tree number of levels, so we can set header width if we need to
28819 if ( grid.treeBase.numberLevels < row.treeLevel + 1) {
28820 grid.treeBase.numberLevels = row.treeLevel + 1;
28821 }
28822 }
28823
28824 renderableRows.forEach( createNode );
28825
28826 // finalize remaining aggregations
28827 while ( parents.length > 0 ) {
28828 var lastParent = parents.pop();
28829 service.finaliseAggregations( lastParent );
28830 }
28831
28832 return grid.treeBase.tree;
28833 },
28834
28835
28836 /**
28837 * @ngdoc function
28838 * @name addOrUseNode
28839 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28840 * @description Creates a tree node for this row. If this row already has a treeNode
28841 * recorded against it, preserves the state, but otherwise overwrites the data.
28842 *
28843 * @param {grid} grid The grid we're operating on
28844 * @param {gridRow} row The row we want to set
28845 * @param {array} parents An array of the parents this row should have
28846 * @param {array} aggregationBase Empty aggregation information
28847 * @returns {undefined} Updates the parents array, updates the row to have a treeNode, and updates the
28848 * grid.treeBase.tree
28849 */
28850 addOrUseNode: function( grid, row, parents, aggregationBase ) {
28851 var newAggregations = [];
28852 aggregationBase.forEach( function(aggregation) {
28853 newAggregations.push(service.buildAggregationObject(aggregation.col));
28854 });
28855
28856 var newNode = { state: uiGridTreeBaseConstants.COLLAPSED, row: row, parentRow: null, aggregations: newAggregations, children: [] };
28857 if ( row.treeNode ) {
28858 newNode.state = row.treeNode.state;
28859 }
28860 if ( parents.length > 0 ) {
28861 newNode.parentRow = parents[parents.length - 1];
28862 }
28863 row.treeNode = newNode;
28864
28865 if ( parents.length === 0 ) {
28866 grid.treeBase.tree.push( newNode );
28867 } else {
28868 parents[parents.length - 1].treeNode.children.push( newNode );
28869 }
28870 },
28871
28872
28873 /**
28874 * @ngdoc function
28875 * @name setCurrentState
28876 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28877 * @description Looks at the parents array to determine our current state.
28878 * If any node in the hierarchy is collapsed, then return collapsed, otherwise return
28879 * expanded.
28880 *
28881 * @param {array} parents An array of the parents this row should have
28882 * @returns {string} The state we should be setting to any nodes we see
28883 */
28884 setCurrentState: function( parents ) {
28885 var currentState = uiGridTreeBaseConstants.EXPANDED;
28886
28887 parents.forEach( function(parent) {
28888 if ( parent.treeNode.state === uiGridTreeBaseConstants.COLLAPSED ) {
28889 currentState = uiGridTreeBaseConstants.COLLAPSED;
28890 }
28891 });
28892 return currentState;
28893 },
28894
28895
28896 /**
28897 * @ngdoc function
28898 * @name sortTree
28899 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28900 * @description Performs a recursive sort on the tree nodes, sorting the
28901 * children of each node and putting them back into the children array.
28902 *
28903 * Before doing this it turns back on all the sortIgnore - things that were previously
28904 * ignored we process now. Since we're sorting within the nodes, presumably anything
28905 * that was already sorted is how we derived the nodes, we can keep those sorts too.
28906 *
28907 * We only sort tree nodes that are expanded - no point in wasting effort sorting collapsed
28908 * nodes
28909 *
28910 * @param {Grid} grid The grid to get the aggregation information from
28911 * @returns {array} The aggregation information
28912 */
28913 sortTree: function( grid ) {
28914 grid.columns.forEach( function( column ) {
28915 if ( column.sort && column.sort.ignoreSort ) {
28916 delete column.sort.ignoreSort;
28917 }
28918 });
28919
28920 grid.treeBase.tree = service.sortInternal( grid, grid.treeBase.tree );
28921 },
28922
28923 sortInternal: function( grid, treeList ) {
28924 var rows = treeList.map( function( node ) {
28925 return node.row;
28926 });
28927
28928 rows = rowSorter.sort( grid, rows, grid.columns );
28929
28930 var treeNodes = rows.map( function( row ) {
28931 return row.treeNode;
28932 });
28933
28934 treeNodes.forEach( function( node ) {
28935 if ( node.state === uiGridTreeBaseConstants.EXPANDED && node.children && node.children.length > 0 ) {
28936 node.children = service.sortInternal( grid, node.children );
28937 }
28938 });
28939
28940 return treeNodes;
28941 },
28942
28943 /**
28944 * @ngdoc function
28945 * @name fixFilter
28946 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28947 * @description After filtering has run, we need to go back through the tree
28948 * and make sure the parent rows are always visible if any of the child rows
28949 * are visible (filtering may make a child visible, but the parent may not
28950 * match the filter criteria)
28951 *
28952 * This has a risk of being computationally expensive, we do it by walking
28953 * the tree and remembering whether there are any invisible nodes on the
28954 * way down.
28955 *
28956 * @param {Grid} grid the grid to fix filters on
28957 */
28958 fixFilter: function( grid ) {
28959 var parentsVisible;
28960
28961 grid.treeBase.tree.forEach( function( node ) {
28962 if ( node.children && node.children.length > 0 ) {
28963 parentsVisible = node.row.visible;
28964 service.fixFilterInternal( node.children, parentsVisible );
28965 }
28966 });
28967 },
28968
28969 fixFilterInternal: function( nodes, parentsVisible) {
28970 nodes.forEach(function( node ) {
28971 if ( node.row.visible && !parentsVisible ) {
28972 service.setParentsVisible( node );
28973 parentsVisible = true;
28974 }
28975
28976 if ( node.children && node.children.length > 0 ) {
28977 if ( service.fixFilterInternal( node.children, ( parentsVisible && node.row.visible ) ) ) {
28978 parentsVisible = true;
28979 }
28980 }
28981 });
28982
28983 return parentsVisible;
28984 },
28985
28986 setParentsVisible: function( node ) {
28987 while ( node.parentRow ) {
28988 node.parentRow.visible = true;
28989 node = node.parentRow.treeNode;
28990 }
28991 },
28992
28993 /**
28994 * @ngdoc function
28995 * @name buildAggregationObject
28996 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
28997 * @description Build the object which is stored on the column for holding meta-data about the aggregation.
28998 * This method should only be called with columns which have an aggregation.
28999 *
29000 * @param {GridColumn} column The column which this object relates to
29001 * @returns {object} {col: GridColumn object, label: string, type: string (optional)}
29002 */
29003 buildAggregationObject: function( column ) {
29004 var newAggregation = { col: column };
29005
29006 if ( column.treeAggregation && column.treeAggregation.type ) {
29007 newAggregation.type = column.treeAggregation.type;
29008 }
29009
29010 if ( column.treeAggregation && column.treeAggregation.label ) {
29011 newAggregation.label = column.treeAggregation.label;
29012 }
29013
29014 return newAggregation;
29015 },
29016
29017 /**
29018 * @ngdoc function
29019 * @name getAggregations
29020 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
29021 * @description Looks through the grid columns to find those with aggregations,
29022 * and collates the aggregation information into an array, returns that array
29023 *
29024 * @param {Grid} grid the grid to get the aggregation information from
29025 * @returns {array} the aggregation information
29026 */
29027 getAggregations: function( grid ) {
29028 var aggregateArray = [];
29029
29030 grid.columns.forEach( function(column) {
29031 if ( typeof(column.treeAggregationFn) !== 'undefined' ) {
29032 aggregateArray.push( service.buildAggregationObject(column) );
29033
29034 if ( grid.options.showColumnFooter && typeof(column.colDef.aggregationType) === 'undefined' && column.treeAggregation ) {
29035 // Add aggregation object for footer
29036 column.treeFooterAggregation = service.buildAggregationObject(column);
29037 column.aggregationType = service.treeFooterAggregationType;
29038 }
29039 }
29040 });
29041 return aggregateArray;
29042 },
29043
29044
29045 /**
29046 * @ngdoc function
29047 * @name aggregate
29048 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
29049 * @description Accumulate the data from this row onto the aggregations for each parent
29050 *
29051 * Iterate over the parents, then iterate over the aggregations for each of those parents,
29052 * and perform the aggregation for each individual aggregation
29053 *
29054 * @param {Grid} grid grid object
29055 * @param {GridRow} row the row we want to set grouping visibility on
29056 * @param {array} parents the parents that we would want to aggregate onto
29057 */
29058 aggregate: function( grid, row, parents ) {
29059 if (parents.length === 0 && row.treeNode && row.treeNode.aggregations) {
29060 row.treeNode.aggregations.forEach(function(aggregation) {
29061 // Calculate aggregations for footer even if there are no grouped rows
29062 if (typeof(aggregation.col.treeFooterAggregation) !== 'undefined') {
29063 var fieldValue = grid.getCellValue(row, aggregation.col);
29064 var numValue = Number(fieldValue);
29065 if (aggregation.col.treeAggregationFn) {
29066 aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);
29067 } else {
29068 aggregation.col.treeFooterAggregation.value = undefined;
29069 }
29070 }
29071 });
29072 }
29073
29074 parents.forEach( function( parent, index ) {
29075 if (parent.treeNode.aggregations) {
29076 parent.treeNode.aggregations.forEach( function( aggregation ) {
29077 var fieldValue = grid.getCellValue(row, aggregation.col);
29078 var numValue = Number(fieldValue);
29079 aggregation.col.treeAggregationFn(aggregation, fieldValue, numValue, row);
29080
29081 if (index === 0 && typeof(aggregation.col.treeFooterAggregation) !== 'undefined') {
29082 if (aggregation.col.treeAggregationFn) {
29083 aggregation.col.treeAggregationFn(aggregation.col.treeFooterAggregation, fieldValue, numValue, row);
29084 } else {
29085 aggregation.col.treeFooterAggregation.value = undefined;
29086 }
29087 }
29088 });
29089 }
29090 });
29091 },
29092
29093
29094 // Aggregation routines - no doco needed as self evident
29095 nativeAggregations: function() {
29096 return {
29097 count: {
29098 label: i18nService.get().aggregation.count,
29099 menuTitle: i18nService.get().grouping.aggregate_count,
29100 aggregationFn: function (aggregation, fieldValue, numValue) {
29101 if (typeof(aggregation.value) === 'undefined') {
29102 aggregation.value = 1;
29103 } else {
29104 aggregation.value++;
29105 }
29106 }
29107 },
29108
29109 sum: {
29110 label: i18nService.get().aggregation.sum,
29111 menuTitle: i18nService.get().grouping.aggregate_sum,
29112 aggregationFn: function( aggregation, fieldValue, numValue ) {
29113 if (!isNaN(numValue)) {
29114 if (typeof(aggregation.value) === 'undefined') {
29115 aggregation.value = numValue;
29116 } else {
29117 aggregation.value += numValue;
29118 }
29119 }
29120 }
29121 },
29122
29123 min: {
29124 label: i18nService.get().aggregation.min,
29125 menuTitle: i18nService.get().grouping.aggregate_min,
29126 aggregationFn: function( aggregation, fieldValue, numValue ) {
29127 if (typeof(aggregation.value) === 'undefined') {
29128 aggregation.value = fieldValue;
29129 } else {
29130 if (typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue < aggregation.value || aggregation.value === null)) {
29131 aggregation.value = fieldValue;
29132 }
29133 }
29134 }
29135 },
29136
29137 max: {
29138 label: i18nService.get().aggregation.max,
29139 menuTitle: i18nService.get().grouping.aggregate_max,
29140 aggregationFn: function( aggregation, fieldValue, numValue ) {
29141 if ( typeof(aggregation.value) === 'undefined' ) {
29142 aggregation.value = fieldValue;
29143 } else {
29144 if ( typeof(fieldValue) !== 'undefined' && fieldValue !== null && (fieldValue > aggregation.value || aggregation.value === null)) {
29145 aggregation.value = fieldValue;
29146 }
29147 }
29148 }
29149 },
29150
29151 avg: {
29152 label: i18nService.get().aggregation.avg,
29153 menuTitle: i18nService.get().grouping.aggregate_avg,
29154 aggregationFn: function( aggregation, fieldValue, numValue ) {
29155 if ( typeof(aggregation.count) === 'undefined' ) {
29156 aggregation.count = 1;
29157 } else {
29158 aggregation.count++;
29159 }
29160
29161 if ( isNaN(numValue) ) {
29162 return;
29163 }
29164
29165 if ( typeof(aggregation.value) === 'undefined' || typeof(aggregation.sum) === 'undefined' ) {
29166 aggregation.value = numValue;
29167 aggregation.sum = numValue;
29168 } else {
29169 aggregation.sum += numValue;
29170 aggregation.value = aggregation.sum / aggregation.count;
29171 }
29172 }
29173 }
29174 };
29175 },
29176
29177 /**
29178 * @ngdoc function
29179 * @name finaliseAggregation
29180 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
29181 * @description Helper function used to finalize aggregation nodes and footer cells
29182 *
29183 * @param {gridRow} row The parent we're finalising
29184 * @param {aggregation} aggregation The aggregation object manipulated by the aggregationFn
29185 */
29186 finaliseAggregation: function(row, aggregation) {
29187 if ( aggregation.col.treeAggregationUpdateEntity && typeof(row) !== 'undefined' && typeof(row.entity[ '$$' + aggregation.col.uid ]) !== 'undefined' ) {
29188 angular.extend( aggregation, row.entity[ '$$' + aggregation.col.uid ]);
29189 }
29190
29191 if ( typeof(aggregation.col.treeAggregationFinalizerFn) === 'function' ) {
29192 aggregation.col.treeAggregationFinalizerFn( aggregation );
29193 }
29194 if ( typeof(aggregation.col.customTreeAggregationFinalizerFn) === 'function' ) {
29195 aggregation.col.customTreeAggregationFinalizerFn( aggregation );
29196 }
29197 if ( typeof(aggregation.rendered) === 'undefined' ) {
29198 aggregation.rendered = aggregation.label ? aggregation.label + aggregation.value : aggregation.value;
29199 }
29200 },
29201
29202 /**
29203 * @ngdoc function
29204 * @name finaliseAggregations
29205 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
29206 * @description Format the data from the aggregation into the rendered text
29207 * e.g. if we had label: 'sum: ' and value: 25, we'd create 'sum: 25'.
29208 *
29209 * As part of this we call any formatting callback routines we've been provided.
29210 *
29211 * We write our aggregation out to the row.entity if treeAggregationUpdateEntity is
29212 * set on the column - we don't overwrite any information that's already there, we append
29213 * to it so that grouping can have set the groupVal beforehand without us overwriting it.
29214 *
29215 * We need to copy the data from the row.entity first before we finalise the aggregation,
29216 * we need that information for the finaliserFn
29217 *
29218 * @param {gridRow} row the parent we're finalising
29219 */
29220 finaliseAggregations: function( row ) {
29221 if ( row == null || typeof(row.treeNode.aggregations) === 'undefined' ) {
29222 return;
29223 }
29224
29225 row.treeNode.aggregations.forEach( function( aggregation ) {
29226 service.finaliseAggregation(row, aggregation);
29227
29228 if ( aggregation.col.treeAggregationUpdateEntity ) {
29229 var aggregationCopy = {};
29230
29231 angular.forEach( aggregation, function( value, key ) {
29232 if ( aggregation.hasOwnProperty(key) && key !== 'col' ) {
29233 aggregationCopy[key] = value;
29234 }
29235 });
29236
29237 row.entity[ '$$' + aggregation.col.uid ] = aggregationCopy;
29238 }
29239 });
29240 },
29241
29242 /**
29243 * @ngdoc function
29244 * @name treeFooterAggregationType
29245 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
29246 * @description Uses the tree aggregation functions and finalizers to set the
29247 * column footer aggregations.
29248 *
29249 * @param {rows} rows The visible rows. not used, but accepted to match signature of GridColumn.aggregationType
29250 * @param {GridColumn} column The column we are finalizing
29251 */
29252 treeFooterAggregationType: function( rows, column ) {
29253 service.finaliseAggregation(undefined, column.treeFooterAggregation);
29254 if ( typeof(column.treeFooterAggregation.value) === 'undefined' || column.treeFooterAggregation.rendered === null ) {
29255 // The was apparently no aggregation performed (perhaps this is a grouped column
29256 return '';
29257 }
29258 return column.treeFooterAggregation.rendered;
29259 }
29260 };
29261
29262 return service;
29263 }]);
29264
29265
29266 /**
29267 * @ngdoc directive
29268 * @name ui.grid.treeBase.directive:uiGridTreeRowHeaderButtons
29269 * @element div
29270 *
29271 * @description Provides the expand/collapse button on rows
29272 */
29273 module.directive('uiGridTreeBaseRowHeaderButtons', ['$templateCache', 'uiGridTreeBaseService',
29274 function ($templateCache, uiGridTreeBaseService) {
29275 return {
29276 replace: true,
29277 restrict: 'E',
29278 template: $templateCache.get('ui-grid/treeBaseRowHeaderButtons'),
29279 scope: true,
29280 require: '^uiGrid',
29281 link: function($scope, $elm, $attrs, uiGridCtrl) {
29282 var self = uiGridCtrl.grid;
29283 $scope.treeButtonClass = function(row) {
29284 if ( ( self.options.showTreeExpandNoChildren && row.treeLevel > -1 ) || ( row.treeNode.children && row.treeNode.children.length > 0 ) ) {
29285 if (row.treeNode.state === 'expanded' ) {
29286 return 'ui-grid-icon-minus-squared';
29287 }
29288 if (row.treeNode.state === 'collapsed' ) {
29289 return 'ui-grid-icon-plus-squared';
29290 }
29291 }
29292 };
29293 $scope.treeButtonClick = function(row, evt) {
29294 evt.stopPropagation();
29295 uiGridTreeBaseService.toggleRowTreeState(self, row, evt);
29296 };
29297 }
29298 };
29299 }]);
29300
29301
29302 /**
29303 * @ngdoc directive
29304 * @name ui.grid.treeBase.directive:uiGridTreeBaseExpandAllButtons
29305 * @element div
29306 *
29307 * @description Provides the expand/collapse all button
29308 */
29309 module.directive('uiGridTreeBaseExpandAllButtons', ['$templateCache', 'uiGridTreeBaseService',
29310 function ($templateCache, uiGridTreeBaseService) {
29311 return {
29312 replace: true,
29313 restrict: 'E',
29314 template: $templateCache.get('ui-grid/treeBaseExpandAllButtons'),
29315 scope: false,
29316 link: function($scope) {
29317 var self = $scope.col.grid;
29318 $scope.headerButtonClass = function() {
29319 if (self.treeBase.numberLevels > 0 && self.treeBase.expandAll) {
29320 return 'ui-grid-icon-minus-squared';
29321 }
29322 if (self.treeBase.numberLevels > 0 && !self.treeBase.expandAll) {
29323 return 'ui-grid-icon-plus-squared';
29324 }
29325 };
29326 $scope.headerButtonClick = function(row, evt) {
29327 if ( self.treeBase.expandAll ) {
29328 uiGridTreeBaseService.collapseAllRows(self, evt);
29329 } else {
29330 uiGridTreeBaseService.expandAllRows(self, evt);
29331 }
29332 };
29333 }
29334 };
29335 }]);
29336
29337
29338 /**
29339 * @ngdoc directive
29340 * @name ui.grid.treeBase.directive:uiGridViewport
29341 * @element div
29342 *
29343 * @description Stacks on top of ui.grid.uiGridViewport to set formatting on a tree header row
29344 */
29345 module.directive('uiGridViewport',
29346 function () {
29347 return {
29348 priority: -200, // run after default directive
29349 scope: false,
29350 compile: function ($elm) {
29351 var rowRepeatDiv = angular.element($elm.children().children()[0]);
29352
29353 var existingNgClass = rowRepeatDiv.attr("ng-class");
29354 var newNgClass = '';
29355 if ( existingNgClass ) {
29356 newNgClass = existingNgClass.slice(0, -1) + ",'ui-grid-tree-header-row': row.treeLevel > -1}";
29357 } else {
29358 newNgClass = "{'ui-grid-tree-header-row': row.treeLevel > -1}";
29359 }
29360 rowRepeatDiv.attr("ng-class", newNgClass);
29361
29362 return {
29363 pre: function ($scope, $elm, $attrs, controllers) {
29364
29365 },
29366 post: function ($scope, $elm, $attrs, controllers) {
29367 }
29368 };
29369 }
29370 };
29371 });
29372 })();
29373
29374 (function () {
29375 'use strict';
29376
29377 /**
29378 * @ngdoc overview
29379 * @name ui.grid.treeView
29380 * @description
29381 *
29382 * # ui.grid.treeView
29383 *
29384 * <div class="alert alert-warning" role="alert"><strong>Beta</strong> This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.</div>
29385 *
29386 * This module provides a tree view of the data that it is provided, with nodes in that
29387 * tree and leaves. Unlike grouping, the tree is an inherent property of the data and must
29388 * be provided with your data array.
29389 *
29390 * Design information:
29391 * -------------------
29392 *
29393 * TreeView uses treeBase for the underlying functionality, and is a very thin wrapper around
29394 * that logic. Most of the design information has now moved to treebase.
29395 * <br/>
29396 * <br/>
29397 *
29398 * <div doc-module-components="ui.grid.treeView"></div>
29399 */
29400
29401 var module = angular.module('ui.grid.treeView', ['ui.grid', 'ui.grid.treeBase']);
29402
29403 /**
29404 * @ngdoc object
29405 * @name ui.grid.treeView.constant:uiGridTreeViewConstants
29406 *
29407 * @description constants available in treeView module, this includes
29408 * all the constants declared in the treeBase module (these are manually copied
29409 * as there isn't an easy way to include constants in another constants file, and
29410 * we don't want to make users include treeBase)
29411 *
29412 */
29413 module.constant('uiGridTreeViewConstants', {
29414 featureName: "treeView",
29415 rowHeaderColName: 'treeBaseRowHeaderCol',
29416 EXPANDED: 'expanded',
29417 COLLAPSED: 'collapsed',
29418 aggregation: {
29419 COUNT: 'count',
29420 SUM: 'sum',
29421 MAX: 'max',
29422 MIN: 'min',
29423 AVG: 'avg'
29424 }
29425 });
29426
29427 /**
29428 * @ngdoc service
29429 * @name ui.grid.treeView.service:uiGridTreeViewService
29430 *
29431 * @description Services for treeView features
29432 */
29433 module.service('uiGridTreeViewService', ['$q', 'uiGridTreeViewConstants', 'uiGridTreeBaseConstants', 'uiGridTreeBaseService', 'gridUtil', 'GridRow', 'gridClassFactory', 'i18nService', 'uiGridConstants',
29434 function ($q, uiGridTreeViewConstants, uiGridTreeBaseConstants, uiGridTreeBaseService, gridUtil, GridRow, gridClassFactory, i18nService, uiGridConstants) {
29435
29436 var service = {
29437
29438 initializeGrid: function (grid, $scope) {
29439 uiGridTreeBaseService.initializeGrid( grid, $scope );
29440
29441 /**
29442 * @ngdoc object
29443 * @name ui.grid.treeView.grid:treeView
29444 *
29445 * @description Grid properties and functions added for treeView
29446 */
29447 grid.treeView = {};
29448
29449 grid.registerRowsProcessor(service.adjustSorting, 60);
29450
29451 /**
29452 * @ngdoc object
29453 * @name ui.grid.treeView.api:PublicApi
29454 *
29455 * @description Public Api for treeView feature
29456 */
29457 var publicApi = {
29458 events: {
29459 treeView: {
29460 }
29461 },
29462 methods: {
29463 treeView: {
29464 }
29465 }
29466 };
29467
29468 grid.api.registerEventsFromObject(publicApi.events);
29469
29470 grid.api.registerMethodsFromObject(publicApi.methods);
29471
29472 },
29473
29474 defaultGridOptions: function (gridOptions) {
29475 // default option to true unless it was explicitly set to false
29476 /**
29477 * @ngdoc object
29478 * @name ui.grid.treeView.api:GridOptions
29479 *
29480 * @description GridOptions for treeView feature, these are available to be
29481 * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
29482 *
29483 * Many tree options are set on treeBase, make sure to look at that feature in
29484 * conjunction with these options.
29485 */
29486
29487 /**
29488 * @ngdoc object
29489 * @name enableTreeView
29490 * @propertyOf ui.grid.treeView.api:GridOptions
29491 * @description Enable row tree view for entire grid.
29492 * <br/>Defaults to true
29493 */
29494 gridOptions.enableTreeView = gridOptions.enableTreeView !== false;
29495
29496 },
29497
29498
29499 /**
29500 * @ngdoc function
29501 * @name adjustSorting
29502 * @methodOf ui.grid.treeBase.service:uiGridTreeBaseService
29503 * @description Trees cannot be sorted the same as flat lists of rows -
29504 * trees are sorted recursively within each level - so the children of each
29505 * node are sorted, but not the full set of rows.
29506 *
29507 * To achieve this, we suppress the normal sorting by setting ignoreSort on
29508 * each of the sort columns. When the treeBase rowsProcessor runs it will then
29509 * unignore these, and will perform a recursive sort against the tree that it builds.
29510 *
29511 * @param {array} renderableRows the rows that we need to pass on through
29512 * @returns {array} renderableRows that we passed on through
29513 */
29514 adjustSorting: function( renderableRows ) {
29515 var grid = this;
29516
29517 grid.columns.forEach( function( column ) {
29518 if ( column.sort ) {
29519 column.sort.ignoreSort = true;
29520 }
29521 });
29522
29523 return renderableRows;
29524 }
29525 };
29526
29527 return service;
29528 }]);
29529
29530 /**
29531 * @ngdoc directive
29532 * @name ui.grid.treeView.directive:uiGridTreeView
29533 * @element div
29534 * @restrict A
29535 *
29536 * @description Adds treeView features to grid
29537 *
29538 * @example
29539 <example module="app">
29540 <file name="app.js">
29541 var app = angular.module('app', ['ui.grid', 'ui.grid.treeView']);
29542
29543 app.controller('MainCtrl', ['$scope', function ($scope) {
29544 $scope.data = [
29545 { name: 'Bob', title: 'CEO' },
29546 { name: 'Frank', title: 'Lowly Developer' }
29547 ];
29548
29549 $scope.columnDefs = [
29550 {name: 'name', enableCellEdit: true},
29551 {name: 'title', enableCellEdit: true}
29552 ];
29553
29554 $scope.gridOptions = { columnDefs: $scope.columnDefs, data: $scope.data };
29555 }]);
29556 </file>
29557 <file name="index.html">
29558 <div ng-controller="MainCtrl">
29559 <div ui-grid="gridOptions" ui-grid-tree-view></div>
29560 </div>
29561 </file>
29562 </example>
29563 */
29564 module.directive('uiGridTreeView', ['uiGridTreeViewConstants', 'uiGridTreeViewService', '$templateCache',
29565 function (uiGridTreeViewConstants, uiGridTreeViewService, $templateCache) {
29566 return {
29567 replace: true,
29568 priority: 0,
29569 require: '^uiGrid',
29570 scope: false,
29571 compile: function () {
29572 return {
29573 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
29574 if (uiGridCtrl.grid.options.enableTreeView !== false) {
29575 uiGridTreeViewService.initializeGrid(uiGridCtrl.grid, $scope);
29576 }
29577 },
29578 post: function ($scope, $elm, $attrs, uiGridCtrl) {
29579
29580 }
29581 };
29582 }
29583 };
29584 }]);
29585 })();
29586
29587 (function () {
29588 'use strict';
29589
29590 /**
29591 * @ngdoc overview
29592 * @name ui.grid.validate
29593 * @description
29594 *
29595 * # ui.grid.validate
29596 *
29597 * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
29598 *
29599 * This module provides the ability to validate cells upon change.
29600 *
29601 * Design information:
29602 * -------------------
29603 *
29604 * Validation is not based on angularjs validation, since it would work only when editing the field.
29605 *
29606 * Instead it adds custom properties to any field considered as invalid.
29607 *
29608 * <br/>
29609 * <br/>
29610 *
29611 * <div doc-module-components="ui.grid.expandable"></div>
29612 */
29613 var module = angular.module('ui.grid.validate', ['ui.grid']);
29614
29615 /**
29616 * @ngdoc service
29617 * @name ui.grid.validate.service:uiGridValidateService
29618 *
29619 * @description Services for validation features
29620 */
29621 module.service('uiGridValidateService', ['$sce', '$q', '$http', 'i18nService', 'uiGridConstants', function ($sce, $q, $http, i18nService, uiGridConstants) {
29622
29623 var service = {
29624
29625 /**
29626 * @ngdoc object
29627 * @name validatorFactories
29628 * @propertyOf ui.grid.validate.service:uiGridValidateService
29629 * @description object containing all the factories used to validate data.<br/>
29630 * These factories will be in the form <br/>
29631 * ```
29632 * {
29633 * validatorFactory: function(argument) {
29634 * return function(newValue, oldValue, rowEntity, colDef) {
29635 * return true || false || promise
29636 * }
29637 * },
29638 * messageFunction: function(argument) {
29639 * return string
29640 * }
29641 * }
29642 * ```
29643 *
29644 * Promises should return true or false as result according to the result of validation.
29645 */
29646 validatorFactories: {},
29647
29648 /**
29649 * @ngdoc service
29650 * @name setExternalFactoryFunction
29651 * @methodOf ui.grid.validate.service:uiGridValidateService
29652 * @description Adds a way to retrieve validators from an external service
29653 * <p>Validators from this external service have a higher priority than default
29654 * ones
29655 * @param {function} externalFactoryFunction a function that accepts name and argument to pass to a
29656 * validator factory and that returns an object with the same properties as
29657 * you can see in {@link ui.grid.validate.service:uiGridValidateService#properties_validatorFactories validatorFactories}
29658 */
29659 setExternalFactoryFunction: function(externalFactoryFunction) {
29660 service.externalFactoryFunction = externalFactoryFunction;
29661 },
29662
29663 /**
29664 * @ngdoc service
29665 * @name clearExternalFactory
29666 * @methodOf ui.grid.validate.service:uiGridValidateService
29667 * @description Removes any link to external factory from this service
29668 */
29669 clearExternalFactory: function() {
29670 delete service.externalFactoryFunction;
29671 },
29672
29673 /**
29674 * @ngdoc service
29675 * @name getValidatorFromExternalFactory
29676 * @methodOf ui.grid.validate.service:uiGridValidateService
29677 * @description Retrieves a validator by executing a validatorFactory
29678 * stored in an external service.
29679 * @param {string} name the name of the validator to retrieve
29680 * @param {object} argument an argument to pass to the validator factory
29681 */
29682 getValidatorFromExternalFactory: function(name, argument) {
29683 return service.externalFactoryFunction(name, argument).validatorFactory(argument);
29684 },
29685
29686 /**
29687 * @ngdoc service
29688 * @name getMessageFromExternalFactory
29689 * @methodOf ui.grid.validate.service:uiGridValidateService
29690 * @description Retrieves a message stored in an external service.
29691 * @param {string} name the name of the validator
29692 * @param {object} argument an argument to pass to the message function
29693 */
29694 getMessageFromExternalFactory: function(name, argument) {
29695 return service.externalFactoryFunction(name, argument).messageFunction(argument);
29696 },
29697
29698 /**
29699 * @ngdoc service
29700 * @name setValidator
29701 * @methodOf ui.grid.validate.service:uiGridValidateService
29702 * @description Adds a new validator to the service
29703 * @param {string} name the name of the validator, must be unique
29704 * @param {function} validatorFactory a factory that return a validatorFunction
29705 * @param {function} messageFunction a function that return the error message
29706 */
29707 setValidator: function(name, validatorFactory, messageFunction) {
29708 service.validatorFactories[name] = {
29709 validatorFactory: validatorFactory,
29710 messageFunction: messageFunction
29711 };
29712 },
29713
29714 /**
29715 * @ngdoc service
29716 * @name getValidator
29717 * @methodOf ui.grid.validate.service:uiGridValidateService
29718 * @description Returns a validator registered to the service
29719 * or retrieved from the external factory
29720 * @param {string} name the name of the validator to retrieve
29721 * @param {object} argument an argument to pass to the validator factory
29722 * @returns {object} the validator function
29723 */
29724 getValidator: function(name, argument) {
29725 if (service.externalFactoryFunction) {
29726 var validator = service.getValidatorFromExternalFactory(name, argument);
29727 if (validator) {
29728 return validator;
29729 }
29730 }
29731 if (!service.validatorFactories[name]) {
29732 throw ("Invalid validator name: " + name);
29733 }
29734 return service.validatorFactories[name].validatorFactory(argument);
29735 },
29736
29737 /**
29738 * @ngdoc service
29739 * @name getMessage
29740 * @methodOf ui.grid.validate.service:uiGridValidateService
29741 * @description Returns the error message related to the validator
29742 * @param {string} name the name of the validator
29743 * @param {object} argument an argument to pass to the message function
29744 * @returns {string} the error message related to the validator
29745 */
29746 getMessage: function(name, argument) {
29747 if (service.externalFactoryFunction) {
29748 var message = service.getMessageFromExternalFactory(name, argument);
29749 if (message) {
29750 return message;
29751 }
29752 }
29753 return service.validatorFactories[name].messageFunction(argument);
29754 },
29755
29756 /**
29757 * @ngdoc service
29758 * @name isInvalid
29759 * @methodOf ui.grid.validate.service:uiGridValidateService
29760 * @description Returns true if the cell (identified by rowEntity, colDef) is invalid
29761 * @param {object} rowEntity the row entity of the cell
29762 * @param {object} colDef the colDef of the cell
29763 * @returns {boolean} true if the cell is invalid
29764 */
29765 isInvalid: function (rowEntity, colDef) {
29766 return rowEntity['$$invalid'+colDef.name];
29767 },
29768
29769 /**
29770 * @ngdoc service
29771 * @name setInvalid
29772 * @methodOf ui.grid.validate.service:uiGridValidateService
29773 * @description Makes the cell invalid by adding the proper field to the entity
29774 * @param {object} rowEntity the row entity of the cell
29775 * @param {object} colDef the colDef of the cell
29776 */
29777 setInvalid: function (rowEntity, colDef) {
29778 rowEntity['$$invalid'+colDef.name] = true;
29779 },
29780
29781 /**
29782 * @ngdoc service
29783 * @name setValid
29784 * @methodOf ui.grid.validate.service:uiGridValidateService
29785 * @description Makes the cell valid by removing the proper error field from the entity
29786 * @param {object} rowEntity the row entity of the cell
29787 * @param {object} colDef the colDef of the cell
29788 */
29789 setValid: function (rowEntity, colDef) {
29790 delete rowEntity['$$invalid'+colDef.name];
29791 },
29792
29793 /**
29794 * @ngdoc service
29795 * @name setError
29796 * @methodOf ui.grid.validate.service:uiGridValidateService
29797 * @description Adds the proper error to the entity errors field
29798 * @param {object} rowEntity the row entity of the cell
29799 * @param {object} colDef the colDef of the cell
29800 * @param {string} validatorName the name of the validator that is failing
29801 */
29802 setError: function(rowEntity, colDef, validatorName) {
29803 if (!rowEntity['$$errors'+colDef.name]) {
29804 rowEntity['$$errors'+colDef.name] = {};
29805 }
29806 rowEntity['$$errors'+colDef.name][validatorName] = true;
29807 },
29808
29809 /**
29810 * @ngdoc service
29811 * @name clearError
29812 * @methodOf ui.grid.validate.service:uiGridValidateService
29813 * @description Removes the proper error from the entity errors field
29814 * @param {object} rowEntity the row entity of the cell
29815 * @param {object} colDef the colDef of the cell
29816 * @param {string} validatorName the name of the validator that is failing
29817 */
29818 clearError: function(rowEntity, colDef, validatorName) {
29819 if (!rowEntity['$$errors'+colDef.name]) {
29820 return;
29821 }
29822 if (validatorName in rowEntity['$$errors'+colDef.name]) {
29823 delete rowEntity['$$errors'+colDef.name][validatorName];
29824 }
29825 },
29826
29827 /**
29828 * @ngdoc function
29829 * @name getErrorMessages
29830 * @methodOf ui.grid.validate.service:uiGridValidateService
29831 * @description returns an array of i18n-ed error messages.
29832 * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
29833 * @param {object} colDef the column whose errors we are looking for
29834 * @returns {array} An array of strings containing all the error messages for the cell
29835 */
29836 getErrorMessages: function(rowEntity, colDef) {
29837 var errors = [];
29838
29839 if (!rowEntity['$$errors'+colDef.name] || Object.keys(rowEntity['$$errors'+colDef.name]).length === 0) {
29840 return errors;
29841 }
29842
29843 Object.keys(rowEntity['$$errors'+colDef.name]).sort().forEach(function(validatorName) {
29844 errors.push(service.getMessage(validatorName, colDef.validators[validatorName]));
29845 });
29846
29847 return errors;
29848 },
29849
29850 /**
29851 * @ngdoc function
29852 * @name getFormattedErrors
29853 * @methodOf ui.grid.validate.service:uiGridValidateService
29854 * @description returns the error i18n-ed and formatted in html to be shown inside the page.
29855 * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
29856 * @param {object} colDef the column whose errors we are looking for
29857 * @returns {object} An object that can be used in a template (like a cellTemplate) to display the
29858 * message inside the page (i.e. inside a div)
29859 */
29860 getFormattedErrors: function(rowEntity, colDef) {
29861 var msgString = "",
29862 errors = service.getErrorMessages(rowEntity, colDef);
29863
29864 if (!errors.length) {
29865 return;
29866 }
29867
29868 errors.forEach(function(errorMsg) {
29869 msgString += errorMsg + "<br/>";
29870 });
29871
29872 return $sce.trustAsHtml('<p><b>' + i18nService.getSafeText('validate.error') + '</b></p>' + msgString );
29873 },
29874
29875 /**
29876 * @ngdoc function
29877 * @name getTitleFormattedErrors
29878 * @methodOf ui.grid.validate.service:uiGridValidateService
29879 * @description returns the error i18n-ed and formatted in javaScript to be shown inside an html
29880 * title attribute.
29881 * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
29882 * @param {object} colDef the column whose errors we are looking for
29883 * @returns {object} An object that can be used in a template (like a cellTemplate) to display the
29884 * message inside an html title attribute
29885 */
29886 getTitleFormattedErrors: function(rowEntity, colDef) {
29887 var newLine = "\n",
29888 msgString = "",
29889 errors = service.getErrorMessages(rowEntity, colDef);
29890
29891 if (!errors.length) {
29892 return;
29893 }
29894
29895 errors.forEach(function(errorMsg) {
29896 msgString += errorMsg + newLine;
29897 });
29898
29899 return $sce.trustAsHtml(i18nService.getSafeText('validate.error') + newLine + msgString);
29900 },
29901
29902 /**
29903 * @ngdoc function
29904 * @name getTitleFormattedErrors
29905 * @methodOf ui.grid.validate.service:uiGridValidateService
29906 * @description Executes all validators on a cell (identified by row entity and column definition) and sets or clears errors
29907 * @param {object} rowEntity the row entity of the cell we want to run the validators on
29908 * @param {object} colDef the column definition of the cell we want to run the validators on
29909 * @param {object} newValue the value the user just entered
29910 * @param {object} oldValue the value the field had before
29911 */
29912 runValidators: function(rowEntity, colDef, newValue, oldValue, grid) {
29913 if (newValue === oldValue) {
29914 // If the value has not changed we perform no validation
29915 return;
29916 }
29917
29918 if (typeof(colDef.name) === 'undefined' || !colDef.name) {
29919 throw new Error('colDef.name is required to perform validation');
29920 }
29921
29922 service.setValid(rowEntity, colDef);
29923
29924 var validateClosureFactory = function(rowEntity, colDef, validatorName) {
29925 return function(value) {
29926 if (!value) {
29927 service.setInvalid(rowEntity, colDef);
29928 service.setError(rowEntity, colDef, validatorName);
29929 if (grid) {
29930 grid.api.validate.raise.validationFailed(rowEntity, colDef, newValue, oldValue);
29931 }
29932 }
29933 };
29934 };
29935
29936 var promises = [];
29937
29938 for (var validatorName in colDef.validators) {
29939 service.clearError(rowEntity, colDef, validatorName);
29940 var validatorFunction = service.getValidator(validatorName, colDef.validators[validatorName]);
29941
29942 // We pass the arguments as oldValue, newValue so they are in the same order
29943 // as ng-model validators (modelValue, viewValue)
29944 var promise = $q.when(validatorFunction(oldValue, newValue, rowEntity, colDef))
29945 .then(validateClosureFactory(rowEntity, colDef, validatorName));
29946
29947 promises.push(promise);
29948 }
29949
29950 return $q.all(promises);
29951 },
29952
29953 /**
29954 * @ngdoc function
29955 * @name createDefaultValidators
29956 * @methodOf ui.grid.validate.service:uiGridValidateService
29957 * @description adds the basic validators to the list of service validators
29958 */
29959 createDefaultValidators: function() {
29960 service.setValidator('minLength', function (argument) {
29961 return function (oldValue, newValue) {
29962 if (newValue === undefined || newValue === null || newValue === '') {
29963 return true;
29964 }
29965 return newValue.length >= argument;
29966 };
29967 }, function(argument) {
29968 return i18nService.getSafeText('validate.minLength').replace('THRESHOLD', argument);
29969 });
29970
29971 service.setValidator('maxLength', function (argument) {
29972 return function (oldValue, newValue) {
29973 if (newValue === undefined || newValue === null || newValue === '') {
29974 return true;
29975 }
29976 return newValue.length <= argument;
29977 };
29978 }, function(threshold) {
29979 return i18nService.getSafeText('validate.maxLength').replace('THRESHOLD', threshold);
29980 });
29981
29982 service.setValidator('required', function (argument) {
29983 return function (oldValue, newValue) {
29984 if (argument) {
29985 return !(newValue === undefined || newValue === null || newValue === '');
29986 }
29987 return true;
29988 };
29989 }, function() {
29990 return i18nService.getSafeText('validate.required');
29991 });
29992 },
29993
29994 initializeGrid: function (scope, grid) {
29995 grid.validate = {
29996
29997 isInvalid: service.isInvalid,
29998
29999 getErrorMessages: service.getErrorMessages,
30000
30001 getFormattedErrors: service.getFormattedErrors,
30002
30003 getTitleFormattedErrors: service.getTitleFormattedErrors,
30004
30005 runValidators: service.runValidators
30006 };
30007
30008 /**
30009 * @ngdoc object
30010 * @name ui.grid.validate.api:PublicApi
30011 *
30012 * @description Public Api for validation feature
30013 */
30014 var publicApi = {
30015 events: {
30016 validate: {
30017 /**
30018 * @ngdoc event
30019 * @name validationFailed
30020 * @eventOf ui.grid.validate.api:PublicApi
30021 * @description raised when one or more failure happened during validation
30022 * <pre>
30023 * gridApi.validate.on.validationFailed(scope, function(rowEntity, colDef, newValue, oldValue){...})
30024 * </pre>
30025 * @param {object} rowEntity the options.data element whose validation failed
30026 * @param {object} colDef the column whose validation failed
30027 * @param {object} newValue new value
30028 * @param {object} oldValue old value
30029 */
30030 validationFailed: function (rowEntity, colDef, newValue, oldValue) {
30031 }
30032 }
30033 },
30034 methods: {
30035 validate: {
30036 /**
30037 * @ngdoc function
30038 * @name isInvalid
30039 * @methodOf ui.grid.validate.api:PublicApi
30040 * @description checks if a cell (identified by rowEntity, colDef) is invalid
30041 * @param {object} rowEntity gridOptions.data[] array instance we want to check
30042 * @param {object} colDef the column whose errors we want to check
30043 * @returns {boolean} true if the cell value is not valid
30044 */
30045 isInvalid: function(rowEntity, colDef) {
30046 return grid.validate.isInvalid(rowEntity, colDef);
30047 },
30048 /**
30049 * @ngdoc function
30050 * @name getErrorMessages
30051 * @methodOf ui.grid.validate.api:PublicApi
30052 * @description returns an array of i18n-ed error messages.
30053 * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
30054 * @param {object} colDef the column whose errors we are looking for
30055 * @returns {array} An array of strings containing all the error messages for the cell
30056 */
30057 getErrorMessages: function (rowEntity, colDef) {
30058 return grid.validate.getErrorMessages(rowEntity, colDef);
30059 },
30060 /**
30061 * @ngdoc function
30062 * @name getFormattedErrors
30063 * @methodOf ui.grid.validate.api:PublicApi
30064 * @description returns the error i18n-ed and formatted in html to be shown inside the page.
30065 * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
30066 * @param {object} colDef the column whose errors we are looking for
30067 * @returns {object} An object that can be used in a template (like a cellTemplate) to display the
30068 * message inside the page (i.e. inside a div)
30069 */
30070 getFormattedErrors: function (rowEntity, colDef) {
30071 return grid.validate.getFormattedErrors(rowEntity, colDef);
30072 },
30073 /**
30074 * @ngdoc function
30075 * @name getTitleFormattedErrors
30076 * @methodOf ui.grid.validate.api:PublicApi
30077 * @description returns the error i18n-ed and formatted in javaScript to be shown inside an html
30078 * title attribute.
30079 * @param {object} rowEntity gridOptions.data[] array instance whose errors we are looking for
30080 * @param {object} colDef the column whose errors we are looking for
30081 * @returns {object} An object that can be used in a template (like a cellTemplate) to display the
30082 * message inside an html title attribute
30083 */
30084 getTitleFormattedErrors: function (rowEntity, colDef) {
30085 return grid.validate.getTitleFormattedErrors(rowEntity, colDef);
30086 }
30087 }
30088 }
30089 };
30090
30091 grid.api.registerEventsFromObject(publicApi.events);
30092 grid.api.registerMethodsFromObject(publicApi.methods);
30093
30094 if (grid.edit) {
30095 grid.api.edit.on.afterCellEdit(scope, function(rowEntity, colDef, newValue, oldValue) {
30096 grid.validate.runValidators(rowEntity, colDef, newValue, oldValue, grid);
30097 });
30098 }
30099
30100 service.createDefaultValidators();
30101 }
30102 };
30103
30104 return service;
30105 }]);
30106
30107 /**
30108 * @ngdoc directive
30109 * @name ui.grid.validate.directive:uiGridValidate
30110 * @element div
30111 * @restrict A
30112 * @description Adds validating features to the ui-grid directive.
30113 * @example
30114 <example module="app">
30115 <file name="app.js">
30116 var app = angular.module('app', ['ui.grid', 'ui.grid.edit', 'ui.grid.validate']);
30117
30118 app.controller('MainCtrl', ['$scope', function ($scope) {
30119 $scope.data = [
30120 { name: 'Bob', title: 'CEO' },
30121 { name: 'Frank', title: 'Lowly Developer' }
30122 ];
30123
30124 $scope.columnDefs = [
30125 {name: 'name', enableCellEdit: true, validators: {minLength: 3, maxLength: 9}, cellTemplate: 'ui-grid/cellTitleValidator'},
30126 {name: 'title', enableCellEdit: true, validators: {required: true}, cellTemplate: 'ui-grid/cellTitleValidator'}
30127 ];
30128 }]);
30129 </file>
30130 <file name="index.html">
30131 <div ng-controller="MainCtrl">
30132 <div ui-grid="{ data: data, columnDefs: columnDefs }" ui-grid-edit ui-grid-validate></div>
30133 </div>
30134 </file>
30135 </example>
30136 */
30137
30138 module.directive('uiGridValidate', ['gridUtil', 'uiGridValidateService', function (gridUtil, uiGridValidateService) {
30139 return {
30140 priority: 0,
30141 replace: true,
30142 require: '^uiGrid',
30143 scope: false,
30144 compile: function () {
30145 return {
30146 pre: function ($scope, $elm, $attrs, uiGridCtrl) {
30147 uiGridValidateService.initializeGrid($scope, uiGridCtrl.grid);
30148 },
30149 post: function ($scope, $elm, $attrs, uiGridCtrl) {
30150 }
30151 };
30152 }
30153 };
30154 }]);
30155 })();
30156
30157 angular.module('ui.grid').run(['$templateCache', function($templateCache) {
30158 'use strict';
30159
30160 $templateCache.put('ui-grid/ui-grid-filter',
30161 "<div class=\"ui-grid-filter-container\" ng-style=\"col.extraStyle\" ng-repeat=\"colFilter in col.filters\" ng-class=\"{'ui-grid-filter-cancel-button-hidden' : colFilter.disableCancelFilterButton === true }\"><div ng-if=\"colFilter.type !== 'select'\"><input type=\"text\" class=\"ui-grid-filter-input ui-grid-filter-input-{{$index}}\" ng-model=\"colFilter.term\" ng-attr-placeholder=\"{{colFilter.placeholder || ''}}\" aria-label=\"{{colFilter.ariaLabel || aria.defaultFilterLabel}}\"><div role=\"button\" class=\"ui-grid-filter-button\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== ''\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div><div ng-if=\"colFilter.type === 'select'\"><select class=\"ui-grid-filter-select ui-grid-filter-input-{{$index}}\" ng-model=\"colFilter.term\" ng-show=\"colFilter.selectOptions.length > 0\" ng-attr-placeholder=\"{{colFilter.placeholder || aria.defaultFilterLabel}}\" aria-label=\"{{colFilter.ariaLabel || ''}}\" ng-options=\"option.value as option.label for option in colFilter.selectOptions\"><option value=\"\"></option></select><div role=\"button\" class=\"ui-grid-filter-button-select\" ng-click=\"removeFilter(colFilter, $index)\" ng-if=\"!colFilter.disableCancelFilterButton\" ng-disabled=\"colFilter.term === undefined || colFilter.term === null || colFilter.term === ''\" ng-show=\"colFilter.term !== undefined && colFilter.term != null\"><i class=\"ui-grid-icon-cancel\" ui-grid-one-bind-aria-label=\"aria.removeFilter\">&nbsp;</i></div></div></div>"
30162 );
30163
30164
30165 $templateCache.put('ui-grid/ui-grid-footer',
30166 "<div class=\"ui-grid-footer-panel ui-grid-footer-aggregates-row\"><!-- tfooter --><div class=\"ui-grid-footer ui-grid-footer-viewport\"><div class=\"ui-grid-footer-canvas\"><div class=\"ui-grid-footer-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\"><div role=\"row\" class=\"ui-grid-footer-cell-row\"><div ui-grid-footer-cell role=\"gridcell\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" col=\"col\" render-index=\"$index\" class=\"ui-grid-footer-cell ui-grid-clearfix\"></div></div></div></div></div></div>"
30167 );
30168
30169
30170 $templateCache.put('ui-grid/ui-grid-grid-footer',
30171 "<div class=\"ui-grid-footer-info ui-grid-grid-footer\"><span>{{'search.totalItems' | t}} {{grid.rows.length}}</span> <span ng-if=\"grid.renderContainers.body.visibleRowCache.length !== grid.rows.length\" class=\"ngLabel\">({{\"search.showingItems\" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>"
30172 );
30173
30174
30175 $templateCache.put('ui-grid/ui-grid-header',
30176 "<div role=\"rowgroup\" class=\"ui-grid-header\"><!-- theader --><div class=\"ui-grid-top-panel\"><div class=\"ui-grid-header-viewport\"><div class=\"ui-grid-header-canvas\"><div class=\"ui-grid-header-cell-wrapper\" ng-style=\"colContainer.headerCellWrapperStyle()\"><div role=\"row\" class=\"ui-grid-header-cell-row\"><div class=\"ui-grid-header-cell ui-grid-clearfix\" ng-repeat=\"col in colContainer.renderedColumns track by col.uid\" ui-grid-header-cell col=\"col\" render-index=\"$index\"></div></div></div></div></div></div></div>"
30177 );
30178
30179
30180 $templateCache.put('ui-grid/ui-grid-menu-button',
30181 "<div class=\"ui-grid-menu-button\"><div role=\"button\" ui-grid-one-bind-id-grid=\"'grid-menu'\" class=\"ui-grid-icon-container\" ng-click=\"toggleMenu()\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-menu\" ui-grid-one-bind-aria-label=\"i18n.aria.buttonLabel\">&nbsp;</i></div><div ui-grid-menu menu-items=\"menuItems\"></div></div>"
30182 );
30183
30184
30185 $templateCache.put('ui-grid/ui-grid-menu-header-item',
30186 "<li role=\"menuitem\"><div class=\"ui-grid-menu-item\" role=\"heading\" aria-level=\"2\" ng-show=\"itemShown()\"><i aria-hidden=\"true\">&nbsp; </i><span ng-bind=\"label()\"></span></div></li>"
30187 );
30188
30189
30190 $templateCache.put('ui-grid/ui-grid-no-header',
30191 "<div class=\"ui-grid-top-panel\"></div>"
30192 );
30193
30194
30195 $templateCache.put('ui-grid/ui-grid-row',
30196 "<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\" ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' + col.uid + '-cell'\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\" ui-grid-cell></div>"
30197 );
30198
30199
30200 $templateCache.put('ui-grid/ui-grid',
30201 "<div ui-i18n=\"en\" class=\"ui-grid\"><!-- TODO (c0bra): add \"scoped\" attr here, eventually? --><style ui-grid-style>.grid{{ grid.id }} {\n" +
30202 " /* Styles for the grid */\n" +
30203 " }\n" +
30204 "\n" +
30205 " .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\n" +
30206 " height: {{ grid.options.rowHeight }}px;\n" +
30207 " }\n" +
30208 "\n" +
30209 " .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\n" +
30210 " border-bottom-width: {{ (((grid.getVisibleRowCount() * grid.options.rowHeight) < grid.getViewportHeight()) && '1') || '0' }}px;\n" +
30211 " }\n" +
30212 "\n" +
30213 " {{ grid.verticalScrollbarStyles }}\n" +
30214 " {{ grid.horizontalScrollbarStyles }}\n" +
30215 "\n" +
30216 " /*\n" +
30217 " .ui-grid[dir=rtl] .ui-grid-viewport {\n" +
30218 " padding-left: {{ grid.verticalScrollbarWidth }}px;\n" +
30219 " }\n" +
30220 " */\n" +
30221 "\n" +
30222 " {{ grid.customStyles }}</style><div class=\"ui-grid-contents-wrapper\" role=\"grid\"><div ui-grid-menu-button ng-if=\"grid.options.enableGridMenu\"></div><div ng-if=\"grid.hasLeftContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'left'\"></div><div ui-grid-render-container container-id=\"'body'\" col-container-name=\"'body'\" row-container-name=\"'body'\" bind-scroll-horizontal=\"true\" bind-scroll-vertical=\"true\" enable-horizontal-scrollbar=\"grid.options.enableHorizontalScrollbar\" enable-vertical-scrollbar=\"grid.options.enableVerticalScrollbar\"></div><div ng-if=\"grid.hasRightContainer()\" style=\"width: 0\" ui-grid-pinned-container=\"'right'\"></div><div ui-grid-grid-footer ng-if=\"grid.options.showGridFooter\"></div><div ui-grid-column-menu ng-if=\"grid.options.enableColumnMenus\"></div><div ng-transclude></div></div></div>"
30223 );
30224
30225
30226 $templateCache.put('ui-grid/uiGridCell',
30227 "<div class=\"ui-grid-cell-contents\" title=\"TOOLTIP\">{{COL_FIELD CUSTOM_FILTERS}}</div>"
30228 );
30229
30230
30231 $templateCache.put('ui-grid/uiGridColumnMenu',
30232 "<div class=\"ui-grid-column-menu\"><div ui-grid-menu menu-items=\"menuItems\"><!-- <div class=\"ui-grid-column-menu\">\n" +
30233 " <div class=\"inner\" ng-show=\"menuShown\">\n" +
30234 " <ul>\n" +
30235 " <div ng-show=\"grid.options.enableSorting\">\n" +
30236 " <li ng-click=\"sortColumn($event, asc)\" ng-class=\"{ 'selected' : col.sort.direction == asc }\"><i class=\"ui-grid-icon-sort-alt-up\"></i> Sort Ascending</li>\n" +
30237 " <li ng-click=\"sortColumn($event, desc)\" ng-class=\"{ 'selected' : col.sort.direction == desc }\"><i class=\"ui-grid-icon-sort-alt-down\"></i> Sort Descending</li>\n" +
30238 " <li ng-show=\"col.sort.direction\" ng-click=\"unsortColumn()\"><i class=\"ui-grid-icon-cancel\"></i> Remove Sort</li>\n" +
30239 " </div>\n" +
30240 " </ul>\n" +
30241 " </div>\n" +
30242 " </div> --></div></div>"
30243 );
30244
30245
30246 $templateCache.put('ui-grid/uiGridFooterCell',
30247 "<div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>"
30248 );
30249
30250
30251 $templateCache.put('ui-grid/uiGridHeaderCell',
30252 "<div role=\"columnheader\" ng-class=\"{ 'sortable': sortable, 'ui-grid-header-cell-last-col': isLastCol }\" ui-grid-one-bind-aria-labelledby-grid=\"col.uid + '-header-text ' + col.uid + '-sortdir-text'\" aria-sort=\"{{col.sort.direction == asc ? 'ascending' : ( col.sort.direction == desc ? 'descending' : (!col.sort.direction ? 'none' : 'other'))}}\"><div role=\"button\" tabindex=\"0\" ng-keydown=\"handleKeyDown($event)\" class=\"ui-grid-cell-contents ui-grid-header-cell-primary-focus\" col-index=\"renderIndex\" title=\"TOOLTIP\"><span class=\"ui-grid-header-cell-label\" ui-grid-one-bind-id-grid=\"col.uid + '-header-text'\">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid=\"col.uid + '-sortdir-text'\" ui-grid-visible=\"col.sort.direction\" aria-label=\"{{getSortDirectionAriaLabel()}}\"><i ng-class=\"{ 'ui-grid-icon-up-dir': col.sort.direction == asc, 'ui-grid-icon-down-dir': col.sort.direction == desc, 'ui-grid-icon-blank': !col.sort.direction }\" title=\"{{isSortPriorityVisible() ? i18n.headerCell.priority + ' ' + ( col.sort.priority + 1 ) : null}}\" aria-hidden=\"true\"></i> <sub ui-grid-visible=\"isSortPriorityVisible()\" class=\"ui-grid-sort-priority-number\">{{col.sort.priority + 1}}</sub></span></div><div role=\"button\" tabindex=\"0\" ui-grid-one-bind-id-grid=\"col.uid + '-menu-button'\" class=\"ui-grid-column-menu-button\" ng-if=\"grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false\" ng-click=\"toggleMenu($event)\" ng-keydown=\"headerCellArrowKeyDown($event)\" ui-grid-one-bind-aria-label=\"i18n.headerCell.aria.columnMenuButtonLabel\" aria-haspopup=\"true\"><i class=\"ui-grid-icon-angle-down\" aria-hidden=\"true\">&nbsp;</i></div><div ui-grid-filter></div></div>"
30253 );
30254
30255
30256 $templateCache.put('ui-grid/uiGridMenu',
30257 "<div class=\"ui-grid-menu\" ng-show=\"shown\"><style ui-grid-style>{{dynamicStyles}}</style><div class=\"ui-grid-menu-mid\" ng-show=\"shownMid\"><div class=\"ui-grid-menu-inner\" ng-if=\"shown\"><ul role=\"menu\" class=\"ui-grid-menu-items\"><li ng-repeat=\"item in menuItems\" role=\"menuitem\" ui-grid-menu-item ui-grid-one-bind-id=\"'menuitem-'+$index\" action=\"item.action\" name=\"item.title\" active=\"item.active\" icon=\"item.icon\" shown=\"item.shown\" context=\"item.context\" template-url=\"item.templateUrl\" leave-open=\"item.leaveOpen\" screen-reader-only=\"item.screenReaderOnly\"></li></ul></div></div></div>"
30258 );
30259
30260
30261 $templateCache.put('ui-grid/uiGridMenuItem',
30262 "<button type=\"button\" class=\"ui-grid-menu-item\" ng-click=\"itemAction($event, title)\" ng-show=\"itemShown()\" ng-class=\"{ 'ui-grid-menu-item-active': active(), 'ui-grid-sr-only': (!focus && screenReaderOnly) }\" aria-pressed=\"{{active()}}\" tabindex=\"0\" ng-focus=\"focus=true\" ng-blur=\"focus=false\"><i ng-class=\"icon\" aria-hidden=\"true\">&nbsp; </i>{{ label() }}</button>"
30263 );
30264
30265
30266 $templateCache.put('ui-grid/uiGridRenderContainer',
30267 "<div role=\"presentation\" ui-grid-one-bind-id-grid=\"containerId + '-grid-container'\" class=\"ui-grid-render-container\" ng-style=\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\"><!-- All of these dom elements are replaced in place --><div ui-grid-header></div><div ui-grid-viewport></div><div ng-if=\"colContainer.needsHScrollbarPlaceholder()\" class=\"ui-grid-scrollbar-placeholder\" ng-style=\"{height: colContainer.grid.scrollbarHeight + 'px'}\"></div><ui-grid-footer ng-if=\"grid.options.showColumnFooter\"></ui-grid-footer></div>"
30268 );
30269
30270
30271 $templateCache.put('ui-grid/uiGridViewport',
30272 "<div role=\"rowgroup\" class=\"ui-grid-viewport\" ng-style=\"colContainer.getViewportStyle()\"><!-- tbody --><div class=\"ui-grid-canvas\"><div ng-repeat=\"(rowRenderIndex, row) in rowContainer.renderedRows track by $index\" class=\"ui-grid-row\" ng-style=\"Viewport.rowStyle(rowRenderIndex)\"><div role=\"row\" ui-grid-row=\"row\" row-render-index=\"rowRenderIndex\"></div></div></div></div>"
30273 );
30274
30275
30276 $templateCache.put('ui-grid/cellEditor',
30277 "<div><form name=\"inputForm\"><input type=\"INPUT_TYPE\" ng-class=\"'colt' + col.uid\" ui-grid-editor ng-model=\"MODEL_COL_FIELD\"></form></div>"
30278 );
30279
30280
30281 $templateCache.put('ui-grid/dropdownEditor',
30282 "<div><form name=\"inputForm\"><select ng-class=\"'colt' + col.uid\" ui-grid-edit-dropdown ng-model=\"MODEL_COL_FIELD\" ng-options=\"field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray\"></select></form></div>"
30283 );
30284
30285
30286 $templateCache.put('ui-grid/fileChooserEditor',
30287 "<div><form name=\"inputForm\"><input ng-class=\"'colt' + col.uid\" ui-grid-edit-file-chooser type=\"file\" id=\"files\" name=\"files[]\" ng-model=\"MODEL_COL_FIELD\"></form></div>"
30288 );
30289
30290
30291 $templateCache.put('ui-grid/emptyBaseLayerContainer',
30292 "<div class=\"ui-grid-empty-base-layer-container ui-grid-canvas\"><div class=\"ui-grid-row\" ng-repeat=\"(rowRenderIndex, row) in grid.baseLayer.emptyRows track by $index\" ng-style=\"Viewport.rowStyle(rowRenderIndex)\"><div><div><div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell {{ col.getColClass(false) }}\"></div></div></div></div></div>"
30293 );
30294
30295
30296 $templateCache.put('ui-grid/expandableRow',
30297 "<div ui-grid-expandable-row ng-if=\"expandableRow.shouldRenderExpand()\" class=\"expandableRow\" style=\"float:left; margin-top: 1px; margin-bottom: 1px\" ng-style=\"{width: (grid.renderContainers.body.getCanvasWidth()) + 'px', height: row.expandedRowHeight + 'px'}\"></div>"
30298 );
30299
30300
30301 $templateCache.put('ui-grid/expandableRowHeader',
30302 "<div class=\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\"><div class=\"ui-grid-cell-contents\"><i class=\"clickable\" ng-if=\"!(row.groupHeader==true || row.entity.subGridOptions.disableRowExpandable)\" ng-class=\"{ 'ui-grid-icon-plus-squared' : !row.isExpanded, 'ui-grid-icon-minus-squared' : row.isExpanded }\" ng-click=\"grid.api.expandable.toggleRowExpansion(row.entity, $event)\"></i></div></div>"
30303 );
30304
30305
30306 $templateCache.put('ui-grid/expandableScrollFiller',
30307 "<div ng-if=\"expandableRow.shouldRenderFiller()\" ng-class=\"{scrollFiller: true, scrollFillerClass:(colContainer.name === 'body')}\" ng-style=\"{ width: (grid.getViewportWidth()) + 'px', height: row.expandedRowHeight + 2 + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\">&nbsp;</div>"
30308 );
30309
30310
30311 $templateCache.put('ui-grid/expandableTopRowHeader',
30312 "<div class=\"ui-grid-row-header-cell ui-grid-expandable-buttons-cell\"><div class=\"ui-grid-cell-contents\"><span class=\"ui-grid-cell-empty\" ng-if=\"!grid.options.showExpandAllButton\"></span> <button type=\"button\" class=\"ui-grid-icon-button clickable\" ng-if=\"grid.options.showExpandAllButton\" ng-class=\"{ 'ui-grid-icon-plus-squared' : !grid.expandable.expandedAll, 'ui-grid-icon-minus-squared' : grid.expandable.expandedAll }\" ng-click=\"grid.api.expandable.toggleAllRows()\"></button></div></div>"
30313 );
30314
30315
30316 $templateCache.put('ui-grid/csvLink',
30317 "<span class=\"ui-grid-exporter-csv-link-span\"><a href=\"data:text/csv;charset=UTF-8,CSV_CONTENT\" download=\"FILE_NAME\">LINK_LABEL</a></span>"
30318 );
30319
30320
30321 $templateCache.put('ui-grid/importerMenuItem',
30322 "<li class=\"ui-grid-menu-item\"><form><input class=\"ui-grid-importer-file-chooser\" type=\"file\" id=\"files\" name=\"files[]\"></form></li>"
30323 );
30324
30325
30326 $templateCache.put('ui-grid/importerMenuItemContainer',
30327 "<div ui-grid-importer-menu-item></div>"
30328 );
30329
30330
30331 $templateCache.put('ui-grid/pagination',
30332 "<div class=\"ui-grid-pager-panel\" ui-grid-pager ng-show=\"grid.options.enablePaginationControls\"><div role=\"navigation\" class=\"ui-grid-pager-container\"><div class=\"ui-grid-pager-control\"><button type=\"button\" class=\"ui-grid-pager-first\" ui-grid-one-bind-title=\"aria.pageToFirst\" ui-grid-one-bind-aria-label=\"aria.pageToFirst\" ng-click=\"pageFirstPageClick()\" ng-disabled=\"cantPageBackward()\"><div ng-class=\"grid.isRTL() ? 'last-triangle' : 'first-triangle'\"><div ng-class=\"grid.isRTL() ? 'last-bar-rtl' : 'first-bar'\"></div></div></button> <button type=\"button\" class=\"ui-grid-pager-previous\" ui-grid-one-bind-title=\"aria.pageBack\" ui-grid-one-bind-aria-label=\"aria.pageBack\" ng-click=\"pagePreviousPageClick()\" ng-disabled=\"cantPageBackward()\"><div ng-class=\"grid.isRTL() ? 'last-triangle prev-triangle' : 'first-triangle prev-triangle'\"></div></button> <input type=\"number\" ui-grid-one-bind-title=\"aria.pageSelected\" ui-grid-one-bind-aria-label=\"aria.pageSelected\" class=\"ui-grid-pager-control-input\" ng-model=\"grid.options.paginationCurrentPage\" min=\"1\" max=\"{{ paginationApi.getTotalPages() }}\" step=\"1\" required> <span class=\"ui-grid-pager-max-pages-number\" ng-show=\"paginationApi.getTotalPages() > 0\"><abbr ui-grid-one-bind-title=\"paginationOf\">/ </abbr>{{ paginationApi.getTotalPages() }} </span><button type=\"button\" class=\"ui-grid-pager-next\" ui-grid-one-bind-title=\"aria.pageForward\" ui-grid-one-bind-aria-label=\"aria.pageForward\" ng-click=\"pageNextPageClick()\" ng-disabled=\"cantPageForward()\"><div ng-class=\"grid.isRTL() ? 'first-triangle next-triangle' : 'last-triangle next-triangle'\"></div></button> <button type=\"button\" class=\"ui-grid-pager-last\" ui-grid-one-bind-title=\"aria.pageToLast\" ui-grid-one-bind-aria-label=\"aria.pageToLast\" ng-click=\"pageLastPageClick()\" ng-disabled=\"cantPageToLast()\"><div ng-class=\"grid.isRTL() ? 'first-triangle' : 'last-triangle'\"><div ng-class=\"grid.isRTL() ? 'first-bar-rtl' : 'last-bar'\"></div></div></button></div><div class=\"ui-grid-pager-row-count-picker\" ng-if=\"grid.options.paginationPageSizes.length > 1 && !grid.options.useCustomPagination\"><select ui-grid-one-bind-aria-labelledby-grid=\"'items-per-page-label'\" ng-model=\"grid.options.paginationPageSize\" ng-options=\"o as o for o in grid.options.paginationPageSizes\"></select><span ui-grid-one-bind-id-grid=\"'items-per-page-label'\" class=\"ui-grid-pager-row-count-label\">&nbsp;{{sizesLabel}}</span></div><span ng-if=\"grid.options.paginationPageSizes.length <= 1\" class=\"ui-grid-pager-row-count-label\">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class=\"ui-grid-pager-count-container\"><div class=\"ui-grid-pager-count\"><span ng-show=\"grid.options.totalItems > 0\">{{ 1 + paginationApi.getFirstRowIndex() }} <abbr ui-grid-one-bind-title=\"paginationThrough\">- </abbr>{{ 1 + paginationApi.getLastRowIndex() }} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>"
30333 );
30334
30335
30336 $templateCache.put('ui-grid/columnResizer',
30337 "<div ui-grid-column-resizer ng-if=\"grid.options.enableColumnResizing\" class=\"ui-grid-column-resizer\" col=\"col\" position=\"right\" render-index=\"renderIndex\" unselectable=\"on\"></div>"
30338 );
30339
30340
30341 $templateCache.put('ui-grid/gridFooterSelectedItems',
30342 "<span ng-if=\"grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected\">({{\"search.selectedItems\" | t}} {{grid.selection.selectedCount}})</span>"
30343 );
30344
30345
30346 $templateCache.put('ui-grid/selectionHeaderCell',
30347 "<div><!-- <div class=\"ui-grid-vertical-bar\">&nbsp;</div> --><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><ui-grid-selection-select-all-buttons ng-if=\"grid.options.enableSelectAll\" role=\"checkbox\" ng-model=\"grid.selection.selectAll\"></ui-grid-selection-select-all-buttons></div></div>"
30348 );
30349
30350
30351 $templateCache.put('ui-grid/selectionRowHeader',
30352 "<div class=\"ui-grid-cell-contents ui-grid-disable-selection clickable\"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div>"
30353 );
30354
30355
30356 $templateCache.put('ui-grid/selectionRowHeaderButtons',
30357 "<div class=\"ui-grid-selection-row-header-buttons ui-grid-icon-ok clickable\" ng-class=\"{'ui-grid-row-selected': row.isSelected}\" ng-click=\"selectButtonClick(row, $event)\" ng-keydown=\"selectButtonKeyDown(row, $event)\" role=\"checkbox\" ng-model=\"row.isSelected\">&nbsp;</div>"
30358 );
30359
30360
30361 $templateCache.put('ui-grid/selectionSelectAllButtons',
30362 "<div role=\"button\" class=\"ui-grid-selection-row-header-buttons ui-grid-icon-ok\" ng-class=\"{'ui-grid-all-selected': grid.selection.selectAll}\" ng-click=\"headerButtonClick($event)\" ng-keydown=\"headerButtonKeyDown($event)\"></div>"
30363 );
30364
30365
30366 $templateCache.put('ui-grid/treeBaseExpandAllButtons',
30367 "<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"headerButtonClass()\" ng-click=\"headerButtonClick($event)\"></div>"
30368 );
30369
30370
30371 $templateCache.put('ui-grid/treeBaseHeaderCell',
30372 "<div><div class=\"ui-grid-cell-contents\" col-index=\"renderIndex\"><ui-grid-tree-base-expand-all-buttons ng-if=\"grid.options.enableExpandAll\"></ui-grid-tree-base-expand-all-buttons></div></div>"
30373 );
30374
30375
30376 $templateCache.put('ui-grid/treeBaseRowHeader',
30377 "<div class=\"ui-grid-cell-contents\"><ui-grid-tree-base-row-header-buttons></ui-grid-tree-base-row-header-buttons></div>"
30378 );
30379
30380
30381 $templateCache.put('ui-grid/treeBaseRowHeaderButtons',
30382 "<div class=\"ui-grid-tree-base-row-header-buttons\" ng-class=\"{'ui-grid-tree-base-header': row.treeLevel > -1 }\" ng-click=\"treeButtonClick(row, $event)\"><i ng-class=\"treeButtonClass(row)\" ng-style=\"{'padding-left': grid.options.treeIndent * row.treeLevel + 'px'}\"></i> &nbsp;</div>"
30383 );
30384
30385
30386 $templateCache.put('ui-grid/cellTitleValidator',
30387 "<div class=\"ui-grid-cell-contents\" ng-class=\"{invalid:grid.validate.isInvalid(row.entity,col.colDef)}\" title=\"{{grid.validate.getTitleFormattedErrors(row.entity,col.colDef)}}\">{{COL_FIELD CUSTOM_FILTERS}}</div>"
30388 );
30389
30390
30391 $templateCache.put('ui-grid/cellTooltipValidator',
30392 "<div class=\"ui-grid-cell-contents\" ng-class=\"{invalid:grid.validate.isInvalid(row.entity,col.colDef)}\" tooltip-html-unsafe=\"{{grid.validate.getFormattedErrors(row.entity,col.colDef)}}\" tooltip-enable=\"grid.validate.isInvalid(row.entity,col.colDef)\" tooltip-append-to-body=\"true\" tooltip-placement=\"top\" title=\"TOOLTIP\">{{COL_FIELD CUSTOM_FILTERS}}</div>"
30393 );
30394
30395 }]);
+0
-7
faraday/server/www/script/ui-grid.min.js less more
0 /*!
1 * ui-grid - v4.6.3 - 2018-08-04
2 * Copyright (c) 2018 ; License: MIT
3 */
4
5
6 !function(){"use strict";angular.module("ui.grid.i18n",[]),angular.module("ui.grid",["ui.grid.i18n"])}(),function(){"use strict";angular.module("ui.grid").constant("uiGridConstants",{LOG_DEBUG_MESSAGES:!0,LOG_WARN_MESSAGES:!0,LOG_ERROR_MESSAGES:!0,CUSTOM_FILTERS:/CUSTOM_FILTERS/g,COL_FIELD:/COL_FIELD/g,MODEL_COL_FIELD:/MODEL_COL_FIELD/g,TOOLTIP:/title=\"TOOLTIP\"/g,DISPLAY_CELL_TEMPLATE:/DISPLAY_CELL_TEMPLATE/g,TEMPLATE_REGEXP:/<.+>/,FUNC_REGEXP:/(\([^)]*\))?$/,DOT_REGEXP:/\./g,APOS_REGEXP:/'/g,BRACKET_REGEXP:/^(.*)((?:\s*\[\s*\d+\s*\]\s*)|(?:\s*\[\s*"(?:[^"\\]|\\.)*"\s*\]\s*)|(?:\s*\[\s*'(?:[^'\\]|\\.)*'\s*\]\s*))(.*)$/,COL_CLASS_PREFIX:"ui-grid-col",ENTITY_BINDING:"$$this",events:{GRID_SCROLL:"uiGridScroll",COLUMN_MENU_SHOWN:"uiGridColMenuShown",ITEM_DRAGGING:"uiGridItemDragStart",COLUMN_HEADER_CLICK:"uiGridColumnHeaderClick"},keymap:{TAB:9,STRG:17,CAPSLOCK:20,CTRL:17,CTRLRIGHT:18,CTRLR:18,SHIFT:16,RETURN:13,ENTER:13,BACKSPACE:8,BCKSP:8,ALT:18,ALTR:17,ALTRIGHT:17,SPACE:32,WIN:91,MAC:91,FN:null,PG_UP:33,PG_DOWN:34,UP:38,DOWN:40,LEFT:37,RIGHT:39,ESC:27,DEL:46,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123},ASC:"asc",DESC:"desc",filter:{STARTS_WITH:2,ENDS_WITH:4,EXACT:8,CONTAINS:16,GREATER_THAN:32,GREATER_THAN_OR_EQUAL:64,LESS_THAN:128,LESS_THAN_OR_EQUAL:256,NOT_EQUAL:512,SELECT:"select",INPUT:"input"},aggregationTypes:{sum:2,count:4,avg:8,min:16,max:32},CURRENCY_SYMBOLS:["¤","؋","Ar","Ƀ","฿","B/.","Br","Bs.","Bs.F.","GH₵","¢","c","Ch.","₡","C$","D","ден","دج",".د.ب","د.ع","JD","د.ك","ل.د","дин","د.ت","د.م.","د.إ","Db","$","₫","Esc","€","ƒ","Ft","FBu","FCFA","CFA","Fr","FRw","G","gr","₲","h","₴","₭","Kč","kr","kn","MK","ZK","Kz","K","L","Le","лв","E","lp","M","KM","MT","₥","Nfk","₦","Nu.","UM","T$","MOP$","₱","Pt.","£","ج.م.","LL","LS","P","Q","q","R","R$","ر.ع.","ر.ق","ر.س","៛","RM","p","Rf.","₹","₨","SRe","Rp","₪","Ksh","Sh.So.","USh","S/","SDR","сом","৳\t","WS$","₮","VT","₩","¥","zł"],scrollDirection:{UP:"up",DOWN:"down",LEFT:"left",RIGHT:"right",NONE:"none"},dataChange:{ALL:"all",EDIT:"edit",ROW:"row",COLUMN:"column",OPTIONS:"options"},scrollbars:{NEVER:0,ALWAYS:1,WHEN_NEEDED:2}})}(),angular.module("ui.grid").directive("uiGridCell",["$compile","$parse","gridUtil","uiGridConstants",function(a,e,l,s){return{priority:0,scope:!1,require:"?^uiGrid",compile:function(){return{pre:function(t,r,e,i){if(i&&t.col.compiledElementFn)(0,t.col.compiledElementFn)(t,function(e,t){r.append(e)});else if(i&&!t.col.compiledElementFn)t.col.getCompiledElementFn().then(function(e){e(t,function(e,t){r.append(e)})}).catch(angular.noop);else{var n=t.col.cellTemplate.replace(s.MODEL_COL_FIELD,"row.entity."+l.preEval(t.col.field)).replace(s.COL_FIELD,"grid.getCellValue(row, col)"),o=a(n)(t);r.append(o)}},post:function(i,n){var o,a=i.col.getColClass(!1);function l(e){var t=n;o&&(t.removeClass(o),o=null),o=angular.isFunction(i.col.cellClass)?i.col.cellClass(i.grid,i.row,i.col,i.rowRenderIndex,i.colRenderIndex):i.col.cellClass,t.addClass(o)}n.addClass(a),i.col.cellClass&&l();var e=i.grid.registerDataChangeCallback(l,[s.dataChange.COLUMN,s.dataChange.EDIT]);var t=i.$watch("row",function(e,t){if(e!==t){(o||i.col.cellClass)&&l();var r=i.col.getColClass(!1);r!==a&&(n.removeClass(a),n.addClass(r),a=r)}});function r(){e(),t()}i.$on("$destroy",r),n.on("$destroy",r)}}}}}]),angular.module("ui.grid").service("uiGridColumnMenuService",["i18nService","uiGridConstants","gridUtil",function(e,r,g){var i={initialize:function(e,t){e.grid=t.grid,(t.columnMenuScope=e).menuShown=!1},setColMenuItemWatch:function(t){var e=t.$watch("col.menuItems",function(e){void 0!==e&&e&&angular.isArray(e)?(e.forEach(function(e){void 0!==e.context&&e.context||(e.context={}),e.context.col=t.col}),t.menuItems=t.defaultMenuItems.concat(e)):t.menuItems=t.defaultMenuItems});t.$on("$destroy",e)},sortable:function(e){return Boolean(e.grid.options.enableSorting&&void 0!==e.col&&e.col&&e.col.enableSorting)},isActiveSort:function(e,t){return Boolean(void 0!==e.col&&void 0!==e.col.sort&&void 0!==e.col.sort.direction&&e.col.sort.direction===t)},suppressRemoveSort:function(e){return Boolean(e.col&&e.col.suppressRemoveSort)},hideable:function(e){return!(void 0!==e.col&&e.col&&e.col.colDef&&!1===e.col.colDef.enableHiding)},getDefaultMenuItems:function(t){return[{title:function(){return e.getSafeText("sort.ascending")},icon:"ui-grid-icon-sort-alt-up",action:function(e){e.stopPropagation(),t.sortColumn(e,r.ASC)},shown:function(){return i.sortable(t)},active:function(){return i.isActiveSort(t,r.ASC)}},{title:function(){return e.getSafeText("sort.descending")},icon:"ui-grid-icon-sort-alt-down",action:function(e){e.stopPropagation(),t.sortColumn(e,r.DESC)},shown:function(){return i.sortable(t)},active:function(){return i.isActiveSort(t,r.DESC)}},{title:function(){return e.getSafeText("sort.remove")},icon:"ui-grid-icon-cancel",action:function(e){e.stopPropagation(),t.unsortColumn()},shown:function(){return i.sortable(t)&&void 0!==t.col&&void 0!==t.col.sort&&void 0!==t.col.sort.direction&&null!==t.col.sort.direction&&!i.suppressRemoveSort(t)}},{title:function(){return e.getSafeText("column.hide")},icon:"ui-grid-icon-cancel",shown:function(){return i.hideable(t)},action:function(e){e.stopPropagation(),t.hideColumn()}}]},getColumnElementPosition:function(e,t,r){var i={};return i.left=r[0].offsetLeft,i.top=r[0].offsetTop,i.parentLeft=r[0].offsetParent.offsetLeft,i.offset=0,t.grid.options.offsetLeft&&(i.offset=t.grid.options.offsetLeft),i.height=g.elementHeight(r,!0),i.width=g.elementWidth(r,!0),i},repositionMenu:function(e,t,r,i,n){var o=i[0].querySelectorAll(".ui-grid-menu"),a=g.closestElm(n,".ui-grid-render-container"),l=a.getBoundingClientRect().left-e.grid.element[0].getBoundingClientRect().left,s=a.querySelectorAll(".ui-grid-viewport")[0].scrollLeft,d=g.elementWidth(o,!0),u=t.lastMenuPaddingRight?t.lastMenuPaddingRight:e.lastMenuPaddingRight?e.lastMenuPaddingRight:10;0!==o.length&&0!==o[0].querySelectorAll(".ui-grid-menu-mid").length&&(u=parseInt(g.getStyles(angular.element(o)[0]).paddingRight,10),e.lastMenuPaddingRight=u,t.lastMenuPaddingRight=u);var c=r.left+l-s+r.parentLeft+r.width+u;c<r.offset+d&&(c=Math.max(r.left-s+r.parentLeft-u+d,r.offset+d)),i.css("left",c+"px"),i.css("top",r.top+r.height+"px")}};return i}]).directive("uiGridColumnMenu",["$timeout","gridUtil","uiGridConstants","uiGridColumnMenuService","$document",function(r,n,a,l,s){return{priority:0,scope:!0,require:"^uiGrid",templateUrl:"ui-grid/uiGridColumnMenu",replace:!0,link:function(o,i,e,t){l.initialize(o,t),o.defaultMenuItems=l.getDefaultMenuItems(o),o.menuItems=o.defaultMenuItems,l.setColMenuItemWatch(o),o.showMenu=function(e,t,r){o.col=e;var i=l.getColumnElementPosition(o,e,t);o.menuShown?(o.colElement=t,o.colElementPosition=i,o.hideThenShow=!0,o.$broadcast("hide-menu",{originalEvent:r})):(o.menuShown=!0,o.colElement=t,o.colElementPosition=i,o.$broadcast("show-menu",{originalEvent:r}))},o.hideMenu=function(e){o.menuShown=!1,e||o.$broadcast("hide-menu")},o.$on("menu-hidden",function(){var e=angular.element(i[0].querySelector(".ui-grid-menu-items"))[0];i[0].removeAttribute("style"),o.hideThenShow?(delete o.hideThenShow,o.$broadcast("show-menu"),o.menuShown=!0):(o.hideMenu(!0),o.col&&n.focus.bySelector(s,".ui-grid-header-cell."+o.col.getColClass()+" .ui-grid-column-menu-button",o.col.grid,!1)),e&&(e.onkeydown=null,angular.forEach(e.children,function(e){e.onkeydown=null}))}),o.$on("menu-shown",function(){r(function(){l.repositionMenu(o,o.col,o.colElementPosition,i,o.colElement),n.focus.bySelector(s,".ui-grid-menu-items .ui-grid-menu-item:not(.ng-hide)",!0),delete o.colElementPosition,delete o.columnElement,function(){var e,t=angular.element(i[0].querySelector(".ui-grid-menu-items"))[0],n=[];function r(e,t,r,i){e.keyCode===a.keymap.TAB&&(t?e.preventDefault():r&&(e.preventDefault(),n[i].focus()))}t&&(t.onkeydown=function(e){e.keyCode===a.keymap.ESC&&(e.preventDefault(),o.hideMenu())},e=t.querySelectorAll(".ui-grid-menu-item:not(.ng-hide)"),angular.forEach(e,function(e){null!==e.offsetParent&&this.push(e)},n),n.length&&(1===n.length?n[0].onkeydown=function(e){r(e,!0)}:(n[0].onkeydown=function(e){r(e,!1,e.shiftKey,n.length-1)},n[n.length-1].onkeydown=function(e){r(e,!1,!e.shiftKey,0)})))}()})}),o.sortColumn=function(e,t){e.stopPropagation(),o.grid.sortColumn(o.col,t,!0).then(function(){o.grid.refresh(),o.hideMenu()}).catch(angular.noop)},o.unsortColumn=function(){o.col.unsort(),o.grid.refresh(),o.hideMenu()},o.hideColumn=function(){o.col.colDef.visible=!1,o.col.visible=!1,o.grid.queueGridRefresh(),o.hideMenu(),o.grid.api.core.notifyDataChange(a.dataChange.COLUMN),o.grid.api.core.raise.columnVisibilityChanged(o.col),r(function(){var r,i,t=function(){return n.focus.byId("grid-menu",o.grid)};if(o.grid.columns.some(function(e,t){if(angular.equals(e,o.col))return r=t,!0}),o.grid.columns.some(function(e,t){if(!e.visible)return!1;if(t<r)i=e;else{if(r<t&&!i)return i=e,!0;if(r<t&&i)return!0}}),i){var e=i.getColClass();n.focus.bySelector(s,".ui-grid-header-cell."+e+" .ui-grid-header-cell-primary-focus",!0).then(angular.noop,function(e){if("canceled"!==e)return t()}).catch(angular.noop)}else t()})}},controller:["$scope",function(e){var t=this;e.$watch("menuItems",function(e){t.menuItems=e})}]}}]),function(){"use strict";angular.module("ui.grid").directive("uiGridFilter",["$compile","$templateCache","i18nService","gridUtil",function(n,e,t,i){return{compile:function(){return{pre:function(r,i){r.col.updateFilters=function(e){if(i.children().remove(),e){var t=r.col.filterHeaderTemplate;void 0===t&&""!==r.col.providedFilterHeaderTemplate?r.col.filterHeaderTemplatePromise&&r.col.filterHeaderTemplatePromise.then(function(){t=r.col.filterHeaderTemplate,i.append(n(t)(r))}):i.append(n(t)(r))}},r.$on("$destroy",function(){delete r.col.updateFilters})},post:function(e,r){e.aria=t.getSafeText("headerCell.aria"),e.removeFilter=function(e,t){e.term=null,i.focus.bySelector(r,".ui-grid-filter-input-"+t)}}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridFooterCell",["$timeout","gridUtil","uiGridConstants","$compile",function(e,t,s,i){return{priority:0,scope:{col:"=",row:"=",renderIndex:"="},replace:!0,require:"^uiGrid",compile:function(){return{pre:function(e,t){var r=e.col.footerCellTemplate;void 0===r&&""!==e.col.providedFooterCellTemplate?e.col.footerCellTemplatePromise&&e.col.footerCellTemplatePromise.then(function(){r=e.col.footerCellTemplate,t.append(i(r)(e))}):t.append(i(r)(e))},post:function(t,r,e,i){t.grid=i.grid;var n,o=t.col.getColClass(!1);r.addClass(o);var a=function(){var e=r;n&&(e.removeClass(n),n=null),n=angular.isFunction(t.col.footerCellClass)?t.col.footerCellClass(t.grid,t.row,t.col,t.rowRenderIndex,t.colRenderIndex):t.col.footerCellClass,e.addClass(n)};t.col.footerCellClass&&a(),t.col.updateAggregationValue();var l=t.grid.registerDataChangeCallback(a,[s.dataChange.COLUMN]);t.grid.api.core.on.rowsRendered(t,t.col.updateAggregationValue),t.grid.api.core.on.rowsRendered(t,a),t.$on("$destroy",l)}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridFooter",["$templateCache","$compile","uiGridConstants","gridUtil","$timeout",function(e,l,t,s,r){return{restrict:"EA",replace:!0,require:["^uiGrid","^uiGridRenderContainer"],scope:!0,compile:function(e,t){return{pre:function(n,o,e,t){var r=t[0],a=t[1];n.grid=r.grid,n.colContainer=a.colContainer,a.footer=o;var i=n.grid.options.footerTemplate;s.getTemplate(i).then(function(e){var t=angular.element(e),r=l(t)(n);if(o.append(r),a){var i=o[0].getElementsByClassName("ui-grid-footer-viewport")[0];i&&(a.footerViewport=i)}}).catch(angular.noop)},post:function(e,t,r,i){var n=i[0],o=i[1];n.grid;s.disableAnimations(t);var a=(o.footer=t)[0].getElementsByClassName("ui-grid-footer-viewport")[0];a&&(o.footerViewport=a)}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridGridFooter",["$templateCache","$compile","uiGridConstants","gridUtil",function(e,o,t,a){return{restrict:"EA",replace:!0,require:"^uiGrid",scope:!0,compile:function(){return{pre:function(i,n,e,t){i.grid=t.grid;var r=i.grid.options.gridFooterTemplate;a.getTemplate(r).then(function(e){var t=angular.element(e),r=o(t)(i);n.append(r)}).catch(angular.noop)}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridHeaderCell",["$compile","$timeout","$window","$document","gridUtil","uiGridConstants","ScrollEvent","i18nService",function(i,p,e,f,t,m,r,h){return{priority:0,scope:{col:"=",row:"=",renderIndex:"="},require:["^uiGrid","^uiGridRenderContainer"],replace:!0,compile:function(){return{pre:function(e,t){var r=e.col.headerCellTemplate;void 0===r&&""!==e.col.providedHeaderCellTemplate?e.col.headerCellTemplatePromise&&e.col.headerCellTemplatePromise.then(function(){r=e.col.headerCellTemplate,t.append(i(r)(e))}):t.append(i(r)(e))},post:function(r,i,e,t){var n=t[0],o=t[1];r.i18n={headerCell:h.getSafeText("headerCell"),sort:h.getSafeText("sort")},r.isSortPriorityVisible=function(){return angular.isNumber(r.col.sort.priority)&&r.grid.columns.some(function(e,t){return angular.isNumber(e.sort.priority)&&e!==r.col})},r.getSortDirectionAriaLabel=function(){var e=r.col,t=e.sort.direction===m.ASC?r.i18n.sort.ascending:e.sort.direction===m.DESC?r.i18n.sort.descending:r.i18n.sort.none;return r.isSortPriorityVisible()&&(t=t+". "+r.i18n.headerCell.priority+" "+(e.sort.priority+1)),t},r.grid=n.grid,r.renderContainer=n.grid.renderContainers[o.containerId];var a=r.col.getColClass(!1);i.addClass(a),r.menuShown=!1,r.asc=m.ASC,r.desc=m.DESC;var l,s,d=angular.element(i[0].querySelectorAll(".ui-grid-cell-contents")),u=[];r.downFn=function(e){e.stopPropagation(),void 0!==e.originalEvent&&void 0!==e.originalEvent&&(e=e.originalEvent),e.button&&0!==e.button||(s=e.pageX,r.mousedownStartTime=(new Date).getTime(),r.mousedownTimeout=p(function(){},500),r.mousedownTimeout.then(function(){r.colMenu&&n.columnMenuScope.showMenu(r.col,i,e)}).catch(angular.noop),n.fireEvent(m.events.COLUMN_HEADER_CLICK,{event:e,columnName:r.col.colDef.name}),r.offAllEvents(),"touchstart"===e.type?(f.on("touchend",r.upFn),f.on("touchmove",r.moveFn)):"mousedown"===e.type&&(f.on("mouseup",r.upFn),f.on("mousemove",r.moveFn)))},r.upFn=function(e){e.stopPropagation(),p.cancel(r.mousedownTimeout),r.offAllEvents(),r.onDownEvents(e.type),500<(new Date).getTime()-r.mousedownStartTime||r.sortable&&r.handleClick(e)},r.handleKeyDown=function(e){32===e.keyCode&&e.preventDefault()},r.moveFn=function(e){0!==e.pageX-s&&(p.cancel(r.mousedownTimeout),r.offAllEvents(),r.onDownEvents(e.type))},r.clickFn=function(e){e.stopPropagation(),d.off("click",r.clickFn)},r.offAllEvents=function(){d.off("touchstart",r.downFn),d.off("mousedown",r.downFn),f.off("touchend",r.upFn),f.off("mouseup",r.upFn),f.off("touchmove",r.moveFn),f.off("mousemove",r.moveFn),d.off("click",r.clickFn)},r.onDownEvents=function(e){switch(e){case"touchmove":case"touchend":d.on("click",r.clickFn),d.on("touchstart",r.downFn),p(function(){d.on("mousedown",r.downFn)},500);break;case"mousemove":case"mouseup":d.on("click",r.clickFn),d.on("mousedown",r.downFn),p(function(){d.on("touchstart",r.downFn)},500);break;default:d.on("click",r.clickFn),d.on("touchstart",r.downFn),d.on("mousedown",r.downFn)}};var c=function(){var e=i;l&&(e.removeClass(l),l=null),l=angular.isFunction(r.col.headerCellClass)?r.col.headerCellClass(r.grid,r.row,r.col,r.rowRenderIndex,r.colRenderIndex):r.col.headerCellClass,e.addClass(l),r.$applyAsync(function(){var e=r.grid.renderContainers.right&&r.grid.renderContainers.right.visibleColumnCache.length?r.grid.renderContainers.right:r.grid.renderContainers.body;r.isLastCol=n.grid.options&&n.grid.options.enableGridMenu&&r.col===e.visibleColumnCache[e.visibleColumnCache.length-1]}),r.sortable=Boolean(r.col.enableSorting);var t=r.filterable;r.filterable=Boolean(n.grid.options.enableFiltering&&r.col.enableFiltering),t!==r.filterable&&(void 0!==r.col.updateFilters&&r.col.updateFilters(r.filterable),r.filterable?(r.col.filters.forEach(function(e,t){u.push(r.$watch("col.filters["+t+"].term",function(e,t){e!==t&&(n.grid.api.core.raise.filterChanged(),n.grid.api.core.notifyDataChange(m.dataChange.COLUMN),n.grid.queueGridRefresh())}))}),r.$on("$destroy",function(){u.forEach(function(e){e()})})):u.forEach(function(e){e()})),r.colMenu=r.col.grid.options&&!1!==r.col.grid.options.enableColumnMenus&&r.col.colDef&&!1!==r.col.colDef.enableColumnMenu,r.offAllEvents(),(r.sortable||r.colMenu)&&(r.onDownEvents(),r.$on("$destroy",function(){r.offAllEvents()}))};c();var g=r.grid.registerDataChangeCallback(c,[m.dataChange.COLUMN]);r.$on("$destroy",g),r.handleClick=function(e){var t=!1;e.shiftKey&&(t=!0),n.grid.sortColumn(r.col,t).then(function(){n.columnMenuScope&&n.columnMenuScope.hideMenu(),n.grid.refresh()}).catch(angular.noop)},r.headerCellArrowKeyDown=function(e){32!==e.keyCode&&13!==e.keyCode||(e.preventDefault(),r.toggleMenu(e))},r.toggleMenu=function(e){e.stopPropagation(),n.columnMenuScope.menuShown&&n.columnMenuScope.col===r.col?n.columnMenuScope.hideMenu():n.columnMenuScope.showMenu(r.col,i)}}}}}}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridHeader",["$templateCache","$compile","uiGridConstants","gridUtil","$timeout","ScrollEvent",function(e,d,t,u,r,c){return{restrict:"EA",replace:!0,require:["^uiGrid","^uiGridRenderContainer"],scope:!0,compile:function(){return{pre:function(n,o,e,t){var r,i=t[0],a=t[1];function l(){a.header=a.colContainer.header=o;var e=o[0].getElementsByClassName("ui-grid-header-canvas");0<e.length?a.headerCanvas=a.colContainer.headerCanvas=e[0]:a.headerCanvas=null}function s(){if(!i.grid.isScrollingHorizontally){var e=u.normalizeScrollLeft(a.headerViewport,i.grid),t=a.colContainer.scrollHorizontal(e),r=new c(i.grid,null,a.colContainer,c.Sources.ViewPortScroll);r.newScrollLeft=e,-1<t&&(r.x={percentage:t}),i.grid.scrollContainers(null,r)}}n.grid=i.grid,n.colContainer=a.colContainer,l(),r=n.grid.options.showHeader?n.grid.options.headerTemplate?n.grid.options.headerTemplate:"ui-grid/ui-grid-header":"ui-grid/ui-grid-no-header",u.getTemplate(r).then(function(e){var t=angular.element(e),r=d(t)(n);if(o.replaceWith(r),o=r,l(),a){var i=o[0].getElementsByClassName("ui-grid-header-viewport")[0];i&&(a.headerViewport=i,angular.element(i).on("scroll",s),n.$on("$destroy",function(){angular.element(i).off("scroll",s)}))}n.grid.queueRefresh()}).catch(angular.noop)},post:function(e,t,r,i){var n=i[0],o=i[1];n.grid;u.disableAnimations(t);var a=(o.header=t)[0].getElementsByClassName("ui-grid-header-viewport")[0];a&&(o.headerViewport=a),n&&n.grid.registerStyleComputation({priority:15,func:function(){var e=o.colContainer.visibleColumnCache,t="",r=0;return e.forEach(function(e){t+=e.getColClassDefinition(),r+=e.drawnWidth}),o.colContainer.canvasWidth=r,t}})}}}}}])}(),angular.module("ui.grid").service("uiGridGridMenuService",["gridUtil","i18nService","uiGridConstants",function(n,a,t){var l={initialize:function(e,t){(t.gridMenuScope=e).grid=t,e.registeredMenuItems=[],e.$on("$destroy",function(){e.grid&&e.grid.gridMenuScope&&(e.grid.gridMenuScope=null),e.grid&&(e.grid=null),e.registeredMenuItems&&(e.registeredMenuItems=null)}),e.registeredMenuItems=[],t.api.registerMethod("core","addToGridMenu",l.addToGridMenu),t.api.registerMethod("core","removeFromGridMenu",l.removeFromGridMenu)},addToGridMenu:function(e,t){angular.isArray(t)?e.gridMenuScope?(e.gridMenuScope.registeredMenuItems=e.gridMenuScope.registeredMenuItems?e.gridMenuScope.registeredMenuItems:[],e.gridMenuScope.registeredMenuItems=e.gridMenuScope.registeredMenuItems.concat(t)):n.logError("Asked to addToGridMenu, but gridMenuScope not present. Timing issue? Please log issue with ui-grid"):n.logError("addToGridMenu: menuItems must be an array, and is not, not adding any items")},removeFromGridMenu:function(e,r){var i=-1;e&&e.gridMenuScope&&e.gridMenuScope.registeredMenuItems.forEach(function(e,t){e.id===r&&(-1<i?n.logError("removeFromGridMenu: found multiple items with the same id, removing only the last"):i=t)}),-1<i&&e.gridMenuScope.registeredMenuItems.splice(i,1)},getMenuItems:function(t){var e=[];t.grid.options.gridMenuCustomItems&&(angular.isArray(t.grid.options.gridMenuCustomItems)?e=e.concat(t.grid.options.gridMenuCustomItems):n.logError("gridOptions.gridMenuCustomItems must be an array, and is not"));var r=[{title:a.getSafeText("gridMenu.clearAllFilters"),action:function(e){t.grid.clearAllFilters()},shown:function(){return t.grid.options.enableFiltering},order:100}];return e=(e=e.concat(r)).concat(t.registeredMenuItems),!1!==t.grid.options.gridMenuShowHideColumns&&(e=e.concat(l.showHideColumns(t))),e.sort(function(e,t){return e.order-t.order}),e},showHideColumns:function(i){var n=[];if(!i.grid.options.columnDefs||0===i.grid.options.columnDefs.length||0===i.grid.columns.length)return n;function o(e){return!0===(t=e).visible||void 0===t.visible?"ui-grid-icon-ok":"ui-grid-icon-cancel";var t}return n.push({title:a.getSafeText("gridMenu.columns"),order:300,templateUrl:"ui-grid/ui-grid-menu-header-item"}),i.grid.options.gridMenuTitleFilter=i.grid.options.gridMenuTitleFilter?i.grid.options.gridMenuTitleFilter:function(e){return e},i.grid.options.columnDefs.forEach(function(e,t){if(!1!==e.enableHiding){var r={icon:o(e),action:function(e){e.stopPropagation(),l.toggleColumnVisibility(this.context.gridCol),e.target&&e.target.firstChild&&("I"===angular.element(e.target)[0].nodeName?e.target.className=o(this.context.gridCol.colDef):e.target.firstChild.className=o(this.context.gridCol.colDef))},shown:function(){return!1!==this.context.gridCol.colDef.enableHiding},context:{gridCol:i.grid.getColumn(e.name||e.field)},leaveOpen:!0,order:301+t};l.setMenuItemTitle(r,e,i.grid),n.push(r)}}),n},setMenuItemTitle:function(t,e,r){var i=r.options.gridMenuTitleFilter(e.displayName||n.readableColumnName(e.name)||e.field);"string"==typeof i?t.title=i:i.then?(t.title="",i.then(function(e){t.title=e},function(e){t.title=e}).catch(angular.noop)):(n.logError("Expected gridMenuTitleFilter to return a string or a promise, it has returned neither, bad config"),t.title="badconfig")},toggleColumnVisibility:function(e){e.colDef.visible=!(!0===e.colDef.visible||void 0===e.colDef.visible),e.grid.refresh(),e.grid.api.core.notifyDataChange(t.dataChange.COLUMN),e.grid.api.core.raise.columnVisibilityChanged(e)}};return l}]).directive("uiGridMenuButton",["gridUtil","uiGridConstants","uiGridGridMenuService","i18nService",function(o,e,a,l){return{priority:0,scope:!0,require:["^uiGrid"],templateUrl:"ui-grid/ui-grid-menu-button",replace:!0,link:function(e,t,r,i){var n=i[0];e.i18n={aria:l.getSafeText("gridMenu.aria")},a.initialize(e,n.grid),e.shown=!1,e.toggleMenu=function(){e.shown?(e.$broadcast("hide-menu"),e.shown=!1):(e.menuItems=a.getMenuItems(e),e.$broadcast("show-menu"),e.shown=!0)},e.$on("menu-hidden",function(){e.shown=!1,o.focus.bySelector(t,".ui-grid-icon-container")})}}}]),angular.module("ui.grid").directive("uiGridMenu",["$compile","$timeout","$window","$document","gridUtil","uiGridConstants","i18nService",function(d,u,c,e,g,p,f){return{priority:0,scope:{menuItems:"=",autoHide:"=?"},require:"?^uiGrid",templateUrl:"ui-grid/uiGridMenu",replace:!1,link:function(i,o,e,r){if(i.dynamicStyles="",r&&r.grid&&r.grid.options&&r.grid.options.gridMenuTemplate){var t=r.grid.options.gridMenuTemplate;g.getTemplate(t).then(function(e){var t=angular.element(e),r=d(t)(i);o.replaceWith(r)}).catch(angular.noop)}var n=function(e){var t=e-r.grid.headerHeight-20;i.dynamicStyles=[".grid"+r.grid.id+" .ui-grid-menu-mid {","max-height: "+t+"px;","}"].join(" ")};r&&(n(r.grid.gridHeight),r.grid.api.core.on.gridDimensionChanged(i,function(e,t,r,i){n(r)})),i.i18n={close:f.getSafeText("columnMenu.close")},i.showMenu=function(e,t){i.shown?i.shownMid||(i.shownMid=!0,i.$emit("menu-shown")):(i.shown=!0,u(function(){i.shownMid=!0,i.$emit("menu-shown")}));var r="click";t&&t.originalEvent&&t.originalEvent.type&&"touchstart"===t.originalEvent.type&&(r=t.originalEvent.type),angular.element(document).off("click touchstart",a),o.off("keyup",l),o.off("keydown",s),u(function(){angular.element(document).on(r,a),o.on("keyup",l),o.on("keydown",s)})},i.hideMenu=function(e){i.shown&&(i.shownMid=!1,u(function(){i.shownMid||(i.shown=!1,i.$emit("menu-hidden"))},40)),angular.element(document).off("click touchstart",a),o.off("keyup",l),o.off("keydown",s)},i.$on("hide-menu",function(e,t){i.hideMenu(e,t)}),i.$on("show-menu",function(e,t){i.showMenu(e,t)});var a=function(){i.shown&&i.$apply(function(){i.hideMenu()})},l=function(e){27===e.keyCode&&i.hideMenu()},s=function(t){var e=function(e){return e.focus(),t.preventDefault(),!1};if(9===t.keyCode){var r,i,n=o[0].querySelectorAll("button:not(.ng-hide)");0<n.length&&(r=n[0],i=n[n.length-1],t.target!==i||t.shiftKey?t.target===r&&t.shiftKey&&e(i):e(r))}};void 0!==i.autoHide&&void 0!==i.autoHide||(i.autoHide=!0),i.autoHide&&angular.element(c).on("resize",a),i.$on("$destroy",function(){angular.element(c).off("resize",a),angular.element(document).off("click touchstart",a),o.off("keyup",l),o.off("keydown",s)}),r&&i.$on("$destroy",r.grid.api.core.on.scrollBegin(i,a)),i.$on("$destroy",i.$on(p.events.ITEM_DRAGGING,a))}}}]).directive("uiGridMenuItem",["gridUtil","$compile","i18nService",function(a,o,i){return{priority:0,scope:{name:"=",active:"=",action:"=",icon:"=",shown:"=",context:"=",templateUrl:"=",leaveOpen:"=",screenReaderOnly:"="},require:["?^uiGrid"],templateUrl:"ui-grid/uiGridMenuItem",replace:!1,compile:function(){return{pre:function(i,n){i.templateUrl&&a.getTemplate(i.templateUrl).then(function(e){var t=angular.element(e),r=o(t)(i);n.replaceWith(r)}).catch(angular.noop)},post:function(n,e,t,r){var o=r[0];void 0!==n.shown&&null!==n.shown||(n.shown=function(){return!0}),n.itemShown=function(){var e={};return n.context&&(e.context=n.context),void 0!==o&&o&&(e.grid=o.grid),n.shown.call(e)},n.itemAction=function(e,t){if(e.stopPropagation(),"function"==typeof n.action){var r={};if(n.context&&(r.context=n.context),void 0!==o&&o&&(r.grid=o.grid),n.action.call(r,e,t),n.leaveOpen){var i=e.target.parentElement;"I"===angular.element(e.target)[0].nodeName&&(i=i.parentElement),a.focus.bySelector(i,"button[type=button]",!0)}else n.$emit("hide-menu")}},n.label=function(){var e=n.name;return"function"==typeof n.name&&(e=n.name.call()),e},n.i18n=i.get()}}}}}]),function(){"use strict";var t=angular.module("ui.grid");angular.forEach([{tag:"Src",method:"attr"},{tag:"Text",method:"text"},{tag:"Href",method:"attr"},{tag:"Class",method:"addClass"},{tag:"Html",method:"html"},{tag:"Alt",method:"attr"},{tag:"Style",method:"css"},{tag:"Value",method:"attr"},{tag:"Id",method:"attr"},{tag:"Id",directiveName:"IdGrid",method:"attr",appendGridId:!0},{tag:"Title",method:"attr"},{tag:"Label",method:"attr",aria:!0},{tag:"Labelledby",method:"attr",aria:!0},{tag:"Labelledby",directiveName:"LabelledbyGrid",appendGridId:!0,method:"attr",aria:!0},{tag:"Describedby",method:"attr",aria:!0},{tag:"Describedby",directiveName:"DescribedbyGrid",appendGridId:!0,method:"attr",aria:!0}],function(d){var e="uiGridOneBind",u=(d.aria?e+"Aria":e)+(d.directiveName?d.directiveName:d.tag);t.directive(u,["gridUtil",function(s){return{restrict:"A",require:["?uiGrid","?^uiGrid"],link:function(n,o,e,a){var l=n.$watch(e[u],function(e){if(e){if(d.appendGridId){var t=null;angular.forEach(e.split(" "),function(e){t=(t?t+" ":"")+function(e){var t;if(n.grid)t=n.grid;else if(n.col&&n.col.grid)t=n.col.grid;else if(!a.some(function(e){if(e&&e.grid)return t=e.grid,!0}))throw s.logError("["+u+"] A valid grid could not be found to bind id. Are you using this directive within the correct scope? Trying to generate id: [gridID]-"+e),new Error("No valid grid could be found");t&&(new RegExp(t.id.toString()).test(e)||(e=t.id.toString()+"-"+e));return e}(e)}),e=t}switch(d.method){case"attr":d.aria?o[d.method]("aria-"+d.tag.toLowerCase(),e):o[d.method](d.tag.toLowerCase(),e);break;case"addClass":if(angular.isObject(e)&&!angular.isArray(e)){var r=[],i=!1;if(angular.forEach(e,function(e,t){null!=e&&(i=!0,e&&r.push(t))}),!i)return;e=r}if(!e)return;o.addClass(angular.isArray(e)?e.join(" "):e);break;default:o[d.method](e)}l()}},!0)}}}])})}(),function(){"use strict";var e=angular.module("ui.grid");e.directive("uiGridRenderContainer",["$timeout","$document","uiGridConstants","gridUtil","ScrollEvent",function(e,t,r,m,h){return{replace:!0,transclude:!0,templateUrl:"ui-grid/uiGridRenderContainer",require:["^uiGrid","uiGridRenderContainer"],scope:{containerId:"=",rowContainerName:"=",colContainerName:"=",bindScrollHorizontal:"=",bindScrollVertical:"=",enableVerticalScrollbar:"=",enableHorizontalScrollbar:"="},controller:"uiGridRenderContainer as RenderContainer",compile:function(){return{pre:function(e,t,r,i){var n,o,a=i[0],l=i[1],s=e.grid=a.grid;if(!e.rowContainerName)throw new Error("No row render container name specified");if(!e.colContainerName)throw new Error("No column render container name specified");if(!s.renderContainers[e.rowContainerName])throw new Error('Row render container "'+e.rowContainerName+'" is not registered.');if(!s.renderContainers[e.colContainerName])throw new Error('Column render container "'+e.colContainerName+'" is not registered.');n=e.rowContainer=s.renderContainers[e.rowContainerName],o=e.colContainer=s.renderContainers[e.colContainerName],l.containerId=e.containerId,l.rowContainer=n,l.colContainer=o},post:function(s,t,e,r){var d=r[0],a=r[1],u=d.grid,c=a.rowContainer,g=a.colContainer,l=null,p=null,f=u.renderContainers[s.containerId];t.addClass("ui-grid-render-container-"+s.containerId),m.on.mousewheel(t,function(e){var t=new h(u,c,g,h.Sources.RenderContainerMouseWheel);if(0!==e.deltaY){var r=-1*e.deltaY*e.deltaFactor;l=a.viewport[0].scrollTop,t.verticalScrollLength=c.getVerticalScrollLength();var i=(l+r)/t.verticalScrollLength;1<=i&&l<t.verticalScrollLength&&(a.viewport[0].scrollTop=t.verticalScrollLength),i<0?i=0:1<i&&(i=1),t.y={percentage:i,pixels:r}}if(0!==e.deltaX){var n=e.deltaX*e.deltaFactor;p=m.normalizeScrollLeft(a.viewport,u),t.horizontalScrollLength=g.getCanvasWidth()-g.getViewportWidth();var o=(p+n)/t.horizontalScrollLength;o<0?o=0:1<o&&(o=1),t.x={percentage:o,pixels:n}}0!==e.deltaY&&(t.atTop(l)||t.atBottom(l))||0!==e.deltaX&&(t.atLeft(p)||t.atRight(p))||(e.preventDefault(),e.stopPropagation(),t.fireThrottledScrollingEvent("",t))}),t.bind("$destroy",function(){t.unbind("keydown"),["touchstart","touchmove","touchend","keydown","wheel","mousewheel","DomMouseScroll","MozMousePixelScroll"].forEach(function(e){t.unbind(e)})}),d.grid.registerStyleComputation({priority:6,func:function(){var e,t,r="",i=g.canvasWidth,n=g.getViewportWidth(),o=c.getCanvasHeight(),a=c.getViewportHeight();if(g.needsHScrollbarPlaceholder()&&(a-=u.scrollbarHeight),e=t=g.getHeaderViewportWidth(),r+="\n .grid"+d.grid.id+" .ui-grid-render-container-"+s.containerId+" .ui-grid-canvas { width: "+i+"px; height: "+o+"px; }",r+="\n .grid"+d.grid.id+" .ui-grid-render-container-"+s.containerId+" .ui-grid-header-canvas { width: "+(i+u.scrollbarWidth)+"px; }",f.explicitHeaderCanvasHeight){var l=document.querySelector(".grid"+d.grid.id+" .ui-grid-render-container-body .ui-grid-header-canvas");l&&(f.explicitHeaderCanvasHeight=l.offsetHeight),r+="\n .grid"+d.grid.id+" .ui-grid-render-container-"+s.containerId+" .ui-grid-header-canvas { height: "+f.explicitHeaderCanvasHeight+"px; }"}else r+="\n .grid"+d.grid.id+" .ui-grid-render-container-"+s.containerId+" .ui-grid-header-canvas { height: inherit; }";return r+="\n .grid"+d.grid.id+" .ui-grid-render-container-"+s.containerId+" .ui-grid-viewport { width: "+n+"px; height: "+a+"px; }",r+="\n .grid"+d.grid.id+" .ui-grid-render-container-"+s.containerId+" .ui-grid-header-viewport { width: "+e+"px; }",r+="\n .grid"+d.grid.id+" .ui-grid-render-container-"+s.containerId+" .ui-grid-footer-canvas { width: "+(i+u.scrollbarWidth)+"px; }",r+="\n .grid"+d.grid.id+" .ui-grid-render-container-"+s.containerId+" .ui-grid-footer-viewport { width: "+t+"px; }"}})}}}}}]),e.controller("uiGridRenderContainer",["$scope","gridUtil",function(e,t){}])}(),function(){"use strict";angular.module("ui.grid").directive("uiGridRow",function(){return{replace:!0,require:["^uiGrid","^uiGridRenderContainer"],scope:{row:"=uiGridRow",rowRenderIndex:"="},compile:function(){return{pre:function(t,i,e,r){var n,o,a=r[0],l=r[1];function s(){t.row.getRowTemplateFn.then(function(e){var r=t.$new();e(r,function(e,t){n&&(n.remove(),o.$destroy()),i.empty().append(e),n=e,o=r})}).catch(angular.noop)}t.grid=a.grid,t.colContainer=l.colContainer,s(),t.$watch("row.getRowTemplateFn",function(e,t){e!==t&&s()})},post:function(e,t){e.row.element=t}}}}})}(),angular.module("ui.grid").directive("uiGridStyle",["gridUtil","$interpolate",function(e,i){return{link:function(e,t){var r=i(t.text(),!0);r&&e.$watch(r,function(e){t.text(e)})}}}]),function(){"use strict";angular.module("ui.grid").directive("uiGridViewport",["gridUtil","ScrollEvent",function(u,c){return{replace:!0,scope:{},controllerAs:"Viewport",templateUrl:"ui-grid/uiGridViewport",require:["^uiGrid","^uiGridRenderContainer"],link:function(o,a,e,t){var r=t[0],i=t[1],l=(o.containerCtrl=i).rowContainer,s=i.colContainer,d=r.grid;o.grid=r.grid,o.rowContainer=i.rowContainer,o.colContainer=i.colContainer,i.viewport=a,d&&d.options&&d.options.customScroller?d.options.customScroller(a,n):a.on("scroll",n);function n(){var e=a[0].scrollTop,t=u.normalizeScrollLeft(a,d),r=l.scrollVertical(e),i=s.scrollHorizontal(t),n=new c(d,l,s,c.Sources.ViewPortScroll);n.newScrollLeft=t,n.newScrollTop=e,-1<i&&(n.x={percentage:i}),-1<r&&(n.y={percentage:r}),d.scrollContainers(o.$parent.containerId,n)}o.$parent.bindScrollVertical&&d.addVerticalScrollSync(o.$parent.containerId,function(e){i.prevScrollArgs=e,a[0].scrollTop=e.getNewScrollTop(l,i.viewport)}),o.$parent.bindScrollHorizontal&&(d.addHorizontalScrollSync(o.$parent.containerId,function(e){var t=(i.prevScrollArgs=e).getNewScrollLeft(s,i.viewport);a[0].scrollLeft=u.denormalizeScrollLeft(i.viewport,t,d)}),d.addHorizontalScrollSync(o.$parent.containerId+"header",function(e){var t=e.getNewScrollLeft(s,i.viewport);i.headerViewport&&(i.headerViewport.scrollLeft=u.denormalizeScrollLeft(i.viewport,t,d))}),d.addHorizontalScrollSync(o.$parent.containerId+"footer",function(e){var t=e.getNewScrollLeft(s,i.viewport);i.footerViewport&&(i.footerViewport.scrollLeft=u.denormalizeScrollLeft(i.viewport,t,d))})),o.$on("$destroy",function(){a.off()})},controller:["$scope",function(n){this.rowStyle=function(){var e=n.rowContainer,t=n.colContainer,r={};if(0!==e.currentTopRow){var i="translateY("+e.currentTopRow*e.grid.options.rowHeight+"px)";r.transform=i,r["-webkit-transform"]=i,r["-ms-transform"]=i}return 0!==t.currentFirstColumn&&(t.grid.isRTL()?r["margin-right"]=t.columnOffset+"px":r["margin-left"]=t.columnOffset+"px"),r}}]}}])}(),angular.module("ui.grid").directive("uiGridVisible",function(){return function(e,t,r){e.$watch(r.uiGridVisible,function(e){t[e?"removeClass":"addClass"]("ui-grid-invisible")})}}),function(){"use strict";function e(g,p,f){return{templateUrl:"ui-grid/ui-grid",scope:{uiGrid:"="},replace:!0,transclude:!0,controller:"uiGridController",compile:function(){return{post:function(l,s,e,t){var d=t.grid;t.scrollbars=[],d.element=s;var r,i,n=100,o=20,a=0;function u(){d.gridWidth=l.gridWidth=p.elementWidth(s),d.canvasWidth=t.grid.gridWidth,d.gridHeight=l.gridHeight=p.elementHeight(s),d.gridHeight-d.scrollbarHeight<=d.options.rowHeight&&d.options.enableMinHeightCheck&&function(){var e=d.options.minRowsToShow*d.options.rowHeight,t=d.options.showHeader?d.options.headerRowHeight:0,r=d.calcFooterHeight(),i=0;d.options.enableHorizontalScrollbar===f.scrollbars.ALWAYS&&(i=p.getScrollbarWidth());var n=0;if(angular.forEach(d.options.columnDefs,function(e){e.hasOwnProperty("filter")?n<1&&(n=1):e.hasOwnProperty("filters")&&n<e.filters.length&&(n=e.filters.length)}),d.options.enableFiltering&&!n){var o=d.options.columnDefs.length&&d.options.columnDefs.every(function(e){return!1===e.enableFiltering});o||(n=1)}var a=t+e+r+i+n*t;s.css("height",a+"px"),d.gridHeight=l.gridHeight=p.elementHeight(s)}(),d.refreshCanvas(!0)}function c(){d.gridWidth=l.gridWidth=p.elementWidth(s),d.gridHeight=l.gridHeight=p.elementHeight(s),d.refreshCanvas(!0)}angular.element(g).on("resize",c),s.on("$destroy",function(){angular.element(g).off("resize",c),r(),i()}),r=l.$watch(function(){return d.hasLeftContainer()},function(e,t){e!==t&&d.refreshCanvas(!0)}),i=l.$watch(function(){return d.hasRightContainer()},function(e,t){e!==t&&d.refreshCanvas(!0)}),u(),d.renderingComplete(),function e(){s[0].offsetWidth<=0&&a<o?(setTimeout(e,n),a++):l.$applyAsync(u)}()}}}}}angular.module("ui.grid").controller("uiGridController",["$scope","$element","$attrs","gridUtil","$q","uiGridConstants","gridClassFactory","$parse","$compile",function(i,e,n,t,o,a,r,l,s){var d,u=this,c=[];function g(e){return e?e.length:0}function p(e,t){e&&e!==t&&(u.grid.options.columnDefs=i.uiGrid.columnDefs,u.grid.callDataChangeCallbacks(a.dataChange.COLUMN,{orderByColumnDefs:!0,preCompileCellTemplates:!0}))}function f(e){var t=[];if(u.grid.options.fastWatch&&(e=angular.isString(i.uiGrid.data)?u.grid.appScope.$eval(i.uiGrid.data):i.uiGrid.data),d=e){var r=u.grid.columns.length>(u.grid.rowHeaderColumns?u.grid.rowHeaderColumns.length:0);!r&&!n.uiGridColumns&&0===u.grid.options.columnDefs.length&&0<e.length&&u.grid.buildColumnDefsFromData(e),!r&&(0<u.grid.options.columnDefs.length||0<e.length)&&t.push(u.grid.buildColumns().then(function(){u.grid.preCompileCellTemplates()}).catch(angular.noop)),o.all(t).then(function(){u.grid.modifyRows(d).then(function(){u.grid.redrawInPlace(!0),i.$evalAsync(function(){u.grid.refreshCanvas(!0),u.grid.callDataChangeCallbacks(a.dataChange.ROW)})}).catch(angular.noop)}).catch(angular.noop)}}u.grid=r.createGrid(i.uiGrid),u.grid.appScope=u.grid.appScope||i.$parent,e.addClass("grid"+u.grid.id),u.grid.rtl="rtl"===t.getStyles(e[0]).direction,i.grid=u.grid,n.uiGridColumns&&c.push(n.$observe("uiGridColumns",function(e){u.grid.options.columnDefs=angular.isString(e)?angular.fromJson(e):e,u.grid.buildColumns().then(function(){u.grid.preCompileCellTemplates(),u.grid.refreshCanvas(!0)}).catch(angular.noop)})),u.grid.options.fastWatch?(u.uiGrid=i.uiGrid,angular.isString(i.uiGrid.data)?(c.push(i.$parent.$watch(i.uiGrid.data,f)),c.push(i.$parent.$watch(function(){return u.grid.appScope[i.uiGrid.data]?u.grid.appScope[i.uiGrid.data].length:void 0},f))):(c.push(i.$parent.$watch(function(){return i.uiGrid.data},f)),c.push(i.$parent.$watch(function(){return g(i.uiGrid.data)},function(){f(i.uiGrid.data)}))),c.push(i.$parent.$watch(function(){return i.uiGrid.columnDefs},p)),c.push(i.$parent.$watch(function(){return g(i.uiGrid.columnDefs)},function(){p(i.uiGrid.columnDefs)}))):(angular.isString(i.uiGrid.data)?c.push(i.$parent.$watchCollection(i.uiGrid.data,f)):c.push(i.$parent.$watchCollection(function(){return i.uiGrid.data},f)),c.push(i.$parent.$watchCollection(function(){return i.uiGrid.columnDefs},p)));var m=i.$watch(function(){return u.grid.styleComputations},function(){u.grid.refreshCanvas(!0)});i.$on("$destroy",function(){c.forEach(function(e){e()}),m()}),u.fireEvent=function(e,t){t=t||{},angular.isUndefined(t.grid)&&(t.grid=u.grid),i.$broadcast(e,t)},u.innerCompile=function(e){s(e)(i)}}]),angular.module("ui.grid").directive("uiGrid",e),e.$inject=["$window","gridUtil","uiGridConstants"]}(),function(){"use strict";angular.module("ui.grid").directive("uiGridPinnedContainer",["gridUtil",function(e){return{restrict:"EA",replace:!0,template:'<div class="ui-grid-pinned-container"><div ui-grid-render-container container-id="side" row-container-name="\'body\'" col-container-name="side" bind-scroll-vertical="true" class="{{ side }} ui-grid-render-container-{{ side }}"></div></div>',scope:{side:"=uiGridPinnedContainer"},require:"^uiGrid",compile:function(){return{post:function(n,t,e,r){var o=r.grid,i=0;function a(){if("left"===n.side||"right"===n.side){for(var e=o.renderContainers[n.side].visibleColumnCache,t=0,r=0;r<e.length;r++){var i=e[r];t+=i.drawnWidth||i.width||0}return t}}t.addClass("ui-grid-pinned-container-"+n.side),"left"!==n.side&&"right"!==n.side||(o.renderContainers[n.side].getViewportWidth=function(){var t=0;this.visibleColumnCache.forEach(function(e){t+=e.drawnWidth});var e=this.getViewportAdjustment();return t+=e.width}),o.renderContainers.body.registerViewportAdjuster(function(e){return i=a(),e.width-=i,e.side=n.side,e}),o.registerStyleComputation({priority:15,func:function(){var e="";return"left"!==n.side&&"right"!==n.side||(i=a(),t.attr("style",null),e+=".grid"+o.id+" .ui-grid-pinned-container-"+n.side+", .grid"+o.id+" .ui-grid-pinned-container-"+n.side+" .ui-grid-render-container-"+n.side+" .ui-grid-viewport { width: "+i+"px; } "),e}})}}}}}])}(),angular.module("ui.grid").factory("Grid",["$q","$compile","$parse","gridUtil","uiGridConstants","GridOptions","GridColumn","GridRow","GridApi","rowSorter","rowSearcher","GridRenderContainer","$timeout","ScrollEvent",function(S,r,o,m,s,d,u,c,g,p,t,f,i,x){var e=function(e){var r=this;if(void 0===e||void 0===e.id||!e.id)throw new Error("No ID provided. An ID must be given when creating a grid.");if(!/^[_a-zA-Z0-9-]+$/.test(e.id))throw new Error("Grid id '"+e.id+'" is invalid. It must follow CSS selector syntax rules.');function t(e){r.isScrollingVertically=!1,r.api.core.raise.scrollEnd(e),r.scrollDirection=s.scrollDirection.NONE}r.id=e.id,delete e.id,r.options=d.initialize(e),r.appScope=r.options.appScopeProvider,r.headerHeight=r.options.headerRowHeight,r.footerHeight=r.calcFooterHeight(),r.columnFooterHeight=r.calcColumnFooterHeight(),r.rtl=!1,r.gridHeight=0,r.gridWidth=0,r.columnBuilders=[],r.rowBuilders=[],r.rowsProcessors=[],r.columnsProcessors=[],r.styleComputations=[],r.viewportAdjusters=[],r.rowHeaderColumns=[],r.dataChangeCallbacks={},r.verticalScrollSyncCallBackFns={},r.horizontalScrollSyncCallBackFns={},r.renderContainers={},r.renderContainers.body=new f("body",r),r.cellValueGetterCache={},r.getRowTemplateFn=null,r.rows=[],r.columns=[],r.isScrollingVertically=!1,r.isScrollingHorizontally=!1,r.scrollDirection=s.scrollDirection.NONE,r.disableScrolling=!1;var i=m.debounce(t,r.options.scrollDebounce),n=m.debounce(t,0);function o(e){r.isScrollingHorizontally=!1,r.api.core.raise.scrollEnd(e),r.scrollDirection=s.scrollDirection.NONE}var a=m.debounce(o,r.options.scrollDebounce),l=m.debounce(o,0);r.flagScrollingVertically=function(e){r.isScrollingVertically||r.isScrollingHorizontally||r.api.core.raise.scrollBegin(e),r.isScrollingVertically=!0,0!==r.options.scrollDebounce&&e.withDelay?i(e):n(e)},r.flagScrollingHorizontally=function(e){r.isScrollingVertically||r.isScrollingHorizontally||r.api.core.raise.scrollBegin(e),r.isScrollingHorizontally=!0,0!==r.options.scrollDebounce&&e.withDelay?a(e):l(e)},r.scrollbarHeight=0,r.scrollbarWidth=0,r.options.enableHorizontalScrollbar!==s.scrollbars.NEVER&&(r.scrollbarHeight=m.getScrollbarWidth()),r.options.enableVerticalScrollbar!==s.scrollbars.NEVER&&(r.scrollbarWidth=m.getScrollbarWidth()),r.api=new g(r),r.api.registerMethod("core","refresh",this.refresh),r.api.registerMethod("core","queueGridRefresh",this.queueGridRefresh),r.api.registerMethod("core","refreshRows",this.refreshRows),r.api.registerMethod("core","queueRefresh",this.queueRefresh),r.api.registerMethod("core","handleWindowResize",this.handleWindowResize),r.api.registerMethod("core","addRowHeaderColumn",this.addRowHeaderColumn),r.api.registerMethod("core","scrollToIfNecessary",function(e,t){return r.scrollToIfNecessary(e,t)}),r.api.registerMethod("core","scrollTo",function(e,t){return r.scrollTo(e,t)}),r.api.registerMethod("core","registerRowsProcessor",this.registerRowsProcessor),r.api.registerMethod("core","registerColumnsProcessor",this.registerColumnsProcessor),r.api.registerMethod("core","sortHandleNulls",p.handleNulls),r.api.registerEvent("core","sortChanged"),r.api.registerEvent("core","columnVisibilityChanged"),r.api.registerMethod("core","notifyDataChange",this.notifyDataChange),r.api.registerMethod("core","clearAllFilters",this.clearAllFilters),r.registerDataChangeCallback(r.columnRefreshCallback,[s.dataChange.COLUMN]),r.registerDataChangeCallback(r.processRowsCallback,[s.dataChange.EDIT]),r.registerDataChangeCallback(r.updateFooterHeightCallback,[s.dataChange.OPTIONS]),r.registerStyleComputation({priority:10,func:r.getFooterStyles})};e.prototype.calcFooterHeight=function(){if(!this.hasFooter())return 0;var e=0;return this.options.showGridFooter&&(e+=this.options.gridFooterHeight),e+=this.calcColumnFooterHeight()},e.prototype.calcColumnFooterHeight=function(){var e=0;return this.options.showColumnFooter&&(e+=this.options.columnFooterHeight),e},e.prototype.getFooterStyles=function(){var e=".grid"+this.id+" .ui-grid-footer-aggregates-row { height: "+this.options.columnFooterHeight+"px; }";return e+=" .grid"+this.id+" .ui-grid-footer-info { height: "+this.options.gridFooterHeight+"px; }"},e.prototype.hasFooter=function(){return this.options.showGridFooter||this.options.showColumnFooter},e.prototype.isRTL=function(){return this.rtl},e.prototype.registerColumnBuilder=function(e){this.columnBuilders.push(e)},e.prototype.buildColumnDefsFromData=function(e){this.options.columnDefs=m.getColumnsFromData(e,this.options.excludeProperties)},e.prototype.registerRowBuilder=function(e){this.rowBuilders.push(e)},e.prototype.registerDataChangeCallback=function(e,t,r){var i=this,n=m.nextUid();return t||(t=[s.dataChange.ALL]),Array.isArray(t)||m.logError("Expected types to be an array or null in registerDataChangeCallback, value passed was: "+t),this.dataChangeCallbacks[n]={callback:e,types:t,_this:r},function(){delete i.dataChangeCallbacks[n]}},e.prototype.callDataChangeCallbacks=function(r,i){angular.forEach(this.dataChangeCallbacks,function(e,t){-1===e.types.indexOf(s.dataChange.ALL)&&-1===e.types.indexOf(r)&&r!==s.dataChange.ALL||(e._this?e.callback.apply(e._this,this,i):e.callback(this,i))},this)},e.prototype.notifyDataChange=function(e){var t=s.dataChange;e===t.ALL||e===t.COLUMN||e===t.EDIT||e===t.ROW||e===t.OPTIONS?this.callDataChangeCallbacks(e):m.logError("Notified of a data change, but the type was not recognised, so no action taken, type was: "+e)},e.prototype.columnRefreshCallback=function(e,t){e.buildColumns(t),e.queueGridRefresh()},e.prototype.processRowsCallback=function(e){e.queueGridRefresh()},e.prototype.updateFooterHeightCallback=function(e){e.footerHeight=e.calcFooterHeight(),e.columnFooterHeight=e.calcColumnFooterHeight()},e.prototype.getColumn=function(t){var e=this.columns.filter(function(e){return e.colDef.name===t});return 0<e.length?e[0]:null},e.prototype.getColDef=function(t){var e=this.options.columnDefs.filter(function(e){return e.name===t});return 0<e.length?e[0]:null},e.prototype.assignTypes=function(){var n=this;n.options.columnDefs.forEach(function(e,t){if(!e.type){var r=new u(e,t,n),i=0<n.rows.length?n.rows[0]:null;e.type=i?m.guessType(n.getCellValue(i,r)):"string"}})},e.prototype.isRowHeaderColumn=function(e){return-1!==this.rowHeaderColumns.indexOf(e)},e.prototype.addRowHeaderColumn=function(e,t,r){var i=this;void 0===t&&(t=0);var n=new u(e,m.nextUid(),i);n.isRowHeader=!0,i.isRTL()?(i.createRightContainer(),n.renderContainer="right"):(i.createLeftContainer(),n.renderContainer="left"),i.columnBuilders[0](e,n,i.options).then(function(){n.enableFiltering=!1,n.enableSorting=!1,n.enableHiding=!1,n.headerPriority=t,i.rowHeaderColumns.push(n),i.rowHeaderColumns=i.rowHeaderColumns.sort(function(e,t){return e.headerPriority-t.headerPriority}),r||i.buildColumns().then(function(){i.preCompileCellTemplates(),i.queueGridRefresh()}).catch(angular.noop)}).catch(angular.noop)},e.prototype.getOnlyDataColumns=function(){var t=this,r=[];return t.columns.forEach(function(e){-1===t.rowHeaderColumns.indexOf(e)&&r.push(e)}),r},e.prototype.buildColumns=function(e){var t={orderByColumnDefs:!1};angular.extend(t,e);var r,i=this,n=[],o=i.rowHeaderColumns.length;for(r=0;r<i.columns.length;r++)i.getColDef(i.columns[r].name)||(i.columns.splice(r,1),r--);for(var a=i.rowHeaderColumns.length-1;0<=a;a--)i.columns.unshift(i.rowHeaderColumns[a]);if(i.options.columnDefs.forEach(function(t,e){i.preprocessColDef(t);var r=i.getColumn(t.name);r?r.updateColumnDef(t,!1):(r=new u(t,m.nextUid(),i),i.columns.splice(e+o,0,r)),i.columnBuilders.forEach(function(e){n.push(e.call(i,t,r,i.options))})}),t.orderByColumnDefs){var l=i.columns.slice(0),s=Math.min(i.options.columnDefs.length,i.columns.length);for(r=0;r<s;r++)i.columns[r+o].name!==i.options.columnDefs[r].name?l[r+o]=i.getColumn(i.options.columnDefs[r].name):l[r+o]=i.columns[r+o];i.columns.length=0,Array.prototype.splice.apply(i.columns,[0,0].concat(l))}return S.all(n).then(function(){0<i.rows.length&&i.assignTypes(),t.preCompileCellTemplates&&i.preCompileCellTemplates()}).catch(angular.noop)},e.prototype.preCompileCellTemplate=function(e){var t=e.cellTemplate.replace(s.MODEL_COL_FIELD,this.getQualifiedColField(e));t=t.replace(s.COL_FIELD,"grid.getCellValue(row, col)"),e.compiledElementFn=r(t),e.compiledElementFnDefer&&e.compiledElementFnDefer.resolve(e.compiledElementFn)},e.prototype.preCompileCellTemplates=function(){var t=this;t.columns.forEach(function(e){e.cellTemplate?t.preCompileCellTemplate(e):e.cellTemplatePromise&&e.cellTemplatePromise.then(function(){t.preCompileCellTemplate(e)}).catch(angular.noop)})},e.prototype.getQualifiedColField=function(e){var t="row.entity";return e.field===s.ENTITY_BINDING?t:m.preEval(t+"."+e.field)},e.prototype.createLeftContainer=function(){this.hasLeftContainer()||(this.renderContainers.left=new f("left",this,{disableColumnOffset:!0}))},e.prototype.createRightContainer=function(){this.hasRightContainer()||(this.renderContainers.right=new f("right",this,{disableColumnOffset:!0}))},e.prototype.hasLeftContainer=function(){return void 0!==this.renderContainers.left},e.prototype.hasRightContainer=function(){return void 0!==this.renderContainers.right},e.prototype.preprocessColDef=function(e){if(!e.field&&!e.name)throw new Error("colDef.name or colDef.field property is required");if(void 0===e.name&&void 0!==e.field){for(var t=e.field,r=2;this.getColumn(t);)t=e.field+r.toString(),r++;e.name=t}},e.prototype.newInN=function(e,t,r,i){for(var n=[],o=0;o<t.length;o++){for(var a=i?t[o][i]:t[o],l=!1,s=0;s<e.length;s++){var d=r?e[s][r]:e[s];if(this.options.rowEquality(a,d)){l=!0;break}}l||n.push(a)}return n},e.prototype.getRow=function(t,e){var r=this,i=(e=void 0===e?r.rows:e).filter(function(e){return r.options.rowEquality(e.entity,t)});return 0<i.length?i[0]:null},e.prototype.modifyRows=function(e){var n=this,o=n.rows.slice(0),a=n.rowHashMap||n.createRowHashMap(),l=!0;n.rowHashMap=n.createRowHashMap(),n.rows.length=0,e.forEach(function(e,t){var r,i;(i=n.options.enableRowHashing?a.get(e):n.getRow(e,o))&&((r=i).entity=e),r||(r=n.processRowBuilders(new c(e,t,n))),n.rows.push(r),n.rowHashMap.put(e,r),r.isSelected||(l=!1)}),n.selection&&n.rows.length&&(n.selection.selectAll=l),n.assignTypes();var t=S.when(n.processRowsProcessors(n.rows)).then(function(e){return n.setVisibleRows(e)}).catch(angular.noop),r=S.when(n.processColumnsProcessors(n.columns)).then(function(e){return n.setVisibleColumns(e)}).catch(angular.noop);return S.all([t,r])},e.prototype.addRows=function(e){for(var t=this,r=t.rows.length,i=0;i<e.length;i++){var n=t.processRowBuilders(new c(e[i],i+r,t));if(t.options.enableRowHashing){var o=t.rowHashMap.get(n.entity);o&&(o.row=n)}t.rows.push(n)}},e.prototype.processRowBuilders=function(t){var r=this;return r.rowBuilders.forEach(function(e){e.call(r,t,r.options)}),t},e.prototype.registerStyleComputation=function(e){this.styleComputations.push(e)},e.prototype.registerRowsProcessor=function(e,t){if(!angular.isFunction(e))throw"Attempt to register non-function rows processor: "+e;this.rowsProcessors.push({processor:e,priority:t}),this.rowsProcessors.sort(function(e,t){return e.priority-t.priority})},e.prototype.removeRowsProcessor=function(r){var i=-1;this.rowsProcessors.forEach(function(e,t){e.processor===r&&(i=t)}),-1!==i&&this.rowsProcessors.splice(i,1)},e.prototype.processRowsProcessors=function(e){var n=this,t=e.slice(0);if(0===n.rowsProcessors.length)return S.when(t);var o=S.defer();return function t(r,e){var i=n.rowsProcessors[r].processor;return S.when(i.call(n,e,n.columns)).then(function(e){if(!e)throw"Processor at index "+r+" did not return a set of renderable rows";if(!angular.isArray(e))throw"Processor at index "+r+" did not return an array";if(++r<=n.rowsProcessors.length-1)return t(r,e);o.resolve(e)}).catch(function(e){throw e})}(0,t),o.promise},e.prototype.setVisibleRows=function(e){var t=this;for(var r in t.renderContainers){var i=t.renderContainers[r];i.canvasHeightShouldUpdate=!0,void 0===i.visibleRowCache?i.visibleRowCache=[]:i.visibleRowCache.length=0}for(var n=0;n<e.length;n++){var o=e[n],a=void 0!==o.renderContainer&&o.renderContainer?o.renderContainer:"body";o.visible&&t.renderContainers[a].visibleRowCache.push(o)}t.api.core.raise.rowsVisibleChanged(this.api),t.api.core.raise.rowsRendered(this.api)},e.prototype.registerColumnsProcessor=function(e,t){if(!angular.isFunction(e))throw"Attempt to register non-function rows processor: "+e;this.columnsProcessors.push({processor:e,priority:t}),this.columnsProcessors.sort(function(e,t){return e.priority-t.priority})},e.prototype.removeColumnsProcessor=function(e){var t=this.columnsProcessors.indexOf(e);void 0!==t&&void 0!==t&&this.columnsProcessors.splice(t,1)},e.prototype.processColumnsProcessors=function(e){var n=this,o=e.slice(0);if(0===n.columnsProcessors.length)return S.when(o);var a=S.defer();return function t(r,e){var i=n.columnsProcessors[r].processor;return S.when(i.call(n,e,n.rows)).then(function(e){if(!e)throw"Processor at index "+r+" did not return a set of renderable rows";if(!angular.isArray(e))throw"Processor at index "+r+" did not return an array";if(++r<=n.columnsProcessors.length-1)return t(r,o);a.resolve(o)}).catch(angular.noop)}(0,o),a.promise},e.prototype.setVisibleColumns=function(e){for(var t in this.renderContainers)this.renderContainers[t].visibleColumnCache.length=0;for(var r=0;r<e.length;r++){var i=e[r];i.visible&&(void 0!==i.renderContainer&&i.renderContainer?this.renderContainers[i.renderContainer].visibleColumnCache.push(i):this.renderContainers.body.visibleColumnCache.push(i))}},e.prototype.handleWindowResize=function(e){var t=this;return t.gridWidth=m.elementWidth(t.element),t.gridHeight=m.elementHeight(t.element),t.queueRefresh()},e.prototype.queueRefresh=function(){var e=this;return e.refreshCanceller&&i.cancel(e.refreshCanceller),e.refreshCanceller=i(function(){e.refreshCanvas(!0)}),e.refreshCanceller.then(function(){e.refreshCanceller=null}).catch(angular.noop),e.refreshCanceller},e.prototype.queueGridRefresh=function(){var e=this;return e.gridRefreshCanceller&&i.cancel(e.gridRefreshCanceller),e.gridRefreshCanceller=i(function(){e.refresh(!0)}),e.gridRefreshCanceller.then(function(){e.gridRefreshCanceller=null}).catch(angular.noop),e.gridRefreshCanceller},e.prototype.updateCanvasHeight=function(){for(var e in this.renderContainers)this.renderContainers.hasOwnProperty(e)&&(this.renderContainers[e].canvasHeightShouldUpdate=!0)},e.prototype.buildStyles=function(){var r=this;r.customStyles="",r.styleComputations.sort(function(e,t){return null===e.priority?1:null===t.priority?-1:null===e.priority&&null===t.priority?0:e.priority-t.priority}).forEach(function(e){var t=e.func.call(r);angular.isString(t)&&(r.customStyles+="\n"+t)})},e.prototype.minColumnsToRender=function(){var n=this,o=this.getViewportWidth(),a=0,l=0;return n.columns.forEach(function(e,t){if(l<o)l+=e.drawnWidth,a++;else{for(var r=0,i=t;t-a<=i;i--)r+=n.columns[i].drawnWidth;r<o&&a++}}),a},e.prototype.getBodyHeight=function(){return this.getViewportHeight()},e.prototype.getViewportHeight=function(){var e=this.gridHeight-this.headerHeight-this.footerHeight;return e+=this.getViewportAdjustment().height},e.prototype.getViewportWidth=function(){var e=this.gridWidth;return e+=this.getViewportAdjustment().width},e.prototype.getHeaderViewportWidth=function(){return this.getViewportWidth()},e.prototype.addVerticalScrollSync=function(e,t){this.verticalScrollSyncCallBackFns[e]=t},e.prototype.addHorizontalScrollSync=function(e,t){this.horizontalScrollSyncCallBackFns[e]=t},e.prototype.scrollContainers=function(e,t){if(t.y){var r=["body","left","right"];this.flagScrollingVertically(t),"body"===e?r=["left","right"]:"left"===e?r=["body","right"]:"right"===e&&(r=["body","left"]);for(var i=0;i<r.length;i++){var n=r[i];this.verticalScrollSyncCallBackFns[n]&&this.verticalScrollSyncCallBackFns[n](t)}}if(t.x){var o=["body","bodyheader","bodyfooter"];this.flagScrollingHorizontally(t),"body"===e&&(o=["bodyheader","bodyfooter"]);for(var a=0;a<o.length;a++){var l=o[a];this.horizontalScrollSyncCallBackFns[l]&&this.horizontalScrollSyncCallBackFns[l](t)}}},e.prototype.registerViewportAdjuster=function(e){this.viewportAdjusters.push(e)},e.prototype.removeViewportAdjuster=function(e){var t=this.viewportAdjusters.indexOf(e);void 0!==t&&void 0!==t&&this.viewportAdjusters.splice(t,1)},e.prototype.getViewportAdjustment=function(){var t={height:0,width:0};return this.viewportAdjusters.forEach(function(e){t=e.call(this,t)}),t},e.prototype.getVisibleRowCount=function(){return this.renderContainers.body.visibleRowCache.length},e.prototype.getVisibleRows=function(){return this.renderContainers.body.visibleRowCache},e.prototype.getVisibleColumnCount=function(){return this.renderContainers.body.visibleColumnCache.length},e.prototype.searchRows=function(e){return t.search(this,e,this.columns)},e.prototype.sortByColumn=function(e){return p.sort(this,e,this.columns)},e.prototype.getCellValue=function(e,t){return void 0!==e.entity["$$"+t.uid]?e.entity["$$"+t.uid].rendered:this.options.flatEntityAccess&&void 0!==t.field?e.entity[t.field]:(t.cellValueGetterCache||(t.cellValueGetterCache=o(e.getEntityQualifiedColField(t))),t.cellValueGetterCache(e))},e.prototype.getCellDisplayValue=function(e,t){if(!t.cellDisplayGetterCache){var r=t.cellFilter?" | "+t.cellFilter:"";if(void 0!==e.entity["$$"+t.uid])t.cellDisplayGetterCache=o(e.entity["$$"+t.uid].rendered+r);else if(this.options.flatEntityAccess&&void 0!==t.field){var i=t.field.replace(/(')|(\\)/g,"\\$&");t.cellDisplayGetterCache=o("entity['"+i+"']"+r)}else t.cellDisplayGetterCache=o(e.getEntityQualifiedColField(t)+r)}var n=angular.extend({},e,{col:t});return t.cellDisplayGetterCache(n)},e.prototype.getNextColumnSortPriority=function(){var t=0;return this.columns.forEach(function(e){e.sort&&void 0!==e.sort.priority&&e.sort.priority>=t&&(t=e.sort.priority+1)}),t},e.prototype.resetColumnSorting=function(t){this.columns.forEach(function(e){e===t||e.suppressRemoveSort||(e.sort={})})},e.prototype.getColumnSorting=function(){var t=[];return this.columns.slice(0).sort(p.prioritySort).forEach(function(e){e.sort&&void 0!==e.sort.direction&&e.sort.direction&&(e.sort.direction===s.ASC||e.sort.direction===s.DESC)&&t.push(e)}),t},e.prototype.sortColumn=function(e,t,r){var i=this,n=null;if(void 0===e||!e)throw new Error("No column parameter provided");if("boolean"==typeof t?r=t:n=t,r?void 0===e.sort.priority&&(e.sort.priority=i.getNextColumnSortPriority()):(i.resetColumnSorting(e),e.sort.priority=void 0,e.sort.priority=i.getNextColumnSortPriority()),n)e.sort.direction=n;else{var o=e.sortDirectionCycle.indexOf(e.sort.direction?e.sort.direction:null);o=(o+1)%e.sortDirectionCycle.length,e.colDef&&e.suppressRemoveSort&&!e.sortDirectionCycle[o]&&(o=(o+1)%e.sortDirectionCycle.length),e.sortDirectionCycle[o]?e.sort.direction=e.sortDirectionCycle[o]:a(e,i)}return i.api.core.raise.sortChanged(i,i.getColumnSorting()),S.when(e)};var a=function(t,e){e.columns.forEach(function(e){e.sort&&void 0!==e.sort.priority&&e.sort.priority>t.sort.priority&&(e.sort.priority-=1)}),t.sort={}};function l(e,t){return e||0<t?t:null}function n(e,t){var r=e/t;return r<=1?r:1}function E(e,t,r){if(n(e,t)!==r)return{percentage:n(e,t)}}function A(e,t,r){var i=e/t;if((i=1<i?1:i)!==r)return{percentage:i}}function h(){}return e.prototype.renderingComplete=function(){angular.isFunction(this.options.onRegisterApi)&&this.options.onRegisterApi(this.api),this.api.core.raise.renderingComplete(this.api)},e.prototype.createRowHashMap=function(){var e=new h;return e.grid=this,e},e.prototype.refresh=function(e){var t=this,r=t.processRowsProcessors(t.rows).then(function(e){t.setVisibleRows(e)}).catch(angular.noop),i=t.processColumnsProcessors(t.columns).then(function(e){t.setVisibleColumns(e)}).catch(angular.noop);return S.all([r,i]).then(function(){t.refreshCanvas(!0),t.redrawInPlace(e)}).catch(angular.noop)},e.prototype.refreshRows=function(){var t=this;return t.processRowsProcessors(t.rows).then(function(e){t.setVisibleRows(e),t.redrawInPlace(),t.refreshCanvas(!0)}).catch(angular.noop)},e.prototype.refreshCanvas=function(c){var g=this,p=S.defer(),f=[];for(var e in g.renderContainers)if(g.renderContainers.hasOwnProperty(e)){var t=g.renderContainers[e];if(null===t.canvasWidth||isNaN(t.canvasWidth))continue;(t.header||t.headerCanvas)&&(t.explicitHeaderHeight=t.explicitHeaderHeight||null,t.explicitHeaderCanvasHeight=t.explicitHeaderCanvasHeight||null,f.push(t))}return c&&g.buildStyles(),0<f.length?i(function(){var e,t,r=!1,i=0,n=0,o=function(e,t){return e!==t&&(r=!0),t};for(e=0;e<f.length;e++)if(null!==(t=f[e]).canvasWidth&&!isNaN(t.canvasWidth)){if(t.header){var a=t.headerHeight=o(t.headerHeight,m.outerElementHeight(t.header)),l=m.getBorderSize(t.header,"top"),s=m.getBorderSize(t.header,"bottom"),d=parseInt(a-l-s,10);d=d<0?0:d,t.innerHeaderHeight=d,!t.explicitHeaderHeight&&i<d&&(i=d)}if(t.headerCanvas){var u=t.headerCanvasHeight=o(t.headerCanvasHeight,parseInt(m.outerElementHeight(t.headerCanvas),10));!t.explicitHeaderCanvasHeight&&n<u&&(n=u)}}for(e=0;e<f.length;e++)t=f[e],0<i&&void 0!==t.headerHeight&&null!==t.headerHeight&&(t.explicitHeaderHeight||t.headerHeight<i)&&(t.explicitHeaderHeight=o(t.explicitHeaderHeight,i)),0<n&&void 0!==t.headerCanvasHeight&&null!==t.headerCanvasHeight&&(t.explicitHeaderCanvasHeight||t.headerCanvasHeight<n)&&(t.explicitHeaderCanvasHeight=o(t.explicitHeaderCanvasHeight,n));c&&r&&g.buildStyles(),p.resolve()}):i(function(){p.resolve()}),p.promise},e.prototype.redrawInPlace=function(e){for(var t in this.renderContainers){var r=this.renderContainers[t],i=l(e,r.prevScrollTop),n=l(e,r.prevScrollLeft),o=e||0<i?null:r.prevScrolltopPercentage,a=e||0<n?null:r.prevScrollleftPercentage;r.adjustRows(i,o),r.adjustColumns(n,a)}},e.prototype.hasLeftContainerColumns=function(){return this.hasLeftContainer()&&0<this.renderContainers.left.renderedColumns.length},e.prototype.hasRightContainerColumns=function(){return this.hasRightContainer()&&0<this.renderContainers.right.renderedColumns.length},e.prototype.scrollToIfNecessary=function(e,t){var r=this,i=new x(r,"uiGrid.scrollToIfNecessary"),n=r.renderContainers.body.visibleRowCache,o=r.renderContainers.body.visibleColumnCache,a=r.renderContainers.body.prevScrollTop+r.headerHeight;a=a<0?0:a;var l=r.renderContainers.body.prevScrollLeft,s=r.renderContainers.body.prevScrollTop+r.gridHeight-r.renderContainers.body.headerHeight-r.footerHeight-r.scrollbarHeight,d=r.renderContainers.body.prevScrollLeft+Math.ceil(r.renderContainers.body.getViewportWidth());if(null!==e){var u,c=n.indexOf(e),g=r.renderContainers.body.getCanvasHeight()-r.renderContainers.body.getViewportHeight(),p=c*r.options.rowHeight+r.headerHeight;(p=p<0?0:p)<Math.floor(a)?(u=r.renderContainers.body.prevScrollTop-(a-p),t&&t.colDef&&t.colDef.enableCellEditOnFocus&&(u=u-r.footerHeight-r.scrollbarHeight),i.y=E(u,g,r.renderContainers.body.prevScrolltopPercentage)):p>Math.ceil(s)&&(u=p-s+r.renderContainers.body.prevScrollTop,i.y=E(u,g,r.renderContainers.body.prevScrolltopPercentage))}if(null!==t){for(var f=o.indexOf(t),m=r.renderContainers.body.getCanvasWidth()-r.renderContainers.body.getViewportWidth(),h=0,v=0;v<f;v++)h+=o[v].drawnWidth;var C,w=(h=h<0?0:h)+t.drawnWidth;w=w<0?0:w,h<l?(C=r.renderContainers.body.prevScrollLeft-(l-h),i.x=A(C,m,r.renderContainers.body.prevScrollleftPercentage)):d<w&&(C=w-d+r.renderContainers.body.prevScrollLeft,i.x=A(C,m,r.renderContainers.body.prevScrollleftPercentage))}var b=S.defer();if(i.y||i.x){i.withDelay=!1,r.scrollContainers("",i);var y=r.api.core.on.scrollEnd(null,function(){b.resolve(i),y()})}else b.resolve();return b.promise},e.prototype.scrollTo=function(e,t){var r=null,i=null;return null!=e&&(r=this.getRow(e)),null!=t&&(i=this.getColumn(t.name?t.name:t.field)),this.scrollToIfNecessary(r,i)},e.prototype.clearAllFilters=function(e,t,r){if(void 0===e&&(e=!0),void 0===t&&(t=!1),void 0===r&&(r=!1),this.columns.forEach(function(e){e.filters.forEach(function(e){e.term=void 0,t&&(e.condition=void 0),r&&(e.flags=void 0)})}),e)return this.refreshRows()},h.prototype={put:function(e,t){this[this.grid.options.rowIdentity(e)]=t},get:function(e){return this[this.grid.options.rowIdentity(e)]},remove:function(e){var t=this[e=this.grid.options.rowIdentity(e)];return delete this[e],t}},e}]),angular.module("ui.grid").factory("GridApi",["$q","$rootScope","gridUtil","uiGridConstants","GridRow",function(e,t,d,r,i){var n=function(e){this.grid=e,this.listeners=[],this.registerEvent("core","renderingComplete"),this.registerEvent("core","filterChanged"),this.registerMethod("core","setRowInvisible",i.prototype.setRowInvisible),this.registerMethod("core","clearRowInvisible",i.prototype.clearRowInvisible),this.registerMethod("core","getVisibleRows",this.grid.getVisibleRows),this.registerEvent("core","rowsVisibleChanged"),this.registerEvent("core","rowsRendered"),this.registerEvent("core","scrollBegin"),this.registerEvent("core","scrollEnd"),this.registerEvent("core","canvasHeightChanged"),this.registerEvent("core","gridDimensionChanged")};function u(e,r,i,n){return t.$on(e,function(e){var t=Array.prototype.slice.call(arguments);t.splice(0,1),r.apply(n||i.api,t)})}return n.prototype.suppressEvents=function(e,t){var r=this,i=angular.isArray(e)?e:[e],n=r.listeners.filter(function(t){return i.some(function(e){return t.handler===e})});n.forEach(function(e){e.dereg()}),t(),n.forEach(function(e){e.dereg=u(e.eventId,e.handler,r.grid,e._this)})},n.prototype.registerEvent=function(o,a){var l=this;l[o]||(l[o]={});var e=l[o];e.on||(e.on={},e.raise={});var s=l.grid.id+o+a;e.raise[a]=function(){t.$emit.apply(t,[s].concat(Array.prototype.slice.call(arguments)))},e.on[a]=function(e,t,r){if(null===e||void 0!==e.$on){var i={handler:t,dereg:u(s,t,l.grid,r),eventId:s,scope:e,_this:r};l.listeners.push(i);var n=function(){i.dereg();var e=l.listeners.indexOf(i);l.listeners.splice(e,1)};return e&&e.$on("$destroy",function(){n()}),n}d.logError("asked to listen on "+o+".on."+a+" but scope wasn't passed in the input parameters. It is legitimate to pass null, but you've passed something else, so you probably forgot to provide scope rather than did it deliberately, not registering")}},n.prototype.registerEventsFromObject=function(e){var r=this,i=[];angular.forEach(e,function(e,t){var r={name:t,events:[]};angular.forEach(e,function(e,t){r.events.push(t)}),i.push(r)}),i.forEach(function(t){t.events.forEach(function(e){r.registerEvent(t.name,e)})})},n.prototype.registerMethod=function(e,t,r,i){this[e]||(this[e]={}),this[e][t]=d.createBoundedWrapper(i||this.grid,r)},n.prototype.registerMethodsFromObject=function(e,r){var i=this,n=[];angular.forEach(e,function(e,t){var r={name:t,methods:[]};angular.forEach(e,function(e,t){r.methods.push({name:t,fn:e})}),n.push(r)}),n.forEach(function(t){t.methods.forEach(function(e){i.registerMethod(t.name,e.name,e.fn,r)})})},n}]),angular.module("ui.grid").factory("GridColumn",["gridUtil","uiGridConstants","i18nService",function(d,u,e){function t(e,t,r){var n=this;n.grid=r,n.uid=t,n.updateColumnDef(e,!0),n.aggregationValue=void 0,n.updateAggregationValue=function(){if(n.aggregationType){var t=0,e=n.grid.getVisibleRows(),r=function(){var i=[];return e.forEach(function(e){var t=n.grid.getCellValue(e,n),r=Number(t);isNaN(r)||i.push(r)}),i};angular.isFunction(n.aggregationType)?n.aggregationValue=n.aggregationType(e,n):n.aggregationType===u.aggregationTypes.count?n.aggregationValue=n.grid.getVisibleRowCount():n.aggregationType===u.aggregationTypes.sum?(r().forEach(function(e){t+=e}),n.aggregationValue=t):n.aggregationType===u.aggregationTypes.avg?(r().forEach(function(e){t+=e}),t/=r().length,n.aggregationValue=t):n.aggregationType===u.aggregationTypes.min?n.aggregationValue=Math.min.apply(null,r()):n.aggregationType===u.aggregationTypes.max?n.aggregationValue=Math.max.apply(null,r()):n.aggregationValue=" "}else n.aggregationValue=void 0},this.getAggregationValue=function(){return n.aggregationValue}}function c(e){return void 0===e.displayName?d.readableColumnName(e.name):e.displayName}return t.prototype.hideColumn=function(){this.colDef.visible=!1},t.prototype.setPropertyOrDefault=function(e,t,r){var i=this;void 0!==e[t]&&e[t]?i[t]=e[t]:void 0!==i[t]?i[t]=i[t]:i[t]=r||{}},t.prototype.updateColumnDef=function(i,e){var n=this;if(void 0===(n.colDef=i).name)throw new Error("colDef.name is required for column at index "+n.grid.options.columnDefs.indexOf(i));if(n.displayName=c(i),!angular.isNumber(n.width)||!n.hasCustomWidth||i.allowCustomWidthOverride){var t=i.width,r="Cannot parse column width '"+t+"' for column named '"+i.name+"'";if(n.hasCustomWidth=!1,angular.isString(t)||angular.isNumber(t))if(angular.isString(t))if(d.endsWith(t,"%")){var o=t.replace(/%/g,""),a=parseInt(o,10);if(isNaN(a))throw new Error(r);n.width=t}else if(t.match(/^(\d+)$/))n.width=parseInt(t.match(/^(\d+)$/)[1],10);else{if(!t.match(/^\*+$/))throw new Error(r);n.width=t}else n.width=t;else n.width="*"}function l(e){return angular.isString(e)||angular.isNumber(e)}["minWidth","maxWidth"].forEach(function(e){var t=i[e],r="Cannot parse column "+e+" '"+t+"' for column named '"+i.name+"'";if("minWidth"===e&&!l(t)&&angular.isDefined(n.grid.options.minimumColumnSize)&&(t=n.grid.options.minimumColumnSize),l(t))if(angular.isString(t)){if(!t.match(/^(\d+)$/))throw new Error(r);n[e]=parseInt(t.match(/^(\d+)$/)[1],10)}else n[e]=t;else n[e]="minWidth"===e?30:9e3}),n.field=void 0===i.field?i.name:i.field,"string"!=typeof n.field&&d.logError("Field is not a string, this is likely to break the code, Field is: "+n.field),n.name=i.name,n.displayName=c(i),n.aggregationType=angular.isDefined(i.aggregationType)?i.aggregationType:null,n.footerCellTemplate=angular.isDefined(i.footerCellTemplate)?i.footerCellTemplate:null,void 0===i.cellTooltip||!1===i.cellTooltip?n.cellTooltip=!1:!0===i.cellTooltip?n.cellTooltip=function(e,t){return n.grid.getCellValue(e,t)}:"function"==typeof i.cellTooltip?n.cellTooltip=i.cellTooltip:n.cellTooltip=function(e,t){return t.colDef.cellTooltip},void 0===i.headerTooltip||!1===i.headerTooltip?n.headerTooltip=!1:!0===i.headerTooltip?n.headerTooltip=function(e){return e.displayName}:"function"==typeof i.headerTooltip?n.headerTooltip=i.headerTooltip:n.headerTooltip=function(e){return e.colDef.headerTooltip},n.footerCellClass=i.footerCellClass,n.cellClass=i.cellClass,n.headerCellClass=i.headerCellClass,n.cellFilter=i.cellFilter?i.cellFilter:"",n.sortCellFiltered=!!i.sortCellFiltered,n.filterCellFiltered=!!i.filterCellFiltered,n.headerCellFilter=i.headerCellFilter?i.headerCellFilter:"",n.footerCellFilter=i.footerCellFilter?i.footerCellFilter:"",n.visible=d.isNullOrUndefined(i.visible)||i.visible,n.headerClass=i.headerClass,n.enableSorting=void 0!==i.enableSorting?i.enableSorting:n.grid.options.enableSorting,n.sortingAlgorithm=i.sortingAlgorithm,n.sortDirectionCycle=void 0!==i.sortDirectionCycle?i.sortDirectionCycle:[null,u.ASC,u.DESC],void 0===n.suppressRemoveSort&&(n.suppressRemoveSort=void 0!==i.suppressRemoveSort&&i.suppressRemoveSort),n.enableFiltering=void 0===i.enableFiltering||i.enableFiltering,n.setPropertyOrDefault(i,"menuItems",[]),e&&n.setPropertyOrDefault(i,"sort"),n.setPropertyOrDefault(i,"defaultSort");var s=[];i.filter?s.push(i.filter):i.filters?s=i.filters:s.push({}),e?(n.setPropertyOrDefault(i,"filter"),n.setPropertyOrDefault(i,"extraStyle"),n.setPropertyOrDefault(i,"filters",s)):n.filters.length===s.length&&n.filters.forEach(function(e,t){void 0!==s[t].placeholder&&(e.placeholder=s[t].placeholder),void 0!==s[t].ariaLabel&&(e.ariaLabel=s[t].ariaLabel),void 0!==s[t].flags&&(e.flags=s[t].flags),void 0!==s[t].type&&(e.type=s[t].type),void 0!==s[t].selectOptions&&(e.selectOptions=s[t].selectOptions)})},t.prototype.unsort=function(){var t=this.sort.priority;this.grid.columns.forEach(function(e){e.sort&&void 0!==e.sort.priority&&e.sort.priority>t&&(e.sort.priority-=1)}),this.sort={},this.grid.api.core.raise.sortChanged(this.grid,this.grid.getColumnSorting())},t.prototype.getColClass=function(e){var t=u.COL_CLASS_PREFIX+this.uid;return e?"."+t:t},t.prototype.isPinnedLeft=function(){return"left"===this.renderContainer},t.prototype.isPinnedRight=function(){return"right"===this.renderContainer},t.prototype.getColClassDefinition=function(){return" .grid"+this.grid.id+" "+this.getColClass(!0)+" { min-width: "+this.drawnWidth+"px; max-width: "+this.drawnWidth+"px; }"},t.prototype.getRenderContainer=function(){var e=this.renderContainer;return null!==e&&""!==e&&void 0!==e||(e="body"),this.grid.renderContainers[e]},t.prototype.showColumn=function(){this.colDef.visible=!0},t.prototype.getAggregationText=function(){if(this.colDef.aggregationHideLabel)return"";if(this.colDef.aggregationLabel)return this.colDef.aggregationLabel;switch(this.colDef.aggregationType){case u.aggregationTypes.count:return e.getSafeText("aggregation.count");case u.aggregationTypes.sum:return e.getSafeText("aggregation.sum");case u.aggregationTypes.avg:return e.getSafeText("aggregation.avg");case u.aggregationTypes.min:return e.getSafeText("aggregation.min");case u.aggregationTypes.max:return e.getSafeText("aggregation.max");default:return""}},t.prototype.getCellTemplate=function(){return this.cellTemplatePromise},t.prototype.getCompiledElementFn=function(){return this.compiledElementFnDefer.promise},t}]),angular.module("ui.grid").factory("GridOptions",["gridUtil","uiGridConstants",function(t,r){return{initialize:function(e){return e.onRegisterApi=e.onRegisterApi||angular.noop(),e.data=e.data||[],e.columnDefs=e.columnDefs||[],e.excludeProperties=e.excludeProperties||["$$hashKey"],e.enableRowHashing=!1!==e.enableRowHashing,e.rowIdentity=e.rowIdentity||function(e){return t.hashKey(e)},e.getRowIdentity=e.getRowIdentity||function(e){return e.$$hashKey},e.flatEntityAccess=!0===e.flatEntityAccess,e.showHeader=void 0===e.showHeader||e.showHeader,e.showHeader?e.headerRowHeight=void 0!==e.headerRowHeight?e.headerRowHeight:30:e.headerRowHeight=0,"string"==typeof e.rowHeight?e.rowHeight=parseInt(e.rowHeight)||30:e.rowHeight=e.rowHeight||30,e.minRowsToShow=void 0!==e.minRowsToShow?e.minRowsToShow:10,e.showGridFooter=!0===e.showGridFooter,e.showColumnFooter=!0===e.showColumnFooter,e.columnFooterHeight=void 0!==e.columnFooterHeight?e.columnFooterHeight:30,e.gridFooterHeight=void 0!==e.gridFooterHeight?e.gridFooterHeight:30,e.columnWidth=void 0!==e.columnWidth?e.columnWidth:50,e.maxVisibleColumnCount=void 0!==e.maxVisibleColumnCount?e.maxVisibleColumnCount:200,e.virtualizationThreshold=void 0!==e.virtualizationThreshold?e.virtualizationThreshold:20,e.columnVirtualizationThreshold=void 0!==e.columnVirtualizationThreshold?e.columnVirtualizationThreshold:10,e.excessRows=void 0!==e.excessRows?e.excessRows:4,e.scrollThreshold=void 0!==e.scrollThreshold?e.scrollThreshold:4,e.excessColumns=void 0!==e.excessColumns?e.excessColumns:4,e.aggregationCalcThrottle=void 0!==e.aggregationCalcThrottle?e.aggregationCalcThrottle:500,e.wheelScrollThrottle=void 0!==e.wheelScrollThrottle?e.wheelScrollThrottle:70,e.scrollDebounce=void 0!==e.scrollDebounce?e.scrollDebounce:300,e.enableSorting=!1!==e.enableSorting,e.enableFiltering=!0===e.enableFiltering,e.enableColumnMenus=!1!==e.enableColumnMenus,e.enableVerticalScrollbar=void 0!==e.enableVerticalScrollbar?e.enableVerticalScrollbar:r.scrollbars.ALWAYS,e.enableHorizontalScrollbar=void 0!==e.enableHorizontalScrollbar?e.enableHorizontalScrollbar:r.scrollbars.ALWAYS,e.enableMinHeightCheck=!1!==e.enableMinHeightCheck,e.minimumColumnSize=void 0!==e.minimumColumnSize?e.minimumColumnSize:30,e.rowEquality=e.rowEquality||function(e,t){return e===t},e.headerTemplate=e.headerTemplate||null,e.footerTemplate=e.footerTemplate||"ui-grid/ui-grid-footer",e.gridFooterTemplate=e.gridFooterTemplate||"ui-grid/ui-grid-grid-footer",e.rowTemplate=e.rowTemplate||"ui-grid/ui-grid-row",e.gridMenuTemplate=e.gridMenuTemplate||"ui-grid/uiGridMenu",e.appScopeProvider=e.appScopeProvider||null,e}}}]),angular.module("ui.grid").factory("GridRenderContainer",["gridUtil","uiGridConstants",function(b,n){function e(e,t,r){var i=this;i.name=e,i.grid=t,i.visibleRowCache=[],i.visibleColumnCache=[],i.renderedRows=[],i.renderedColumns=[],i.prevScrollTop=0,i.prevScrolltopPercentage=0,i.prevRowScrollIndex=0,i.prevScrollLeft=0,i.prevScrollleftPercentage=0,i.prevColumnScrollIndex=0,i.columnStyles="",i.viewportAdjusters=[],i.hasHScrollbar=!1,i.hasVScrollbar=!1,i.canvasHeightShouldUpdate=!0,i.$$canvasHeight=0,r&&angular.isObject(r)&&angular.extend(i,r),t.registerStyleComputation({priority:5,func:function(){return i.updateColumnWidths(),i.columnStyles}})}return e.prototype.reset=function(){this.visibleColumnCache.length=0,this.visibleRowCache.length=0,this.renderedRows.length=0,this.renderedColumns.length=0},e.prototype.containsColumn=function(e){return-1!==this.visibleColumnCache.indexOf(e)},e.prototype.minRowsToRender=function(){for(var e=0,t=0,r=this.getViewportHeight(),i=this.visibleRowCache.length-1;t<r&&0<=i;i--)t+=this.visibleRowCache[i].height,e++;return e},e.prototype.minColumnsToRender=function(){for(var e=this.getViewportWidth(),t=0,r=0,i=0;i<this.visibleColumnCache.length;i++){var n=this.visibleColumnCache[i];if(r<e)r+=n.drawnWidth?n.drawnWidth:0,t++;else{for(var o=0,a=i;i-t<=a;a--)o+=this.visibleColumnCache[a].drawnWidth?this.visibleColumnCache[a].drawnWidth:0;o<e&&t++}}return t},e.prototype.getVisibleRowCount=function(){return this.visibleRowCache.length},e.prototype.registerViewportAdjuster=function(e){this.viewportAdjusters.push(e)},e.prototype.removeViewportAdjuster=function(e){var t=this.viewportAdjusters.indexOf(e);-1<t&&this.viewportAdjusters.splice(t,1)},e.prototype.getViewportAdjustment=function(){var t={height:0,width:0};return this.viewportAdjusters.forEach(function(e){t=e.call(this,t)}),t},e.prototype.getMargin=function(r){var i=0;return this.viewportAdjusters.forEach(function(e){var t=e.call(this,{height:0,width:0});t.side&&t.side===r&&(i+=-1*t.width)}),i},e.prototype.getViewportHeight=function(){var e=this,t=e.headerHeight?e.headerHeight:e.grid.headerHeight,r=e.grid.gridHeight-t-e.grid.footerHeight;return r+=e.getViewportAdjustment().height},e.prototype.getViewportWidth=function(){var e=this.grid.gridWidth;return e+=this.getViewportAdjustment().width},e.prototype.getHeaderViewportWidth=function(){return this.getViewportWidth()},e.prototype.getCanvasHeight=function(){var t=this;if(!t.canvasHeightShouldUpdate)return t.$$canvasHeight;var e=t.$$canvasHeight;return t.$$canvasHeight=0,t.visibleRowCache.forEach(function(e){t.$$canvasHeight+=e.height}),t.canvasHeightShouldUpdate=!1,t.grid.api.core.raise.canvasHeightChanged(e,t.$$canvasHeight),t.$$canvasHeight},e.prototype.getVerticalScrollLength=function(){return this.getCanvasHeight()-this.getViewportHeight()+this.grid.scrollbarHeight!==0?this.getCanvasHeight()-this.getViewportHeight()+this.grid.scrollbarHeight:-1},e.prototype.getHorizontalScrollLength=function(){return this.getCanvasWidth()-this.getViewportWidth()+this.grid.scrollbarWidth!==0?this.getCanvasWidth()-this.getViewportWidth()+this.grid.scrollbarWidth:-1},e.prototype.getCanvasWidth=function(){return this.canvasWidth},e.prototype.setRenderedRows=function(e){this.renderedRows.length=e.length;for(var t=0;t<e.length;t++)this.renderedRows[t]=e[t]},e.prototype.setRenderedColumns=function(e){this.renderedColumns.length=e.length;for(var t=0;t<e.length;t++)this.renderedColumns[t]=e[t];this.updateColumnOffset()},e.prototype.updateColumnOffset=function(){for(var e=0,t=0;t<this.currentFirstColumn;t++)e+=this.visibleColumnCache[t].drawnWidth;this.columnOffset=e},e.prototype.scrollVertical=function(e){var t=-1;if(e!==this.prevScrollTop){var r=e-this.prevScrollTop;return 0<r&&(this.grid.scrollDirection=n.scrollDirection.DOWN),r<0&&(this.grid.scrollDirection=n.scrollDirection.UP),1<(t=e/this.getVerticalScrollLength())&&(t=1),t<0&&(t=0),this.adjustScrollVertical(e,t),t}},e.prototype.scrollHorizontal=function(e){var t=-1;if(e!==this.prevScrollLeft){var r=e-this.prevScrollLeft;0<r&&(this.grid.scrollDirection=n.scrollDirection.RIGHT),r<0&&(this.grid.scrollDirection=n.scrollDirection.LEFT);var i=this.getHorizontalScrollLength();return t=0!==i?e/i:0,this.adjustScrollHorizontal(e,t),t}},e.prototype.adjustScrollVertical=function(e,t,r){(this.prevScrollTop!==e||r)&&(void 0!==e&&null!=e||(e=(this.getCanvasHeight()-this.getViewportHeight())*t),this.adjustRows(e,t,!1),this.prevScrollTop=e,this.prevScrolltopPercentage=t,this.grid.queueRefresh())},e.prototype.adjustScrollHorizontal=function(e,t,r){(this.prevScrollLeft!==e||r)&&(void 0!==e&&null!=e||(e=(this.getCanvasWidth()-this.getViewportWidth())*t),this.adjustColumns(e,t),this.prevScrollLeft=e,this.prevScrollleftPercentage=t,this.grid.queueRefresh())},e.prototype.adjustRows=function(e,t,r){var i=this,n=i.minRowsToRender(),o=i.visibleRowCache,a=o.length-n;null==t&&e&&(t=e/i.getVerticalScrollLength());var l=Math.ceil(Math.min(a,a*t));a<l&&(l=a);var s=[];if(o.length>i.grid.options.virtualizationThreshold){if(null!=e){if(!i.grid.suppressParentScrollDown&&i.prevScrollTop<e&&l<i.prevRowScrollIndex+i.grid.options.scrollThreshold&&l<a)return;if(!i.grid.suppressParentScrollUp&&i.prevScrollTop>e&&l>i.prevRowScrollIndex-i.grid.options.scrollThreshold&&l<a)return}s=[Math.max(0,l-i.grid.options.excessRows),Math.min(o.length,l+n+i.grid.options.excessRows)]}else{var d=i.visibleRowCache.length;s=[0,Math.max(d,n+i.grid.options.excessRows)]}i.updateViewableRowRange(s),i.prevRowScrollIndex=l},e.prototype.adjustColumns=function(e,t){var r=this,i=r.minColumnsToRender(),n=r.visibleColumnCache,o=n.length-i;null==t&&e&&(t=e/r.getHorizontalScrollLength());var a=Math.ceil(Math.min(o,o*t));o<a&&(a=o);var l=[];if(n.length>r.grid.options.columnVirtualizationThreshold&&r.getCanvasWidth()>r.getViewportWidth())l=[Math.max(0,a-r.grid.options.excessColumns),Math.min(n.length,a+i+r.grid.options.excessColumns)];else{var s=r.visibleColumnCache.length;l=[0,Math.max(s,i+r.grid.options.excessColumns)]}r.updateViewableColumnRange(l),r.prevColumnScrollIndex=a},e.prototype.updateViewableRowRange=function(e){var t=this.visibleRowCache.slice(e[0],e[1]);this.currentTopRow=e[0],this.setRenderedRows(t)},e.prototype.updateViewableColumnRange=function(e){var t=this.visibleColumnCache.slice(e[0],e[1]);this.currentFirstColumn=e[0],this.setRenderedColumns(t)},e.prototype.headerCellWrapperStyle=function(){if(0!==this.currentFirstColumn){var e=this.columnOffset;return this.grid.isRTL()?{"margin-right":e+"px"}:{"margin-left":e+"px"}}return null},e.prototype.updateColumnWidths=function(){var i=this,n=[],o=0,a=0,t="",l=!1,s=[],d=[],u=0,c=i.grid.getViewportWidth()-i.grid.scrollbarWidth,r=[];angular.forEach(i.grid.renderContainers,function(e){r=r.concat(e.visibleColumnCache)}),r.forEach(function(e){var t=0;if(e.visible)if(l&&(c+=i.grid.scrollbarWidth),!l&&e.colDef.pinnedRight&&(l=!0),angular.isNumber(e.width))t=parseInt(e.width,10),a+=t,e.drawnWidth=t,s.push(e);else if(b.endsWith(e.width,"%")){var r=parseInt(e.width.replace(/%/g,""),10);(t=parseInt(r/100*c))>e.maxWidth&&(t=e.maxWidth),t<e.minWidth&&(t=e.minWidth),a+=t,e.drawnWidth=t,u+=r,d.push(e)}else angular.isString(e.width)&&-1!==e.width.indexOf("*")&&(o+=e.width.length,n.push(e))});var e,g=c-a;if(0<n.length){var p=g/o;n.forEach(function(e){var t=parseInt(e.width.length*p,10);t>e.maxWidth&&(t=e.maxWidth),t<e.minWidth&&(t=e.minWidth),a+=t,e.drawnWidth=t})}if(0<n.length?e=n:0<d.length&&0===s.length&&100===u&&(e=d),!angular.isUndefined(e)){for(var f=function(e){e.drawnWidth<e.maxWidth&&0<m&&(e.drawnWidth++,a++,m--,h=!0)},m=c-a,h=!0;0<m&&h;)h=!1,e.forEach(f);var v=function(e){e.drawnWidth>e.minWidth&&0<C&&(e.drawnWidth--,a--,C--,h=!0)},C=a-c;for(h=!0;0<C&&h;)h=!1,e.forEach(v)}var w=0;i.visibleColumnCache.forEach(function(e){e.visible&&(w+=e.drawnWidth)}),r.forEach(function(e){t+=e.getColClassDefinition()}),i.canvasWidth=w,this.columnStyles=t},e.prototype.needsHScrollbarPlaceholder=function(){var e;return("left"===this.name||"right"===this.name&&!this.hasHScrollbar&&!this.grid.disableScrolling)&&(this.grid.options.enableHorizontalScrollbar===n.scrollbars.ALWAYS||(e=this.grid.element[0].querySelector(".ui-grid-render-container-body .ui-grid-viewport")).scrollWidth>e.offsetWidth)},e.prototype.getViewportStyle=function(){var e=this,t={},r={};return r[n.scrollbars.ALWAYS]="scroll",r[n.scrollbars.WHEN_NEEDED]="auto",e.hasHScrollbar=!1,e.hasVScrollbar=!1,e.grid.disableScrolling?(t["overflow-x"]="hidden",t["overflow-y"]="hidden"):("body"===e.name?(e.hasHScrollbar=e.grid.options.enableHorizontalScrollbar!==n.scrollbars.NEVER,e.grid.isRTL()?e.grid.hasLeftContainerColumns()||(e.hasVScrollbar=e.grid.options.enableVerticalScrollbar!==n.scrollbars.NEVER):e.grid.hasRightContainerColumns()||(e.hasVScrollbar=e.grid.options.enableVerticalScrollbar!==n.scrollbars.NEVER)):"left"===e.name?e.hasVScrollbar=!!e.grid.isRTL()&&e.grid.options.enableVerticalScrollbar!==n.scrollbars.NEVER:e.hasVScrollbar=!e.grid.isRTL()&&e.grid.options.enableVerticalScrollbar!==n.scrollbars.NEVER,t["overflow-x"]=e.hasHScrollbar?r[e.grid.options.enableHorizontalScrollbar]:"hidden",t["overflow-y"]=e.hasVScrollbar?r[e.grid.options.enableVerticalScrollbar]:"hidden"),t},e}]),angular.module("ui.grid").factory("GridRow",["gridUtil","uiGridConstants",function(i,t){function e(e,t,r){this.grid=r,this.entity=e,this.uid=i.nextUid(),this.visible=!0,this.isSelected=!1,this.$$height=r.options.rowHeight}return Object.defineProperty(e.prototype,"height",{get:function(){return this.$$height},set:function(e){e!==this.$$height&&(this.grid.updateCanvasHeight(),this.$$height=e)}}),e.prototype.getQualifiedColField=function(e){return"row."+this.getEntityQualifiedColField(e)},e.prototype.getEntityQualifiedColField=function(e){return e.field===t.ENTITY_BINDING?"entity":i.preEval("entity."+e.field)},e.prototype.setRowInvisible=function(e){e&&e.setThisRowInvisible&&e.setThisRowInvisible("user")},e.prototype.clearRowInvisible=function(e){e&&e.clearThisRowInvisible&&e.clearThisRowInvisible("user")},e.prototype.setThisRowInvisible=function(e,t){this.invisibleReason||(this.invisibleReason={}),this.invisibleReason[e]=!0,this.evaluateRowVisibility(t)},e.prototype.clearThisRowInvisible=function(e,t){void 0!==this.invisibleReason&&delete this.invisibleReason[e],this.evaluateRowVisibility(t)},e.prototype.evaluateRowVisibility=function(e){var r=!0;void 0!==this.invisibleReason&&angular.forEach(this.invisibleReason,function(e,t){e&&(r=!1)}),void 0!==this.visible&&this.visible===r||(this.visible=r,e||(this.grid.queueGridRefresh(),this.grid.api.core.raise.rowsVisibleChanged(this)))},e}]),function(){"use strict";angular.module("ui.grid").factory("GridRowColumn",["$parse","$filter",function(e,t){var r=function e(t,r){if(!(this instanceof e))throw"Using GridRowColumn as a function insead of as a constructor. Must be called with `new` keyword";this.row=t,this.col=r};return r.prototype.getIntersectionValueRaw=function(){return e(this.row.getEntityQualifiedColField(this.col))(this.row)},r}])}(),angular.module("ui.grid").factory("ScrollEvent",["gridUtil",function(a){function e(e,t,r,i){var n=this;if(!e)throw new Error("grid argument is required");n.grid=e,n.source=i,n.withDelay=!0,n.sourceRowContainer=t,n.sourceColContainer=r,n.newScrollLeft=null,n.newScrollTop=null,n.x=null,n.y=null,n.verticalScrollLength=-9999999,n.horizontalScrollLength=-999999,n.fireThrottledScrollingEvent=a.throttle(function(e){n.grid.scrollContainers(e,n)},n.grid.options.wheelScrollThrottle,{trailing:!0})}return e.prototype.getNewScrollLeft=function(e,t){var r=this;if(!r.newScrollLeft){var i,n=e.getCanvasWidth()-e.getViewportWidth(),o=a.normalizeScrollLeft(t,r.grid);if(void 0!==r.x.percentage&&void 0!==r.x.percentage)i=r.x.percentage;else{if(void 0===r.x.pixels||void 0===r.x.pixels)throw new Error("No percentage or pixel value provided for scroll event X axis");i=r.x.percentage=(o+r.x.pixels)/n}return Math.max(0,i*n)}return r.newScrollLeft},e.prototype.getNewScrollTop=function(e,t){var r=this;if(!r.newScrollTop){var i,n=e.getVerticalScrollLength(),o=t[0].scrollTop;if(void 0!==r.y.percentage&&void 0!==r.y.percentage)i=r.y.percentage;else{if(void 0===r.y.pixels||void 0===r.y.pixels)throw new Error("No percentage or pixel value provided for scroll event Y axis");i=r.y.percentage=(o+r.y.pixels)/n}return Math.max(0,i*n)}return r.newScrollTop},e.prototype.atTop=function(e){return this.y&&(0===this.y.percentage||this.verticalScrollLength<0)&&0===e},e.prototype.atBottom=function(e){return this.y&&(1===this.y.percentage||0===this.verticalScrollLength)&&0<e},e.prototype.atLeft=function(e){return this.x&&(0===this.x.percentage||this.horizontalScrollLength<0)&&0===e},e.prototype.atRight=function(e){return this.x&&(1===this.x.percentage||0===this.horizontalScrollLength)&&0<e},e.Sources={ViewPortScroll:"ViewPortScroll",RenderContainerMouseWheel:"RenderContainerMouseWheel",RenderContainerTouchMove:"RenderContainerTouchMove",Other:99},e}]),function(){"use strict";angular.module("ui.grid").service("gridClassFactory",["gridUtil","$q","$compile","$templateCache","uiGridConstants","Grid","GridColumn","GridRow",function(d,i,n,e,u,o,t,r){var a={createGrid:function(e){(e=void 0!==e?e:{}).id=d.newId();var t=new o(e);if(t.options.rowTemplate){var r=i.defer();t.getRowTemplateFn=r.promise,d.getTemplate(t.options.rowTemplate).then(function(e){var t=n(e);r.resolve(t)},function(){throw new Error("Couldn't fetch/use row template '"+t.options.rowTemplate+"'")}).catch(angular.noop)}return t.registerColumnBuilder(a.defaultColumnBuilder),t.registerRowBuilder(a.rowTemplateAssigner),t.registerRowsProcessor(function(e){return e.forEach(function(e){e.evaluateRowVisibility(!0)}),e},50),t.registerColumnsProcessor(function(e){return e.forEach(function(e){e.visible=!angular.isDefined(e.colDef.visible)||e.colDef.visible}),e},50),t.registerRowsProcessor(t.searchRows,100),t.options.externalSort&&angular.isFunction(t.options.externalSort)?t.registerRowsProcessor(t.options.externalSort,200):t.registerRowsProcessor(t.sortByColumn,200),t},defaultColumnBuilder:function(a,l,e){var s=[],t=function(r,e,t,i,n){a[r]?l[e]=a[r]:l[e]=t;var o=d.getTemplate(l[e]).then(function(e){angular.isFunction(e)&&(e=e());var t="cellTooltip"===n?"col.cellTooltip(row,col)":"col.headerTooltip(col)";n&&!1===l[n]?e=e.replace(u.TOOLTIP,""):n&&l[n]&&(e=e.replace(u.TOOLTIP,'title="{{'+t+' CUSTOM_FILTERS }}"')),l[r]=i?e.replace(u.CUSTOM_FILTERS,function(){return l[i]?"|"+l[i]:""}):e},function(){throw new Error("Couldn't fetch/use colDef."+r+" '"+a[r]+"'")}).catch(angular.noop);return s.push(o),o};return l.cellTemplatePromise=t("cellTemplate","providedCellTemplate","ui-grid/uiGridCell","cellFilter","cellTooltip"),l.headerCellTemplatePromise=t("headerCellTemplate","providedHeaderCellTemplate","ui-grid/uiGridHeaderCell","headerCellFilter","headerTooltip"),l.footerCellTemplatePromise=t("footerCellTemplate","providedFooterCellTemplate","ui-grid/uiGridFooterCell","footerCellFilter"),l.filterHeaderTemplatePromise=t("filterHeaderTemplate","providedFilterHeaderTemplate","ui-grid/ui-grid-filter"),l.compiledElementFnDefer=i.defer(),i.all(s)},rowTemplateAssigner:function(e){if(e.rowTemplate){var r=i.defer();e.getRowTemplateFn=r.promise,d.getTemplate(e.rowTemplate).then(function(e){var t=n(e);r.resolve(t)},function(){throw new Error("Couldn't fetch/use row template '"+e.rowTemplate+"'")})}else e.rowTemplate=this.options.rowTemplate,e.getRowTemplateFn=this.getRowTemplateFn;return e.getRowTemplateFn}};return a}])}(),angular.module("ui.grid").service("rowSearcher",["gridUtil","uiGridConstants",function(c,s){var n=s.filter.CONTAINS,g={getTerm:function(e){if(void 0===e.term)return e.term;var t=e.term;return"string"==typeof t&&(t=t.trim()),t},stripTerm:function(e){var t=g.getTerm(e);return"string"==typeof t?t.replace(/(^\*|\*$)/g,"").replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"):t},guessCondition:function(e){if(void 0===e.term||!e.term)return n;var t=g.getTerm(e);if(/\*/.test(t)){var r="";e.flags&&e.flags.caseSensitive||(r+="i");var i=t.replace(/(\\)?\*/g,function(e,t){return t?e:"[\\s\\S]*?"});return new RegExp("^"+i+"$",r)}return n},setupFilters:function(e){for(var t=[],r=e.length,i=0;i<r;i++){var n=e[i];if(n.noTerm||!c.isNullOrUndefined(n.term)){var o={},a="";n.flags&&n.flags.caseSensitive||(a+="i"),c.isNullOrUndefined(n.term)||(n.rawTerm?o.term=n.term:o.term=g.stripTerm(n)),o.noTerm=n.noTerm,n.condition?o.condition=n.condition:o.condition=g.guessCondition(n),o.flags=angular.extend({caseSensitive:!1,date:!1},n.flags),o.condition===s.filter.STARTS_WITH&&(o.startswithRE=new RegExp("^"+o.term,a)),o.condition===s.filter.ENDS_WITH&&(o.endswithRE=new RegExp(o.term+"$",a)),o.condition===s.filter.CONTAINS&&(o.containsRE=new RegExp(o.term,a)),o.condition===s.filter.EXACT&&(o.exactRE=new RegExp("^"+o.term+"$",a)),t.push(o)}}return t},runColumnFilter:function(e,t,r,i){var n,o=typeof i.condition,a=i.term;if(n=r.filterCellFiltered?e.getCellDisplayValue(t,r):e.getCellValue(t,r),i.condition instanceof RegExp)return i.condition.test(n);if("function"===o)return i.condition(a,n,t,r);if(i.startswithRE)return i.startswithRE.test(n);if(i.endswithRE)return i.endswithRE.test(n);if(i.containsRE)return i.containsRE.test(n);if(i.exactRE)return i.exactRE.test(n);if(i.condition===s.filter.NOT_EQUAL)return!new RegExp("^"+a+"$").exec(n);if("number"==typeof n&&"string"==typeof a){var l=parseFloat(a.replace(/\\\./,".").replace(/\\\-/,"-"));isNaN(l)||(a=l)}return!0===i.flags.date&&(n=new Date(n),a=new Date(a.replace(/\\/g,""))),i.condition===s.filter.GREATER_THAN?a<n:i.condition===s.filter.GREATER_THAN_OR_EQUAL?a<=n:i.condition===s.filter.LESS_THAN?n<a:i.condition!==s.filter.LESS_THAN_OR_EQUAL||n<=a},searchColumn:function(e,t,r,i){if(e.options.useExternalFiltering)return!0;for(var n=i.length,o=0;o<n;o++){var a=i[o];if((!c.isNullOrUndefined(a.term)&&""!==a.term||a.noTerm)&&!g.runColumnFilter(e,t,r,a))return!1}return!0},search:function(e,s,t){if(s){if(!e.options.enableFiltering)return s;for(var r=[],i=t.length,n=function(e){var t=!1;return e.forEach(function(e){(!c.isNullOrUndefined(e.term)&&""!==e.term||e.noTerm)&&(t=!0)}),t},o=0;o<i;o++){var a=t[o];void 0!==a.filters&&n(a.filters)&&r.push({col:a,filters:g.setupFilters(a.filters)})}if(0<r.length){for(var l=function(e,t){for(var r,i,n,o,a=s.length,l=0;l<a;l++)r=e,i=s[l],n=t.col,o=t.filters,i.visible&&!g.searchColumn(r,i,n,o)&&(i.visible=!1)},d=r.length,u=0;u<d;u++)l(e,r[u]);e.api.core.raise.rowsVisibleChanged&&e.api.core.raise.rowsVisibleChanged()}return s}}};return g}]),angular.module("ui.grid").service("rowSorter",["$parse","uiGridConstants",function(e,g){var t="("+g.CURRENCY_SYMBOLS.map(function(e){return"\\"+e}).join("|")+")?",p=(new RegExp("^[-+]?"+t+"[\\d,.]+"+t+"%?$"),{colSortFnCache:{},guessSortFn:function(e){switch(e){case"number":return p.sortNumber;case"numberStr":return p.sortNumberStr;case"boolean":return p.sortBool;case"string":return p.sortAlpha;case"date":return p.sortDate;case"object":return p.basicSort;default:throw new Error("No sorting function found for type: "+e)}},handleNulls:function(e,t){if(!e&&0!==e&&!1!==e||!t&&0!==t&&!1!==t){if(!e&&0!==e&&!1!==e&&!t&&0!==t&&!1!==t)return 0;if(!e&&0!==e&&!1!==e)return 1;if(!t&&0!==t&&!1!==t)return-1}return null},basicSort:function(e,t){var r=p.handleNulls(e,t);return null!==r?r:e===t?0:e<t?-1:1},sortNumber:function(e,t){var r=p.handleNulls(e,t);return null!==r?r:e-t},sortNumberStr:function(e,t){var r=p.handleNulls(e,t);if(null!==r)return r;var i,n,o=!1,a=!1;return i=parseFloat(e.replace(/[^0-9.-]/g,"")),isNaN(i)&&(o=!0),n=parseFloat(t.replace(/[^0-9.-]/g,"")),isNaN(n)&&(a=!0),o&&a?0:o?1:a?-1:i-n},sortAlpha:function(e,t){var r=p.handleNulls(e,t);if(null!==r)return r;var i=e.toString().toLowerCase(),n=t.toString().toLowerCase();return i===n?0:i.localeCompare(n)},sortDate:function(e,t){var r=p.handleNulls(e,t);if(null!==r)return r;e instanceof Date||(e=new Date(e)),t instanceof Date||(t=new Date(t));var i=e.getTime(),n=t.getTime();return i===n?0:i<n?-1:1},sortBool:function(e,t){var r=p.handleNulls(e,t);return null!==r?r:e&&t?0:e||t?e?1:-1:0},getSortFn:function(e,t,r){var i;return p.colSortFnCache[t.colDef.name]?i=p.colSortFnCache[t.colDef.name]:void 0!==t.sortingAlgorithm?(i=t.sortingAlgorithm,p.colSortFnCache[t.colDef.name]=t.sortingAlgorithm):t.sortCellFiltered&&t.cellFilter?(i=p.sortAlpha,p.colSortFnCache[t.colDef.name]=i):(i=p.guessSortFn(t.colDef.type))?p.colSortFnCache[t.colDef.name]=i:i=p.sortAlpha,i},prioritySort:function(e,t){return void 0!==e.sort.priority&&void 0!==t.sort.priority?e.sort.priority<t.sort.priority?-1:e.sort.priority===t.sort.priority?0:1:void 0!==e.sort.priority?-1:void 0!==t.sort.priority?1:0},sort:function(l,e,t){if(e){if(l.options.useExternalSorting)return e;var s,d,u=[],r=[];if(t.forEach(function(e){!e.sort||e.sort.ignoreSort||!e.sort.direction||e.sort.direction!==g.ASC&&e.sort.direction!==g.DESC?e.defaultSort&&e.defaultSort.direction&&(e.defaultSort.direction===g.ASC||e.defaultSort.direction===g.DESC)&&r.push({col:e,sort:e.defaultSort}):u.push({col:e,sort:e.sort})}),u=u.sort(p.prioritySort),r=r.sort(p.prioritySort),0===(u=u.concat(r)).length)return e;e.forEach(function(e,t){e.entity.$$uiGridIndex=t});var c=e.slice(0),i=e.sort(function(e,t){for(var r,i=0,n=0;0===i&&n<u.length;){var o,a;s=u[n].col,d=u[n].sort.direction,r=p.getSortFn(l,s,c),s.sortCellFiltered?(o=l.getCellDisplayValue(e,s),a=l.getCellDisplayValue(t,s)):(o=l.getCellValue(e,s),a=l.getCellValue(t,s)),i=r(o,a,e,t,d,s),n++}return 0===i?e.entity.$$uiGridIndex-t.entity.$$uiGridIndex:d===g.ASC?i:0-i});return e.forEach(function(e,t){delete e.entity.$$uiGridIndex}),i}}});return p}]),function(){var C,e=angular.module("ui.grid");function w(e){var t=e;return void 0!==t.length&&t.length&&(t=e[0]),t.ownerDocument.defaultView.getComputedStyle(t,null)}"function"!=typeof Function.prototype.bind&&(C=function(){var i=Array.prototype.slice;return function(e){var t=this,r=i.call(arguments,1);return r.length?function(){return arguments.length?t.apply(e,r.concat(i.call(arguments))):t.apply(e,r)}:function(){return arguments.length?t.apply(e,arguments):t.call(e)}}});var l=new RegExp("^("+/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source+")(?!px)[a-z%]+$","i"),b=/^(block|none|table(?!-c[ea]).+)/,y={position:"absolute",visibility:"hidden",display:"block"};function S(e,t,r,i,n){for(var o=r===(i?"border":"content")?4:"width"===t?1:0,a=0,l=["Top","Right","Bottom","Left"];o<4;o+=2){var s=l[o];if("margin"===r){var d=parseFloat(n[r+s]);isNaN(d)||(a+=d)}if(i){if("content"===r){var u=parseFloat(n["padding"+s]);isNaN(u)||(a-=u)}if("margin"!==r){var c=parseFloat(n["border"+s+"Width"]);isNaN(c)||(a-=c)}}else{var g=parseFloat(n["padding"+s]);if(isNaN(g)||(a+=g),"padding"!==r){var p=parseFloat(n["border"+s+"Width"]);isNaN(p)||(a+=p)}}}return a}function x(e,t,r){var i,n=!0,o=w(e),a="border-box"===o.boxSizing;if(i<=0||null==i){if(((i=o[t])<0||null==i)&&(i=e.style[t]),l.test(i))return i;n=a&&!0,i=parseFloat(i)||0}return i+S(0,t,r||(a?"border":"content"),n,o)}var E=["0","0","0","0"],A="uiGrid-";e.service("gridUtil",["$log","$window","$document","$http","$templateCache","$timeout","$interval","$injector","$q","$interpolate","uiGridConstants",function(t,n,r,e,i,s,d,o,a,l,u){var c,g={augmentWidthOrHeight:S,getStyles:w,createBoundedWrapper:function(e,t){return function(){return t.apply(e,arguments)}},readableColumnName:function(e){return void 0===e||null==e?e:("string"!=typeof e&&(e=String(e)),e.replace(/_+/g," ").replace(/^[A-Z]+$/,function(e){return e.toLowerCase()}).replace(/([\w\u00C0-\u017F]+)/g,function(e){return e.charAt(0).toUpperCase()+e.slice(1)}).replace(/(\w+?(?=[A-Z]))/g,"$1 "))},getColumnsFromData:function(e,r){var i=[];if(!e||void 0===e[0]||void 0===e[0])return[];angular.isUndefined(r)&&(r=[]);var t=e[0];return angular.forEach(t,function(e,t){-1===r.indexOf(t)&&i.push({name:t})}),i},newId:(c=(new Date).getTime(),function(){return c+=1}),getTemplate:function(r){if(i.get(r))return g.postProcessTemplate(i.get(r));if(angular.isFunction(r.then))return r.then(g.postProcessTemplate).catch(angular.noop);try{if(0<angular.element(r).length)return a.when(r).then(g.postProcessTemplate).catch(angular.noop)}catch(e){}return e({method:"GET",url:r}).then(function(e){var t=e.data.trim();return i.put(r,t),t},function(e){throw new Error("Could not get template "+r+": "+e)}).then(g.postProcessTemplate).catch(angular.noop)},postProcessTemplate:function(e){var t=l.startSymbol(),r=l.endSymbol();return"{{"===t&&"}}"===r||(e=(e=e.replace(/\{\{/g,t)).replace(/\}\}/g,r)),a.when(e)},guessType:function(e){var t=typeof e;switch(t){case"number":case"boolean":case"string":return t;default:return angular.isDate(e)?"date":"object"}},elementWidth:function(e){},elementHeight:function(e){},getScrollbarWidth:function(){var e=document.createElement("div");e.style.visibility="hidden",e.style.width="100px",e.style.msOverflowStyle="scrollbar",document.body.appendChild(e);var t=e.offsetWidth;e.style.overflow="scroll";var r=document.createElement("div");r.style.width="100%",e.appendChild(r);var i=r.offsetWidth;return e.parentNode.removeChild(e),t-i},swap:function(e,t,r,i){var n,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in n=r.apply(e,i||[]),t)e.style[o]=a[o];return n},fakeElement:function(e,t,r,i){var n,o,a=angular.element(e).clone()[0];for(o in t)a.style[o]=t[o];return angular.element(document.body).append(a),n=r.call(a,a),angular.element(a).remove(),n},normalizeWheelEvent:function(e){var t,r,i,n,o,a=e||window.event,l=([].slice.call(arguments,1),0),s=0,d=0;return a.originalEvent&&(a=a.originalEvent),a.wheelDelta&&(l=a.wheelDelta),a.detail&&(l=-1*a.detail),d=l,void 0!==a.axis&&a.axis===a.HORIZONTAL_AXIS&&(d=0,s=-1*l),a.deltaY&&(l=d=-1*a.deltaY),a.deltaX&&(l=-1*(s=a.deltaX)),void 0!==a.wheelDeltaY&&(d=a.wheelDeltaY),void 0!==a.wheelDeltaX&&(s=a.wheelDeltaX),i=Math.abs(l),(!t||i<t)&&(t=i),n=Math.max(Math.abs(d),Math.abs(s)),(!r||n<r)&&(r=n),o=0<l?"floor":"ceil",{delta:l=Math[o](l/t),deltaX:s=Math[o](s/r),deltaY:d=Math[o](d/r)}},isTouchEnabled:function(){var e;return("ontouchstart"in n||n.DocumentTouch&&r instanceof DocumentTouch)&&(e=!0),e},isNullOrUndefined:function(e){return null==e},endsWith:function(e,t){return!(!e||!t||"string"!=typeof e)&&-1!==e.indexOf(t,e.length-t.length)},arrayContainsObjectWithProperty:function(e,t,r){var i=!1;return angular.forEach(e,function(e){e[t]===r&&(i=!0)}),i},numericAndNullSort:function(e,t){return null===e?1:null===t?-1:null===e&&null===t?0:e-t},disableAnimations:function(e){var t;try{t=o.get("$animate"),1<angular.version.major||1===angular.version.major&&4<=angular.version.minor?t.enabled(e,!1):t.enabled(!1,e)}catch(e){}},enableAnimations:function(e){var t;try{return t=o.get("$animate"),1<angular.version.major||1===angular.version.major&&4<=angular.version.minor?t.enabled(e,!0):t.enabled(!0,e),t}catch(e){}},nextUid:function(){for(var e,t=E.length;t;){if(57===(e=E[--t].charCodeAt(0)))return E[t]="A",A+E.join("");if(90!==e)return E[t]=String.fromCharCode(e+1),A+E.join("");E[t]="0"}return E.unshift("0"),A+E.join("")},hashKey:function(e){var t,r=typeof e;return"object"===r&&null!==e?"function"==typeof(t=e.$$hashKey)?t=e.$$hashKey():void 0!==e.$$hashKey&&e.$$hashKey?t=e.$$hashKey:void 0===t&&(t=e.$$hashKey=g.nextUid()):t=e,r+": "+t},resetUids:function(){E=["0","0","0"]},logError:function(e){u.LOG_ERROR_MESSAGES&&t.error(e)},logWarn:function(e){u.LOG_WARN_MESSAGES&&t.warn(e)},logDebug:function(){u.LOG_DEBUG_MESSAGES&&t.debug.apply(t,arguments)}};g.focus={queue:[],byId:function(r,i){this._purgeQueue();var e=s(function(){var e=(i&&i.id?i.id+"-":"")+r,t=n.document.getElementById(e);t?t.focus():g.logWarn("[focus.byId] Element id "+e+" was not found.")},0,!1);return this.queue.push(e),e},byElement:function(e){if(!angular.isElement(e))return g.logWarn("Trying to focus on an element that isn't an element."),a.reject("not-element");e=angular.element(e),this._purgeQueue();var t=s(function(){e&&e[0].focus()},0,!1);return this.queue.push(t),t},bySelector:function(t,r,e){var i=this;if(!angular.isElement(t))throw new Error("The parent element is not an element.");t=angular.element(t);var n=function(){var e=t[0].querySelector(r);return i.byElement(e)};if(this._purgeQueue(),e){var o=s(n,0,!1);return this.queue.push(o),o}return n()},_purgeQueue:function(){this.queue.forEach(function(e){s.cancel(e)}),this.queue=[]}},["width","height"].forEach(function(n){var r=n.charAt(0).toUpperCase()+n.substr(1);g["element"+r]=function(e,t){var r=e;if(r&&void 0!==r.length&&r.length&&(r=e[0]),r&&null!==r){var i=w(r);return 0===r.offsetWidth&&b.test(i.display)?g.swap(r,y,function(){return x(r,n,t)}):x(r,n,t)}return null},g["outerElement"+r]=function(e,t){return e?g["element"+r].call(this,e,t?"margin":"border"):null}}),g.closestElm=function(e,t){var r,i;for(void 0!==e.length&&e.length&&(e=e[0]),["matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector"].some(function(e){return"function"==typeof document.body[e]&&(r=e,!0)});null!==e;){if(null!==(i=e.parentElement)&&i[r](t))return i;e=i}return null},g.type=function(e){return Function.prototype.toString.call(e.constructor).match(/function (.*?)\(/)[1]},g.getBorderSize=function(e,t){void 0!==e.length&&e.length&&(e=e[0]);var r=w(e);t=t?"border"+t.charAt(0).toUpperCase()+t.slice(1):"border",t+="Width";var i=parseInt(r[t],10);return isNaN(i)?0:i},g.detectBrowser=function(){var e=n.navigator.userAgent,t={chrome:/chrome/i,safari:/safari/i,firefox:/firefox/i,ie:/internet explorer|trident\//i};for(var r in t)if(t[r].test(e))return r;return"unknown"},g.rtlScrollType=function e(){if(e.type)return e.type;var t=angular.element('<div dir="rtl" style="font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll">A</div>')[0],r="reverse";return document.body.appendChild(t),0<t.scrollLeft?r="default":(t.scrollLeft=1,0===t.scrollLeft&&(r="negative")),angular.element(t).remove(),e.type=r},g.normalizeScrollLeft=function(e,t){void 0!==e.length&&e.length&&(e=e[0]);var r=e.scrollLeft;if(t.isRTL())switch(g.rtlScrollType()){case"default":return e.scrollWidth-r-e.clientWidth;case"negative":return Math.abs(r);case"reverse":return r}return r},g.denormalizeScrollLeft=function(e,t,r){if(void 0!==e.length&&e.length&&(e=e[0]),r.isRTL())switch(g.rtlScrollType()){case"default":return e.scrollWidth-e.clientWidth-t;case"negative":return-1*t;case"reverse":return t}return t},g.preEval=function(e){var t=u.BRACKET_REGEXP.exec(e);if(t)return(t[1]?g.preEval(t[1]):t[1])+t[2]+(t[3]?g.preEval(t[3]):t[3]);var r=(e=e.replace(u.APOS_REGEXP,"\\'")).split(u.DOT_REGEXP),i=[r.shift()];return angular.forEach(r,function(e){i.push(e.replace(u.FUNC_REGEXP,"']$1"))}),i.join("['")},g.debounce=function(t,r,i){var n,o,a,l;function e(){a=this,o=arguments;var e=i&&!n;return n&&s.cancel(n),n=s(function(){n=null,i||(l=t.apply(a,o))},r,!1),e&&(l=t.apply(a,o)),l}return e.cancel=function(){s.cancel(n),n=null},e},g.throttle=function(t,r,i){i=i||{};var n,o,a=0,l=null;function s(e){a=+new Date,t.apply(n,o),d(function(){l=null},0,1,!1)}return function(){if(n=this,o=arguments,null===l){var e=+new Date-a;r<e?s():i.trailing&&(l=d(s,r-e,1,!1))}}},g.on={},g.off={},g._events={},g.addOff=function(i){g.off[i]=function(e,t){var r=g._events[i].indexOf(t);0<r&&g._events[i].removeAt(r)}};var p,f,m="onwheel"in document||9<=document.documentMode?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"];function h(e,t){var r,i=angular.element(this),n=0,o=0,a=0;if(t.originalEvent&&(t=t.originalEvent),"detail"in t&&(a=-1*t.detail),"wheelDelta"in t&&(a=t.wheelDelta),"wheelDeltaY"in t&&(a=t.wheelDeltaY),"wheelDeltaX"in t&&(o=-1*t.wheelDeltaX),"axis"in t&&t.axis===t.HORIZONTAL_AXIS&&(o=-1*a,a=0),n=0===a?o:a,"deltaY"in t&&(n=a=-1*t.deltaY),"deltaX"in t&&(o=t.deltaX,0===a&&(n=-1*o)),0!==a||0!==o){if(1===t.deltaMode){var l=i.data("mousewheel-line-height");n*=l,a*=l,o*=l}else if(2===t.deltaMode){var s=i.data("mousewheel-page-height");n*=s,a*=s,o*=s}var d;r=Math.max(Math.abs(a),Math.abs(o)),(!f||r<f)&&(d=f=r,"mousewheel"===t.type&&d%120==0&&(f/=40)),n=Math[1<=n?"floor":"ceil"](n/f),o=Math[1<=o?"floor":"ceil"](o/f),a=Math[1<=a?"floor":"ceil"](a/f);var u={originalEvent:t,deltaX:o,deltaY:a,deltaFactor:f,preventDefault:function(){t.preventDefault()},stopPropagation:function(){t.stopPropagation()}};p&&clearTimeout(p),p=setTimeout(v,200),e.call(i[0],u)}}function v(){f=null}return g.on.mousewheel=function(e,t){if(e&&t){var r,i,n=angular.element(e);n.data("mousewheel-line-height",(r=n,(i=(r=angular.element(r)[0]).parentElement)||(i=document.getElementsByTagName("body")[0]),parseInt(w(i).fontSize)||parseInt(w(r).fontSize)||16)),n.data("mousewheel-page-height",g.elementHeight(n)),n.data("mousewheel-callbacks")||n.data("mousewheel-callbacks",{});var o=n.data("mousewheel-callbacks");o[t]=(Function.prototype.bind||C).call(h,n[0],t);for(var a=m.length;a;)n.on(m[--a],o[t]);n.on("$destroy",function(){for(var e=m.length;e;)n.off(m[--e],o[t])})}},g.off.mousewheel=function(e,t){var r=angular.element(e),i=r.data("mousewheel-callbacks"),n=i[t];if(n)for(var o=m.length;o;)r.off(m[--o],n);delete i[t],0===Object.keys(i).length&&(r.removeData("mousewheel-line-height"),r.removeData("mousewheel-page-height"),r.removeData("mousewheel-callbacks"))},g}]),e.filter("px",function(){return function(e){return e.match(/^[\d\.]+$/)?e+"px":e}})}(),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("ar",{headerCell:{aria:{defaultFilterLabel:"التصفيه بالعمود",removeFilter:"محو التصفيه",columnMenuButtonLabel:"قاءمه الاعمده"},priority:"أولويه : ",filterLabel:"تصفيه بالاعمده :"},aggregate:{label:"العناصر"},groupPanel:{description:"اسحب رأس العمود هنا وأسقطه لإنشاء مجموعه"},search:{placeholder:"بحث ...",showingItems:"العناصر الظاهره :",selectedItems:"العناصر المحدده :",totalItems:"عدد العناصر :",size:"حجم الصفحه :",first:"اول صفحه",next:"الصفحه التاليه",previous:"الصفحه الصابقه",last:"الصفحه الاخيره"},menu:{text:"اختيار العمود :"},sort:{ascending:"ترتيب تصاعدى",descending:"ترتيب تنازلى",none:"عدم التحديد",remove:"حذف الترتيب"},column:{hide:"إخفاء عمود"},aggregation:{count:"عدد الصفوف: ",sum:"جمع: ",avg:"المتوسط الحسابى: ",min:"الادنى: ",max:"الاقصى: "},pinning:{pinLeft:"تثبيت لليسار",pinRight:"تثبيت لليمين",unpin:"فك التثبيت"},columnMenu:{close:"غلق"},gridMenu:{aria:{buttonLabel:"قائمه الجدول"},columns:"الاعمده:",importerTitle:"إدخال ملف",exporterAllAsCsv:"إخراج كل البيانات ك(csv)",exporterVisibleAsCsv:"إخراج كل البيانات الواضحه ك (csv)",exporterSelectedAsCsv:"إخراج كل البيانات المحدده ك (csv)",exporterAllAsPdf:"إخراج كل البيانات ك(pdf)",exporterVisibleAsPdf:"إخراج كل البيانات الواضحه ك (pdf)",exporterSelectedAsPdf:"إخراج كل البيانات المحدده ك (pdf)",clearAllFilters:"محو كل الترشيح"},importer:{noHeaders:"اسماء هؤلاء الاعمده غير واضحه، هل يوجد رأس للملف؟",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"الملف غير قادر على الاتمام ، هل ال (CSV) صحيح؟",invalidJson:"الملف غير قادر على الاتمام ، هل ال (JSON) صحيح؟",jsonNotArray:"Imported json file must contain an array, aborting."},pagination:{aria:{pageToFirst:"الصفحه الاولى",pageBack:"الصفه السابقه",pageSelected:"الصفحه المحدده",pageForward:"الصفحه التاليه",pageToLast:"الصفحه الاخيره"},sizes:"عدد العناصر فى الصفحه",totalItems:"عناصر",through:"إلى",of:"من"},grouping:{group:"جمع",ungroup:"فك الجمع",aggregate_count:"جمله : العدد",aggregate_sum:"جمله : الحاصل",aggregate_max:"جمله : الاقصى",aggregate_min:"جمله : الاقل",aggregate_avg:"جمله :المتوسط ",aggregate_remove:"جمله : حذف"},validate:{error:"خطأ :",minLength:"القيمه لابد ان لا تقل عن THRESHOLD حرف.",maxLength:"القيمه لابد ان لا تزيد عن THRESHOLD حرف.",required:"مطلوب قيمه"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("bg",{headerCell:{aria:{defaultFilterLabel:"Филттър за колоната",removeFilter:"Премахни филтър",columnMenuButtonLabel:"Меню на колоната"},priority:"Приоритет:",filterLabel:"Филтър за колоната: "},aggregate:{label:"обекти"},search:{placeholder:"Търсене...",showingItems:"Показани обекти:",selectedItems:"избрани обекти:",totalItems:"Общо:",size:"Размер на страницата:",first:"Първа страница",next:"Следваща страница",previous:"Предишна страница",last:"Последна страница"},menu:{text:"Избери колони:"},sort:{ascending:"Сортиране по възходящ ред",descending:"Сортиране по низходящ ред",none:"Без сортиране",remove:"Премахни сортирането"},column:{hide:"Скрий колоната"},aggregation:{count:"Общо редове: ",sum:"общо: ",avg:"средно: ",min:"най-малко: ",max:"най-много: "},pinning:{pinLeft:"Прикрепи вляво",pinRight:"Прикрепи вдясно",unpin:"Премахване"},columnMenu:{close:"Затвори"},gridMenu:{aria:{buttonLabel:"Меню на таблицата"},columns:"Колони:",importerTitle:"Импортиране на файл",exporterAllAsCsv:"Експортиране на данните като csv",exporterVisibleAsCsv:"Експортиране на видимите данни като csv",exporterSelectedAsCsv:"Експортиране на избраните данни като csv",exporterAllAsPdf:"Експортиране на данните като pdf",exporterVisibleAsPdf:"Експортиране на видимите данни като pdf",exporterSelectedAsPdf:"Експортиране на избраните данни като pdf",clearAllFilters:"Премахни всички филтри"},importer:{noHeaders:"Имената на колоните не успяха да бъдат извлечени, файлът има ли хедър?",noObjects:"Обектите не успяха да бъдат извлечени, файлът съдържа ли данни, различни от хедър?",invalidCsv:"Файлът не може да бъде обработеб, уверете се, че е валиден CSV файл",invalidJson:"Файлът не може да бъде обработеб, уверете се, че е валиден JSON файл",jsonNotArray:"Импортираният JSON файл трябва да съдържа масив, прекратяване."},pagination:{aria:{pageToFirst:"Към първа страница",pageBack:"Страница назад",pageSelected:"Избрана страница",pageForward:"Страница напред",pageToLast:"Към последна страница"},sizes:"обекта на страница",totalItems:"обекта",through:"до",of:"от"},grouping:{group:"Групиране",ungroup:"Премахване на групирането",aggregate_count:"Сбор: Брой",aggregate_sum:"Сбор: Сума",aggregate_max:"Сбор: Максимум",aggregate_min:"Сбор: Минимум",aggregate_avg:"Сбор: Средно",aggregate_remove:"Сбор: Премахване"},validate:{error:"Грешка:",minLength:"Стойността трябва да съдържа поне THRESHOLD символа.",maxLength:"Стойността не трябва да съдържа повече от THRESHOLD символа.",required:"Необходима е стойност."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){var t={aggregate:{label:"položky"},groupPanel:{description:"Přesuňte záhlaví zde pro vytvoření skupiny dle sloupce."},search:{placeholder:"Hledat...",showingItems:"Zobrazuji položky:",selectedItems:"Vybrané položky:",totalItems:"Celkem položek:",size:"Velikost strany:",first:"První strana",next:"Další strana",previous:"Předchozí strana",last:"Poslední strana"},menu:{text:"Vyberte sloupec:"},sort:{ascending:"Seřadit od A-Z",descending:"Seřadit od Z-A",remove:"Odebrat seřazení"},column:{hide:"Schovat sloupec"},aggregation:{count:"celkem řádků: ",sum:"celkem: ",avg:"avg: ",min:"min.: ",max:"max.: "},pinning:{pinLeft:"Zamknout vlevo",pinRight:"Zamknout vpravo",unpin:"Odemknout"},gridMenu:{columns:"Sloupce:",importerTitle:"Importovat soubor",exporterAllAsCsv:"Exportovat všechna data do csv",exporterVisibleAsCsv:"Exportovat viditelná data do csv",exporterSelectedAsCsv:"Exportovat vybraná data do csv",exporterAllAsPdf:"Exportovat všechna data do pdf",exporterVisibleAsPdf:"Exportovat viditelná data do pdf",exporterSelectedAsPdf:"Exportovat vybraná data do pdf",exporterAllAsExcel:"Exportovat všechna data do excel",exporterVisibleAsExcel:"Exportovat viditelná data do excel",exporterSelectedAsExcel:"Exportovat vybraná data do excel",clearAllFilters:"Odstranit všechny filtry"},importer:{noHeaders:"Názvy sloupců se nepodařilo získat, obsahuje soubor záhlaví?",noObjects:"Data se nepodařilo zpracovat, obsahuje soubor řádky mimo záhlaví?",invalidCsv:"Soubor nelze zpracovat, jedná se o CSV?",invalidJson:"Soubor nelze zpracovat, je to JSON?",jsonNotArray:"Soubor musí obsahovat json. Ukončuji.."},pagination:{sizes:"položek na stránku",totalItems:"položek"},grouping:{group:"Seskupit",ungroup:"Odebrat seskupení",aggregate_count:"Agregace: Count",aggregate_sum:"Agregace: Sum",aggregate_max:"Agregace: Max",aggregate_min:"Agregace: Min",aggregate_avg:"Agregace: Avg",aggregate_remove:"Agregace: Odebrat"}};return e.add("cs",t),e.add("cz",t),e.add("cs-cz",t),e.add("cs-CZ",t),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("da",{aggregate:{label:"artikler"},groupPanel:{description:"Grupér rækker udfra en kolonne ved at trække dens overskift hertil."},search:{placeholder:"Søg...",showingItems:"Viste rækker:",selectedItems:"Valgte rækker:",totalItems:"Rækker totalt:",size:"Side størrelse:",first:"Første side",next:"Næste side",previous:"Forrige side",last:"Sidste side"},menu:{text:"Vælg kolonner:"},sort:{ascending:"Sorter stigende",descending:"Sorter faldende",none:"Sorter ingen",remove:"Fjern sortering"},column:{hide:"Skjul kolonne"},aggregation:{count:"antal rækker: ",sum:"sum: ",avg:"gns: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Fastgør til venstre",pinRight:"Fastgør til højre",unpin:"Frigør"},gridMenu:{columns:"Kolonner:",importerTitle:"Importer fil",exporterAllAsCsv:"Eksporter alle data som csv",exporterVisibleAsCsv:"Eksporter synlige data som csv",exporterSelectedAsCsv:"Eksporter markerede data som csv",exporterAllAsPdf:"Eksporter alle data som pdf",exporterVisibleAsPdf:"Eksporter synlige data som pdf",exporterSelectedAsPdf:"Eksporter markerede data som pdf",exporterAllAsExcel:"Eksporter alle data som excel",exporterVisibleAsExcel:"Eksporter synlige data som excel",exporterSelectedAsExcel:"Eksporter markerede data som excel",clearAllFilters:"Clear all filters"},importer:{noHeaders:"Column names were unable to be derived, does the file have a header?",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"File was unable to be processed, is it valid CSV?",invalidJson:"File was unable to be processed, is it valid Json?",jsonNotArray:"Imported json file must contain an array, aborting."},pagination:{aria:{pageToFirst:"Gå til første",pageBack:"Gå tilbage",pageSelected:"Valgte side",pageForward:"Gå frem",pageToLast:"Gå til sidste"},sizes:"genstande per side",totalItems:"genstande",through:"gennem",of:"af"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("de",{headerCell:{aria:{defaultFilterLabel:"Filter für Spalte",removeFilter:"Filter löschen",columnMenuButtonLabel:"Spaltenmenü",column:"Spalte"},priority:"Priorität:",filterLabel:"Filter für Spalte: "},aggregate:{label:"Eintrag"},groupPanel:{description:"Ziehen Sie eine Spaltenüberschrift hierhin, um nach dieser Spalte zu gruppieren."},search:{aria:{selected:"Zeile markiert",notSelected:"Zeile nicht markiert"},placeholder:"Suche...",showingItems:"Zeige Einträge:",selectedItems:"Ausgewählte Einträge:",totalItems:"Einträge gesamt:",size:"Einträge pro Seite:",first:"Erste Seite",next:"Nächste Seite",previous:"Vorherige Seite",last:"Letzte Seite"},menu:{text:"Spalten auswählen:"},sort:{ascending:"aufsteigend sortieren",descending:"absteigend sortieren",none:"keine Sortierung",remove:"Sortierung zurücksetzen"},column:{hide:"Spalte ausblenden"},aggregation:{count:"Zeilen insgesamt: ",sum:"gesamt: ",avg:"Durchschnitt: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Links anheften",pinRight:"Rechts anheften",unpin:"Lösen"},columnMenu:{close:"Schließen"},gridMenu:{aria:{buttonLabel:"Tabellenmenü"},columns:"Spalten:",importerTitle:"Datei importieren",exporterAllAsCsv:"Alle Daten als CSV exportieren",exporterVisibleAsCsv:"Sichtbare Daten als CSV exportieren",exporterSelectedAsCsv:"Markierte Daten als CSV exportieren",exporterAllAsPdf:"Alle Daten als PDF exportieren",exporterVisibleAsPdf:"Sichtbare Daten als PDF exportieren",exporterSelectedAsPdf:"Markierte Daten als PDF exportieren",exporterAllAsExcel:"Alle Daten als Excel exportieren",exporterVisibleAsExcel:"Sichtbare Daten als Excel exportieren",exporterSelectedAsExcel:"Markierte Daten als Excel exportieren",clearAllFilters:"Alle Filter zurücksetzen"},importer:{noHeaders:"Es konnten keine Spaltennamen ermittelt werden. Sind in der Datei Spaltendefinitionen enthalten?",noObjects:"Es konnten keine Zeileninformationen gelesen werden, Sind in der Datei außer den Spaltendefinitionen auch Daten enthalten?",invalidCsv:"Die Datei konnte nicht eingelesen werden, ist es eine gültige CSV-Datei?",invalidJson:"Die Datei konnte nicht eingelesen werden. Enthält sie gültiges JSON?",jsonNotArray:"Die importierte JSON-Datei muß ein Array enthalten. Breche Import ab."},pagination:{aria:{pageToFirst:"Zum Anfang",pageBack:"Seite zurück",pageSelected:"Ausgewählte Seite",pageForward:"Seite vor",pageToLast:"Zum Ende"},sizes:"Einträge pro Seite",totalItems:"Einträgen",through:"bis",of:"von"},grouping:{group:"Gruppieren",ungroup:"Gruppierung aufheben",aggregate_count:"Agg: Anzahl",aggregate_sum:"Agg: Summe",aggregate_max:"Agg: Maximum",aggregate_min:"Agg: Minimum",aggregate_avg:"Agg: Mittelwert",aggregate_remove:"Aggregation entfernen"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("en",{headerCell:{aria:{defaultFilterLabel:"Filter for column",removeFilter:"Remove Filter",columnMenuButtonLabel:"Column Menu",column:"Column"},priority:"Priority:",filterLabel:"Filter for column: "},aggregate:{label:"items"},groupPanel:{description:"Drag a column header here and drop it to group by that column."},search:{aria:{selected:"Row selected",notSelected:"Row not selected"},placeholder:"Search...",showingItems:"Showing Items:",selectedItems:"Selected Items:",totalItems:"Total Items:",size:"Page Size:",first:"First Page",next:"Next Page",previous:"Previous Page",last:"Last Page"},menu:{text:"Choose Columns:"},sort:{ascending:"Sort Ascending",descending:"Sort Descending",none:"Sort None",remove:"Remove Sort"},column:{hide:"Hide Column"},aggregation:{count:"total rows: ",sum:"total: ",avg:"avg: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Pin Left",pinRight:"Pin Right",unpin:"Unpin"},columnMenu:{close:"Close"},gridMenu:{aria:{buttonLabel:"Grid Menu"},columns:"Columns:",importerTitle:"Import file",exporterAllAsCsv:"Export all data as csv",exporterVisibleAsCsv:"Export visible data as csv",exporterSelectedAsCsv:"Export selected data as csv",exporterAllAsPdf:"Export all data as pdf",exporterVisibleAsPdf:"Export visible data as pdf",exporterSelectedAsPdf:"Export selected data as pdf",exporterAllAsExcel:"Export all data as excel",exporterVisibleAsExcel:"Export visible data as excel",exporterSelectedAsExcel:"Export selected data as excel",clearAllFilters:"Clear all filters"},importer:{noHeaders:"Column names were unable to be derived, does the file have a header?",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"File was unable to be processed, is it valid CSV?",invalidJson:"File was unable to be processed, is it valid Json?",jsonNotArray:"Imported json file must contain an array, aborting."},pagination:{aria:{pageToFirst:"Page to first",pageBack:"Page back",pageSelected:"Selected page",pageForward:"Page forward",pageToLast:"Page to last"},sizes:"items per page",totalItems:"items",through:"through",of:"of"},grouping:{group:"Group",ungroup:"Ungroup",aggregate_count:"Agg: Count",aggregate_sum:"Agg: Sum",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Avg",aggregate_remove:"Agg: Remove"},validate:{error:"Error:",minLength:"Value should be at least THRESHOLD characters long.",maxLength:"Value should be at most THRESHOLD characters long.",required:"A value is needed."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("es-ct",{headerCell:{aria:{defaultFilterLabel:"Filtre per columna",removeFilter:"Elimina el filtre",columnMenuButtonLabel:"Menú de Columna",column:"Columna"},priority:"Priority:",filterLabel:"Filtre per columna: "},aggregate:{label:"items"},groupPanel:{description:"Arrossegueu una capçalera de columna aquí i deixeu-lo anar per agrupar per aquesta columna."},search:{aria:{selected:"Fila seleccionada",notSelected:"Fila no seleccionada"},placeholder:"Cerca...",showingItems:"Ítems Mostrats:",selectedItems:"Ítems Seleccionats:",totalItems:"Ítems Totals:",size:"Mida de la pàgina:",first:"Primera Pàgina",next:"Propera Pàgina",previous:"Pàgina Anterior",last:"Última Pàgina"},menu:{text:"Triar Columnes:"},sort:{ascending:"Ordena Ascendent",descending:"Ordena Descendent",none:"Sense Ordre",remove:"Eliminar Ordre"},column:{hide:"Amaga la Columna"},aggregation:{count:"Files Totals: ",sum:"total: ",avg:"mitjà: ",min:"mín: ",max:"màx: "},pinning:{pinLeft:"Fixar a l'Esquerra",pinRight:"Fixar a la Dreta",unpin:"Treure Fixació"},columnMenu:{close:"Tanca"},gridMenu:{aria:{buttonLabel:"Menú de Quadrícula"},columns:"Columnes:",importerTitle:"Importa el fitxer",exporterAllAsCsv:"Exporta tot com CSV",exporterVisibleAsCsv:"Exporta les dades visibles com a CSV",exporterSelectedAsCsv:"Exporta les dades seleccionades com a CSV",exporterAllAsPdf:"Exporta tot com PDF",exporterVisibleAsPdf:"Exporta les dades visibles com a PDF",exporterSelectedAsPdf:"Exporta les dades seleccionades com a PDF",exporterAllAsExcel:"Exporta tot com Excel",exporterVisibleAsExcel:"Exporta les dades visibles com Excel",exporterSelectedAsExcel:"Exporta les dades seleccionades com Excel",clearAllFilters:"Netejar tots els filtres"},importer:{noHeaders:"No va ser possible derivar els noms de les columnes, té encapçalats l'arxiu?",noObjects:"No va ser possible obtenir registres, conté dades l'arxiu, a part de les capçaleres?",invalidCsv:"No va ser possible processar l'arxiu, ¿és un CSV vàlid?",invalidJson:"No va ser possible processar l'arxiu, ¿és un JSON vàlid?",jsonNotArray:"El fitxer json importat ha de contenir una matriu, avortant."},pagination:{aria:{pageToFirst:"Page to first",pageBack:"Page back",pageSelected:"Selected page",pageForward:"Page forward",pageToLast:"Page to last"},sizes:"ítems per pàgina",totalItems:"ítems",through:"a",of:"de"},grouping:{group:"Agrupar",ungroup:"Desagrupar",aggregate_count:"Agr: Compte",aggregate_sum:"Agr: Sum",aggregate_max:"Agr: Máx",aggregate_min:"Agr: Mín",aggregate_avg:"Agr: Mitjà",aggregate_remove:"Agr: Treure"},validate:{error:"Error:",minLength:"El valor ha de tenir almenys caràcters THRESHOLD.",maxLength:"El valor ha de tenir com a màxim caràcters THRESHOLD.",required:"Un valor és necessari."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("es",{aggregate:{label:"Artículos"},groupPanel:{description:"Arrastre un encabezado de columna aquí y suéltelo para agrupar por esa columna."},search:{placeholder:"Buscar...",showingItems:"Artículos Mostrados:",selectedItems:"Artículos Seleccionados:",totalItems:"Artículos Totales:",size:"Tamaño de Página:",first:"Primera Página",next:"Página Siguiente",previous:"Página Anterior",last:"Última Página"},menu:{text:"Elegir columnas:"},sort:{ascending:"Orden Ascendente",descending:"Orden Descendente",remove:"Sin Ordenar"},column:{hide:"Ocultar la columna"},aggregation:{count:"filas totales: ",sum:"total: ",avg:"media: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Fijar a la Izquierda",pinRight:"Fijar a la Derecha",unpin:"Quitar Fijación"},gridMenu:{columns:"Columnas:",importerTitle:"Importar archivo",exporterAllAsCsv:"Exportar todo como csv",exporterVisibleAsCsv:"Exportar vista como csv",exporterSelectedAsCsv:"Exportar selección como csv",exporterAllAsPdf:"Exportar todo como pdf",exporterVisibleAsPdf:"Exportar vista como pdf",exporterSelectedAsPdf:"Exportar selección como pdf",exporterAllAsExcel:"Exportar todo como excel",exporterVisibleAsExcel:"Exportar vista como excel",exporterSelectedAsExcel:"Exportar selección como excel",clearAllFilters:"Limpiar todos los filtros"},importer:{noHeaders:"No fue posible derivar los nombres de las columnas, ¿tiene encabezados el archivo?",noObjects:"No fue posible obtener registros, ¿contiene datos el archivo, aparte de los encabezados?",invalidCsv:"No fue posible procesar el archivo, ¿es un CSV válido?",invalidJson:"No fue posible procesar el archivo, ¿es un Json válido?",jsonNotArray:"El archivo json importado debe contener un array, abortando."},pagination:{sizes:"registros por página",totalItems:"registros",of:"de"},grouping:{group:"Agrupar",ungroup:"Desagrupar",aggregate_count:"Agr: Cont",aggregate_sum:"Agr: Sum",aggregate_max:"Agr: Máx",aggregate_min:"Agr: Min",aggregate_avg:"Agr: Prom",aggregate_remove:"Agr: Quitar"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("fa",{aggregate:{label:"قلم"},groupPanel:{description:"عنوان یک ستون را بگیر و به گروهی از آن ستون رها کن."},search:{placeholder:"جستجو...",showingItems:"نمایش اقلام:",selectedItems:"قلم‌های انتخاب شده:",totalItems:"مجموع اقلام:",size:"اندازه‌ی صفحه:",first:"اولین صفحه",next:"صفحه‌ی‌بعدی",previous:"صفحه‌ی‌ قبلی",last:"آخرین صفحه"},menu:{text:"ستون‌های انتخابی:"},sort:{ascending:"ترتیب صعودی",descending:"ترتیب نزولی",remove:"حذف مرتب کردن"},column:{hide:"پنهان‌کردن ستون"},aggregation:{count:"تعداد: ",sum:"مجموع: ",avg:"میانگین: ",min:"کمترین: ",max:"بیشترین: "},pinning:{pinLeft:"پین کردن سمت چپ",pinRight:"پین کردن سمت راست",unpin:"حذف پین"},gridMenu:{columns:"ستون‌ها:",importerTitle:"وارد کردن فایل",exporterAllAsCsv:"خروجی تمام داده‌ها در فایل csv",exporterVisibleAsCsv:"خروجی داده‌های قابل مشاهده در فایل csv",exporterSelectedAsCsv:"خروجی داده‌های انتخاب‌شده در فایل csv",exporterAllAsPdf:"خروجی تمام داده‌ها در فایل pdf",exporterVisibleAsPdf:"خروجی داده‌های قابل مشاهده در فایل pdf",exporterSelectedAsPdf:"خروجی داده‌های انتخاب‌شده در فایل pdf",clearAllFilters:"پاک کردن تمام فیلتر"},importer:{noHeaders:"نام ستون قابل استخراج نیست. آیا فایل عنوان دارد؟",noObjects:"اشیا قابل استخراج نیستند. آیا به جز عنوان‌ها در فایل داده وجود دارد؟",invalidCsv:"فایل قابل پردازش نیست. آیا فرمت csv معتبر است؟",invalidJson:"فایل قابل پردازش نیست. آیا فرمت json معتبر است؟",jsonNotArray:"فایل json وارد شده باید حاوی آرایه باشد. عملیات ساقط شد."},pagination:{sizes:"اقلام در هر صفحه",totalItems:"اقلام",of:"از"},grouping:{group:"گروه‌بندی",ungroup:"حذف گروه‌بندی",aggregate_count:"Agg: تعداد",aggregate_sum:"Agg: جمع",aggregate_max:"Agg: بیشینه",aggregate_min:"Agg: کمینه",aggregate_avg:"Agg: میانگین",aggregate_remove:"Agg: حذف"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("fi",{aggregate:{label:"rivit"},groupPanel:{description:"Raahaa ja pudota otsikko tähän ryhmittääksesi sarakkeen mukaan."},search:{placeholder:"Hae...",showingItems:"Näytetään rivejä:",selectedItems:"Valitut rivit:",totalItems:"Rivejä yht.:",size:"Näytä:",first:"Ensimmäinen sivu",next:"Seuraava sivu",previous:"Edellinen sivu",last:"Viimeinen sivu"},menu:{text:"Valitse sarakkeet:"},sort:{ascending:"Järjestä nouseva",descending:"Järjestä laskeva",remove:"Poista järjestys"},column:{hide:"Piilota sarake"},aggregation:{count:"Rivejä yht.: ",sum:"Summa: ",avg:"K.a.: ",min:"Min: ",max:"Max: "},pinning:{pinLeft:"Lukitse vasemmalle",pinRight:"Lukitse oikealle",unpin:"Poista lukitus"},gridMenu:{columns:"Sarakkeet:",importerTitle:"Tuo tiedosto",exporterAllAsCsv:"Vie tiedot csv-muodossa",exporterVisibleAsCsv:"Vie näkyvä tieto csv-muodossa",exporterSelectedAsCsv:"Vie valittu tieto csv-muodossa",exporterAllAsPdf:"Vie tiedot pdf-muodossa",exporterVisibleAsPdf:"Vie näkyvä tieto pdf-muodossa",exporterSelectedAsPdf:"Vie valittu tieto pdf-muodossa",exporterAllAsExcel:"Vie tiedot excel-muodossa",exporterVisibleAsExcel:"Vie näkyvä tieto excel-muodossa",exporterSelectedAsExcel:"Vie valittu tieto excel-muodossa",clearAllFilters:"Puhdista kaikki suodattimet"},importer:{noHeaders:"Sarakkeen nimiä ei voitu päätellä, onko tiedostossa otsikkoriviä?",noObjects:"Tietoja ei voitu lukea, onko tiedostossa muuta kuin otsikkot?",invalidCsv:"Tiedostoa ei voitu käsitellä, oliko se CSV-muodossa?",invalidJson:"Tiedostoa ei voitu käsitellä, oliko se JSON-muodossa?",jsonNotArray:"Tiedosto ei sisältänyt taulukkoa, lopetetaan."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("fr",{headerCell:{aria:{defaultFilterLabel:"Filtre de la colonne",removeFilter:"Supprimer le filtre",columnMenuButtonLabel:"Menu de la colonne"},priority:"Priorité:",filterLabel:"Filtre de la colonne: "},aggregate:{label:"éléments"},groupPanel:{description:"Faites glisser une en-tête de colonne ici pour créer un groupe de colonnes."},search:{placeholder:"Recherche...",showingItems:"Affichage des éléments :",selectedItems:"Éléments sélectionnés :",totalItems:"Nombre total d'éléments:",size:"Taille de page:",first:"Première page",next:"Page Suivante",previous:"Page précédente",last:"Dernière page"},menu:{text:"Choisir des colonnes :"},sort:{ascending:"Trier par ordre croissant",descending:"Trier par ordre décroissant",none:"Aucun tri",remove:"Enlever le tri"},column:{hide:"Cacher la colonne"},aggregation:{count:"lignes totales: ",sum:"total: ",avg:"moy: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Épingler à gauche",pinRight:"Épingler à droite",unpin:"Détacher"},columnMenu:{close:"Fermer"},gridMenu:{aria:{buttonLabel:"Menu du tableau"},columns:"Colonnes:",importerTitle:"Importer un fichier",exporterAllAsCsv:"Exporter toutes les données en CSV",exporterVisibleAsCsv:"Exporter les données visibles en CSV",exporterSelectedAsCsv:"Exporter les données sélectionnées en CSV",exporterAllAsPdf:"Exporter toutes les données en PDF",exporterVisibleAsPdf:"Exporter les données visibles en PDF",exporterSelectedAsPdf:"Exporter les données sélectionnées en PDF",exporterAllAsExcel:"Exporter toutes les données en Excel",exporterVisibleAsExcel:"Exporter les données visibles en Excel",exporterSelectedAsExcel:"Exporter les données sélectionnées en Excel",clearAllFilters:"Nettoyez tous les filtres"},importer:{noHeaders:"Impossible de déterminer le nom des colonnes, le fichier possède-t-il une en-tête ?",noObjects:"Aucun objet trouvé, le fichier possède-t-il des données autres que l'en-tête ?",invalidCsv:"Le fichier n'a pas pu être traité, le CSV est-il valide ?",invalidJson:"Le fichier n'a pas pu être traité, le JSON est-il valide ?",jsonNotArray:"Le fichier JSON importé doit contenir un tableau, abandon."},pagination:{aria:{pageToFirst:"Aller à la première page",pageBack:"Page précédente",pageSelected:"Page sélectionnée",pageForward:"Page suivante",pageToLast:"Aller à la dernière page"},sizes:"éléments par page",totalItems:"éléments",through:"à",of:"sur"},grouping:{group:"Grouper",ungroup:"Dégrouper",aggregate_count:"Agg: Compter",aggregate_sum:"Agg: Somme",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Moy",aggregate_remove:"Agg: Retirer"},validate:{error:"Erreur:",minLength:"La valeur doit être supérieure ou égale à THRESHOLD caractères.",maxLength:"La valeur doit être inférieure ou égale à THRESHOLD caractères.",required:"Une valeur est nécéssaire."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("he",{aggregate:{label:"items"},groupPanel:{description:"גרור עמודה לכאן ושחרר בכדי לקבץ עמודה זו."},search:{placeholder:"חפש...",showingItems:"מציג:",selectedItems:'סה"כ נבחרו:',totalItems:'סה"כ רשומות:',size:"תוצאות בדף:",first:"דף ראשון",next:"דף הבא",previous:"דף קודם",last:"דף אחרון"},menu:{text:"בחר עמודות:"},sort:{ascending:"סדר עולה",descending:"סדר יורד",remove:"בטל"},column:{hide:"טור הסתר"},aggregation:{count:"total rows: ",sum:"total: ",avg:"avg: ",min:"min: ",max:"max: "},gridMenu:{columns:"Columns:",importerTitle:"Import file",exporterAllAsCsv:"Export all data as csv",exporterVisibleAsCsv:"Export visible data as csv",exporterSelectedAsCsv:"Export selected data as csv",exporterAllAsPdf:"Export all data as pdf",exporterVisibleAsPdf:"Export visible data as pdf",exporterSelectedAsPdf:"Export selected data as pdf",exporterAllAsExcel:"Export all data as excel",exporterVisibleAsExcel:"Export visible data as excel",exporterSelectedAsExcel:"Export selected data as excel",clearAllFilters:"Clean all filters"},importer:{noHeaders:"Column names were unable to be derived, does the file have a header?",noObjects:"Objects were not able to be derived, was there data in the file other than headers?",invalidCsv:"File was unable to be processed, is it valid CSV?",invalidJson:"File was unable to be processed, is it valid Json?",jsonNotArray:"Imported json file must contain an array, aborting."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("hy",{aggregate:{label:"տվյալներ"},groupPanel:{description:"Ըստ սյան խմբավորելու համար քաշեք և գցեք վերնագիրն այստեղ։"},search:{placeholder:"Փնտրում...",showingItems:"Ցուցադրված տվյալներ՝",selectedItems:"Ընտրված:",totalItems:"Ընդամենը՝",size:"Տողերի քանակը էջում՝",first:"Առաջին էջ",next:"Հաջորդ էջ",previous:"Նախորդ էջ",last:"Վերջին էջ"},menu:{text:"Ընտրել սյուները:"},sort:{ascending:"Աճման կարգով",descending:"Նվազման կարգով",remove:"Հանել "},column:{hide:"Թաքցնել սյունը"},aggregation:{count:"ընդամենը տող՝ ",sum:"ընդամենը՝ ",avg:"միջին՝ ",min:"մին՝ ",max:"մաքս՝ "},pinning:{pinLeft:"Կպցնել ձախ կողմում",pinRight:"Կպցնել աջ կողմում",unpin:"Արձակել"},gridMenu:{columns:"Սյուներ:",importerTitle:"Ներմուծել ֆայլ",exporterAllAsCsv:"Արտահանել ամբողջը CSV",exporterVisibleAsCsv:"Արտահանել երևացող տվյալները CSV",exporterSelectedAsCsv:"Արտահանել ընտրված տվյալները CSV",exporterAllAsPdf:"Արտահանել PDF",exporterVisibleAsPdf:"Արտահանել երևացող տվյալները PDF",exporterSelectedAsPdf:"Արտահանել ընտրված տվյալները PDF",exporterAllAsExcel:"Արտահանել excel",exporterVisibleAsExcel:"Արտահանել երևացող տվյալները excel",exporterSelectedAsExcel:"Արտահանել ընտրված տվյալները excel",clearAllFilters:"Մաքրել բոլոր ֆիլտրերը"},importer:{noHeaders:"Հնարավոր չեղավ որոշել սյան վերնագրերը։ Արդյո՞ք ֆայլը ունի վերնագրեր։",noObjects:"Հնարավոր չեղավ կարդալ տվյալները։ Արդյո՞ք ֆայլում կան տվյալներ։",invalidCsv:"Հնարավոր չեղավ մշակել ֆայլը։ Արդյո՞ք այն վավեր CSV է։",invalidJson:"Հնարավոր չեղավ մշակել ֆայլը։ Արդյո՞ք այն վավեր Json է։",jsonNotArray:"Ներմուծված json ֆայլը պետք է պարունակի զանգված, կասեցվում է։"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("is",{headerCell:{aria:{defaultFilterLabel:"Sía fyrir dálk",removeFilter:"Fjarlægja síu",columnMenuButtonLabel:"Dálkavalmynd"},priority:"Forgangsröðun:",filterLabel:"Sía fyrir dálka: "},aggregate:{label:"hlutir"},groupPanel:{description:"Dragðu dálkhaus hingað til að flokka saman eftir þeim dálki."},search:{placeholder:"Leita...",showingItems:"Sýni hluti:",selectedItems:"Valdir hlutir:",totalItems:"Hlutir alls:",size:"Stærð síðu:",first:"Fyrsta síða",next:"Næsta síða",previous:"Fyrri síða",last:"Síðasta síða"},menu:{text:"Veldu dálka:"},sort:{ascending:"Raða hækkandi",descending:"Raða lækkandi",none:"Engin röðun",remove:"Fjarlægja röðun"},column:{hide:"Fela dálk"},aggregation:{count:"fjöldi raða: ",sum:"summa: ",avg:"meðaltal: ",min:"lágmark: ",max:"hámark: "},pinning:{pinLeft:"Festa til vinstri",pinRight:"Festa til hægri",unpin:"Losa"},columnMenu:{close:"Loka"},gridMenu:{aria:{buttonLabel:"Töflu valmynd"},columns:"Dálkar:",importerTitle:"Flytja inn skjal",exporterAllAsCsv:"Flytja út gögn sem csv",exporterVisibleAsCsv:"Flytja út sýnileg gögn sem csv",exporterSelectedAsCsv:"Flytja út valin gögn sem csv",exporterAllAsPdf:"Flytja út öll gögn sem pdf",exporterVisibleAsPdf:"Flytja út sýnileg gögn sem pdf",exporterSelectedAsPdf:"Flytja út valin gögn sem pdf",clearAllFilters:"Hreinsa allar síur"},importer:{noHeaders:"Ekki hægt að vinna dálkanöfn úr skjalinu, er skjalið örugglega með haus?",noObjects:"Ekki hægt að vinna hluti úr skjalinu, voru örugglega gögn í skjalinu önnur en hausinn?",invalidCsv:"Tókst ekki að vinna skjal, er það örggulega gilt CSV?",invalidJson:"Tókst ekki að vinna skjal, er það örugglega gilt Json?",jsonNotArray:"Innflutt json skjal verður að innihalda fylki, hætti við."},pagination:{aria:{pageToFirst:"Fletta að fyrstu",pageBack:"Fletta til baka",pageSelected:"Valin síða",pageForward:"Fletta áfram",pageToLast:"Fletta að síðustu"},sizes:"hlutir á síðu",totalItems:"hlutir",through:"gegnum",of:"af"},grouping:{group:"Flokka",ungroup:"Sundurliða",aggregate_count:"Fjöldi: ",aggregate_sum:"Summa: ",aggregate_max:"Hámark: ",aggregate_min:"Lágmark: ",aggregate_avg:"Meðaltal: ",aggregate_remove:"Fjarlægja: "},validate:{error:"Villa:",minLength:"Gildi ætti að vera a.m.k. THRESHOLD stafa langt.",maxLength:"Gildi ætti að vera í mesta lagi THRESHOLD stafa langt.",required:"Þarf að hafa gildi."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("it",{aggregate:{label:"elementi"},groupPanel:{description:"Trascina un'intestazione all'interno del gruppo della colonna."},search:{placeholder:"Ricerca...",showingItems:"Mostra:",selectedItems:"Selezionati:",totalItems:"Totali:",size:"Tot Pagine:",first:"Prima",next:"Prossima",previous:"Precedente",last:"Ultima"},menu:{text:"Scegli le colonne:"},sort:{ascending:"Asc.",descending:"Desc.",remove:"Annulla ordinamento"},column:{hide:"Nascondi"},aggregation:{count:"righe totali: ",sum:"tot: ",avg:"media: ",min:"minimo: ",max:"massimo: "},pinning:{pinLeft:"Blocca a sx",pinRight:"Blocca a dx",unpin:"Blocca in alto"},gridMenu:{columns:"Colonne:",importerTitle:"Importa",exporterAllAsCsv:"Esporta tutti i dati in CSV",exporterVisibleAsCsv:"Esporta i dati visibili in CSV",exporterSelectedAsCsv:"Esporta i dati selezionati in CSV",exporterAllAsPdf:"Esporta tutti i dati in PDF",exporterVisibleAsPdf:"Esporta i dati visibili in PDF",exporterSelectedAsPdf:"Esporta i dati selezionati in PDF",exporterAllAsExcel:"Esporta tutti i dati in excel",exporterVisibleAsExcel:"Esporta i dati visibili in excel",exporterSelectedAsExcel:"Esporta i dati selezionati in excel",clearAllFilters:"Pulire tutti i filtri"},importer:{noHeaders:"Impossibile reperire i nomi delle colonne, sicuro che siano indicati all'interno del file?",noObjects:"Impossibile reperire gli oggetti, sicuro che siano indicati all'interno del file?",invalidCsv:"Impossibile elaborare il file, sicuro che sia un CSV?",invalidJson:"Impossibile elaborare il file, sicuro che sia un JSON valido?",jsonNotArray:"Errore! Il file JSON da importare deve contenere un array."},pagination:{aria:{pageToFirst:"Prima",pageBack:"Indietro",pageSelected:"Pagina selezionata",pageForward:"Avanti",pageToLast:"Ultima"},sizes:"elementi per pagina",totalItems:"elementi",through:"a",of:"di"},grouping:{group:"Raggruppa",ungroup:"Separa",aggregate_count:"Agg: N. Elem.",aggregate_sum:"Agg: Somma",aggregate_max:"Agg: Massimo",aggregate_min:"Agg: Minimo",aggregate_avg:"Agg: Media",aggregate_remove:"Agg: Rimuovi"},validate:{error:"Errore:",minLength:"Lunghezza minima pari a THRESHOLD caratteri.",maxLength:"Lunghezza massima pari a THRESHOLD caratteri.",required:"Necessario inserire un valore."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("ja",{headerCell:{aria:{defaultFilterLabel:"列のフィルター",removeFilter:"フィルターの解除",columnMenuButtonLabel:"列のメニュー"},priority:"優先度:",filterLabel:"列フィルター: "},aggregate:{label:"項目"},groupPanel:{description:"ここに列ヘッダをドラッグアンドドロップして、その列でグループ化します。"},search:{placeholder:"検索...",showingItems:"表示中の項目:",selectedItems:"選択した項目:",totalItems:"項目の総数:",size:"ページサイズ:",first:"最初のページ",next:"次のページ",previous:"前のページ",last:"前のページ"},menu:{text:"列の選択:"},sort:{ascending:"昇順に並べ替え",descending:"降順に並べ替え",none:"並べ替え無し",remove:"並べ替えの解除"},column:{hide:"列の非表示"},aggregation:{count:"行数: ",sum:"合計: ",avg:"平均: ",min:"最小: ",max:"最大: "},pinning:{pinLeft:"左に固定",pinRight:"右に固定",unpin:"固定解除"},columnMenu:{close:"閉じる"},gridMenu:{aria:{buttonLabel:"グリッドメニュー"},columns:"列の表示/非表示:",importerTitle:"ファイルのインポート",exporterAllAsCsv:"すべてのデータをCSV形式でエクスポート",exporterVisibleAsCsv:"表示中のデータをCSV形式でエクスポート",exporterSelectedAsCsv:"選択したデータをCSV形式でエクスポート",exporterAllAsPdf:"すべてのデータをPDF形式でエクスポート",exporterVisibleAsPdf:"表示中のデータをPDF形式でエクスポート",exporterSelectedAsPdf:"選択したデータをPDF形式でエクスポート",clearAllFilters:"すべてのフィルタをクリア"},importer:{noHeaders:"列名を取得できません。ファイルにヘッダが含まれていることを確認してください。",noObjects:"オブジェクトを取得できません。ファイルにヘッダ以外のデータが含まれていることを確認してください。",invalidCsv:"ファイルを処理できません。ファイルが有効なCSV形式であることを確認してください。",invalidJson:"ファイルを処理できません。ファイルが有効なJSON形式であることを確認してください。",jsonNotArray:"インポートしたJSONファイルには配列が含まれている必要があります。処理を中止します。"},pagination:{aria:{pageToFirst:"最初のページ",pageBack:"前のページ",pageSelected:"現在のページ",pageForward:"次のページ",pageToLast:"最後のページ"},sizes:"件/ページ",totalItems:"件",through:"から",of:"件/全"},grouping:{group:"グループ化",ungroup:"グループ化の解除",aggregate_count:"集計表示: 行数",aggregate_sum:"集計表示: 合計",aggregate_max:"集計表示: 最大",aggregate_min:"集計表示: 最小",aggregate_avg:"集計表示: 平均",aggregate_remove:"集計表示: 解除"},validate:{error:"Error:",minLength:"THRESHOLD 文字以上で入力してください。",maxLength:"THRESHOLD 文字以下で入力してください。",required:"値が必要です。"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("ko",{aggregate:{label:"아이템"},groupPanel:{description:"컬럼으로 그룹핑하기 위해서는 컬럼 헤더를 끌어 떨어뜨려 주세요."},search:{placeholder:"검색...",showingItems:"항목 보여주기:",selectedItems:"선택 항목:",totalItems:"전체 항목:",size:"페이지 크기:",first:"첫번째 페이지",next:"다음 페이지",previous:"이전 페이지",last:"마지막 페이지"},menu:{text:"컬럼을 선택하세요:"},sort:{ascending:"오름차순 정렬",descending:"내림차순 정렬",remove:"소팅 제거"},column:{hide:"컬럼 제거"},aggregation:{count:"전체 갯수: ",sum:"전체: ",avg:"평균: ",min:"최소: ",max:"최대: "},pinning:{pinLeft:"왼쪽 핀",pinRight:"오른쪽 핀",unpin:"핀 제거"},gridMenu:{columns:"컬럼:",importerTitle:"파일 가져오기",exporterAllAsCsv:"csv로 모든 데이터 내보내기",exporterVisibleAsCsv:"csv로 보이는 데이터 내보내기",exporterSelectedAsCsv:"csv로 선택된 데이터 내보내기",exporterAllAsPdf:"pdf로 모든 데이터 내보내기",exporterVisibleAsPdf:"pdf로 보이는 데이터 내보내기",exporterSelectedAsPdf:"pdf로 선택 데이터 내보내기",clearAllFilters:"모든 필터를 청소"},importer:{noHeaders:"컬럼명이 지정되어 있지 않습니다. 파일에 헤더가 명시되어 있는지 확인해 주세요.",noObjects:"데이터가 지정되어 있지 않습니다. 데이터가 파일에 있는지 확인해 주세요.",invalidCsv:"파일을 처리할 수 없습니다. 올바른 csv인지 확인해 주세요.",invalidJson:"파일을 처리할 수 없습니다. 올바른 json인지 확인해 주세요.",jsonNotArray:"json 파일은 배열을 포함해야 합니다."},pagination:{sizes:"페이지당 항목",totalItems:"전체 항목"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("nl",{aggregate:{label:"items"},groupPanel:{description:"Sleep hier een kolomnaam heen om op te groeperen."},search:{placeholder:"Zoeken...",showingItems:"Getoonde items:",selectedItems:"Geselecteerde items:",totalItems:"Totaal aantal items:",size:"Items per pagina:",first:"Eerste pagina",next:"Volgende pagina",previous:"Vorige pagina",last:"Laatste pagina"},menu:{text:"Kies kolommen:"},sort:{ascending:"Sorteer oplopend",descending:"Sorteer aflopend",remove:"Verwijder sortering"},column:{hide:"Verberg kolom"},aggregation:{count:"Aantal rijen: ",sum:"Som: ",avg:"Gemiddelde: ",min:"Min: ",max:"Max: "},pinning:{pinLeft:"Zet links vast",pinRight:"Zet rechts vast",unpin:"Maak los"},gridMenu:{columns:"Kolommen:",importerTitle:"Importeer bestand",exporterAllAsCsv:"Exporteer alle data als csv",exporterVisibleAsCsv:"Exporteer zichtbare data als csv",exporterSelectedAsCsv:"Exporteer geselecteerde data als csv",exporterAllAsPdf:"Exporteer alle data als pdf",exporterVisibleAsPdf:"Exporteer zichtbare data als pdf",exporterSelectedAsPdf:"Exporteer geselecteerde data als pdf",exporterAllAsExcel:"Exporteer alle data als excel",exporterVisibleAsExcel:"Exporteer zichtbare data als excel",exporterSelectedAsExcel:"Exporteer alle data als excel",clearAllFilters:"Reinig alle filters"},importer:{noHeaders:"Kolomnamen kunnen niet worden afgeleid. Heeft het bestand een header?",noObjects:"Objecten kunnen niet worden afgeleid. Bevat het bestand data naast de headers?",invalidCsv:"Het bestand kan niet verwerkt worden. Is het een valide csv bestand?",invalidJson:"Het bestand kan niet verwerkt worden. Is het valide json?",jsonNotArray:"Het json bestand moet een array bevatten. De actie wordt geannuleerd."},pagination:{sizes:"items per pagina",totalItems:"items",of:"van de"},grouping:{group:"Groepeer",ungroup:"Groepering opheffen",aggregate_count:"Agg: Aantal",aggregate_sum:"Agg: Som",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Gem",aggregate_remove:"Agg: Verwijder"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("no",{headerCell:{aria:{defaultFilterLabel:"Filter for kolonne",removeFilter:"Fjern filter",columnMenuButtonLabel:"Kolonnemeny"},priority:"Prioritet:",filterLabel:"Filter for kolonne: "},aggregate:{label:"elementer"},groupPanel:{description:"Trekk en kolonneoverskrift hit og slipp den for å gruppere etter den kolonnen."},search:{placeholder:"Søk...",showingItems:"Viste elementer:",selectedItems:"Valgte elementer:",totalItems:"Antall elementer:",size:"Sidestørrelse:",first:"Første side",next:"Neste side",previous:"Forrige side",last:"Siste side"},menu:{text:"Velg kolonner:"},sort:{ascending:"Sortere stigende",descending:"Sortere fallende",none:"Ingen sortering",remove:"Fjern sortering"},column:{hide:"Skjul kolonne"},aggregation:{count:"antall rader: ",sum:"total: ",avg:"gjennomsnitt: ",min:"minimum: ",max:"maksimum: "},pinning:{pinLeft:"Fest til venstre",pinRight:"Fest til høyre",unpin:"Løsne"},columnMenu:{close:"Lukk"},gridMenu:{aria:{buttonLabel:"Grid Menu"},columns:"Kolonner:",importerTitle:"Importer fil",exporterAllAsCsv:"Eksporter alle data som csv",exporterVisibleAsCsv:"Eksporter synlige data som csv",exporterSelectedAsCsv:"Eksporter utvalgte data som csv",exporterAllAsPdf:"Eksporter alle data som pdf",exporterVisibleAsPdf:"Eksporter synlige data som pdf",exporterSelectedAsPdf:"Eksporter utvalgte data som pdf",exporterAllAsExcel:"Eksporter alle data som excel",exporterVisibleAsExcel:"Eksporter synlige data som excel",exporterSelectedAsExcel:"Eksporter utvalgte data som excel",clearAllFilters:"Clear all filters"},importer:{noHeaders:"Kolonnenavn kunne ikke avledes. Har filen en overskrift?",noObjects:"Objekter kunne ikke avledes. Er der andre data i filen enn overskriften?",invalidCsv:"Filen kunne ikke behandles. Er den gyldig CSV?",invalidJson:"Filen kunne ikke behandles. Er den gyldig JSON?",jsonNotArray:"Importert JSON-fil må inneholde en liste. Avbryter."},pagination:{aria:{pageToFirst:"Gå til første side",pageBack:"Gå til forrige side",pageSelected:"Valgte side",pageForward:"Gå til neste side",pageToLast:"Gå til siste side"},sizes:"elementer per side",totalItems:"elementer",through:"til",of:"av"},grouping:{group:"Gruppere",ungroup:"Fjerne gruppering",aggregate_count:"Agr: Antall",aggregate_sum:"Agr: Sum",aggregate_max:"Agr: Maksimum",aggregate_min:"Agr: Minimum",aggregate_avg:"Agr: Gjennomsnitt",aggregate_remove:"Agr: Fjern"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("pl",{headerCell:{aria:{defaultFilterLabel:"Filtr dla kolumny",removeFilter:"Usuń filtr",columnMenuButtonLabel:"Opcje kolumny",column:"Kolumna"},priority:"Priorytet:",filterLabel:"Filtr dla kolumny: "},aggregate:{label:"pozycji"},groupPanel:{description:"Przeciągnij nagłówek kolumny tutaj, aby pogrupować według niej."},search:{aria:{selected:"Wiersz zaznaczony",notSelected:"Wiersz niezaznaczony"},placeholder:"Szukaj...",showingItems:"Widoczne pozycje:",selectedItems:"Zaznaczone pozycje:",totalItems:"Wszystkich pozycji:",size:"Rozmiar strony:",first:"Pierwsza strona",next:"Następna strona",previous:"Poprzednia strona",last:"Ostatnia strona"},menu:{text:"Wybierz kolumny:"},sort:{ascending:"Sortuj rosnąco",descending:"Sortuj malejąco",none:"Brak sortowania",remove:"Wyłącz sortowanie"},column:{hide:"Ukryj kolumnę"},aggregation:{count:"Razem pozycji: ",sum:"Razem: ",avg:"Średnia: ",min:"Min: ",max:"Max: "},pinning:{pinLeft:"Przypnij do lewej",pinRight:"Przypnij do prawej",unpin:"Odepnij"},columnMenu:{close:"Zamknij"},gridMenu:{aria:{buttonLabel:"Opcje tabeli"},columns:"Kolumny:",importerTitle:"Importuj plik",exporterAllAsCsv:"Eksportuj wszystkie dane do csv",exporterVisibleAsCsv:"Eksportuj widoczne dane do csv",exporterSelectedAsCsv:"Eksportuj zaznaczone dane do csv",exporterAllAsPdf:"Eksportuj wszystkie dane do pdf",exporterVisibleAsPdf:"Eksportuj widoczne dane do pdf",exporterSelectedAsPdf:"Eksportuj zaznaczone dane do pdf",exporterAllAsExcel:"Eksportuj wszystkie dane do excel",exporterVisibleAsExcel:"Eksportuj widoczne dane do excel",exporterSelectedAsExcel:"Eksportuj zaznaczone dane do excel",clearAllFilters:"Wyczyść filtry"},importer:{noHeaders:"Nie udało się wczytać nazw kolumn. Czy plik posiada nagłówek?",noObjects:"Nie udalo się wczytać pozycji. Czy plik zawiera dane?",invalidCsv:"Nie udało się przetworzyć pliku. Czy to prawidłowy plik CSV?",invalidJson:"Nie udało się przetworzyć pliku. Czy to prawidłowy plik JSON?",jsonNotArray:"Importowany plik JSON musi zawierać tablicę. Importowanie przerwane."},pagination:{aria:{pageToFirst:"Pierwsza strona",pageBack:"Poprzednia strona",pageSelected:"Wybrana strona",pageForward:"Następna strona",pageToLast:"Ostatnia strona"},sizes:"pozycji na stronę",totalItems:"pozycji",through:"do",of:"z"},grouping:{group:"Grupuj",ungroup:"Rozgrupuj",aggregate_count:"Zbiorczo: Razem",aggregate_sum:"Zbiorczo: Suma",aggregate_max:"Zbiorczo: Max",aggregate_min:"Zbiorczo: Min",aggregate_avg:"Zbiorczo: Średnia",aggregate_remove:"Zbiorczo: Usuń"},validate:{error:"Błąd:",minLength:"Wartość powinna składać się z co najmniej THRESHOLD znaków.",maxLength:"Wartość powinna składać się z przynajmniej THRESHOLD znaków.",required:"Wartość jest wymagana."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("pt-br",{headerCell:{aria:{defaultFilterLabel:"Filtro por coluna",removeFilter:"Remover filtro",columnMenuButtonLabel:"Menu coluna",column:"Coluna"},priority:"Prioridade:",filterLabel:"Filtro por coluna: "},aggregate:{label:"itens"},groupPanel:{description:"Arraste e solte uma coluna aqui para agrupar por essa coluna"},search:{aria:{selected:"Linha selecionada",notSelected:"Linha não está selecionada"},placeholder:"Procurar...",showingItems:"Mostrando os Itens:",selectedItems:"Items Selecionados:",totalItems:"Total de Itens:",size:"Tamanho da Página:",first:"Primeira Página",next:"Próxima Página",previous:"Página Anterior",last:"Última Página"},menu:{text:"Selecione as colunas:"},sort:{ascending:"Ordenar Ascendente",descending:"Ordenar Descendente",none:"Nenhuma Ordem",remove:"Remover Ordenação"},column:{hide:"Esconder coluna"},aggregation:{count:"total de linhas: ",sum:"total: ",avg:"med: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Fixar Esquerda",pinRight:"Fixar Direita",unpin:"Desprender"},columnMenu:{close:"Fechar"},gridMenu:{aria:{buttonLabel:"Menu Grid"},columns:"Colunas:",importerTitle:"Importar arquivo",exporterAllAsCsv:"Exportar todos os dados como csv",exporterVisibleAsCsv:"Exportar dados visíveis como csv",exporterSelectedAsCsv:"Exportar dados selecionados como csv",exporterAllAsPdf:"Exportar todos os dados como pdf",exporterVisibleAsPdf:"Exportar dados visíveis como pdf",exporterSelectedAsPdf:"Exportar dados selecionados como pdf",exporterAllAsExcel:"Exportar todos os dados como excel",exporterVisibleAsExcel:"Exportar dados visíveis como excel",exporterSelectedAsExcel:"Exportar dados selecionados como excel",clearAllFilters:"Limpar todos os filtros"},importer:{noHeaders:"Nomes de colunas não puderam ser derivados. O arquivo tem um cabeçalho?",noObjects:"Objetos não puderam ser derivados. Havia dados no arquivo, além dos cabeçalhos?",invalidCsv:"Arquivo não pode ser processado. É um CSV válido?",invalidJson:"Arquivo não pode ser processado. É um Json válido?",jsonNotArray:"Arquivo json importado tem que conter um array. Abortando."},pagination:{aria:{pageToFirst:"Primeira página",pageBack:"Página anterior",pageSelected:"Página Selecionada",pageForward:"Proxima",pageToLast:"Anterior"},sizes:"itens por página",totalItems:"itens",through:"através dos",of:"de"},grouping:{group:"Agrupar",ungroup:"Desagrupar",aggregate_count:"Agr: Contar",aggregate_sum:"Agr: Soma",aggregate_max:"Agr: Max",aggregate_min:"Agr: Min",aggregate_avg:"Agr: Med",aggregate_remove:"Agr: Remover"},validate:{error:"Erro:",minLength:"O valor deve ter, no minimo, THRESHOLD caracteres.",maxLength:"O valor deve ter, no máximo, THRESHOLD caracteres.",required:"Um valor é necessário."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("pt",{headerCell:{aria:{defaultFilterLabel:"Filtro por coluna",removeFilter:"Remover filtro",columnMenuButtonLabel:"Menu coluna",column:"Coluna"},priority:"Prioridade:",filterLabel:"Filtro por coluna: "},aggregate:{label:"itens"},groupPanel:{description:"Arraste e solte uma coluna aqui para agrupar por essa coluna"},search:{aria:{selected:"Linha selecionada",notSelected:"Linha não está selecionada"},placeholder:"Procurar...",showingItems:"Mostrando os Itens:",selectedItems:"Itens Selecionados:",totalItems:"Total de Itens:",size:"Tamanho da Página:",first:"Primeira Página",next:"Próxima Página",previous:"Página Anterior",last:"Última Página"},menu:{text:"Selecione as colunas:"},sort:{ascending:"Ordenar Ascendente",descending:"Ordenar Descendente",none:"Nenhuma Ordem",remove:"Remover Ordenação"},column:{hide:"Esconder coluna"},aggregation:{count:"total de linhas: ",sum:"total: ",avg:"med: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Fixar Esquerda",pinRight:"Fixar Direita",unpin:"Desprender"},columnMenu:{close:"Fechar"},gridMenu:{aria:{buttonLabel:"Menu Grid"},columns:"Colunas:",importerTitle:"Importar ficheiro",exporterAllAsCsv:"Exportar todos os dados como csv",exporterVisibleAsCsv:"Exportar dados visíveis como csv",exporterSelectedAsCsv:"Exportar dados selecionados como csv",exporterAllAsPdf:"Exportar todos os dados como pdf",exporterVisibleAsPdf:"Exportar dados visíveis como pdf",exporterSelectedAsPdf:"Exportar dados selecionados como pdf",exporterAllAsExcel:"Exportar todos os dados como excel",exporterVisibleAsExcel:"Exportar dados visíveis como excel",exporterSelectedAsExcel:"Exportar dados selecionados como excel",clearAllFilters:"Limpar todos os filtros"},importer:{noHeaders:"Nomes de colunas não puderam ser derivados. O ficheiro tem um cabeçalho?",noObjects:"Objetos não puderam ser derivados. Havia dados no ficheiro, além dos cabeçalhos?",invalidCsv:"Ficheiro não pode ser processado. É um CSV válido?",invalidJson:"Ficheiro não pode ser processado. É um Json válido?",jsonNotArray:"Ficheiro json importado tem que conter um array. Interrompendo."},pagination:{aria:{pageToFirst:"Primeira página",pageBack:"Página anterior",pageSelected:"Página Selecionada",pageForward:"Próxima",pageToLast:"Anterior"},sizes:"itens por página",totalItems:"itens",through:"a",of:"de"},grouping:{group:"Agrupar",ungroup:"Desagrupar",aggregate_count:"Agr: Contar",aggregate_sum:"Agr: Soma",aggregate_max:"Agr: Max",aggregate_min:"Agr: Min",aggregate_avg:"Agr: Med",aggregate_remove:"Agr: Remover"},validate:{error:"Erro:",minLength:"O valor deve ter, no minimo, THRESHOLD caracteres.",maxLength:"O valor deve ter, no máximo, THRESHOLD caracteres.",required:"Um valor é necessário."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("ro",{headerCell:{aria:{defaultFilterLabel:"Filtru pentru coloana",removeFilter:"Sterge filtru",columnMenuButtonLabel:"Column Menu"},priority:"Prioritate:",filterLabel:"Filtru pentru coloana:"},aggregate:{label:"Elemente"},groupPanel:{description:"Trage un cap de coloana aici pentru a grupa elementele dupa coloana respectiva"},search:{placeholder:"Cauta...",showingItems:"Arata elementele:",selectedItems:"Elementele selectate:",totalItems:"Total elemente:",size:"Marime pagina:",first:"Prima pagina",next:"Pagina urmatoare",previous:"Pagina anterioara",last:"Ultima pagina"},menu:{text:"Alege coloane:"},sort:{ascending:"Ordoneaza crescator",descending:"Ordoneaza descrescator",none:"Fara ordonare",remove:"Sterge ordonarea"},column:{hide:"Ascunde coloana"},aggregation:{count:"total linii: ",sum:"total: ",avg:"medie: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Pin la stanga",pinRight:"Pin la dreapta",unpin:"Sterge pinul"},columnMenu:{close:"Inchide"},gridMenu:{aria:{buttonLabel:"Grid Menu"},columns:"Coloane:",importerTitle:"Incarca fisier",exporterAllAsCsv:"Exporta toate datele ca csv",exporterVisibleAsCsv:"Exporta datele vizibile ca csv",exporterSelectedAsCsv:"Exporta datele selectate ca csv",exporterAllAsPdf:"Exporta toate datele ca pdf",exporterVisibleAsPdf:"Exporta datele vizibile ca pdf",exporterSelectedAsPdf:"Exporta datele selectate ca csv pdf",clearAllFilters:"Sterge toate filtrele"},importer:{noHeaders:"Numele coloanelor nu a putut fi incarcat, acest fisier are un header?",noObjects:"Datele nu au putut fi incarcate, exista date in fisier in afara numelor de coloane?",invalidCsv:"Fisierul nu a putut fi procesat, ati incarcat un CSV valid ?",invalidJson:"Fisierul nu a putut fi procesat, ati incarcat un Json valid?",jsonNotArray:"Json-ul incarcat trebuie sa contina un array, inchidere."},pagination:{aria:{pageToFirst:"Prima pagina",pageBack:"O pagina inapoi",pageSelected:"Pagina selectata",pageForward:"O pagina inainte",pageToLast:"Ultima pagina"},sizes:"Elemente per pagina",totalItems:"elemente",through:"prin",of:"of"},grouping:{group:"Grupeaza",ungroup:"Opreste gruparea",aggregate_count:"Agg: Count",aggregate_sum:"Agg: Sum",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Avg",aggregate_remove:"Agg: Remove"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("rs-lat",{headerCell:{aria:{defaultFilterLabel:"Filter za kolonu",removeFilter:"Ukloni Filter",columnMenuButtonLabel:"Meni Kolone",column:"Kolona"},priority:"Prioritet:",filterLabel:"Filter za kolonu: "},aggregate:{label:"stavke"},groupPanel:{description:"Ovde prevuci zaglavlje kolone i spusti do grupe pored te kolone."},search:{aria:{selected:"Red odabran",notSelected:"Red nije odabran"},placeholder:"Pretraga...",showingItems:"Prikazane Stavke:",selectedItems:"Odabrane Stavke:",totalItems:"Ukupno Stavki:",size:"Veličina Stranice:",first:"Prva Stranica",next:"Sledeća Stranica",previous:"Prethodna Stranica",last:"Poslednja Stranica"},menu:{text:"Odaberite kolonu:"},sort:{ascending:"Sortiraj po rastućem redosledu",descending:"Sortiraj po opadajućem redosledu",none:"Bez Sortiranja",remove:"Ukloni Sortiranje"},column:{hide:"Sakrij Kolonu"},aggregation:{count:"ukupno redova: ",sum:"ukupno: ",avg:"prosecno: ",min:"minimum: ",max:"maksimum: "},pinning:{pinLeft:"Zakači Levo",pinRight:"Zakači Desno",unpin:"Otkači"},columnMenu:{close:"Zatvori"},gridMenu:{aria:{buttonLabel:"Rešetkasti Meni"},columns:"Kolone:",importerTitle:"Importuj fajl",exporterAllAsCsv:"Eksportuj sve podatke kao csv",exporterVisibleAsCsv:"Eksportuj vidljive podatke kao csv",exporterSelectedAsCsv:"Eksportuj obeležene podatke kao csv",exporterAllAsPdf:"Eksportuj sve podatke kao pdf",exporterVisibleAsPdf:"Eksportuj vidljive podake kao pdf",exporterSelectedAsPdf:"Eksportuj odabrane podatke kao pdf",exporterAllAsExcel:"Eksportuj sve podatke kao excel",exporterVisibleAsExcel:"Eksportuj vidljive podatke kao excel",exporterSelectedAsExcel:"Eksportuj odabrane podatke kao excel",clearAllFilters:"Obriši sve filtere"},importer:{noHeaders:"Kolone se nisu mogle podeliti, da li fajl poseduje heder?",noObjects:"Objecti nisu mogli biti podeljeni, da li je bilo i drugih podataka sem hedera?",invalidCsv:"Fajl nije bilo moguće procesirati, da li je ispravni CSV?",invalidJson:"Fajl nije bilo moguće procesirati, da li je ispravni JSON",jsonNotArray:"Importovani json fajl mora da sadrži niz, prekidam operaciju."},pagination:{aria:{pageToFirst:"Prva stranica",pageBack:"Stranica pre",pageSelected:"Odabrana stranica",pageForward:"Sledeća stranica",pageToLast:"Poslednja stranica"},sizes:"stavki po stranici",totalItems:"stavke",through:"kroz",of:"od"},grouping:{group:"Grupiši",ungroup:"Odrupiši",aggregate_count:"Agg: Broj",aggregate_sum:"Agg: Suma",aggregate_max:"Agg: Maksimum",aggregate_min:"Agg: Minimum",aggregate_avg:"Agg: Prosečna",aggregate_remove:"Agg: Ukloni"},validate:{error:"Greška:",minLength:"Vrednost bi trebala da bude duga bar THRESHOLD karaktera.",maxLength:"Vrednost bi trebalo da bude najviše duga THRESHOLD karaktera.",required:"Portreba je vrednost."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("ru",{headerCell:{aria:{defaultFilterLabel:"Фильтр столбца",removeFilter:"Удалить фильтр",columnMenuButtonLabel:"Меню столбца"},priority:"Приоритет:",filterLabel:"Фильтр столбца: "},aggregate:{label:"элементы"},groupPanel:{description:"Для группировки по столбцу перетащите сюда его название."},search:{placeholder:"Поиск...",showingItems:"Показать элементы:",selectedItems:"Выбранные элементы:",totalItems:"Всего элементов:",size:"Размер страницы:",first:"Первая страница",next:"Следующая страница",previous:"Предыдущая страница",last:"Последняя страница"},menu:{text:"Выбрать столбцы:"},sort:{ascending:"По возрастанию",descending:"По убыванию",none:"Без сортировки",remove:"Убрать сортировку"},column:{hide:"Спрятать столбец"},aggregation:{count:"всего строк: ",sum:"итого: ",avg:"среднее: ",min:"мин: ",max:"макс: "},pinning:{pinLeft:"Закрепить слева",pinRight:"Закрепить справа",unpin:"Открепить"},columnMenu:{close:"Закрыть"},gridMenu:{aria:{buttonLabel:"Меню"},columns:"Столбцы:",importerTitle:"Импортировать файл",exporterAllAsCsv:"Экспортировать всё в CSV",exporterVisibleAsCsv:"Экспортировать видимые данные в CSV",exporterSelectedAsCsv:"Экспортировать выбранные данные в CSV",exporterAllAsPdf:"Экспортировать всё в PDF",exporterVisibleAsPdf:"Экспортировать видимые данные в PDF",exporterSelectedAsPdf:"Экспортировать выбранные данные в PDF",clearAllFilters:"Очистите все фильтры"},importer:{noHeaders:"Не удалось получить названия столбцов, есть ли в файле заголовок?",noObjects:"Не удалось получить данные, есть ли в файле строки кроме заголовка?",invalidCsv:"Не удалось обработать файл, это правильный CSV-файл?",invalidJson:"Не удалось обработать файл, это правильный JSON?",jsonNotArray:"Импортируемый JSON-файл должен содержать массив, операция отменена."},pagination:{aria:{pageToFirst:"Первая страница",pageBack:"Предыдущая страница",pageSelected:"Выбранная страница",pageForward:"Следующая страница",pageToLast:"Последняя страница"},sizes:"строк на страницу",totalItems:"строк",through:"по",of:"из"},grouping:{group:"Группировать",ungroup:"Разгруппировать",aggregate_count:"Группировать: Count",aggregate_sum:"Для группы: Сумма",aggregate_max:"Для группы: Максимум",aggregate_min:"Для группы: Минимум",aggregate_avg:"Для группы: Среднее",aggregate_remove:"Для группы: Пусто"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("sk",{headerCell:{aria:{defaultFilterLabel:"Filter pre stĺpec",removeFilter:"Odstrániť filter",columnMenuButtonLabel:"Menu pre stĺpec",column:"Stĺpec"},priority:"Priorita:",filterLabel:"Filter pre stĺpec: "},aggregate:{label:"položky"},groupPanel:{description:"Pretiahni sem názov stĺpca pre zoskupenie podľa toho stĺpca."},search:{aria:{selected:"Označený riadok",notSelected:"Neoznačený riadok"},placeholder:"Hľadaj...",showingItems:"Zobrazujem položky:",selectedItems:"Vybraté položky:",totalItems:"Počet položiek:",size:"Počet:",first:"Prvá strana",next:"Ďalšia strana",previous:"Predchádzajúca strana",last:"Posledná strana"},menu:{text:"Vyberte stĺpce:"},sort:{ascending:"Zotriediť vzostupne",descending:"Zotriediť zostupne",none:"Nezotriediť",remove:"Vymazať triedenie"},column:{hide:"Skryť stĺpec"},aggregation:{count:"počet riadkov: ",sum:"spolu: ",avg:"avg: ",min:"min: ",max:"max: "},pinning:{pinLeft:"Pripnúť vľavo",pinRight:"Pripnúť vpravo",unpin:"Odopnúť"},columnMenu:{close:"Zavrieť"},gridMenu:{aria:{buttonLabel:"Grid Menu"},columns:"Stĺpce:",importerTitle:"Importovať súbor",exporterAllAsCsv:"Exportovať všetky údaje ako CSV",exporterVisibleAsCsv:"Exportovť viditeľné údaje ako CSV",exporterSelectedAsCsv:"Exportovať označené údaje ako CSV",exporterAllAsPdf:"Exportovať všetky údaje ako pdf",exporterVisibleAsPdf:"Exportovať viditeľné údaje ako pdf",exporterSelectedAsPdf:"Exportovať označené údaje ako pdf",exporterAllAsExcel:"Exportovať všetky údaje ako excel",exporterVisibleAsExcel:"Exportovať viditeľné údaje ako excel",exporterSelectedAsExcel:"Exportovať označené údaje ako excel",clearAllFilters:"Zrušiť všetky filtre"},importer:{noHeaders:"Názvy stĺpcov sa nedali odvodiť, má súbor hlavičku?",noObjects:"Objekty nebolo možné odvodiť, existovali iné údaje v súbore ako hlavičky?",invalidCsv:"Súbor sa nepodarilo spracovať, je to platný súbor CSV?",invalidJson:"Súbor nebolo možné spracovať, je to platný súbor typu Json?",jsonNotArray:"Importovaný súbor json musí obsahovať pole, ukončujem."},pagination:{aria:{pageToFirst:"Strana na začiatok",pageBack:"Strana dozadu",pageSelected:"Označená strana",pageForward:"Strana dopredu",pageToLast:"Strana na koniec"},sizes:"položky na stranu",totalItems:"položky spolu",through:"do konca",of:"z"},grouping:{group:"Zoskupiť",ungroup:"Zrušiť zoskupenie",aggregate_count:"Agg: Počet",aggregate_sum:"Agg: Suma",aggregate_max:"Agg: Max",aggregate_min:"Agg: Min",aggregate_avg:"Agg: Avg",aggregate_remove:"Agg: Zrušiť"},validate:{error:"Chyba:",minLength:"Hodnota by mala mať aspoň THRESHOLD znakov dlhá.",maxLength:"Hodnota by mala byť maximálne THRESHOLD znakov dlhá.",required:"Vyžaduje sa hodnota."}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("sv",{aggregate:{label:"Artiklar"},groupPanel:{description:"Dra en kolumnrubrik hit och släpp den för att gruppera efter den kolumnen."},search:{placeholder:"Sök...",showingItems:"Visar artiklar:",selectedItems:"Valda artiklar:",totalItems:"Antal artiklar:",size:"Sidstorlek:",first:"Första sidan",next:"Nästa sida",previous:"Föregående sida",last:"Sista sidan"},menu:{text:"Välj kolumner:"},sort:{ascending:"Sortera stigande",descending:"Sortera fallande",remove:"Inaktivera sortering"},column:{hide:"Göm kolumn"},aggregation:{count:"Antal rader: ",sum:"Summa: ",avg:"Genomsnitt: ",min:"Min: ",max:"Max: "},pinning:{pinLeft:"Fäst vänster",pinRight:"Fäst höger",unpin:"Lösgör"},gridMenu:{columns:"Kolumner:",importerTitle:"Importera fil",exporterAllAsCsv:"Exportera all data som CSV",exporterVisibleAsCsv:"Exportera synlig data som CSV",exporterSelectedAsCsv:"Exportera markerad data som CSV",exporterAllAsPdf:"Exportera all data som PDF",exporterVisibleAsPdf:"Exportera synlig data som PDF",exporterSelectedAsPdf:"Exportera markerad data som PDF",clearAllFilters:"Rengör alla filter"},importer:{noHeaders:"Kolumnnamn kunde inte härledas. Har filen ett sidhuvud?",noObjects:"Objekt kunde inte härledas. Har filen data undantaget sidhuvud?",invalidCsv:"Filen kunde inte behandlas, är den en giltig CSV?",invalidJson:"Filen kunde inte behandlas, är den en giltig JSON?",jsonNotArray:"Importerad JSON-fil måste innehålla ett fält. Import avbruten."},pagination:{sizes:"Artiklar per sida",totalItems:"Artiklar"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("ta",{aggregate:{label:"உருப்படிகள்"},groupPanel:{description:"ஒரு பத்தியை குழுவாக அமைக்க அப்பத்தியின் தலைப்பை இங்கே இழுத்து வரவும் "},search:{placeholder:"தேடல் ...",showingItems:"உருப்படிகளை காண்பித்தல்:",selectedItems:"தேர்ந்தெடுக்கப்பட்ட உருப்படிகள்:",totalItems:"மொத்த உருப்படிகள்:",size:"பக்க அளவு: ",first:"முதல் பக்கம்",next:"அடுத்த பக்கம்",previous:"முந்தைய பக்கம் ",last:"இறுதி பக்கம்"},menu:{text:"பத்திகளை தேர்ந்தெடு:"},sort:{ascending:"மேலிருந்து கீழாக",descending:"கீழிருந்து மேலாக",remove:"வரிசையை நீக்கு"},column:{hide:"பத்தியை மறைத்து வை "},aggregation:{count:"மொத்த வரிகள்:",sum:"மொத்தம்: ",avg:"சராசரி: ",min:"குறைந்தபட்ச: ",max:"அதிகபட்ச: "},pinning:{pinLeft:"இடதுபுறமாக தைக்க ",pinRight:"வலதுபுறமாக தைக்க",unpin:"பிரி"},gridMenu:{columns:"பத்திகள்:",importerTitle:"கோப்பு : படித்தல்",exporterAllAsCsv:"எல்லா தரவுகளையும் கோப்பாக்கு: csv",exporterVisibleAsCsv:"இருக்கும் தரவுகளை கோப்பாக்கு: csv",exporterSelectedAsCsv:"தேர்ந்தெடுத்த தரவுகளை கோப்பாக்கு: csv",exporterAllAsPdf:"எல்லா தரவுகளையும் கோப்பாக்கு: pdf",exporterVisibleAsPdf:"இருக்கும் தரவுகளை கோப்பாக்கு: pdf",exporterSelectedAsPdf:"தேர்ந்தெடுத்த தரவுகளை கோப்பாக்கு: pdf",clearAllFilters:"Clear all filters"},importer:{noHeaders:"பத்தியின் தலைப்புகளை பெற இயலவில்லை, கோப்பிற்கு தலைப்பு உள்ளதா?",noObjects:"இலக்குகளை உருவாக்க முடியவில்லை, கோப்பில் தலைப்புகளை தவிர தரவு ஏதேனும் உள்ளதா? ",invalidCsv:"சரிவர நடைமுறை படுத்த இயலவில்லை, கோப்பு சரிதானா? - csv",invalidJson:"சரிவர நடைமுறை படுத்த இயலவில்லை, கோப்பு சரிதானா? - json",jsonNotArray:"படித்த கோப்பில் வரிசைகள் உள்ளது, நடைமுறை ரத்து செய் : json"},pagination:{sizes:"உருப்படிகள் / பக்கம்",totalItems:"உருப்படிகள் "},grouping:{group:"குழு",ungroup:"பிரி",aggregate_count:"மதிப்பீட்டு : எண்ணு",aggregate_sum:"மதிப்பீட்டு : கூட்டல்",aggregate_max:"மதிப்பீட்டு : அதிகபட்சம்",aggregate_min:"மதிப்பீட்டு : குறைந்தபட்சம்",aggregate_avg:"மதிப்பீட்டு : சராசரி",aggregate_remove:"மதிப்பீட்டு : நீக்கு"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("tr",{headerCell:{aria:{defaultFilterLabel:"Sütun için filtre",removeFilter:"Filtreyi Kaldır",columnMenuButtonLabel:"Sütun Menüsü"},priority:"Öncelik:",filterLabel:"Sütun için filtre: "},aggregate:{label:"kayıtlar"},groupPanel:{description:"Sütuna göre gruplamak için sütun başlığını buraya sürükleyin ve bırakın."},search:{placeholder:"Arama...",showingItems:"Gösterilen Kayıt:",selectedItems:"Seçili Kayıt:",totalItems:"Toplam Kayıt:",size:"Sayfa Boyutu:",first:"İlk Sayfa",next:"Sonraki Sayfa",previous:"Önceki Sayfa",last:"Son Sayfa"},menu:{text:"Sütunları Seç:"},sort:{ascending:"Artan Sırada Sırala",descending:"Azalan Sırada Sırala",none:"Sıralama Yapma",remove:"Sıralamayı Kaldır"},column:{hide:"Sütunu Gizle"},aggregation:{count:"toplam satır: ",sum:"toplam: ",avg:"ort: ",min:"min: ",max:"maks: "},pinning:{pinLeft:"Sola Sabitle",pinRight:"Sağa Sabitle",unpin:"Sabitlemeyi Kaldır"},columnMenu:{close:"Kapat"},gridMenu:{aria:{buttonLabel:"Tablo Menü"},columns:"Sütunlar:",importerTitle:"Dosya içeri aktar",exporterAllAsCsv:"Bütün veriyi CSV olarak dışarı aktar",exporterVisibleAsCsv:"Görünen veriyi CSV olarak dışarı aktar",exporterSelectedAsCsv:"Seçili veriyi CSV olarak dışarı aktar",exporterAllAsPdf:"Bütün veriyi PDF olarak dışarı aktar",exporterVisibleAsPdf:"Görünen veriyi PDF olarak dışarı aktar",exporterSelectedAsPdf:"Seçili veriyi PDF olarak dışarı aktar",clearAllFilters:"Bütün filtreleri kaldır"},importer:{noHeaders:"Sütun isimleri üretilemiyor, dosyanın bir başlığı var mı?",noObjects:"Nesneler üretilemiyor, dosyada başlıktan başka bir veri var mı?",invalidCsv:"Dosya işlenemedi, geçerli bir CSV dosyası mı?",invalidJson:"Dosya işlenemedi, geçerli bir Json dosyası mı?",jsonNotArray:"Alınan Json dosyasında bir dizi bulunmalıdır, işlem iptal ediliyor."},pagination:{aria:{pageToFirst:"İlk sayfaya",pageBack:"Geri git",pageSelected:"Seçili sayfa",pageForward:"İleri git",pageToLast:"Sona git"},sizes:"Sayfadaki nesne sayısı",totalItems:"kayıtlar",through:"",of:""},grouping:{group:"Grupla",ungroup:"Gruplama",aggregate_count:"Yekun: Sayı",aggregate_sum:"Yekun: Toplam",aggregate_max:"Yekun: Maks",aggregate_min:"Yekun: Min",aggregate_avg:"Yekun: Ort",aggregate_remove:"Yekun: Sil"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("ua",{headerCell:{aria:{defaultFilterLabel:"Фільтр стовпчика",removeFilter:"Видалити фільтр",columnMenuButtonLabel:"Меню ствпчика"},priority:"Пріоритет:",filterLabel:"Фільтр стовпчика: "},aggregate:{label:"елементи"},groupPanel:{description:"Для групування за стовпчиком перетягніть сюди його назву."},search:{placeholder:"Пошук...",showingItems:"Показати елементи:",selectedItems:"Обрані елементи:",totalItems:"Усього елементів:",size:"Розмір сторінки:",first:"Перша сторінка",next:"Наступна сторінка",previous:"Попередня сторінка",last:"Остання сторінка"},menu:{text:"Обрати ствпчики:"},sort:{ascending:"За зростанням",descending:"За спаданням",none:"Без сортування",remove:"Прибрати сортування"},column:{hide:"Приховати стовпчик"},aggregation:{count:"усього рядків: ",sum:"ітого: ",avg:"середнє: ",min:"мін: ",max:"макс: "},pinning:{pinLeft:"Закріпити ліворуч",pinRight:"Закріпити праворуч",unpin:"Відкріпити"},columnMenu:{close:"Закрити"},gridMenu:{aria:{buttonLabel:"Меню"},columns:"Стовпчики:",importerTitle:"Імпортувати файл",exporterAllAsCsv:"Експортувати все в CSV",exporterVisibleAsCsv:"Експортувати видимі дані в CSV",exporterSelectedAsCsv:"Експортувати обрані дані в CSV",exporterAllAsPdf:"Експортувати все в PDF",exporterVisibleAsPdf:"Експортувати видимі дані в PDF",exporterSelectedAsPdf:"Експортувати обрані дані в PDF",clearAllFilters:"Очистити всі фільтри"},importer:{noHeaders:"Не вдалося отримати назви стовпчиків, чи є в файлі заголовок?",noObjects:"Не вдалося отримати дані, чи є в файлі рядки окрім заголовка?",invalidCsv:"Не вдалося обробити файл, чи це коректний CSV-файл?",invalidJson:"Не вдалося обробити файл, чи це коректний JSON?",jsonNotArray:"JSON-файл що імпортується повинен містити масив, операцію скасовано."},pagination:{aria:{pageToFirst:"Перша сторінка",pageBack:"Попередня сторінка",pageSelected:"Обрана сторінка",pageForward:"Наступна сторінка",pageToLast:"Остання сторінка"},sizes:"рядків на сторінку",totalItems:"рядків",through:"по",of:"з"},grouping:{group:"Групувати",ungroup:"Розгрупувати",aggregate_count:"Групувати: Кількість",aggregate_sum:"Для групи: Сума",aggregate_max:"Для групи: Максимум",aggregate_min:"Для групи: Мінімум",aggregate_avg:"Для групи: Серднє",aggregate_remove:"Для групи: Пусто"}}),e}])}]),function(){var g=["uiT","uiTranslate"],t=angular.module("ui.grid.i18n");function r(u,c){return{restrict:"EA",compile:function(){return{pre:function(e,r,t){var i,n,o,a=g[0],l=g[1],s=t[a]||t[l]||r.html();function d(e){var t=u.getSafeText(e);r.html(t)}t.$$observers&&(o=t[a]?a:l,n=t.$observe(o,function(e){e&&d(e)})),i=e.$on(c.UPDATE_EVENT,function(){n?n(t[a]||t[l]):d(s)}),e.$on("$destroy",i),d(s)}}}}}function i(r){return function(e,t){return r.getSafeText(e,t)}}t.constant("i18nConstants",{MISSING:"[MISSING]",UPDATE_EVENT:"$uiI18n",LOCALE_DIRECTIVE_ALIAS:"uiI18n",DEFAULT_LANG:"en"}),t.service("i18nService",["$log","$parse","i18nConstants","$rootScope",function(e,a,l,t){var s={_langs:{},current:null,fallback:l.DEFAULT_LANG,get:function(e){var t=this,r=t.getFallbackLang();return e!==t.fallback?angular.extend({},t._langs[r],t._langs[e.toLowerCase()]):t._langs[e.toLowerCase()]},add:function(e,t){var r=e.toLowerCase();this._langs[r]||(this._langs[r]={}),angular.merge(this._langs[r],t)},getAllLangs:function(){var e=[];if(!this._langs)return e;for(var t in this._langs)e.push(t);return e},setCurrent:function(e){this.current=e.toLowerCase()},setFallback:function(e){this.fallback=e.toLowerCase()},getCurrentLang:function(){return this.current},getFallbackLang:function(){return this.fallback.toLowerCase()}},d={add:function(e,t){"object"==typeof e?angular.forEach(e,function(e){e&&s.add(e,t)}):s.add(e,t)},getAllLangs:function(){return s.getAllLangs()},get:function(e){var t=e||d.getCurrentLang();return s.get(t)},getSafeText:function(e,t){var r=t||d.getCurrentLang(),i=s.get(r),n=l.MISSING+e,o=a(e);return i&&o(i)||n},setCurrentLang:function(e){e&&(s.setCurrent(e),t.$broadcast(l.UPDATE_EVENT))},setFallbackLang:function(e){e&&s.setFallback(e)},getCurrentLang:function(){var e=s.getCurrentLang();return e||(e=l.DEFAULT_LANG,s.setCurrent(e)),e},getFallbackLang:function(){return s.getFallbackLang()}};return d}]),t.directive("uiI18n",["i18nService","i18nConstants",function(o,a){return{compile:function(){return{pre:function(e,t,r){var i=a.LOCALE_DIRECTIVE_ALIAS,n=e.$eval(r[i]);n?e.$watch(r[i],function(){o.setCurrentLang(n)}):r.$$observers&&r.$observe(i,function(){o.setCurrentLang(r[i]||a.DEFAULT_LANG)})}}}}}]),angular.forEach(g,function(e){t.directive(e,["i18nService","i18nConstants",r])}),angular.forEach(["t","uiTranslate"],function(e){t.filter(e,["i18nService",i])})}(),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("zh-cn",{headerCell:{aria:{defaultFilterLabel:"列过滤器",removeFilter:"移除过滤器",columnMenuButtonLabel:"列菜单"},priority:"优先级:",filterLabel:"列过滤器: "},aggregate:{label:"行"},groupPanel:{description:"拖曳表头到此处进行分组"},search:{placeholder:"查找",showingItems:"已显示行数:",selectedItems:"已选择行数:",totalItems:"总行数:",size:"每页显示行数:",first:"首页",next:"下一页",previous:"上一页",last:"末页"},menu:{text:"选择列:"},sort:{ascending:"升序",descending:"降序",none:"无序",remove:"取消排序"},column:{hide:"隐藏列"},aggregation:{count:"计数:",sum:"求和:",avg:"均值:",min:"最小值:",max:"最大值:"},pinning:{pinLeft:"左侧固定",pinRight:"右侧固定",unpin:"取消固定"},columnMenu:{close:"关闭"},gridMenu:{aria:{buttonLabel:"表格菜单"},columns:"列:",importerTitle:"导入文件",exporterAllAsCsv:"导出全部数据到CSV",exporterVisibleAsCsv:"导出可见数据到CSV",exporterSelectedAsCsv:"导出已选数据到CSV",exporterAllAsPdf:"导出全部数据到PDF",exporterVisibleAsPdf:"导出可见数据到PDF",exporterSelectedAsPdf:"导出已选数据到PDF",clearAllFilters:"清除所有过滤器"},importer:{noHeaders:"无法获取列名,确定文件包含表头?",noObjects:"无法获取数据,确定文件包含数据?",invalidCsv:"无法处理文件,确定是合法的CSV文件?",invalidJson:"无法处理文件,确定是合法的JSON文件?",jsonNotArray:"导入的文件不是JSON数组!"},pagination:{aria:{pageToFirst:"第一页",pageBack:"上一页",pageSelected:"当前页",pageForward:"下一页",pageToLast:"最后一页"},sizes:"行每页",totalItems:"行",through:"至",of:"共"},grouping:{group:"分组",ungroup:"取消分组",aggregate_count:"合计: 计数",aggregate_sum:"合计: 求和",aggregate_max:"合计: 最大",aggregate_min:"合计: 最小",aggregate_avg:"合计: 平均",aggregate_remove:"合计: 移除"}}),e}])}]),angular.module("ui.grid").config(["$provide",function(e){e.decorator("i18nService",["$delegate",function(e){return e.add("zh-tw",{aggregate:{label:"行"},groupPanel:{description:"拖曳表頭到此處進行分組"},search:{placeholder:"查找",showingItems:"已顯示行數:",selectedItems:"已選擇行數:",totalItems:"總行數:",size:"每頁顯示行數:",first:"首頁",next:"下壹頁",previous:"上壹頁",last:"末頁"},menu:{text:"選擇列:"},sort:{ascending:"升序",descending:"降序",remove:"取消排序"},column:{hide:"隱藏列"},aggregation:{count:"計數:",sum:"求和:",avg:"均值:",min:"最小值:",max:"最大值:"},pinning:{pinLeft:"左側固定",pinRight:"右側固定",unpin:"取消固定"},gridMenu:{columns:"列:",importerTitle:"導入文件",exporterAllAsCsv:"導出全部數據到CSV",exporterVisibleAsCsv:"導出可見數據到CSV",exporterSelectedAsCsv:"導出已選數據到CSV",exporterAllAsPdf:"導出全部數據到PDF",exporterVisibleAsPdf:"導出可見數據到PDF",exporterSelectedAsPdf:"導出已選數據到PDF",clearAllFilters:"清除所有过滤器"},importer:{noHeaders:"無法獲取列名,確定文件包含表頭?",noObjects:"無法獲取數據,確定文件包含數據?",invalidCsv:"無法處理文件,確定是合法的CSV文件?",invalidJson:"無法處理文件,確定是合法的JSON文件?",jsonNotArray:"導入的文件不是JSON數組!"},pagination:{sizes:"行每頁",totalItems:"行"}}),e}])}]),function(){"use strict";angular.module("ui.grid.autoResize",["ui.grid"]).directive("uiGridAutoResize",["gridUtil",function(i){return{require:"uiGrid",scope:!1,link:function(e,n,t,o){var r;r=i.debounce(function(e,t,r,i){null!==n[0].offsetParent&&(o.grid.gridWidth=r,o.grid.gridHeight=i,o.grid.queueGridRefresh().then(function(){o.grid.api.core.raise.gridDimensionChanged(t,e,i,r)}))},400),e.$watchCollection(function(){return{width:i.elementWidth(n),height:i.elementHeight(n)}},function(e,t){angular.equals(e,t)||r(t.width,t.height,e.width,e.height)})}}}])}(),function(){"use strict";var e=angular.module("ui.grid.cellNav",["ui.grid"]);e.constant("uiGridCellNavConstants",{FEATURE_NAME:"gridCellNav",CELL_NAV_EVENT:"cellNav",direction:{LEFT:0,RIGHT:1,UP:2,DOWN:3,PG_UP:4,PG_DOWN:5},EVENT_TYPE:{KEYDOWN:0,CLICK:1,CLEAR:2}}),e.factory("uiGridCellNavFactory",["gridUtil","uiGridConstants","uiGridCellNavConstants","GridRowColumn","$q",function(e,t,i,l,r){var n=function(e,t,r,i){this.rows=e.visibleRowCache,this.columns=t.visibleColumnCache,this.leftColumns=r?r.visibleColumnCache:[],this.rightColumns=i?i.visibleColumnCache:[],this.bodyContainer=e};return n.prototype.getFocusableCols=function(){return this.leftColumns.concat(this.columns,this.rightColumns).filter(function(e){return e.colDef.allowCellFocus})},n.prototype.getFocusableRows=function(){return this.rows.filter(function(e){return!1!==e.allowCellFocus})},n.prototype.getNextRowCol=function(e,t,r){switch(e){case i.direction.LEFT:return this.getRowColLeft(t,r);case i.direction.RIGHT:return this.getRowColRight(t,r);case i.direction.UP:return this.getRowColUp(t,r);case i.direction.DOWN:return this.getRowColDown(t,r);case i.direction.PG_UP:return this.getRowColPageUp(t,r);case i.direction.PG_DOWN:return this.getRowColPageDown(t,r)}},n.prototype.initializeSelection=function(){var e=this.getFocusableCols(),t=this.getFocusableRows();return 0===e.length||0===t.length?null:new l(t[0],e[0])},n.prototype.getRowColLeft=function(e,t){var r=this.getFocusableCols(),i=this.getFocusableRows(),n=r.indexOf(t),o=i.indexOf(e);-1===n&&(n=1);var a=0===n?r.length-1:n-1;return new l(n<=a?0===o?e:i[o-1]:e,r[a])},n.prototype.getRowColRight=function(e,t){var r=this.getFocusableCols(),i=this.getFocusableRows(),n=r.indexOf(t),o=i.indexOf(e);-1===n&&(n=0);var a=n===r.length-1?0:n+1;return a<=n?o===i.length-1?new l(e,r[a]):new l(i[o+1],r[a]):new l(e,r[a])},n.prototype.getRowColDown=function(e,t){var r=this.getFocusableCols(),i=this.getFocusableRows(),n=r.indexOf(t),o=i.indexOf(e);return-1===n&&(n=0),o===i.length-1?new l(e,r[n]):new l(i[o+1],r[n])},n.prototype.getRowColPageDown=function(e,t){var r=this.getFocusableCols(),i=this.getFocusableRows(),n=r.indexOf(t),o=i.indexOf(e);-1===n&&(n=0);var a=this.bodyContainer.minRowsToRender();return o>=i.length-a?new l(i[i.length-1],r[n]):new l(i[o+a],r[n])},n.prototype.getRowColUp=function(e,t){var r=this.getFocusableCols(),i=this.getFocusableRows(),n=r.indexOf(t),o=i.indexOf(e);return-1===n&&(n=0),new l(0===o?e:i[o-1],r[n])},n.prototype.getRowColPageUp=function(e,t){var r=this.getFocusableCols(),i=this.getFocusableRows(),n=r.indexOf(t),o=i.indexOf(e);-1===n&&(n=0);var a=this.bodyContainer.minRowsToRender();return new l(o-a<0?i[0]:i[o-a],r[n])},n}]),e.service("uiGridCellNavService",["gridUtil","uiGridConstants","uiGridCellNavConstants","$q","uiGridCellNavFactory","GridRowColumn","ScrollEvent",function(e,t,r,i,n,o,a){var l={initializeGrid:function(i){i.registerColumnBuilder(l.cellNavColumnBuilder),i.cellNav={},i.cellNav.lastRowCol=null,i.cellNav.focusedCells=[],l.defaultGridOptions(i.options);var e={events:{cellNav:{navigate:function(e,t){},viewPortKeyDown:function(e,t){},viewPortKeyPress:function(e,t){}}},methods:{cellNav:{scrollToFocus:function(e,t){return l.scrollToFocus(i,e,t)},getFocusedCell:function(){return i.cellNav.lastRowCol},getCurrentSelection:function(){return i.cellNav.focusedCells},rowColSelectIndex:function(e){for(var t=-1,r=0;r<i.cellNav.focusedCells.length;r++)if(i.cellNav.focusedCells[r].col.uid===e.col.uid&&i.cellNav.focusedCells[r].row.uid===e.row.uid){t=r;break}return t}}}};i.api.registerEventsFromObject(e.events),i.api.registerMethodsFromObject(e.methods)},defaultGridOptions:function(e){e.modifierKeysToMultiSelectCells=!0===e.modifierKeysToMultiSelectCells,e.keyDownOverrides=e.keyDownOverrides||[]},decorateRenderContainers:function(e){var t=e.hasRightContainer()?e.renderContainers.right:null,r=e.hasLeftContainer()?e.renderContainers.left:null;null!==r&&(e.renderContainers.left.cellNav=new n(e.renderContainers.body,r,t,e.renderContainers.body)),null!==t&&(e.renderContainers.right.cellNav=new n(e.renderContainers.body,t,e.renderContainers.body,r)),e.renderContainers.body.cellNav=new n(e.renderContainers.body,e.renderContainers.body,r,t)},getDirection:function(e){return e.keyCode===t.keymap.LEFT||e.keyCode===t.keymap.TAB&&e.shiftKey?r.direction.LEFT:e.keyCode===t.keymap.RIGHT||e.keyCode===t.keymap.TAB?r.direction.RIGHT:e.keyCode===t.keymap.UP||e.keyCode===t.keymap.ENTER&&e.shiftKey?r.direction.UP:e.keyCode===t.keymap.PG_UP?r.direction.PG_UP:e.keyCode===t.keymap.DOWN||e.keyCode===t.keymap.ENTER&&!e.ctrlKey&&!e.altKey?r.direction.DOWN:e.keyCode===t.keymap.PG_DOWN?r.direction.PG_DOWN:null},cellNavColumnBuilder:function(e,t,r){return e.allowCellFocus=void 0===e.allowCellFocus||e.allowCellFocus,i.all([])},scrollToFocus:function(t,e,r){var i=null,n=null;return null!=e&&(i=t.getRow(e)),null!=r&&(n=t.getColumn(r.name?r.name:r.field)),t.api.core.scrollToIfNecessary(i,n).then(function(){var e={row:i,col:n};null!==i&&null!==n&&t.cellNav.broadcastCellNav(e,null,null)})},getLeftWidth:function(e,t){var r=0;if(!t)return r;var i=e.renderContainers.body.visibleColumnCache.indexOf(t);e.renderContainers.body.visibleColumnCache.forEach(function(e,t){t<i&&(r+=e.drawnWidth)});var n=0===i?0:(i+1)/e.renderContainers.body.visibleColumnCache.length;return r+=t.drawnWidth*n}};return l}]),e.directive("uiGridCellnav",["gridUtil","uiGridCellNavService","uiGridCellNavConstants","uiGridConstants","GridRowColumn","$timeout","$compile","i18nService",function(e,d,u,c,g,t,a,f){return{replace:!0,priority:-150,require:"^uiGrid",scope:!1,controller:function(){},compile:function(){return{pre:function(e,t,r,l){var i=e,s=l.grid;d.initializeGrid(s),l.cellNav={},l.cellNav.makeRowCol=function(e){return e instanceof g||(e=new g(e.row,e.col)),e},l.cellNav.getActiveCell=function(){var e=t[0].getElementsByClassName("ui-grid-cell-focus");if(0<e.length)return e[0]},l.cellNav.broadcastCellNav=s.cellNav.broadcastCellNav=function(e,t,r){t=!(void 0===t||!t),e=l.cellNav.makeRowCol(e),l.cellNav.broadcastFocus(e,t,r),i.$broadcast(u.CELL_NAV_EVENT,e,t,r)},l.cellNav.clearFocus=s.cellNav.clearFocus=function(){s.cellNav.focusedCells=[],i.$broadcast(u.CELL_NAV_EVENT)},l.cellNav.broadcastFocus=function(e,t,r){t=!(void 0===t||!t);var i=(e=l.cellNav.makeRowCol(e)).row,n=e.col,o=l.grid.api.cellNav.rowColSelectIndex(e);if(null===s.cellNav.lastRowCol||-1===o||s.cellNav.lastRowCol.col===n&&s.cellNav.lastRowCol.row===i){var a=new g(i,n);(null===s.cellNav.lastRowCol||s.cellNav.lastRowCol.row!==a.row||s.cellNav.lastRowCol.col!==a.col||s.options.enableCellEditOnFocus)&&(s.api.cellNav.raise.navigate(a,s.cellNav.lastRowCol,r),s.cellNav.lastRowCol=a),l.grid.options.modifierKeysToMultiSelectCells&&t?s.cellNav.focusedCells.push(e):s.cellNav.focusedCells=[e]}else s.options.modifierKeysToMultiSelectCells&&t&&0<=o&&s.cellNav.focusedCells.splice(o,1)},l.cellNav.handleKeyDown=function(e){var t=d.getDirection(e);if(null===t)return null;var r="body";e.uiGridTargetRenderContainerId&&(r=e.uiGridTargetRenderContainerId);var i=l.grid.api.cellNav.getFocusedCell();if(i){var n=l.grid.renderContainers[r].cellNav.getNextRowCol(t,i.row,i.col),o=l.grid.renderContainers[r].cellNav.getFocusableCols(),a=l.grid.api.cellNav.rowColSelectIndex(n);return t===u.direction.LEFT&&n.col===o[o.length-1]&&n.row===i.row&&e.keyCode===c.keymap.TAB&&e.shiftKey?(s.cellNav.focusedCells.splice(a,1),l.cellNav.clearFocus(),!0):t!==u.direction.RIGHT||n.col!==o[0]||n.row!==i.row||e.keyCode!==c.keymap.TAB||e.shiftKey?(s.scrollToIfNecessary(n.row,n.col).then(function(){l.cellNav.broadcastCellNav(n,null,e)}),e.stopPropagation(),e.preventDefault(),!1):(s.cellNav.focusedCells.splice(a,1),l.cellNav.clearFocus(),!0)}}},post:function(e,t,r,i){var n,g,p=i.grid,o=!0;try{angular.module("ngAria")}catch(e){o=!1}o&&(n='<div id="'+p.id+'-aria-speakable" class="ui-grid-a11y-ariascreenreader-speakable ui-grid-offscreen" aria-live="assertive" role="alert" aria-atomic="true" aria-hidden="false" aria-relevant="additions" >&nbsp;</div>',g=a(n)(e),t.prepend(g),e.$on(u.CELL_NAV_EVENT,function(e,t,r,i){if(!i||"focus"!==i.type){for(var n,o,a=[],l=p.api.cellNav.getCurrentSelection(),s=0;s<l.length;s++){var d=("selectionRowHeaderCol"===(o=l[s]).col.field?o.row.isSelected?f.getSafeText("search.aria.selected"):f.getSafeText("search.aria.notSelected"):p.getCellDisplayValue(o.row,o.col))+(n=l[s].col,", "+f.getSafeText("headerCell.aria.column")+" "+n.displayName);a.push(d)}var u,c=a.toString();(u=c)!==g.text().trim()&&(g[0].style.clip="rect(0px,0px,0px,0px)",g[0].innerHTML="",g[0].style.visibility="hidden",g[0].style.visibility="visible",""!==u&&(g[0].style.clip="auto",g[0].appendChild(document.createTextNode(u+" ")),g[0].style.visibility="hidden",g[0].style.visibility="visible"))}}))}}}}}]),e.directive("uiGridRenderContainer",["$timeout","$document","gridUtil","uiGridConstants","uiGridCellNavService","$compile","uiGridCellNavConstants",function(c,e,g,t,p,f,m){return{replace:!0,priority:-99999,require:["^uiGrid","uiGridRenderContainer","?^uiGridCellnav"],scope:!1,compile:function(){return{post:function(e,t,r,i){var n=i[0],o=i[1],a=i[2];if(n.grid.api.cellNav){var l=o.containerId,s=n.grid;if(p.decorateRenderContainers(s),"body"===l){n.grid.options.modifierKeysToMultiSelectCells?t.attr("aria-multiselectable",!0):t.attr("aria-multiselectable",!1);var d=f('<div class="ui-grid-focuser" role="region" aria-live="assertive" aria-atomic="false" tabindex="0" aria-controls="'+s.id+"-aria-speakable "+s.id+'-grid-container" aria-owns="'+s.id+'-grid-container"></div>')(e);t.append(d),d.on("focus",function(e){e.uiGridTargetRenderContainerId=l;var t=n.grid.api.cellNav.getFocusedCell();null===t&&(t=n.grid.renderContainers[l].cellNav.getNextRowCol(m.direction.DOWN,null,null)).row&&t.col&&n.cellNav.broadcastCellNav(t)}),a.setAriaActivedescendant=function(e){t.attr("aria-activedescendant",e)},a.removeAriaActivedescendant=function(e){t.attr("aria-activedescendant")===e&&t.attr("aria-activedescendant","")},n.focus=function(){g.focus.byElement(d[0])};var u=null;d.on("keydown",function(r){r.uiGridTargetRenderContainerId=l;var e=n.grid.api.cellNav.getFocusedCell();null===(n.grid.options.keyDownOverrides.some(function(t){return Object.keys(t).every(function(e){return t[e]===r[e]})})?null:n.cellNav.handleKeyDown(r))&&(n.grid.api.cellNav.raise.viewPortKeyDown(r,e,n.cellNav.handleKeyDown),u=e)}),d.on("keypress",function(e){u&&(c(function(){n.grid.api.cellNav.raise.viewPortKeyPress(e,u)},4),u=null)}),e.$on("$destroy",function(){d.off()})}}}}}}}]),e.directive("uiGridViewport",function(){return{replace:!0,priority:-99999,require:["^uiGrid","^uiGridRenderContainer","?^uiGridCellnav"],scope:!1,compile:function(){return{pre:function(e,t,r,i){},post:function(e,t,r,i){var n=i[0],o=i[1];if(n.grid.api.cellNav&&"body"===o.containerId){var a=n.grid;a.api.core.on.scrollBegin(e,function(){var e=n.grid.api.cellNav.getFocusedCell();null!==e&&o.colContainer.containsColumn(e.col)&&n.cellNav.clearFocus()}),a.api.core.on.scrollEnd(e,function(e){var t=n.grid.api.cellNav.getFocusedCell();null!==t&&o.colContainer.containsColumn(t.col)&&n.cellNav.broadcastCellNav(t)}),a.api.cellNav.on.navigate(e,function(){n.focus()})}}}}}}),e.directive("uiGridCell",["$timeout","$document","uiGridCellNavService","gridUtil","uiGridCellNavConstants","uiGridConstants","GridRowColumn",function(e,t,r,i,c,g,p){return{priority:-150,restrict:"A",require:["^uiGrid","?^uiGridCellnav"],scope:!1,link:function(r,t,e,i){var n=i[0],o=i[1];if(n.grid.api.cellNav&&r.col.colDef.allowCellFocus){var a=n.grid;r.focused=!1,t.attr("tabindex",-1),t.find("div").on("click",function(e){n.cellNav.broadcastCellNav(new p(r.row,r.col),e.ctrlKey||e.metaKey,e),e.stopPropagation(),r.$apply()}),t.on("mousedown",s),n.grid.api.edit&&(n.grid.api.edit.on.beginCellEdit(r,function(){t.off("mousedown",s)}),n.grid.api.edit.on.afterCellEdit(r,function(){t.on("mousedown",s)}),n.grid.api.edit.on.cancelCellEdit(r,function(){t.on("mousedown",s)})),d(),t.on("focus",function(e){n.cellNav.broadcastCellNav(new p(r.row,r.col),!1,e),e.stopPropagation(),r.$apply()}),r.$on(c.CELL_NAV_EVENT,d);var l=n.grid.registerDataChangeCallback(function(e){u(),r.$applyAsync(d)},[g.dataChange.ROW]);r.$on("$destroy",function(){l(),t.find("div").off(),t.off()})}function s(e){e.preventDefault()}function d(){a.cellNav.focusedCells.some(function(e,t){return e.row===r.row&&e.col===r.col})?function(){if(!r.focused){var e=t.find("div");e.addClass("ui-grid-cell-focus"),t.attr("aria-selected",!0),o.setAriaActivedescendant(t.attr("id")),r.focused=!0}}():u()}function u(){r.focused&&(t.find("div").removeClass("ui-grid-cell-focus"),t.attr("aria-selected",!1),o.removeAriaActivedescendant(t.attr("id")),r.focused=!1)}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.edit",["ui.grid"]);e.constant("uiGridEditConstants",{EDITABLE_CELL_TEMPLATE:/EDITABLE_CELL_TEMPLATE/g,EDITABLE_CELL_DIRECTIVE:/editable_cell_directive/g,events:{BEGIN_CELL_EDIT:"uiGridEventBeginCellEdit",END_CELL_EDIT:"uiGridEventEndCellEdit",CANCEL_CELL_EDIT:"uiGridEventCancelCellEdit"}}),e.service("uiGridEditService",["$q","uiGridConstants","gridUtil",function(n,t,o){var r={initializeGrid:function(e){r.defaultGridOptions(e.options),e.registerColumnBuilder(r.editColumnBuilder),e.edit={};e.api.registerEventsFromObject({edit:{afterCellEdit:function(e,t,r,i){},beginCellEdit:function(e,t,r){},cancelCellEdit:function(e,t){}}})},defaultGridOptions:function(e){e.cellEditableCondition=void 0===e.cellEditableCondition||e.cellEditableCondition,e.enableCellEditOnFocus=void 0!==e.enableCellEditOnFocus&&e.enableCellEditOnFocus},editColumnBuilder:function(t,r,e){var i=[];return t.enableCellEdit=void 0===t.enableCellEdit?void 0===e.enableCellEdit?"object"!==t.type:e.enableCellEdit:t.enableCellEdit,t.cellEditableCondition=void 0===t.cellEditableCondition?e.cellEditableCondition:t.cellEditableCondition,t.enableCellEdit&&(t.editableCellTemplate=t.editableCellTemplate||e.editableCellTemplate||"ui-grid/cellEditor",i.push(o.getTemplate(t.editableCellTemplate).then(function(e){r.editableCellTemplate=e},function(e){throw new Error("Couldn't fetch/use colDef.editableCellTemplate '"+t.editableCellTemplate+"'")}))),t.enableCellEditOnFocus=void 0===t.enableCellEditOnFocus?e.enableCellEditOnFocus:t.enableCellEditOnFocus,n.all(i)},isStartEditKey:function(e){return!(e.metaKey||e.keyCode===t.keymap.ESC||e.keyCode===t.keymap.SHIFT||e.keyCode===t.keymap.CTRL||e.keyCode===t.keymap.ALT||e.keyCode===t.keymap.WIN||e.keyCode===t.keymap.CAPSLOCK||e.keyCode===t.keymap.LEFT||e.keyCode===t.keymap.TAB&&e.shiftKey||e.keyCode===t.keymap.RIGHT||e.keyCode===t.keymap.TAB||e.keyCode===t.keymap.UP||e.keyCode===t.keymap.ENTER&&e.shiftKey||e.keyCode===t.keymap.DOWN||e.keyCode===t.keymap.ENTER)}};return r}]),e.directive("uiGridEdit",["gridUtil","uiGridEditService",function(e,n){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){n.initializeGrid(i.grid)},post:function(e,t,r,i){}}}}}]),e.directive("uiGridViewport",["uiGridEditConstants",function(o){return{replace:!0,priority:-99998,require:["^uiGrid","^uiGridRenderContainer"],scope:!1,compile:function(){return{post:function(e,t,r,i){var n=i[0];n.grid.api.edit&&n.grid.api.cellNav&&("body"===i[1].containerId&&(e.$on(o.events.CANCEL_CELL_EDIT,function(){n.focus()}),e.$on(o.events.END_CELL_EDIT,function(){n.focus()})))}}}}}]),e.directive("uiGridCell",["$compile","$injector","$timeout","uiGridConstants","uiGridEditConstants","gridUtil","$parse","uiGridEditService","$rootScope","$q",function(S,e,x,E,A,R,F,g,T,P){var L=500;if(e.has("uiGridCellNavService"))e.get("uiGridCellNavService");return{priority:-100,restrict:"A",scope:!1,require:"?^uiGrid",link:function(p,f,e,i){var m,h,v,t,C,w=!1;if(p.col.colDef.enableCellEdit){var r=function(){},n=function(){},o=function(){p.col.colDef.enableCellEdit&&!1!==p.row.enableCellEdit?p.beginEditEventsWired||l():p.beginEditEventsWired&&b()};o();var a=p.$watch("row",function(e,t){e!==t&&o()});p.$on("$destroy",function(){a(),f.off()})}function l(){f.on("dblclick",c),f.on("touchstart",s),i&&i.grid.api.cellNav&&(n=i.grid.api.cellNav.on.viewPortKeyDown(p,function(e,t){null!==t&&(t.row!==p.row||t.col!==p.col||p.col.colDef.enableCellEditOnFocus||u(e))}),r=i.grid.api.cellNav.on.navigate(p,function(e,t,r){p.col.colDef.enableCellEditOnFocus&&(e.row!==p.row||e.col!==p.col||null!==r&&(!r||"click"!==r.type&&"keydown"!==r.type)||x(function(){c(r)}))})),p.beginEditEventsWired=!0}function s(e){void 0!==e.originalEvent&&void 0!==e.originalEvent&&(e=e.originalEvent),f.on("touchend",d),(t=x(function(){},L)).then(function(){setTimeout(c,0),f.off("touchend",d)})}function d(){x.cancel(t),f.off("touchend",d)}function b(){f.off("dblclick",c),f.off("keydown",u),f.off("touchstart",s),r(),n(),p.beginEditEventsWired=!1}function u(e){g.isStartEditKey(e)&&c(e)}function c(e){p.grid.api.core.scrollToIfNecessary(p.row,p.col).then(function(){!function(e){if(w)return;if(t=p.col,r=p.row,i=e,r.isSaving||(angular.isFunction(t.colDef.cellEditableCondition)?!t.colDef.cellEditableCondition(p,i):!t.colDef.cellEditableCondition))return;var t,r,i;var n=p.row.getQualifiedColField(p.col);p.col.colDef.editModelField&&(n=R.preEval("row.entity."+p.col.colDef.editModelField));v=F(n),h=v(p),m=(m=(m=p.col.editableCellTemplate).replace(E.MODEL_COL_FIELD,n)).replace(E.COL_FIELD,"grid.getCellValue(row, col)");var o=p.col.colDef.editDropdownFilter?"|"+p.col.colDef.editDropdownFilter:"";m=m.replace(E.CUSTOM_FILTERS,o);var a="text";switch(p.col.colDef.type){case"boolean":a="checkbox";break;case"number":a="number";break;case"date":a="date"}m=m.replace("INPUT_TYPE",a);var l=p.col.colDef.editDropdownOptionsFunction;if(l)P.when(l(p.row.entity,p.col.colDef)).then(function(e){p.editDropdownOptionsArray=e});else{var s=p.col.colDef.editDropdownRowEntityOptionsArrayPath;p.editDropdownOptionsArray=s?function(e,t){var r=(t=(t=t.replace(/\[(\w+)\]/g,".$1")).replace(/^\./,"")).split(".");for(;r.length;){var i=r.shift();if(!(i in e))return;e=e[i]}return e}(p.row.entity,s):p.col.colDef.editDropdownOptionsArray}p.editDropdownIdLabel=p.col.colDef.editDropdownIdLabel?p.col.colDef.editDropdownIdLabel:"id",p.editDropdownValueLabel=p.col.colDef.editDropdownValueLabel?p.col.colDef.editDropdownValueLabel:"value";var d=function(){w=!0,b();var e=angular.element(m);f.append(e),C=p.$new(),S(e)(C);var t=angular.element(f.children()[0]);t.addClass("ui-grid-cell-contents-hidden")};T.$$phase?d():p.$apply(d);var u=p.col.grid.api.core.on.scrollBegin(p,function(){p.grid.disableScrolling||(y(),p.grid.api.edit.raise.afterCellEdit(p.row.entity,p.col.colDef,v(p),h),u(),c(),g())}),c=p.$on(A.events.END_CELL_EDIT,function(){y(),p.grid.api.edit.raise.afterCellEdit(p.row.entity,p.col.colDef,v(p),h),c(),u(),g()}),g=p.$on(A.events.CANCEL_CELL_EDIT,function(){!function(){if(p.grid.disableScrolling=!1,!w)return;v.assign(p,h),p.$apply(),p.grid.api.edit.raise.cancelCellEdit(p.row.entity,p.col.colDef),y()}(),g(),u(),c()});p.$broadcast(A.events.BEGIN_CELL_EDIT,e),x(function(){p.grid.api.edit.raise.beginCellEdit(p.row.entity,p.col.colDef,e)})}(e)})}function y(){if(p.grid.disableScrolling=!1,w){i&&i.grid.api.cellNav&&i.focus();var e=angular.element(f.children()[0]);C.$destroy();for(var t=f.children(),r=1;r<t.length;r++)angular.element(t[r]).remove();e.removeClass("ui-grid-cell-contents-hidden"),w=!1,l(),p.grid.api.core.notifyDataChange(E.dataChange.EDIT)}}}}}]),e.directive("uiGridEditor",["gridUtil","uiGridConstants","uiGridEditConstants","$timeout","uiGridEditService",function(e,l,s,d,u){return{scope:!0,require:["?^uiGrid","?^uiGridRenderContainer","ngModel"],compile:function(){return{pre:function(e,t,r){},post:function(t,r,e,i){var n,o,a;i[0]&&(n=i[0]),i[1]&&(o=i[1]),i[2]&&(a=i[2]),t.$on(s.events.BEGIN_CELL_EDIT,function(){if(d(function(){if(r[0].focus(),!r[0].select||!t.col.colDef.enableCellEditOnFocus&&n&&n.grid.api.cellNav)try{r[0].setSelectionRange(r[0].value.length,r[0].value.length)}catch(e){}else r[0].select()}),n&&n.grid.api.cellNav)var i=n.grid.api.cellNav.on.viewPortKeyPress(t,function(e,t){if(u.isStartEditKey(e)){var r="number"==typeof e.which?e.which:e.keyCode;0<r&&(a.$setViewValue(String.fromCharCode(r),e),a.$render())}i()});r.on("mousedown",function(e){"checkbox"===r[0].type&&(r.off("blur",t.stopEdit),d(function(){r[0].focus(),r.on("blur",t.stopEdit)}))}),r.on("blur",t.stopEdit)}),t.deepEdit=!1,t.stopEdit=function(e){t.inputForm&&!t.inputForm.$valid?(e.stopPropagation(),t.$emit(s.events.CANCEL_CELL_EDIT)):t.$emit(s.events.END_CELL_EDIT),t.deepEdit=!1},r.on("click",function(e){"checkbox"!==r[0].type&&(t.deepEdit=!0,t.$applyAsync(function(){t.grid.disableScrolling=!0}))}),r.on("keydown",function(e){switch(e.keyCode){case l.keymap.ESC:e.stopPropagation(),t.$emit(s.events.CANCEL_CELL_EDIT)}if(!t.deepEdit||e.keyCode!==l.keymap.LEFT&&e.keyCode!==l.keymap.RIGHT&&e.keyCode!==l.keymap.UP&&e.keyCode!==l.keymap.DOWN)if(n&&n.grid.api.cellNav)e.uiGridTargetRenderContainerId=o.containerId,null!==n.cellNav.handleKeyDown(e)&&t.stopEdit(e);else switch(e.keyCode){case l.keymap.ENTER:case l.keymap.TAB:e.stopPropagation(),e.preventDefault(),t.stopEdit(e)}else e.stopPropagation();return!0}),t.$on("$destroy",function(){r.off()})}}}}}]),e.directive("uiGridEditor",["$filter",function(n){return{priority:-100,require:"?ngModel",link:function(e,t,r,i){2===angular.version.minor&&r.type&&"date"===r.type&&i&&(i.$formatters.push(function(e){return i.$setValidity(null,!e||!isNaN(e.getTime())),n("date")(e,"yyyy-MM-dd")}),i.$parsers.push(function(e){if(e&&0<e.length){var t=function(e){if(void 0===e||""===e)return null;var t=e.split("-");if(3!==t.length)return null;var r=parseInt(t[0],10),i=parseInt(t[1],10),n=parseInt(t[2],10);return i<1||r<1||n<1?null:new Date(r,i-1,n)}(e);return i.$setValidity(null,t&&!isNaN(t.getTime())),t}return i.$setValidity(null,!0),null}))}}}]),e.directive("uiGridEditDropdown",["uiGridConstants","uiGridEditConstants","$timeout",function(a,l,s){return{require:["?^uiGrid","?^uiGridRenderContainer"],scope:!0,compile:function(){return{pre:function(e,t,r){},post:function(t,e,r,i){var n=i[0],o=i[1];t.$on(l.events.BEGIN_CELL_EDIT,function(){s(function(){e[0].focus()}),e[0].style.width=e[0].parentElement.offsetWidth-1+"px",e.on("blur",function(e){t.stopEdit(e)})}),t.stopEdit=function(e){t.$emit(l.events.END_CELL_EDIT)},e.on("keydown",function(e){switch(e.keyCode){case a.keymap.ESC:e.stopPropagation(),t.$emit(l.events.CANCEL_CELL_EDIT)}if(n&&n.grid.api.cellNav)e.uiGridTargetRenderContainerId=o.containerId,null!==n.cellNav.handleKeyDown(e)&&t.stopEdit(e);else switch(e.keyCode){case a.keymap.ENTER:case a.keymap.TAB:e.stopPropagation(),e.preventDefault(),t.stopEdit(e)}return!0}),t.$on("$destroy",function(){e.off()})}}}}}]),e.directive("uiGridEditFileChooser",["gridUtil","uiGridConstants","uiGridEditConstants",function(o,e,a){return{scope:!0,require:["?^uiGrid","?^uiGridRenderContainer"],compile:function(){return{pre:function(e,t,r){},post:function(i,n){n[0].addEventListener("change",function e(t){var r=t.srcElement||t.target;r&&r.files&&0<r.files.length?("function"==typeof i.col.colDef.editFileChooserCallback?i.col.colDef.editFileChooserCallback(i.row,i.col,r.files):o.logError("You need to set colDef.editFileChooserCallback to use the file chooser"),r.form.reset(),i.$emit(a.events.END_CELL_EDIT)):i.$emit(a.events.CANCEL_CELL_EDIT),n[0].removeEventListener("change",e,!1)},!1),i.$on(a.events.BEGIN_CELL_EDIT,function(){n[0].focus(),n[0].select(),n.on("blur",function(){i.$emit(a.events.END_CELL_EDIT),n.off()})})}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.emptyBaseLayer",["ui.grid"]);e.service("uiGridBaseLayerService",["gridUtil","$compile",function(e,t){return{initializeGrid:function(e,t){!(e.baseLayer={emptyRows:[]})!==e.options.enableEmptyGridBaseLayer&&(e.options.enableEmptyGridBaseLayer=!t)},setNumberOfEmptyRows:function(e,t){var r=t.options.rowHeight,i=Math.ceil(e/r);if(0<i){t.baseLayer.emptyRows=[];for(var n=0;n<i;n++)t.baseLayer.emptyRows.push({})}}}}]),e.directive("uiGridEmptyBaseLayer",["gridUtil","uiGridBaseLayerService","$parse",function(e,a,o){return{require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){var n=!1===o(r.uiGridEmptyBaseLayer)(e);a.initializeGrid(i.grid,n)},post:function(e,t,r,i){if(i.grid.options.enableEmptyGridBaseLayer){var n=i.grid.renderContainers.body,o=n.getViewportHeight();i.grid.registerStyleComputation({func:function(){var e,t;return(e=n.getViewportHeight())!==o&&(o=e,1)&&a.setNumberOfEmptyRows(o,i.grid),t=o,".grid"+i.grid.id+" .ui-grid-render-container .ui-grid-empty-base-layer-container.ui-grid-canvas { height: "+t+"px; }"}})}}}}}}]),e.directive("uiGridViewport",["$compile","gridUtil","$templateCache",function(e,t,r){return{priority:-200,scope:!1,compile:function(e){var t=r.get("ui-grid/emptyBaseLayerContainer");return e.prepend(t),{pre:function(e,t,r,i){},post:function(e,t,r,i){}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.expandable",["ui.grid"]);e.service("uiGridExpandableService",["gridUtil",function(t){var n={initializeGrid:function(i){i.expandable={},i.expandable.expandedAll=!1,i.options.enableOnDblClickExpand=!1!==i.options.enableOnDblClickExpand,i.options.enableExpandable=!1!==i.options.enableExpandable,i.options.showExpandAllButton=!1!==i.options.showExpandAllButton,i.options.expandableRowHeight=i.options.expandableRowHeight||150,i.options.expandableRowHeaderWidth=i.options.expandableRowHeaderWidth||40,i.options.enableExpandable&&!i.options.expandableRowTemplate&&(t.logError("You have not set the expandableRowTemplate, disabling expandable module"),i.options.enableExpandable=!1);var e={events:{expandable:{rowExpandedBeforeStateChanged:function(e,t,r){},rowExpandedStateChanged:function(e,t,r){},rowExpandedRendered:function(e,t,r){}}},methods:{expandable:{toggleRowExpansion:function(e,t){var r=i.getRow(e);null!==r&&n.toggleRowExpansion(i,r,t)},expandAllRows:function(){n.expandAllRows(i)},collapseAllRows:function(){n.collapseAllRows(i)},toggleAllRows:function(){n.toggleAllRows(i)},expandRow:function(e){var t=i.getRow(e);null===t||t.isExpanded||n.toggleRowExpansion(i,t)},collapseRow:function(e){var t=i.getRow(e);null!==t&&t.isExpanded&&n.toggleRowExpansion(i,t)},getExpandedRows:function(){return n.getExpandedRows(i).map(function(e){return e.entity})}}}};i.api.registerEventsFromObject(e.events),i.api.registerMethodsFromObject(e.methods)},toggleRowExpansion:function(t,r,i){t.api.expandable.raise.rowExpandedBeforeStateChanged(r),r.isExpanded=!r.isExpanded,angular.isUndefined(r.expandedRowHeight)&&(r.expandedRowHeight=t.options.expandableRowHeight),r.isExpanded?(r.height=r.grid.options.rowHeight+r.expandedRowHeight,t.expandable.expandedAll=n.getExpandedRows(t).length===t.rows.length):(r.height=r.grid.options.rowHeight,t.expandable.expandedAll=!1),t.api.expandable.raise.rowExpandedStateChanged(r,i),function e(){r.expandedRendered?t.api.expandable.raise.rowExpandedRendered(r,i):window.setTimeout(e,100)}()},expandAllRows:function(t){t.renderContainers.body.visibleRowCache.forEach(function(e){e.isExpanded||e.entity.subGridOptions&&e.entity.subGridOptions.disableRowExpandable||n.toggleRowExpansion(t,e)}),t.expandable.expandedAll=!0,t.queueGridRefresh()},collapseAllRows:function(t){t.renderContainers.body.visibleRowCache.forEach(function(e){e.isExpanded&&n.toggleRowExpansion(t,e)}),t.expandable.expandedAll=!1,t.queueGridRefresh()},toggleAllRows:function(e){e.expandable.expandedAll?n.collapseAllRows(e):n.expandAllRows(e)},getExpandedRows:function(e){return e.rows.filter(function(e){return e.isExpanded})}};return n}]),e.directive("uiGridExpandable",["uiGridExpandableService","$templateCache",function(o,a){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){if(o.initializeGrid(i.grid),i.grid.options.enableExpandable&&!1!==i.grid.options.enableExpandableRowHeader){var n={name:"expandableButtons",displayName:"",exporterSuppressExport:!0,enableColumnResizing:!1,enableColumnMenu:!1,width:i.grid.options.expandableRowHeaderWidth||30};n.cellTemplate=a.get("ui-grid/expandableRowHeader"),n.headerCellTemplate=a.get("ui-grid/expandableTopRowHeader"),i.grid.addRowHeaderColumn(n,-90)}},post:function(e,t,r,i){}}}}}]),e.directive("uiGrid",function(){return{replace:!0,priority:599,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){i.grid.api.core.on.renderingComplete(e,function(){e.row&&e.row.grid&&e.row.grid.options&&e.row.grid.options.enableExpandable&&(i.grid.parentRow=e.row)})},post:function(e,t,r,i){}}}}}),e.directive("uiGridExpandableRow",["uiGridExpandableService","$compile","uiGridConstants","gridUtil",function(e,a,t,r){return{replace:!1,priority:0,scope:!1,compile:function(){return{pre:function(n,o){r.getTemplate(n.grid.options.expandableRowTemplate).then(function(e){if(n.grid.options.expandableRowScope){var t=n.grid.options.expandableRowScope;for(var r in t)t.hasOwnProperty(r)&&(n[r]=t[r])}var i=angular.element(e);i=a(i)(n),o.append(i),n.row.element=o,n.row.expandedRendered=!0})},post:function(e,t){e.row.element=t,e.$on("$destroy",function(){e.row.expandedRendered=!1})}}}}}]),e.directive("uiGridRow",function(){return{priority:-200,scope:!1,compile:function(){return{pre:function(t,e){t.grid.options.enableExpandable&&(t.expandableRow={},t.expandableRow.shouldRenderExpand=function(){return"body"===t.colContainer.name&&!1!==t.grid.options.enableExpandable&&t.row.isExpanded&&(!t.grid.isScrollingVertically||t.row.expandedRendered)},t.expandableRow.shouldRenderFiller=function(){return t.row.isExpanded&&("body"!==t.colContainer.name||t.grid.isScrollingVertically&&!t.row.expandedRendered)},t.grid.options.enableOnDblClickExpand&&e.on("dblclick",function(e){t.grid.api.expandable.toggleRowExpansion(t.row.entity,e)}))},post:function(e,t,r,i){}}}}}),e.directive("uiGridViewport",["$compile","gridUtil","$templateCache",function(e,t,n){return{priority:-200,scope:!1,compile:function(e){var t=angular.element(e.children().children()[0]),r=n.get("ui-grid/expandableScrollFiller"),i=n.get("ui-grid/expandableRow");return t.append(i),t.append(r),{pre:function(e,t,r,i){},post:function(e,t,r,i){}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.exporter",["ui.grid"]);e.constant("uiGridExporterConstants",{featureName:"exporter",rowHeaderColName:"treeBaseRowHeaderCol",selectionRowHeaderColName:"selectionRowHeaderCol",ALL:"all",VISIBLE:"visible",SELECTED:"selected",CSV_CONTENT:"CSV_CONTENT",BUTTON_LABEL:"BUTTON_LABEL",FILE_NAME:"FILE_NAME"}),e.service("uiGridExporterService",["$filter","$q","uiGridExporterConstants","gridUtil","$compile","$interval","i18nService",function(s,n,p,u,e,t,r){var i={delay:100,initializeGrid:function(r){r.exporter={},this.defaultGridOptions(r.options);var e={events:{exporter:{}},methods:{exporter:{csvExport:function(e,t){i.csvExport(r,e,t)},pdfExport:function(e,t){i.pdfExport(r,e,t)},excelExport:function(e,t){i.excelExport(r,e,t)}}}};r.api.registerEventsFromObject(e.events),r.api.registerMethodsFromObject(e.methods),r.api.core.addToGridMenu?i.addToMenu(r):t(function(){r.api.core.addToGridMenu&&i.addToMenu(r)},this.delay,1)},defaultGridOptions:function(e){e.exporterSuppressMenu=!0===e.exporterSuppressMenu,e.exporterMenuLabel=e.exporterMenuLabel?e.exporterMenuLabel:"Export",e.exporterSuppressColumns=e.exporterSuppressColumns?e.exporterSuppressColumns:[],e.exporterCsvColumnSeparator=e.exporterCsvColumnSeparator?e.exporterCsvColumnSeparator:",",e.exporterCsvFilename=e.exporterCsvFilename?e.exporterCsvFilename:"download.csv",e.exporterPdfFilename=e.exporterPdfFilename?e.exporterPdfFilename:"download.pdf",e.exporterExcelFilename=e.exporterExcelFilename?e.exporterExcelFilename:"download.xlsx",e.exporterExcelSheetName=e.exporterExcelSheetName?e.exporterExcelSheetName:"Sheet1",e.exporterOlderExcelCompatibility=!0===e.exporterOlderExcelCompatibility,e.exporterIsExcelCompatible=!0===e.exporterIsExcelCompatible,e.exporterMenuItemOrder=e.exporterMenuItemOrder?e.exporterMenuItemOrder:200,e.exporterPdfDefaultStyle=e.exporterPdfDefaultStyle?e.exporterPdfDefaultStyle:{fontSize:11},e.exporterPdfTableStyle=e.exporterPdfTableStyle?e.exporterPdfTableStyle:{margin:[0,5,0,15]},e.exporterPdfTableHeaderStyle=e.exporterPdfTableHeaderStyle?e.exporterPdfTableHeaderStyle:{bold:!0,fontSize:12,color:"black"},e.exporterPdfHeader=e.exporterPdfHeader?e.exporterPdfHeader:null,e.exporterPdfFooter=e.exporterPdfFooter?e.exporterPdfFooter:null,e.exporterPdfOrientation=e.exporterPdfOrientation?e.exporterPdfOrientation:"landscape",e.exporterPdfPageSize=e.exporterPdfPageSize?e.exporterPdfPageSize:"A4",e.exporterPdfMaxGridWidth=e.exporterPdfMaxGridWidth?e.exporterPdfMaxGridWidth:720,e.exporterMenuAllData=void 0===e.exporterMenuAllData||e.exporterMenuAllData,e.exporterMenuVisibleData=void 0===e.exporterMenuVisibleData||e.exporterMenuVisibleData,e.exporterMenuSelectedData=void 0===e.exporterMenuSelectedData||e.exporterMenuSelectedData,e.exporterMenuCsv=void 0===e.exporterMenuCsv||e.exporterMenuCsv,e.exporterMenuPdf=void 0===e.exporterMenuPdf||e.exporterMenuPdf,e.exporterMenuExcel=void 0===e.exporterMenuExcel||e.exporterMenuExcel,e.exporterPdfCustomFormatter=e.exporterPdfCustomFormatter&&"function"==typeof e.exporterPdfCustomFormatter?e.exporterPdfCustomFormatter:function(e){return e},e.exporterHeaderFilterUseName=!0===e.exporterHeaderFilterUseName,e.exporterFieldCallback=e.exporterFieldCallback?e.exporterFieldCallback:o,e.exporterFieldFormatCallback=e.exporterFieldFormatCallback?e.exporterFieldFormatCallback:function(e,t,r,i){return null},e.exporterExcelCustomFormatters=e.exporterExcelCustomFormatters?e.exporterExcelCustomFormatters:function(e,t,r){return r},e.exporterExcelHeader=e.exporterExcelHeader?e.exporterExcelHeader:function(e,t,r,i){return null},e.exporterColumnScaleFactor=e.exporterColumnScaleFactor?e.exporterColumnScaleFactor:3.5,e.exporterFieldApplyFilters=!0===e.exporterFieldApplyFilters,e.exporterAllDataFn=e.exporterAllDataFn?e.exporterAllDataFn:null,null===e.exporterAllDataFn&&e.exporterAllDataPromise&&(e.exporterAllDataFn=e.exporterAllDataPromise)},addToMenu:function(e){e.api.core.addToGridMenu(e,[{title:r.getSafeText("gridMenu.exporterAllAsCsv"),action:function(){e.api.exporter.csvExport(p.ALL,p.ALL)},shown:function(){return e.options.exporterMenuCsv&&e.options.exporterMenuAllData},order:e.options.exporterMenuItemOrder},{title:r.getSafeText("gridMenu.exporterVisibleAsCsv"),action:function(){e.api.exporter.csvExport(p.VISIBLE,p.VISIBLE)},shown:function(){return e.options.exporterMenuCsv&&e.options.exporterMenuVisibleData},order:e.options.exporterMenuItemOrder+1},{title:r.getSafeText("gridMenu.exporterSelectedAsCsv"),action:function(){e.api.exporter.csvExport(p.SELECTED,p.VISIBLE)},shown:function(){return e.options.exporterMenuCsv&&e.options.exporterMenuSelectedData&&e.api.selection&&0<e.api.selection.getSelectedRows().length},order:e.options.exporterMenuItemOrder+2},{title:r.getSafeText("gridMenu.exporterAllAsPdf"),action:function(){e.api.exporter.pdfExport(p.ALL,p.ALL)},shown:function(){return e.options.exporterMenuPdf&&e.options.exporterMenuAllData},order:e.options.exporterMenuItemOrder+3},{title:r.getSafeText("gridMenu.exporterVisibleAsPdf"),action:function(){e.api.exporter.pdfExport(p.VISIBLE,p.VISIBLE)},shown:function(){return e.options.exporterMenuPdf&&e.options.exporterMenuVisibleData},order:e.options.exporterMenuItemOrder+4},{title:r.getSafeText("gridMenu.exporterSelectedAsPdf"),action:function(){e.api.exporter.pdfExport(p.SELECTED,p.VISIBLE)},shown:function(){return e.options.exporterMenuPdf&&e.options.exporterMenuSelectedData&&e.api.selection&&0<e.api.selection.getSelectedRows().length},order:e.options.exporterMenuItemOrder+5},{title:r.getSafeText("gridMenu.exporterAllAsExcel"),action:function(){e.api.exporter.excelExport(p.ALL,p.ALL)},shown:function(){return e.options.exporterMenuExcel&&e.options.exporterMenuAllData},order:e.options.exporterMenuItemOrder+6},{title:r.getSafeText("gridMenu.exporterVisibleAsExcel"),action:function(){e.api.exporter.excelExport(p.VISIBLE,p.VISIBLE)},shown:function(){return e.options.exporterMenuExcel&&e.options.exporterMenuVisibleData},order:e.options.exporterMenuItemOrder+7},{title:r.getSafeText("gridMenu.exporterSelectedAsExcel"),action:function(){e.api.exporter.excelExport(p.SELECTED,p.VISIBLE)},shown:function(){return e.options.exporterMenuExcel&&e.options.exporterMenuSelectedData&&e.api.selection&&0<e.api.selection.getSelectedRows().length},order:e.options.exporterMenuItemOrder+8}])},csvExport:function(i,n,o){var a=this;this.loadAllDataIfNeeded(i,n,o).then(function(){var e=i.options.showHeader?a.getColumnHeaders(i,o):[],t=a.getData(i,n,o),r=a.formatAsCsv(e,t,i.options.exporterCsvColumnSeparator);a.downloadFile(i.options.exporterCsvFilename,r,i.options.exporterCsvColumnSeparator,i.options.exporterOlderExcelCompatibility,i.options.exporterIsExcelCompatible)})},loadAllDataIfNeeded:function(t,e,r){if(e===p.ALL&&t.rows.length!==t.options.totalItems&&t.options.exporterAllDataFn)return t.options.exporterAllDataFn().then(function(e){t.modifyRows(e)});var i=n.defer();return i.resolve(),i.promise},getColumnHeaders:function(r,e){var t,i=[];if(e===p.ALL)t=r.columns;else{var n=r.renderContainers.left?r.renderContainers.left.visibleColumnCache.filter(function(e){return e.visible}):[],o=r.renderContainers.body?r.renderContainers.body.visibleColumnCache.filter(function(e){return e.visible}):[],a=r.renderContainers.right?r.renderContainers.right.visibleColumnCache.filter(function(e){return e.visible}):[];t=n.concat(o,a)}return t.forEach(function(e){if(!0!==e.colDef.exporterSuppressExport&&"$$hashKey"!==e.field&&-1===r.options.exporterSuppressColumns.indexOf(e.name)){var t={name:e.field,displayName:function(e,t){if(e.options.exporterHeaderFilter)return e.options.exporterHeaderFilterUseName?e.options.exporterHeaderFilter(t.name):e.options.exporterHeaderFilter(t.displayName);return t.headerCellFilter?s(t.headerCellFilter)(t.displayName):t.displayName}(r,e),width:e.drawnWidth?e.drawnWidth:e.width,align:e.colDef.align?e.colDef.align:"number"===e.colDef.type?"right":"left"};i.push(t)}}),i},getRowsFromNode:function(e){for(var t=[],r=0;r<e.children.length;r++)if(e.children[r].children&&0===e.children[r].children.length)t.push(e.children[r]);else{var i=this.getRowsFromNode(e.children[r]);t=t.concat(i)}return t},getDataSorted:function(e){if(!e.treeBase||0===e.treeBase.numberLevels)return e.rows;for(var t=[],r=0;r<e.treeBase.tree.length;r++)for(var i=this.getRowsFromNode(e.treeBase.tree[r]),n=0;n<i.length;n++)t.push(i[n].row);return t},getData:function(a,e,l,s){var t,r,i=[];switch(e){case p.ALL:t=this.getDataSorted(a,e,l,s);break;case p.VISIBLE:t=a.getVisibleRows();break;case p.SELECTED:a.api.selection?t=a.api.selection.getSelectedGridRows():u.logError("selection feature must be enabled to allow selected rows to be exported")}if(l===p.ALL)r=a.columns;else{var n=a.renderContainers.left?a.renderContainers.left.visibleColumnCache.filter(function(e){return e.visible}):[],o=a.renderContainers.body?a.renderContainers.body.visibleColumnCache.filter(function(e){return e.visible}):[],d=a.renderContainers.right?a.renderContainers.right.visibleColumnCache.filter(function(e){return e.visible}):[];r=n.concat(o,d)}return t.forEach(function(n){if(!1!==n.exporterEnableExporting){var o=[];r.forEach(function(e){if((e.visible||l===p.ALL)&&!0!==e.colDef.exporterSuppressExport&&"$$hashKey"!==e.field&&-1===a.options.exporterSuppressColumns.indexOf(e.name)){var t=s?a.getCellDisplayValue(n,e):a.getCellValue(n,e),r={value:a.options.exporterFieldCallback(a,n,e,t)},i=a.options.exporterFieldFormatCallback(a,n,e,t);i&&Object.assign(r,i),e.colDef.exporterPdfAlign&&(r.alignment=e.colDef.exporterPdfAlign),o.push(r)}}),i.push(o)}}),i},formatAsCsv:function(e,t,r){var i=e.map(function(e){return{value:e.displayName}}),n=0<i.length?this.formatRowAsCsv(this,r)(i)+"\n":"";return n+=t.map(this.formatRowAsCsv(this,r)).join("\n")},formatRowAsCsv:function(t,r){return function(e){return e.map(t.formatFieldAsCsv).join(r)}},formatFieldAsCsv:function(e){return null==e.value?"":"number"==typeof e.value?e.value:"boolean"==typeof e.value?e.value?"TRUE":"FALSE":"string"==typeof e.value?'"'+e.value.replace(/"/g,'""')+'"':JSON.stringify(e.value)},isIE:function(){var e=!1;return-1!==navigator.userAgent.search(/(?:Edge|MSIE|Trident\/.*; rv:)/)&&(e=!0),e},downloadFile:function(e,t,r,i,n){var o,a=document,l=a.createElement("a"),s="application/octet-stream;charset=utf-8",d=this.isIE();if(n&&(t="sep="+r+"\r\n"+t),navigator.msSaveBlob)return navigator.msSaveOrOpenBlob(new Blob([i?"\ufeff":"",t],{type:s}),e);if(d){var u=a.createElement("iframe");return document.body.appendChild(u),u.contentWindow.document.open("text/html","replace"),u.contentWindow.document.write(t),u.contentWindow.document.close(),u.contentWindow.focus(),u.contentWindow.document.execCommand("SaveAs",!0,e),document.body.removeChild(u),!0}if("download"in l){var c=new Blob([i?"\ufeff":"",t],{type:s});o=URL.createObjectURL(c),l.setAttribute("download",e)}else o="data: "+s+","+encodeURIComponent(t),l.setAttribute("target","_blank");l.href=o,l.setAttribute("style","display:none;"),a.body.appendChild(l),setTimeout(function(){if(l.click)l.click();else if(document.createEvent){var e=document.createEvent("MouseEvents");e.initEvent("click",!0,!0),l.dispatchEvent(e)}a.body.removeChild(l)},this.delay)},pdfExport:function(i,n,o){var a=this;this.loadAllDataIfNeeded(i,n,o).then(function(){var e=a.getColumnHeaders(i,o),t=a.getData(i,n,o),r=a.prepareAsPdf(i,e,t);a.isIE()||-1!==navigator.appVersion.indexOf("Edge")?a.downloadPDF(i.options.exporterPdfFilename,r):pdfMake.createPdf(r).open()})},downloadPDF:function(r,e){var i,n,o=document;o.createElement("a");i=this.isIE(),pdfMake.createPdf(e).getBuffer(function(e){if(n=new Blob([e]),navigator.msSaveBlob)return navigator.msSaveBlob(n,r);if(i){var t=o.createElement("iframe");return document.body.appendChild(t),t.contentWindow.document.open("text/html","replace"),t.contentWindow.document.write(n),t.contentWindow.document.close(),t.contentWindow.focus(),t.contentWindow.document.execCommand("SaveAs",!0,r),document.body.removeChild(t),!0}})},prepareAsPdf:function(e,t,r){var i=this.calculatePdfHeaderWidths(e,t),n=t.map(function(e){return{text:e.displayName,style:"tableHeader"}}),o=r.map(this.formatRowAsPdf(this)),a=[n].concat(o),l={pageOrientation:e.options.exporterPdfOrientation,pageSize:e.options.exporterPdfPageSize,content:[{style:"tableStyle",table:{headerRows:1,widths:i,body:a}}],styles:{tableStyle:e.options.exporterPdfTableStyle,tableHeader:e.options.exporterPdfTableHeaderStyle},defaultStyle:e.options.exporterPdfDefaultStyle};return e.options.exporterPdfLayout&&(l.layout=e.options.exporterPdfLayout),e.options.exporterPdfHeader&&(l.header=e.options.exporterPdfHeader),e.options.exporterPdfFooter&&(l.footer=e.options.exporterPdfFooter),e.options.exporterPdfCustomFormatter&&(l=e.options.exporterPdfCustomFormatter(l)),l},calculatePdfHeaderWidths:function(t,e){var r=0;e.forEach(function(e){"number"==typeof e.width&&(r+=e.width)});var i=0;e.forEach(function(e){if("*"===e.width&&(i+=100),"string"==typeof e.width&&e.width.match(/(\d)*%/)){var t=parseInt(e.width.match(/(\d)*%/)[0]);e.width=r*t/100,i+=e.width}});var n=r+i;return e.map(function(e){return"*"===e.width?e.width:e.width*t.options.exporterPdfMaxGridWidth/n})},formatRowAsPdf:function(t){return function(e){return e.map(t.formatFieldAsPdfString)}},formatFieldAsPdfString:function(e){var t;return t=null==e.value?"":"number"==typeof e.value?e.value.toString():"boolean"==typeof e.value?e.value?"TRUE":"FALSE":"string"==typeof e.value?e.value.replace(/"/g,'""'):e.value instanceof Date?JSON.stringify(e.value).replace(/^"/,"").replace(/"$/,""):"object"==typeof e.value?e.value:JSON.stringify(e.value).replace(/^"/,"").replace(/"$/,""),e.alignment&&"string"==typeof e.alignment&&(t={text:t,alignment:e.alignment}),t},formatAsExcel:function(e,t,r,i,n){for(var o=e.map(function(e){return{value:e.displayName}}),a=[],l=[],s=0;s<o.length;s++){var d="header";switch(e[s].align){case"center":d="headerCenter";break;case"right":d="headerRight"}var u=n.styles&&n.styles[d]?{style:n.styles[d].id}:null;l.push({value:o[s].value,metadata:u})}a.push(l);for(var c=t.map(this.formatRowAsExcel(this,r,i)),g=0;g<c.length;g++)a.push(c[g]);return a},formatRowAsExcel:function(n,o,a){return function(e){for(var t=[],r=0;r<e.length;r++){var i=n.formatFieldAsExcel(e[r],o,a);t.push({value:i,metadata:e[r].metadata})}return t}},formatFieldAsExcel:function(e,t,r,i){return null==e.value?"":"number"==typeof e.value?e.value:"boolean"==typeof e.value?e.value?"TRUE":"FALSE":"string"==typeof e.value?e.value.replace(/"/g,'""'):JSON.stringify(e.value)},prepareAsExcel:function(e,t,r){var i={styles:{}};if(e.options.exporterExcelCustomFormatters&&(i=e.options.exporterExcelCustomFormatters(e,t,i)),e.options.exporterExcelHeader)if(angular.isFunction(e.options.exporterExcelHeader))e.options.exporterExcelHeader(e,t,r,i);else{var n=e.options.exporterExcelHeader.text,o=e.options.exporterExcelHeader.style;r.data.push([{value:n,metadata:{style:i.styles[o].id}}])}return i},excelExport:function(d,u,c){var g=this;this.loadAllDataIfNeeded(d,u,c).then(function(){var e=d.options.showHeader?g.getColumnHeaders(d,c):[],t=new ExcelBuilder.Workbook,r=d.options.exporterExcelSheetName?d.options.exporterExcelSheetName:"Sheet1",i=new ExcelBuilder.Worksheet({name:r});t.addWorksheet(i);for(var n=g.prepareAsExcel(d,t,i),o=[],a=d.treeBase?d.treeBase.numberLevels:d.enableRowSelection?1:0;a<d.columns.length;a++)d.columns[a].field!==p.rowHeaderColName&&d.columns[a].field!==p.selectionRowHeaderColName&&o.push({width:d.columns[a].drawnWidth/d.options.exporterColumnScaleFactor});i.setColumns(o);var l=g.getData(d,u,c,d.options.exporterFieldApplyFilters),s=g.formatAsExcel(e,l,t,i,n);i.setData(i.data.concat(s)),ExcelBuilder.Builder.createFile(t,{type:"blob"}).then(function(e){g.downloadFile(d.options.exporterExcelFilename,e,d.options.exporterCsvColumnSeparator,d.options.exporterOlderExcelCompatibility)})})}};function o(e,t,r,i){var n,o,a,l;return r.cellFilter?(o=(n=r.cellFilter.replace(/[\'\"\s]/g,"").split(":"))[0]?n[0]:null,a=n[1]?n[1]:null,l=n[2]?n[2]:null,s(o)(i,a,l)):i}return i}]),e.directive("uiGridExporter",["uiGridExporterConstants","uiGridExporterService","gridUtil","$compile",function(e,n,t,r){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,link:function(e,t,r,i){n.initializeGrid(i.grid),i.grid.exporter.$scope=e}}}])}(),function(){"use strict";var e=angular.module("ui.grid.grouping",["ui.grid","ui.grid.treeBase"]);e.constant("uiGridGroupingConstants",{featureName:"grouping",rowHeaderColName:"treeBaseRowHeaderCol",EXPANDED:"expanded",COLLAPSED:"collapsed",aggregation:{COUNT:"count",SUM:"sum",MAX:"max",MIN:"min",AVG:"avg"}}),e.service("uiGridGroupingService",["$q","uiGridGroupingConstants","gridUtil","rowSorter","GridRow","gridClassFactory","i18nService","uiGridConstants","uiGridTreeBaseService",function(e,l,s,d,g,p,u,i,c){var f={initializeGrid:function(n,e){c.initializeGrid(n,e),n.grouping={},n.grouping.groupHeaderCache={},f.defaultGridOptions(n.options),n.registerRowsProcessor(f.groupRows,400),n.registerColumnBuilder(f.groupingColumnBuilder),n.registerColumnsProcessor(f.groupingColumnProcessor,400);var t={events:{grouping:{aggregationChanged:{},groupingChanged:{}}},methods:{grouping:{getGrouping:function(e){var t=f.getGrouping(n);return t.grouping.forEach(function(e){e.colName=e.col.name,delete e.col}),t.aggregations.forEach(function(e){e.colName=e.col.name,delete e.col}),t.aggregations=t.aggregations.filter(function(e){return!e.aggregation.source||"grouping"!==e.aggregation.source}),e&&(t.rowExpandedStates=f.getRowExpandedStates(n.grouping.groupingHeaderCache)),t},setGrouping:function(e){f.setGrouping(n,e)},groupColumn:function(e){var t=n.getColumn(e);f.groupColumn(n,t)},ungroupColumn:function(e){var t=n.getColumn(e);f.ungroupColumn(n,t)},clearGrouping:function(){f.clearGrouping(n)},aggregateColumn:function(e,t,r){var i=n.getColumn(e);f.aggregateColumn(n,i,t,r)}}}};n.api.registerEventsFromObject(t.events),n.api.registerMethodsFromObject(t.methods),n.api.core.on.sortChanged(e,f.tidyPriorities)},defaultGridOptions:function(e){e.enableGrouping=!1!==e.enableGrouping,e.groupingShowCounts=!1!==e.groupingShowCounts,e.groupingNullLabel=void 0===e.groupingNullLabel?"Null":e.groupingNullLabel,e.enableGroupHeaderSelection=!0===e.enableGroupHeaderSelection},groupingColumnBuilder:function(e,i,t){if(!1!==e.enableGrouping){void 0===i.grouping&&void 0!==e.grouping?(i.grouping=angular.copy(e.grouping),void 0!==i.grouping.groupPriority&&-1<i.grouping.groupPriority&&(i.treeAggregationFn=c.nativeAggregations()[l.aggregation.COUNT].aggregationFn,i.treeAggregationFinalizerFn=f.groupedFinalizerFn)):void 0===i.grouping&&(i.grouping={}),void 0!==i.grouping&&void 0!==i.grouping.groupPriority&&0<=i.grouping.groupPriority&&(i.suppressRemoveSort=!0);var r={name:"ui.grid.grouping.group",title:u.get().grouping.group,icon:"ui-grid-icon-indent-right",shown:function(){return void 0===this.context.col.grouping||void 0===this.context.col.grouping.groupPriority||this.context.col.grouping.groupPriority<0},action:function(){f.groupColumn(this.context.col.grid,this.context.col)}},n={name:"ui.grid.grouping.ungroup",title:u.get().grouping.ungroup,icon:"ui-grid-icon-indent-left",shown:function(){return void 0!==this.context.col.grouping&&void 0!==this.context.col.grouping.groupPriority&&0<=this.context.col.grouping.groupPriority},action:function(){f.ungroupColumn(this.context.col.grid,this.context.col)}},o={name:"ui.grid.grouping.aggregateRemove",title:u.get().grouping.aggregate_remove,shown:function(){return void 0!==this.context.col.treeAggregationFn},action:function(){f.aggregateColumn(this.context.col.grid,this.context.col,null)}},a=function(e,t){t=t||u.get().grouping["aggregate_"+e]||e;var r={name:"ui.grid.grouping.aggregate"+e,title:t,shown:function(){return void 0===this.context.col.treeAggregation||void 0===this.context.col.treeAggregation.type||this.context.col.treeAggregation.type!==e},action:function(){f.aggregateColumn(this.context.col.grid,this.context.col,e)}};s.arrayContainsObjectWithProperty(i.menuItems,"name","ui.grid.grouping.aggregate"+e)||i.menuItems.push(r)};!1!==i.colDef.groupingShowGroupingMenu&&(s.arrayContainsObjectWithProperty(i.menuItems,"name","ui.grid.grouping.group")||i.menuItems.push(r),s.arrayContainsObjectWithProperty(i.menuItems,"name","ui.grid.grouping.ungroup")||i.menuItems.push(n)),!1!==i.colDef.groupingShowAggregationMenu&&(angular.forEach(c.nativeAggregations(),function(e,t){a(t)}),angular.forEach(t.treeCustomAggregations,function(e,t){a(t,e.menuTitle)}),s.arrayContainsObjectWithProperty(i.menuItems,"name","ui.grid.grouping.aggregateRemove")||i.menuItems.push(o))}},groupingColumnProcessor:function(e,t){return e=f.moveGroupColumns(this,e,t)},groupedFinalizerFn:function(e){void 0!==e.groupVal?(e.rendered=e.groupVal,this.grid.options.groupingShowCounts&&"date"!==this.colDef.type&&"object"!==this.colDef.type&&(e.rendered+=" ("+e.value+")")):e.rendered=null},moveGroupColumns:function(e,t){return!1===e.options.moveGroupColumns||(t.forEach(function(e,t){e.groupingPosition=t}),t.sort(function(e,t){var r,i;return r=e.isRowHeader?e.headerPriority:void 0===e.grouping||void 0===e.grouping.groupPriority||e.grouping.groupPriority<0?null:e.grouping.groupPriority,i=t.isRowHeader?t.headerPriority:void 0===t.grouping||void 0===t.grouping.groupPriority||t.grouping.groupPriority<0?null:t.grouping.groupPriority,null!==r&&null===i?-1:null!==i&&null===r?1:null!==r&&null!==i?r-i:e.groupingPosition-t.groupingPosition}),t.forEach(function(e){delete e.groupingPosition})),t},groupColumn:function(e,t){void 0===t.grouping&&(t.grouping={});var r=f.getGrouping(e);t.grouping.groupPriority=r.grouping.length,t.previousSort=angular.copy(t.sort),t.sort?void 0!==t.sort.direction&&null!==t.sort.direction||(t.sort.direction=i.ASC):t.sort={direction:i.ASC},t.treeAggregation={type:l.aggregation.COUNT,source:"grouping"},t.treeAggregationFn=c.nativeAggregations()[l.aggregation.COUNT].aggregationFn,t.treeAggregationFinalizerFn=f.groupedFinalizerFn,e.api.grouping.raise.groupingChanged(t),e.api.core.raise.sortChanged(e,e.getColumnSorting()),e.queueGridRefresh()},ungroupColumn:function(e,t){void 0!==t.grouping&&(delete t.grouping.groupPriority,delete t.treeAggregation,delete t.customTreeAggregationFinalizer,t.previousSort&&(t.sort=t.previousSort,delete t.previousSort),f.tidyPriorities(e),e.api.grouping.raise.groupingChanged(t),e.api.core.raise.sortChanged(e,e.getColumnSorting()),e.queueGridRefresh())},aggregateColumn:function(e,t,r){void 0!==t.grouping&&void 0!==t.grouping.groupPriority&&0<=t.grouping.groupPriority&&f.ungroupColumn(e,t);var i={};void 0!==e.options.treeCustomAggregations[r]?i=e.options.treeCustomAggregations[r]:void 0!==c.nativeAggregations()[r]&&(i=c.nativeAggregations()[r]),t.treeAggregation={type:r,label:u.get().aggregation[i.label]||i.label},t.treeAggregationFn=i.aggregationFn,t.treeAggregationFinalizerFn=i.finalizerFn,e.api.grouping.raise.aggregationChanged(t),e.queueGridRefresh()},setGrouping:function(r,e){void 0!==e&&(f.clearGrouping(r),e.grouping&&e.grouping.length&&0<e.grouping.length&&e.grouping.forEach(function(e){var t=r.getColumn(e.colName);t&&f.groupColumn(r,t)}),e.aggregations&&e.aggregations.length&&e.aggregations.forEach(function(e){var t=r.getColumn(e.colName);t&&f.aggregateColumn(r,t,e.aggregation.type)}),e.rowExpandedStates&&f.applyRowExpandedStates(r.grouping.groupingHeaderCache,e.rowExpandedStates))},clearGrouping:function(t){var e=f.getGrouping(t);0<e.grouping.length&&e.grouping.forEach(function(e){e.col||(e.col=t.getColumn(e.colName)),f.ungroupColumn(t,e.col)}),0<e.aggregations.length&&e.aggregations.forEach(function(e){e.col||(e.col=t.getColumn(e.colName)),f.aggregateColumn(t,e.col,null)})},tidyPriorities:function(e){void 0!==e&&void 0===e.grid||void 0===this.grid||(e=this.grid);var r=[],i=[];e.columns.forEach(function(e,t){void 0!==e.grouping&&void 0!==e.grouping.groupPriority&&0<=e.grouping.groupPriority?r.push(e):void 0!==e.sort&&void 0!==e.sort.priority&&0<=e.sort.priority&&i.push(e)}),r.sort(function(e,t){return e.grouping.groupPriority-t.grouping.groupPriority}),r.forEach(function(e,t){e.grouping.groupPriority=t,e.suppressRemoveSort=!0,void 0===e.sort&&(e.sort={}),e.sort.priority=t});var t=r.length;i.sort(function(e,t){return e.sort.priority-t.sort.priority}),i.forEach(function(e){e.sort.priority=t,e.suppressRemoveSort=e.colDef.suppressRemoveSort,t++})},groupRows:function(i){if(0===i.length)return i;var n=this;n.grouping.oldGroupingHeaderCache=n.grouping.groupingHeaderCache||{},n.grouping.groupingHeaderCache={};for(var o=f.initialiseProcessingState(n),e=function(e,t){var r=n.getCellValue(l,e.col);e.initialised&&0===d.getSortFn(n,e.col,i)(r,e.currentValue)||(f.insertGroupHeader(n,i,a,o,t),a++)},a=0;a<i.length;a++){var l=i[a];l.visible&&o.forEach(e)}return delete n.grouping.oldGroupingHeaderCache,i},initialiseProcessingState:function(e){var r=[];return f.getGrouping(e).grouping.forEach(function(e,t){r.push({fieldName:e.field,col:e.col,initialised:!1,currentValue:null,currentRow:null})}),r},getGrouping:function(e){var t=[],r=[];return e.columns.forEach(function(e){e.grouping&&void 0!==e.grouping.groupPriority&&0<=e.grouping.groupPriority&&t.push({field:e.field,col:e,groupPriority:e.grouping.groupPriority,grouping:e.grouping}),e.treeAggregation&&e.treeAggregation.type&&r.push({field:e.field,col:e,aggregation:e.treeAggregation})}),t.sort(function(e,t){return e.groupPriority-t.groupPriority}),t.forEach(function(e,t){e.grouping.groupPriority=t,e.groupPriority=t,delete e.grouping}),{grouping:t,aggregations:r}},insertGroupHeader:function(e,t,r,i,n){var o=i[n].col,a=e.getCellValue(t[r],o),l=a;function s(e){return angular.isObject(e)?JSON.stringify(e):e}null==a&&(l=e.options.groupingNullLabel);for(var d,u=e.grouping.oldGroupingHeaderCache,c=0;c<n;c++)u&&u[s(i[c].currentValue)]&&(u=u[s(i[c].currentValue)].children);for(u&&u[s(a)]?(d=u[s(a)].row).entity={}:(d=new g({},null,e),p.rowTemplateAssigner.call(e,d)),d.entity["$$"+i[n].col.uid]={groupVal:l},d.treeLevel=n,d.groupHeader=!0,d.internalRow=!0,d.enableCellEdit=!1,d.enableSelection=e.options.enableGroupHeaderSelection,i[n].initialised=!0,i[n].currentValue=a,i[n].currentRow=d,f.finaliseProcessingState(i,n+1),t.splice(r,0,d),u=e.grouping.groupingHeaderCache,c=0;c<n;c++)u=u[s(i[c].currentValue)].children;u[s(a)]={row:d,children:{}}},finaliseProcessingState:function(e,t){for(var r=t;r<e.length;r++)e[r].initialised=!1,e[r].currentRow=null,e[r].currentValue=null},getRowExpandedStates:function(e){if(void 0===e)return{};var r={};return angular.forEach(e,function(e,t){r[t]={state:e.row.treeNode.state},e.children?r[t].children=f.getRowExpandedStates(e.children):r[t].children={}}),r},applyRowExpandedStates:function(r,e){void 0!==e&&angular.forEach(e,function(e,t){r[t]&&(r[t].row.treeNode.state=e.state,e.children&&r[t].children&&f.applyRowExpandedStates(r[t].children,e.children))})}};return f}]),e.directive("uiGridGrouping",["uiGridGroupingConstants","uiGridGroupingService",function(e,n){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){!1!==i.grid.options.enableGrouping&&n.initializeGrid(i.grid,e)},post:function(e,t,r,i){}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.importer",["ui.grid"]);e.constant("uiGridImporterConstants",{featureName:"importer"}),e.service("uiGridImporterService",["$q","uiGridConstants","uiGridImporterConstants","gridUtil","$compile","$interval","i18nService","$window",function(e,i,t,n,r,o,a,l){var s={initializeGrid:function(e,t){t.importer={$scope:e},this.defaultGridOptions(t.options);var r={events:{importer:{}},methods:{importer:{importFile:function(e){s.importThisFile(t,e)}}}};t.api.registerEventsFromObject(r.events),t.api.registerMethodsFromObject(r.methods),t.options.enableImporter&&t.options.importerShowMenu&&(t.api.core.addToGridMenu?s.addToMenu(t):o(function(){t.api.core.addToGridMenu&&s.addToMenu(t)},100,1))},defaultGridOptions:function(e){e.enableImporter||void 0===e.enableImporter?l.hasOwnProperty("File")&&l.hasOwnProperty("FileReader")&&l.hasOwnProperty("FileList")&&l.hasOwnProperty("Blob")?e.enableImporter=!0:(n.logError("The File APIs are not fully supported in this browser, grid importer cannot be used."),e.enableImporter=!1):e.enableImporter=!1,e.importerProcessHeaders=e.importerProcessHeaders||s.processHeaders,e.importerHeaderFilter=e.importerHeaderFilter||function(e){return e},e.importerErrorCallback&&"function"==typeof e.importerErrorCallback||delete e.importerErrorCallback,!0!==e.enableImporter||e.importerDataAddCallback||(n.logError("You have not set an importerDataAddCallback, importer is disabled"),e.enableImporter=!1),e.importerShowMenu=!1!==e.importerShowMenu,e.importerObjectCallback=e.importerObjectCallback||function(e,t){return t}},addToMenu:function(e){e.api.core.addToGridMenu(e,[{title:a.getSafeText("gridMenu.importerTitle"),order:150},{templateUrl:"ui-grid/importerMenuItemContainer",action:function(){this.grid.api.importer.importAFile(e)},order:151}])},importThisFile:function(e,t){if(t){var r=new FileReader;switch(t.type){case"application/json":r.onload=s.importJsonClosure(e);break;default:r.onload=s.importCsvClosure(e)}r.readAsText(t)}else n.logError("No file object provided to importThisFile, should be impossible, aborting")},importJsonClosure:function(n){return function(e){var t,r=[],i=s.parseJson(n,e);null!==i&&(i.forEach(function(e){t=s.newObject(n),angular.extend(t,e),t=n.options.importerObjectCallback(n,t),r.push(t)}),s.addObjects(n,r))}},parseJson:function(t,r){var e;try{e=JSON.parse(r.target.result)}catch(e){return void s.alertError(t,"importer.invalidJson","File could not be processed, is it valid json? Content was: ",r.target.result)}return Array.isArray(e)?e:(s.alertError(t,"importer.jsonNotarray","Import failed, file is not an array, file was: ",r.target.result),[])},importCsvClosure:function(i){return function(e){var t=s.parseCsv(e);if(!t||t.length<1)s.alertError(i,"importer.invalidCsv","File could not be processed, is it valid csv? Content was: ",e.target.result);else{var r=s.createCsvObjects(i,t);r&&0!==r.length?s.addObjects(i,r):s.alertError(i,"importer.noObjects","Objects were not able to be derived, content was: ",e.target.result)}}},parseCsv:function(e){var t=e.target.result;return CSV.parse(t)},createCsvObjects:function(t,e){var r=t.options.importerProcessHeaders(t,e.shift());if(!r||0===r.length)return s.alertError(t,"importer.noHeaders","Column names could not be derived, content was: ",e),[];var i,n=[];return e.forEach(function(e){i=s.newObject(t),null!==e&&e.forEach(function(e,t){null!==r[t]&&(i[r[t]]=e)}),i=t.options.importerObjectCallback(t,i),n.push(i)}),n},processHeaders:function(e,t){var r=[];if(e.options.columnDefs&&0!==e.options.columnDefs.length){var i=s.flattenColumnDefs(e,e.options.columnDefs);return t.forEach(function(e){i[e]?r.push(i[e]):i[e.toLowerCase()]?r.push(i[e.toLowerCase()]):r.push(null)}),r}return t.forEach(function(e){r.push(e.replace(/[^0-9a-zA-Z\-_]/g,"_"))}),r},flattenColumnDefs:function(t,e){var r={};return e.forEach(function(e){e.name&&(r[e.name]=e.field||e.name,r[e.name.toLowerCase()]=e.field||e.name),e.field&&(r[e.field]=e.field||e.name,r[e.field.toLowerCase()]=e.field||e.name),e.displayName&&(r[e.displayName]=e.field||e.name,r[e.displayName.toLowerCase()]=e.field||e.name),e.displayName&&t.options.importerHeaderFilter&&(r[t.options.importerHeaderFilter(e.displayName)]=e.field||e.name,r[t.options.importerHeaderFilter(e.displayName).toLowerCase()]=e.field||e.name)}),r},addObjects:function(e,t){if(e.api.rowEdit){var r=e.registerDataChangeCallback(function(){e.api.rowEdit.setRowsDirty(t),r()},[i.dataChange.ROW]);e.importer.$scope.$on("$destroy",r)}e.importer.$scope.$apply(e.options.importerDataAddCallback(e,t))},newObject:function(e){return void 0!==e.options&&void 0!==e.options.importerNewObject?new e.options.importerNewObject:{}},alertError:function(e,t,r,i){e.options.importerErrorCallback?e.options.importerErrorCallback(e,t,r,i):(l.alert(a.getSafeText(t)),n.logError(r+i))}};return s}]),e.directive("uiGridImporter",["uiGridImporterConstants","uiGridImporterService","gridUtil","$compile",function(e,n,t,r){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,link:function(e,t,r,i){n.initializeGrid(e,i.grid)}}}]),e.directive("uiGridImporterMenuItem",["uiGridImporterConstants","uiGridImporterService","gridUtil","$compile",function(e,a,l,t){return{replace:!0,priority:0,require:"?^uiGrid",scope:!1,templateUrl:"ui-grid/importerMenuItem",link:function(e,t,r,i){var n;var o=t[0].querySelectorAll(".ui-grid-importer-file-chooser");1!==o.length?l.logError("Found > 1 or < 1 file choosers within the menu item, error, cannot continue"):o[0].addEventListener("change",function(e){var t=e.srcElement||e.target;if(t&&t.files&&1===t.files.length){var r=t.files[0];void 0!==i&&i?(n=i.grid,a.importThisFile(n,r),t.form.reset()):l.logError("Could not import file because UI Grid was not found.")}},!1)}}}])}(),function(){"use strict";var e=angular.module("ui.grid.infiniteScroll",["ui.grid"]);e.service("uiGridInfiniteScrollService",["gridUtil","$compile","$rootScope","uiGridConstants","ScrollEvent","$q",function(e,t,l,s,a,r){var d={initializeGrid:function(r,e){if(d.defaultGridOptions(r.options),r.options.enableInfiniteScroll){r.infiniteScroll={dataLoading:!1},d.setScrollDirections(r,r.options.infiniteScrollUp,r.options.infiniteScrollDown),r.api.core.on.scrollEnd(e,d.handleScroll);var t={events:{infiniteScroll:{needLoadMoreData:function(e,t){},needLoadMoreDataTop:function(e,t){}}},methods:{infiniteScroll:{dataLoaded:function(e,t){return d.setScrollDirections(r,e,t),d.adjustScroll(r).then(function(){r.infiniteScroll.dataLoading=!1})},resetScroll:function(e,t){d.setScrollDirections(r,e,t),d.adjustInfiniteScrollPosition(r,0)},saveScrollPercentage:function(){r.infiniteScroll.prevScrollTop=r.renderContainers.body.prevScrollTop,r.infiniteScroll.previousVisibleRows=r.getVisibleRowCount()},dataRemovedTop:function(e,t){d.dataRemovedTop(r,e,t)},dataRemovedBottom:function(e,t){d.dataRemovedBottom(r,e,t)},setScrollDirections:function(e,t){d.setScrollDirections(r,e,t)}}}};r.api.registerEventsFromObject(t.events),r.api.registerMethodsFromObject(t.methods)}},defaultGridOptions:function(e){e.enableInfiniteScroll=!1!==e.enableInfiniteScroll,e.infiniteScrollRowsFromEnd=e.infiniteScrollRowsFromEnd||20,e.infiniteScrollUp=!0===e.infiniteScrollUp,e.infiniteScrollDown=!1!==e.infiniteScrollDown},setScrollDirections:function(e,t,r){e.infiniteScroll.scrollUp=!0===t,e.suppressParentScrollUp=!0===t,e.infiniteScroll.scrollDown=!1!==r,e.suppressParentScrollDown=!1!==r},handleScroll:function(e){if(!(e.grid.infiniteScroll&&e.grid.infiniteScroll.dataLoading||"ui.grid.adjustInfiniteScrollPosition"===e.source)&&e.y)if(0===e.y.percentage)e.grid.scrollDirection=s.scrollDirection.UP,d.loadData(e.grid);else if(1===e.y.percentage)e.grid.scrollDirection=s.scrollDirection.DOWN,d.loadData(e.grid);else{var t=e.grid.options.infiniteScrollRowsFromEnd/e.grid.renderContainers.body.visibleRowCache.length;e.grid.scrollDirection===s.scrollDirection.UP?e.y.percentage<=t&&d.loadData(e.grid):e.grid.scrollDirection===s.scrollDirection.DOWN&&1-e.y.percentage<=t&&d.loadData(e.grid)}},loadData:function(e){e.infiniteScroll.previousVisibleRows=e.renderContainers.body.visibleRowCache.length,e.infiniteScroll.direction=e.scrollDirection,delete e.infiniteScroll.prevScrollTop,e.scrollDirection===s.scrollDirection.UP&&e.infiniteScroll.scrollUp?(e.infiniteScroll.dataLoading=!0,e.api.infiniteScroll.raise.needLoadMoreDataTop()):e.scrollDirection===s.scrollDirection.DOWN&&e.infiniteScroll.scrollDown&&(e.infiniteScroll.dataLoading=!0,e.api.infiniteScroll.raise.needLoadMoreData())},adjustScroll:function(o){var a=r.defer();return l.$applyAsync(function(){var e,t,r,i;e=o.getViewportHeight()+o.headerHeight-o.renderContainers.body.headerHeight-o.scrollbarHeight,t=o.options.rowHeight,void 0===o.infiniteScroll.direction&&d.adjustInfiniteScrollPosition(o,0);var n=t*(r=o.getVisibleRowCount());o.infiniteScroll.scrollDown&&n<e&&o.api.infiniteScroll.raise.needLoadMoreData(),o.infiniteScroll.direction===s.scrollDirection.UP&&(i=(o.infiniteScroll.prevScrollTop||0)+(r-o.infiniteScroll.previousVisibleRows)*t,d.adjustInfiniteScrollPosition(o,i),l.$applyAsync(function(){a.resolve()})),o.infiniteScroll.direction===s.scrollDirection.DOWN&&(i=o.infiniteScroll.prevScrollTop||o.infiniteScroll.previousVisibleRows*t-e,d.adjustInfiniteScrollPosition(o,i),l.$applyAsync(function(){a.resolve()}))},0),a.promise},adjustInfiniteScrollPosition:function(e,t){var r=new a(e,null,null,"ui.grid.adjustInfiniteScrollPosition"),i=e.getVisibleRowCount(),n=e.getViewportHeight()+e.headerHeight-e.renderContainers.body.headerHeight-e.scrollbarHeight,o=i*e.options.rowHeight-n;0===t&&e.infiniteScroll.scrollUp?r.y={percentage:1/o}:r.y={percentage:t/o},e.scrollContainers("",r)},dataRemovedTop:function(e,t,r){var i,n,o,a;d.setScrollDirections(e,t,r),i=e.renderContainers.body.visibleRowCache.length,n=e.infiniteScroll.prevScrollTop,a=e.options.rowHeight,o=n-(e.infiniteScroll.previousVisibleRows-i)*a,d.adjustInfiniteScrollPosition(e,o)},dataRemovedBottom:function(e,t,r){var i;d.setScrollDirections(e,t,r),i=e.infiniteScroll.prevScrollTop,d.adjustInfiniteScrollPosition(e,i)}};return d}]),e.directive("uiGridInfiniteScroll",["uiGridInfiniteScrollService",function(n){return{priority:-200,scope:!1,require:"^uiGrid",compile:function(){return{pre:function(e,t,r,i){n.initializeGrid(i.grid,e)},post:function(e,t,r){}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.moveColumns",["ui.grid"]);e.service("uiGridMoveColumnService",["$q","$rootScope","$log","ScrollEvent","uiGridConstants","gridUtil",function(i,d,e,t,u,s){var c={initializeGrid:function(e){this.registerPublicApi(e),this.defaultGridOptions(e.options),e.moveColumns={orderCache:[]},e.registerColumnBuilder(this.movableColumnBuilder),e.registerDataChangeCallback(this.verifyColumnOrder,[u.dataChange.COLUMN])},registerPublicApi:function(a){var l=this,e={events:{colMovable:{columnPositionChanged:function(e,t,r){}}},methods:{colMovable:{moveColumn:function(e,t){var i=a.columns;if(angular.isNumber(e)&&angular.isNumber(t)){for(var r=0,n=0;n<i.length;n++)(angular.isDefined(i[n].colDef.visible)&&!1===i[n].colDef.visible||!0===i[n].isRowHeader)&&r++;if(e>=i.length-r||t>=i.length-r)s.logError("MoveColumn: Invalid values for originalPosition, finalPosition");else{var o=function(e){for(var t=e,r=0;r<=t;r++)angular.isDefined(i[r])&&(angular.isDefined(i[r].colDef.visible)&&!1===i[r].colDef.visible||!0===i[r].isRowHeader)&&t++;return t};l.redrawColumnAtPosition(a,o(e),o(t))}}else s.logError("MoveColumn: Please provide valid values for originalPosition and finalPosition")}}}};a.api.registerEventsFromObject(e.events),a.api.registerMethodsFromObject(e.methods)},defaultGridOptions:function(e){e.enableColumnMoving=!1!==e.enableColumnMoving},movableColumnBuilder:function(e,t,r){return e.enableColumnMoving=void 0===e.enableColumnMoving?r.enableColumnMoving:e.enableColumnMoving,i.all([])},updateColumnCache:function(e){e.moveColumns.orderCache=e.getOnlyDataColumns()},verifyColumnOrder:function(i){var n,o=i.rowHeaderColumns.length;angular.forEach(i.moveColumns.orderCache,function(e,t){if(-1!==(n=i.columns.indexOf(e))&&n-o!==t){var r=i.columns.splice(n,1)[0];i.columns.splice(t+o,0,r)}})},redrawColumnAtPosition:function(e,t,r){var i=e.columns;if(t!==r){for(var n=t<r?t+1:t-1,o=Math.min(n,r);o<=Math.max(n,r)&&!i[o].visible;o++);if(!(o>Math.max(n,r))){var a=i[t];if(a.colDef.enableColumnMoving){if(r<t)for(var l=t;r<l;l--)i[l]=i[l-1];else if(t<r)for(var s=t;s<r;s++)i[s]=i[s+1];i[r]=a,c.updateColumnCache(e),e.queueGridRefresh(),d.$applyAsync(function(){e.api.core.notifyDataChange(u.dataChange.COLUMN),e.api.colMovable.raise.columnPositionChanged(a.colDef,t,r)})}}}}};return c}]),e.directive("uiGridMoveColumns",["uiGridMoveColumnService",function(n){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){n.initializeGrid(i.grid)},post:function(e,t,r,i){}}}}}]),e.directive("uiGridHeaderCell",["$q","gridUtil","uiGridMoveColumnService","$document","$log","uiGridConstants","ScrollEvent",function(e,t,b,y,r,i,S){return{priority:-10,require:"^uiGrid",compile:function(){return{post:function(u,i,e,c){if(u.col.colDef.enableColumnMoving){var g,n,p,f,m,h,t=angular.element(i[0].querySelectorAll(".ui-grid-cell-contents")),d=!1,v=!1,r=function(e){g=u.grid.element[0].getBoundingClientRect().left,u.grid.hasLeftContainer()&&(g+=u.grid.renderContainers.left.header[0].getBoundingClientRect().width),n=e.pageX||(e.originalEvent?e.originalEvent.pageX:0),p=0,f=g+u.grid.getViewportWidth(),"mousedown"===e.type?(y.on("mousemove",o),y.on("mouseup",a)):"touchstart"===e.type&&(y.on("touchmove",o),y.on("touchend",a))},o=function(e){var t=e.pageX||(e.originalEvent?e.originalEvent.pageX:0),r=t-n;0!==r&&(document.onselectstart=function(){return!1},v=!0,d?d&&(s(r),n=t):l())},a=function(e){if(document.onselectstart=null,m&&(m.remove(),d=!1),w(),C(),v){for(var t,r=u.grid.columns,i=0,n=0;n<r.length&&r[n].colDef.name!==u.col.colDef.name;n++)i++;if(p<0){var o,a=0;if(u.grid.isRTL()){for(o=i+1;o<r.length;o++)if((angular.isUndefined(r[o].colDef.visible)||!0===r[o].colDef.visible)&&(a+=r[o].drawnWidth||r[o].width||r[o].colDef.width)>Math.abs(p)){b.redrawColumnAtPosition(u.grid,i,o-1);break}}else for(o=i-1;0<=o;o--)if((angular.isUndefined(r[o].colDef.visible)||!0===r[o].colDef.visible)&&(a+=r[o].drawnWidth||r[o].width||r[o].colDef.width)>Math.abs(p)){b.redrawColumnAtPosition(u.grid,i,o+1);break}a<Math.abs(p)&&(t=0,u.grid.isRTL()&&(t=r.length-1),b.redrawColumnAtPosition(u.grid,i,t))}else if(0<p){var l,s=0;if(u.grid.isRTL()){for(l=i-1;0<l;l--)if((angular.isUndefined(r[l].colDef.visible)||!0===r[l].colDef.visible)&&(s+=r[l].drawnWidth||r[l].width||r[l].colDef.width,p<s)){b.redrawColumnAtPosition(u.grid,i,l);break}}else for(l=i+1;l<r.length;l++)if((angular.isUndefined(r[l].colDef.visible)||!0===r[l].colDef.visible)&&(s+=r[l].drawnWidth||r[l].width||r[l].colDef.width,p<s)){b.redrawColumnAtPosition(u.grid,i,l-1);break}s<p&&(t=r.length-1,u.grid.isRTL()&&(t=0),b.redrawColumnAtPosition(u.grid,i,t))}}},C=function(){t.on("touchstart",r),t.on("mousedown",r)},w=function(){t.off("touchstart",r),t.off("mousedown",r),y.off("mousemove",o),y.off("touchmove",o),y.off("mouseup",a),y.off("touchend",a)};C();var l=function(){d=!0,m=i.clone(),i.parent().append(m),m.addClass("movingColumn");var e={};e.left=i[0].offsetLeft+"px";var t=u.grid.element[0].getBoundingClientRect().right,r=i[0].getBoundingClientRect().right;t<r&&(h=u.col.drawnWidth+(t-r),e.width=h+"px"),m.css(e)},s=function(e){for(var t=u.grid.columns,r=0,i=0;i<t.length;i++)(angular.isUndefined(t[i].colDef.visible)||!0===t[i].colDef.visible)&&(r+=t[i].drawnWidth||t[i].width||t[i].colDef.width);var n,o=m[0].getBoundingClientRect().left-1,a=m[0].getBoundingClientRect().right;if(n=(n=o-g+e)<f?n:f,(g<=o||0<e)&&(a<=f||e<0))m.css({visibility:"visible",left:m[0].offsetLeft+(n<f?e:f-o)+"px"});else if(r>Math.ceil(c.grid.gridWidth)){e*=8;var l=new S(u.col.grid,null,null,"uiGridHeaderCell.moveElement");l.x={pixels:e},l.grid.scrollContainers("",l)}for(var s=0,d=0;d<t.length;d++)if(angular.isUndefined(t[d].colDef.visible)||!0===t[d].colDef.visible){if(t[d].colDef.name===u.col.colDef.name)break;s+=t[d].drawnWidth||t[d].width||t[d].colDef.width}void 0===u.newScrollLeft?p+=e:p=u.newScrollLeft+n-s,h<u.col.drawnWidth&&(h+=Math.abs(e),m.css({width:h+"px"}))};u.$on("$destroy",w)}}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.pagination",["ng","ui.grid"]);e.service("uiGridPaginationService",["gridUtil",function(t){var e={initializeGrid:function(o){e.defaultGridOptions(o.options);var a={events:{pagination:{paginationChanged:function(e,t){}}},methods:{pagination:{getPage:function(){return o.options.enablePagination?o.options.paginationCurrentPage:null},getFirstRowIndex:function(){return o.options.useCustomPagination?o.options.paginationPageSizes.reduce(function(e,t,r){return r<o.options.paginationCurrentPage-1?e+t:e},0):(o.options.paginationCurrentPage-1)*o.options.paginationPageSize},getLastRowIndex:function(){return o.options.useCustomPagination?a.methods.pagination.getFirstRowIndex()+o.options.paginationPageSizes[o.options.paginationCurrentPage-1]-1:Math.min(o.options.paginationCurrentPage*o.options.paginationPageSize,o.options.totalItems)-1},getTotalPages:function(){return o.options.enablePagination?o.options.useCustomPagination?o.options.paginationPageSizes.length:0===o.options.totalItems?1:Math.ceil(o.options.totalItems/o.options.paginationPageSize):null},nextPage:function(){o.options.enablePagination&&(0<o.options.totalItems?o.options.paginationCurrentPage=Math.min(o.options.paginationCurrentPage+1,a.methods.pagination.getTotalPages()):o.options.paginationCurrentPage++)},previousPage:function(){o.options.enablePagination&&(o.options.paginationCurrentPage=Math.max(o.options.paginationCurrentPage-1,1))},seek:function(e){if(o.options.enablePagination){if(!angular.isNumber(e)||e<1)throw"Invalid page number: "+e;o.options.paginationCurrentPage=Math.min(e,a.methods.pagination.getTotalPages())}}}}};o.api.registerEventsFromObject(a.events),o.api.registerMethodsFromObject(a.methods);o.registerRowsProcessor(function(e){if(o.options.useExternalPagination||!o.options.enablePagination)return e;var t=parseInt(o.options.paginationPageSize,10),r=(parseInt(o.options.paginationCurrentPage,10),e.filter(function(e){return e.visible}));o.options.totalItems=r.length;var i=a.methods.pagination.getFirstRowIndex(),n=a.methods.pagination.getLastRowIndex();return i>r.length&&(i=((o.options.paginationCurrentPage=1)-1)*t),r.slice(i,n+1)},900)},defaultGridOptions:function(e){e.enablePagination=!1!==e.enablePagination,e.enablePaginationControls=!1!==e.enablePaginationControls,e.useExternalPagination=!0===e.useExternalPagination,e.useCustomPagination=!0===e.useCustomPagination,t.isNullOrUndefined(e.totalItems)&&(e.totalItems=0),t.isNullOrUndefined(e.paginationPageSizes)&&(e.paginationPageSizes=[250,500,1e3]),t.isNullOrUndefined(e.paginationPageSize)&&(0<e.paginationPageSizes.length?e.paginationPageSize=e.paginationPageSizes[0]:e.paginationPageSize=0),t.isNullOrUndefined(e.paginationCurrentPage)&&(e.paginationCurrentPage=1),t.isNullOrUndefined(e.paginationTemplate)&&(e.paginationTemplate="ui-grid/pagination")},onPaginationChanged:function(e,t,r){e.api.pagination.raise.paginationChanged(t,r),e.options.useExternalPagination||e.queueGridRefresh()}};return e}]),e.directive("uiGridPagination",["gridUtil","uiGridPaginationService",function(n,o){return{priority:-200,scope:!1,require:"uiGrid",link:{pre:function(e,r,t,i){o.initializeGrid(i.grid),n.getTemplate(i.grid.options.paginationTemplate).then(function(e){var t=angular.element(e);r.append(t),i.innerCompile(t)})}}}}]),e.directive("uiGridPager",["uiGridPaginationService","uiGridConstants","gridUtil","i18nService","i18nConstants",function(d,u,c,g,p){return{priority:-200,scope:!0,require:"^uiGrid",link:function(r,t,e,i){r.aria=g.getSafeText("pagination.aria");var n=function(){r.paginationApi=i.grid.api.pagination,r.sizesLabel=g.getSafeText("pagination.sizes"),r.totalItemsLabel=g.getSafeText("pagination.totalItems"),r.paginationOf=g.getSafeText("pagination.of"),r.paginationThrough=g.getSafeText("pagination.through")};n(),r.$on(p.UPDATE_EVENT,n);var o=i.grid.options;i.grid.renderContainers.body.registerViewportAdjuster(function(e){return o.enablePaginationControls&&(e.height=e.height-c.elementHeight(t,"padding")),e});var a=i.grid.registerDataChangeCallback(function(e){e.options.useExternalPagination||(e.options.totalItems=e.rows.length)},[u.dataChange.ROW]);r.$on("$destroy",a);var l=r.$watch("grid.options.paginationCurrentPage + grid.options.paginationPageSize",function(e,t){e!==t&&void 0!==t&&(!angular.isNumber(o.paginationCurrentPage)||o.paginationCurrentPage<1?o.paginationCurrentPage=1:0<o.totalItems&&o.paginationCurrentPage>r.paginationApi.getTotalPages()?o.paginationCurrentPage=r.paginationApi.getTotalPages():d.onPaginationChanged(r.grid,o.paginationCurrentPage,o.paginationPageSize))});r.$on("$destroy",function(){l()}),r.cantPageForward=function(){return r.paginationApi.getTotalPages()?r.cantPageToLast():o.data.length<1},r.cantPageToLast=function(){var e=r.paginationApi.getTotalPages();return!e||o.paginationCurrentPage>=e},r.cantPageBackward=function(){return o.paginationCurrentPage<=1};var s=function(e){e&&c.focus.bySelector(t,".ui-grid-pager-control-input")};r.pageFirstPageClick=function(){r.paginationApi.seek(1),s(r.cantPageBackward())},r.pagePreviousPageClick=function(){r.paginationApi.previousPage(),s(r.cantPageBackward())},r.pageNextPageClick=function(){r.paginationApi.nextPage(),s(r.cantPageForward())},r.pageLastPageClick=function(){r.paginationApi.seek(r.paginationApi.getTotalPages()),s(r.cantPageToLast())}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.pinning",["ui.grid"]);e.constant("uiGridPinningConstants",{container:{LEFT:"left",RIGHT:"right",NONE:""}}),e.service("uiGridPinningService",["gridUtil","GridRenderContainer","i18nService","uiGridPinningConstants",function(a,e,l,s){var d={initializeGrid:function(r){d.defaultGridOptions(r.options),r.registerColumnBuilder(d.pinningColumnBuilder);var e={events:{pinning:{columnPinned:function(e,t){}}},methods:{pinning:{pinColumn:function(e,t){d.pinColumn(r,e,t)}}}};r.api.registerEventsFromObject(e.events),r.api.registerMethodsFromObject(e.methods)},defaultGridOptions:function(e){e.enablePinning=!1!==e.enablePinning,e.hidePinLeft=e.enablePinning&&e.hidePinLeft,e.hidePinRight=e.enablePinning&&e.hidePinRight},pinningColumnBuilder:function(e,t,r){if(e.enablePinning=void 0===e.enablePinning?r.enablePinning:e.enablePinning,e.hidePinLeft=void 0===e.hidePinLeft?r.hidePinLeft:e.hidePinLeft,e.hidePinRight=void 0===e.hidePinRight?r.hidePinRight:e.hidePinRight,e.pinnedLeft?(t.renderContainer="left",t.grid.createLeftContainer()):e.pinnedRight&&(t.renderContainer="right",t.grid.createRightContainer()),e.enablePinning){var i={name:"ui.grid.pinning.pinLeft",title:l.get().pinning.pinLeft,icon:"ui-grid-icon-left-open",shown:function(){return void 0===this.context.col.renderContainer||!this.context.col.renderContainer||"left"!==this.context.col.renderContainer},action:function(){d.pinColumn(this.context.col.grid,this.context.col,s.container.LEFT)}},n={name:"ui.grid.pinning.pinRight",title:l.get().pinning.pinRight,icon:"ui-grid-icon-right-open",shown:function(){return void 0===this.context.col.renderContainer||!this.context.col.renderContainer||"right"!==this.context.col.renderContainer},action:function(){d.pinColumn(this.context.col.grid,this.context.col,s.container.RIGHT)}},o={name:"ui.grid.pinning.unpin",title:l.get().pinning.unpin,icon:"ui-grid-icon-cancel",shown:function(){return void 0!==this.context.col.renderContainer&&null!==this.context.col.renderContainer&&"body"!==this.context.col.renderContainer},action:function(){d.pinColumn(this.context.col.grid,this.context.col,s.container.NONE)}};e.hidePinLeft||a.arrayContainsObjectWithProperty(t.menuItems,"name","ui.grid.pinning.pinLeft")||t.menuItems.push(i),e.hidePinRight||a.arrayContainsObjectWithProperty(t.menuItems,"name","ui.grid.pinning.pinRight")||t.menuItems.push(n),a.arrayContainsObjectWithProperty(t.menuItems,"name","ui.grid.pinning.unpin")||t.menuItems.push(o)}},pinColumn:function(e,t,r){r===s.container.NONE?(t.renderContainer=null,t.colDef.pinnedLeft=t.colDef.pinnedRight=!1):(t.renderContainer=r)===s.container.LEFT?e.createLeftContainer():r===s.container.RIGHT&&e.createRightContainer(),e.refresh().then(function(){e.api.pinning.raise.columnPinned(t.colDef,r)})}};return d}]),e.directive("uiGridPinning",["gridUtil","uiGridPinningService",function(e,n){return{require:"uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){n.initializeGrid(i.grid)},post:function(e,t,r,i){}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.resizeColumns",["ui.grid"]);e.service("uiGridResizeColumnsService",["gridUtil","$q","$rootScope",function(i,n,o){return{defaultGridOptions:function(e){e.enableColumnResizing=!1!==e.enableColumnResizing,!1===e.enableColumnResize&&(e.enableColumnResizing=!1)},colResizerColumnBuilder:function(e,t,r){return e.enableColumnResizing=void 0===e.enableColumnResizing?r.enableColumnResizing:e.enableColumnResizing,!1===e.enableColumnResize&&(e.enableColumnResizing=!1),n.all([])},registerPublicApi:function(e){e.api.registerEventsFromObject({colResizable:{columnSizeChanged:function(e,t){}}})},fireColumnSizeChanged:function(e,t,r){o.$applyAsync(function(){e.api.colResizable?e.api.colResizable.raise.columnSizeChanged(t,r):i.logError("The resizeable api is not registered, this may indicate that you've included the module but not added the 'ui-grid-resize-columns' directive to your grid definition. Cannot raise any events.")})},findTargetCol:function(e,t,r){var i=e.getRenderContainer();if("left"===t){var n=i.visibleColumnCache.indexOf(e);return i.visibleColumnCache[n-1*r]}return e}}}]),e.directive("uiGridResizeColumns",["gridUtil","uiGridResizeColumnsService",function(e,n){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){n.defaultGridOptions(i.grid.options),i.grid.registerColumnBuilder(n.colResizerColumnBuilder),n.registerPublicApi(i.grid)},post:function(e,t,r,i){}}}}}]),e.directive("uiGridHeaderCell",["gridUtil","$templateCache","$compile","$q","uiGridResizeColumnsService","uiGridConstants",function(e,o,u,t,c,g){return{priority:-10,require:"^uiGrid",compile:function(){return{post:function(a,l,e,t){var r=t.grid;if(r.options.enableColumnResizing){var s=o.get("ui-grid/columnResizer"),d=1;r.isRTL()&&(a.position="left",d=-1);var i=function(){for(var e=l[0].getElementsByClassName("ui-grid-column-resizer"),t=0;t<e.length;t++)angular.element(e[t]).remove();var r=c.findTargetCol(a.col,"left",d),i=a.col.getRenderContainer();if(r&&0!==i.visibleColumnCache.indexOf(a.col)&&!1!==r.colDef.enableColumnResizing){var n=angular.element(s).clone();n.attr("position","left"),l.prepend(n),u(n)(a)}if(!1!==a.col.colDef.enableColumnResizing){var o=angular.element(s).clone();o.attr("position","right"),l.append(o),u(o)(a)}};i();var n=r.registerDataChangeCallback(function(){a.$applyAsync(i)},[g.dataChange.COLUMN]);a.$on("$destroy",n)}}}}}}]),e.directive("uiGridColumnResizer",["$document","gridUtil","uiGridConstants","uiGridResizeColumnsService",function(h,v,C,w){var b=angular.element('<div class="ui-grid-resize-overlay"></div>');return{priority:0,scope:{col:"=",position:"@",renderIndex:"="},require:"?^uiGrid",link:function(l,s,e,d){var o=0,a=0,u=0,c=1;function g(e){d.grid.refreshCanvas(!0).then(function(){d.grid.queueGridRefresh()})}function p(e,t){var r=t;return e.minWidth&&r<e.minWidth?r=e.minWidth:e.maxWidth&&r>e.maxWidth&&(r=e.maxWidth),r}function r(e,t){e.originalEvent&&(e=e.originalEvent),e.preventDefault(),(a=(e.targetTouches?e.targetTouches[0]:e).clientX-u)<0?a=0:a>d.grid.gridWidth&&(a=d.grid.gridWidth);var r=w.findTargetCol(l.col,l.position,c);if(!1!==r.colDef.enableColumnResizing){d.grid.element.hasClass("column-resizing")||d.grid.element.addClass("column-resizing");var i=a-o,n=parseInt(r.drawnWidth+i*c,10);a+=(p(r,n)-n)*c,b.css({left:a+"px"}),d.fireEvent(C.events.ITEM_DRAGGING)}}function i(e){e.originalEvent&&(e=e.originalEvent),e.preventDefault(),d.grid.element.removeClass("column-resizing"),b.remove();var t=(a=(e.changedTouches?e.changedTouches[0]:e).clientX-u)-o;if(0===t)return m(),void f();var r=w.findTargetCol(l.col,l.position,c);if(!1!==r.colDef.enableColumnResizing){var i=parseInt(r.drawnWidth+t*c,10);r.width=p(r,i),r.hasCustomWidth=!0,g(),w.fireColumnSizeChanged(d.grid,r.colDef,t),m(),f()}}d.grid.isRTL()&&(l.position="left",c=-1),"left"===l.position?s.addClass("left"):"right"===l.position&&s.addClass("right");var n=function(e,t){e.originalEvent&&(e=e.originalEvent),e.stopPropagation(),u=d.grid.element[0].getBoundingClientRect().left,o=(e.targetTouches?e.targetTouches[0]:e).clientX-u,d.grid.element.append(b),b.css({left:o}),"touchstart"===e.type?(h.on("touchend",i),h.on("touchmove",r),s.off("mousedown",n)):(h.on("mouseup",i),h.on("mousemove",r),s.off("touchstart",n))},f=function(){s.on("mousedown",n),s.on("touchstart",n)},m=function(){h.off("mouseup",i),h.off("touchend",i),h.off("mousemove",r),h.off("touchmove",r),s.off("mousedown",n),s.off("touchstart",n)};f();var t=function(e,t){e.stopPropagation();var r=w.findTargetCol(l.col,l.position,c);if(!1!==r.colDef.enableColumnResizing){var n=0,i=v.closestElm(s,".ui-grid-render-container").querySelectorAll("."+C.COL_CLASS_PREFIX+r.uid+" .ui-grid-cell-contents");Array.prototype.forEach.call(i,function(e){var i;angular.element(e).parent().hasClass("ui-grid-header-cell")&&(i=angular.element(e).parent()[0].querySelectorAll(".ui-grid-column-menu-button")),v.fakeElement(e,{},function(e){var t=angular.element(e);t.attr("style","float: left");var r=v.elementWidth(t);i&&(r+=v.elementWidth(i));n<r&&(n=r)})});var o=p(r,n),a=o-r.drawnWidth;r.width=o,r.hasCustomWidth=!0,g(),w.fireColumnSizeChanged(d.grid,r.colDef,a)}};s.on("dblclick",t),s.on("$destroy",function(){s.off("dblclick",t),m()})}}}])}(),function(){"use strict";var e=angular.module("ui.grid.rowEdit",["ui.grid","ui.grid.edit","ui.grid.cellNav"]);e.constant("uiGridRowEditConstants",{}),e.service("uiGridRowEditService",["$interval","$q","uiGridConstants","uiGridRowEditConstants","gridUtil",function(i,e,t,r,a){var l={initializeGrid:function(t,r){r.rowEdit={};var e={events:{rowEdit:{saveRow:function(e){}}},methods:{rowEdit:{setSavePromise:function(e,t){l.setSavePromise(r,e,t)},getDirtyRows:function(){return r.rowEdit.dirtyRows?r.rowEdit.dirtyRows:[]},getErrorRows:function(){return r.rowEdit.errorRows?r.rowEdit.errorRows:[]},flushDirtyRows:function(){return l.flushDirtyRows(r)},setRowsDirty:function(e){l.setRowsDirty(r,e)},setRowsClean:function(e){l.setRowsClean(r,e)}}}};r.api.registerEventsFromObject(e.events),r.api.registerMethodsFromObject(e.methods),r.api.core.on.renderingComplete(t,function(e){r.api.edit.on.afterCellEdit(t,l.endEditCell),r.api.edit.on.beginCellEdit(t,l.beginEditCell),r.api.edit.on.cancelCellEdit(t,l.cancelEditCell),r.api.cellNav&&r.api.cellNav.on.navigate(t,l.navigate)})},defaultGridOptions:function(e){},saveRow:function(t,r){var i=this;return function(){if(r.isSaving=!0,r.rowEditSavePromise)return r.rowEditSavePromise;var e=t.api.rowEdit.raise.saveRow(r.entity);return r.rowEditSavePromise?r.rowEditSavePromise.then(i.processSuccessPromise(t,r),i.processErrorPromise(t,r)):a.logError("A promise was not returned when saveRow event was raised, either nobody is listening to event, or event handler did not return a promise"),e}},setSavePromise:function(e,t,r){e.getRow(t).rowEditSavePromise=r},processSuccessPromise:function(e,t){var r=this;return function(){delete t.isSaving,delete t.isDirty,delete t.isError,delete t.rowEditSaveTimer,delete t.rowEditSavePromise,r.removeRow(e.rowEdit.errorRows,t),r.removeRow(e.rowEdit.dirtyRows,t)}},processErrorPromise:function(e,t){return function(){delete t.isSaving,delete t.rowEditSaveTimer,delete t.rowEditSavePromise,t.isError=!0,e.rowEdit.errorRows||(e.rowEdit.errorRows=[]),l.isRowPresent(e.rowEdit.errorRows,t)||e.rowEdit.errorRows.push(t)}},removeRow:function(r,i){null!=r&&r.forEach(function(e,t){e.uid===i.uid&&r.splice(t,1)})},isRowPresent:function(e,r){var i=!1;return e.forEach(function(e,t){e.uid===r.uid&&(i=!0)}),i},flushDirtyRows:function(t){var r=[];return t.api.rowEdit.getDirtyRows().forEach(function(e){l.cancelTimer(t,e),l.saveRow(t,e)(),r.push(e.rowEditSavePromise)}),e.all(r)},endEditCell:function(e,t,r,i){var n=this.grid,o=n.getRow(e);o?(r!==i||o.isDirty)&&(n.rowEdit.dirtyRows||(n.rowEdit.dirtyRows=[]),o.isDirty||(o.isDirty=!0,n.rowEdit.dirtyRows.push(o)),delete o.isError,l.considerSetTimer(n,o)):a.logError("Unable to find rowEntity in grid data, dirty flag cannot be set")},beginEditCell:function(e,t){var r=this.grid,i=r.getRow(e);i?l.cancelTimer(r,i):a.logError("Unable to find rowEntity in grid data, timer cannot be cancelled")},cancelEditCell:function(e,t){var r=this.grid,i=r.getRow(e);i?l.considerSetTimer(r,i):a.logError("Unable to find rowEntity in grid data, timer cannot be set")},navigate:function(e,t){var r=this.grid;e.row.rowEditSaveTimer&&l.cancelTimer(r,e.row),t&&t.row&&t.row!==e.row&&l.considerSetTimer(r,t.row)},considerSetTimer:function(e,t){if(l.cancelTimer(e,t),t.isDirty&&!t.isSaving&&-1!==e.options.rowEditWaitInterval){var r=e.options.rowEditWaitInterval?e.options.rowEditWaitInterval:2e3;t.rowEditSaveTimer=i(l.saveRow(e,t),r,1)}},cancelTimer:function(e,t){t.rowEditSaveTimer&&!t.isSaving&&(i.cancel(t.rowEditSaveTimer),delete t.rowEditSaveTimer)},setRowsDirty:function(r,e){var i;e.forEach(function(e,t){(i=r.getRow(e))?(r.rowEdit.dirtyRows||(r.rowEdit.dirtyRows=[]),i.isDirty||(i.isDirty=!0,r.rowEdit.dirtyRows.push(i)),delete i.isError,l.considerSetTimer(r,i)):a.logError("requested row not found in rowEdit.setRowsDirty, row was: "+e)})},setRowsClean:function(r,e){var i;e.forEach(function(e,t){(i=r.getRow(e))?(delete i.isDirty,l.removeRow(r.rowEdit.dirtyRows,i),l.cancelTimer(r,i),delete i.isError,l.removeRow(r.rowEdit.errorRows,i)):a.logError("requested row not found in rowEdit.setRowsClean, row was: "+e)})}};return l}]),e.directive("uiGridRowEdit",["gridUtil","uiGridRowEditService","uiGridEditConstants",function(e,n,t){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){n.initializeGrid(e,i.grid)},post:function(e,t,r,i){}}}}}]),e.directive("uiGridViewport",["$compile","uiGridConstants","gridUtil","$parse",function(e,t,r,i){return{priority:-200,scope:!1,compile:function(e,t){var r=angular.element(e.children().children()[0]),i=r.attr("ng-class"),n="";return n=i?i.slice(0,-1)+", 'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}":"{'ui-grid-row-dirty': row.isDirty, 'ui-grid-row-saving': row.isSaving, 'ui-grid-row-error': row.isError}",r.attr("ng-class",n),{pre:function(e,t,r,i){},post:function(e,t,r,i){}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.saveState",["ui.grid","ui.grid.selection","ui.grid.cellNav","ui.grid.grouping","ui.grid.pinning","ui.grid.treeView"]);e.constant("uiGridSaveStateConstants",{featureName:"saveState"}),e.service("uiGridSaveStateService",function(){var l={initializeGrid:function(r){r.saveState={},this.defaultGridOptions(r.options);var e={events:{saveState:{}},methods:{saveState:{save:function(){return l.save(r)},restore:function(e,t){return l.restore(r,e,t)}}}};r.api.registerEventsFromObject(e.events),r.api.registerMethodsFromObject(e.methods)},defaultGridOptions:function(e){e.saveWidths=!1!==e.saveWidths,e.saveOrder=!1!==e.saveOrder,e.saveScroll=!0===e.saveScroll,e.saveFocus=!0!==e.saveScroll&&!1!==e.saveFocus,e.saveVisible=!1!==e.saveVisible,e.saveSort=!1!==e.saveSort,e.saveFilter=!1!==e.saveFilter,e.saveSelection=!1!==e.saveSelection,e.saveGrouping=!1!==e.saveGrouping,e.saveGroupingExpandedStates=!0===e.saveGroupingExpandedStates,e.savePinning=!1!==e.savePinning,e.saveTreeView=!1!==e.saveTreeView},save:function(e){var t={};return t.columns=l.saveColumns(e),t.scrollFocus=l.saveScrollFocus(e),t.selection=l.saveSelection(e),t.grouping=l.saveGrouping(e),t.treeView=l.saveTreeView(e),t.pagination=l.savePagination(e),t},restore:function(e,t,r){return r.columns&&l.restoreColumns(e,r.columns),r.scrollFocus&&l.restoreScrollFocus(e,t,r.scrollFocus),r.selection&&l.restoreSelection(e,r.selection),r.grouping&&l.restoreGrouping(e,r.grouping),r.treeView&&l.restoreTreeView(e,r.treeView),r.pagination&&l.restorePagination(e,r.pagination),e.refresh()},saveColumns:function(r){var i=[];return r.getOnlyDataColumns().forEach(function(e){var t={};t.name=e.name,r.options.saveVisible&&(t.visible=e.visible),r.options.saveWidths&&(t.width=e.width),r.options.saveSort&&(t.sort=angular.copy(e.sort)),r.options.saveFilter&&(t.filters=[],e.filters.forEach(function(e){var r={};angular.forEach(e,function(e,t){"condition"!==t&&"$$hashKey"!==t&&"placeholder"!==t&&(r[t]=e)}),t.filters.push(r)})),r.api.pinning&&r.options.savePinning&&(t.pinned=e.renderContainer?e.renderContainer:""),i.push(t)}),i},saveScrollFocus:function(e){if(!e.api.cellNav)return{};var t={};if(e.options.saveFocus){t.focus=!0;var r=e.api.cellNav.getFocusedCell();null!==r&&(null!==r.col&&(t.colName=r.col.colDef.name),null!==r.row&&(t.rowVal=l.getRowVal(e,r.row)))}return(e.options.saveScroll||e.options.saveFocus&&!t.colName&&!t.rowVal)&&(t.focus=!1,e.renderContainers.body.prevRowScrollIndex&&(t.rowVal=l.getRowVal(e,e.renderContainers.body.visibleRowCache[e.renderContainers.body.prevRowScrollIndex])),e.renderContainers.body.prevColScrollIndex&&(t.colName=e.renderContainers.body.visibleColumnCache[e.renderContainers.body.prevColScrollIndex].name)),t},saveSelection:function(t){return t.api.selection&&t.options.saveSelection?t.api.selection.getSelectedGridRows().map(function(e){return l.getRowVal(t,e)}):[]},saveGrouping:function(e){return e.api.grouping&&e.options.saveGrouping?e.api.grouping.getGrouping(e.options.saveGroupingExpandedStates):{}},savePagination:function(e){return e.api.pagination&&e.options.paginationPageSize?{paginationCurrentPage:e.options.paginationCurrentPage,paginationPageSize:e.options.paginationPageSize}:{}},saveTreeView:function(e){return e.api.treeView&&e.options.saveTreeView?e.api.treeView.getTreeView():{}},getRowVal:function(e,t){if(!t)return null;var r={};return e.options.saveRowIdentity?(r.identity=!0,r.row=e.options.saveRowIdentity(t.entity)):(r.identity=!1,r.row=e.renderContainers.body.visibleRowCache.indexOf(t)),r},restoreColumns:function(o,e){var a=!1;e.forEach(function(e,t){var r=o.getColumn(e.name);if(r&&!o.isRowHeaderColumn(r)){!o.options.saveVisible||r.visible===e.visible&&r.colDef.visible===e.visible||(r.visible=e.visible,r.colDef.visible=e.visible,o.api.core.raise.columnVisibilityChanged(r)),o.options.saveWidths&&r.width!==e.width&&(r.width=e.width,r.hasCustomWidth=!0),!o.options.saveSort||angular.equals(r.sort,e.sort)||void 0===r.sort&&angular.isEmpty(e.sort)||(r.sort=angular.copy(e.sort),a=!0),o.options.saveFilter&&!angular.equals(r.filters,e.filters)&&(e.filters.forEach(function(e,t){angular.extend(r.filters[t],e),void 0!==e.term&&null!==e.term||delete r.filters[t].term}),o.api.core.raise.filterChanged()),o.api.pinning&&o.options.savePinning&&r.renderContainer!==e.pinned&&o.api.pinning.pinColumn(r,e.pinned);var i=o.getOnlyDataColumns().indexOf(r);if(-1!==i&&o.options.saveOrder&&i!==t){var n=o.columns.splice(i+o.rowHeaderColumns.length,1)[0];o.columns.splice(t+o.rowHeaderColumns.length,0,n)}}}),a&&o.api.core.raise.sortChanged(o,o.getColumnSorting())},restoreScrollFocus:function(e,t,r){if(e.api.cellNav){var i,n;if(r.colName){var o=e.options.columnDefs.filter(function(e){return e.name===r.colName});0<o.length&&(i=o[0])}r.rowVal&&r.rowVal.row&&(n=r.rowVal.identity?l.findRowByIdentity(e,r.rowVal):e.renderContainers.body.visibleRowCache[r.rowVal.row]);var a=n&&n.entity?n.entity:null;(i||a)&&(r.focus?e.api.cellNav.scrollToFocus(a,i):e.scrollTo(a,i))}},restoreSelection:function(r,e){r.api.selection&&(r.api.selection.clearSelectedRows(),e.forEach(function(e){if(e.identity){var t=l.findRowByIdentity(r,e);t&&r.api.selection.selectRow(t.entity)}else r.api.selection.selectRowByVisibleIndex(e.row)}))},restoreGrouping:function(e,t){e.api.grouping&&null!=t&&!angular.equals(t,{})&&e.api.grouping.setGrouping(t)},restoreTreeView:function(e,t){e.api.treeView&&null!=t&&!angular.equals(t,{})&&e.api.treeView.setTreeView(t)},restorePagination:function(e,t){e.api.pagination&&e.options.paginationPageSize&&(e.options.paginationCurrentPage=t.paginationCurrentPage,e.options.paginationPageSize=t.paginationPageSize)},findRowByIdentity:function(t,r){if(!t.options.saveRowIdentity)return null;var e=t.rows.filter(function(e){return t.options.saveRowIdentity(e.entity)===r.row});return 0<e.length?e[0]:null}};return l}),e.directive("uiGridSaveState",["uiGridSaveStateConstants","uiGridSaveStateService","gridUtil","$compile",function(e,n,t,r){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,link:function(e,t,r,i){n.initializeGrid(i.grid)}}}])}(),function(){"use strict";var e=angular.module("ui.grid.selection",["ui.grid"]);e.constant("uiGridSelectionConstants",{featureName:"selection",selectionRowHeaderColName:"selectionRowHeaderCol"}),angular.module("ui.grid").config(["$provide",function(e){e.decorator("GridRow",["$delegate",function(e){return e.prototype.setSelected=function(e){e!==this.isSelected&&(this.isSelected=e,this.grid.selection.selectedCount+=e?1:-1)},e.prototype.setFocused=function(e){e!==this.isFocused&&(this.grid.selection.focusedRow&&(this.grid.selection.focusedRow.isFocused=!1),this.grid.selection.focusedRow=e?this:null,this.isFocused=e)},e}])}]),e.service("uiGridSelectionService",function(){var u={initializeGrid:function(i){i.selection={lastSelectedRow:null,focusedRow:null,selectAll:!1},i.selection.selectedCount=0,u.defaultGridOptions(i.options);var e={events:{selection:{rowFocusChanged:function(e,t,r){},rowSelectionChanged:function(e,t,r){},rowSelectionChangedBatch:function(e,t,r){}}},methods:{selection:{toggleRowSelection:function(e,t){var r=i.getRow(e);null!==r&&u.toggleRowSelection(i,r,t,i.options.multiSelect,i.options.noUnselect)},selectRow:function(e,t){var r=i.getRow(e);null===r||r.isSelected||u.toggleRowSelection(i,r,t,i.options.multiSelect,i.options.noUnselect)},selectRowByVisibleIndex:function(e,t){var r=i.renderContainers.body.visibleRowCache[e];null==r||r.isSelected||u.toggleRowSelection(i,r,t,i.options.multiSelect,i.options.noUnselect)},unSelectRow:function(e,t){var r=i.getRow(e);null!==r&&r.isSelected&&u.toggleRowSelection(i,r,t,i.options.multiSelect,i.options.noUnselect)},unSelectRowByVisibleIndex:function(e,t){var r=i.renderContainers.body.visibleRowCache[e];null!=r&&r.isSelected&&u.toggleRowSelection(i,r,t,i.options.multiSelect,i.options.noUnselect)},selectAllRows:function(t){if(!1!==i.options.multiSelect){var r=[];i.rows.forEach(function(e){e.isSelected||!1===e.enableSelection||!1===i.options.isRowSelectable(e)||(e.setSelected(!0),u.decideRaiseSelectionEvent(i,e,r,t))}),i.selection.selectAll=!0,u.decideRaiseSelectionBatchEvent(i,r,t)}},selectAllVisibleRows:function(t){if(!1!==i.options.multiSelect){var r=[];i.rows.forEach(function(e){e.visible?e.isSelected||!1===e.enableSelection||!1===i.options.isRowSelectable(e)||(e.setSelected(!0),u.decideRaiseSelectionEvent(i,e,r,t)):e.isSelected&&(e.setSelected(!1),u.decideRaiseSelectionEvent(i,e,r,t))}),i.selection.selectAll=!0,u.decideRaiseSelectionBatchEvent(i,r,t)}},clearSelectedRows:function(e){u.clearSelectedRows(i,e)},getSelectedRows:function(){return u.getSelectedRows(i).map(function(e){return e.entity}).filter(function(e){return e.hasOwnProperty("$$hashKey")||!angular.isObject(e)})},getSelectedGridRows:function(){return u.getSelectedRows(i)},getSelectedCount:function(){return i.selection.selectedCount},setMultiSelect:function(e){i.options.multiSelect=e},setModifierKeysToMultiSelect:function(e){i.options.modifierKeysToMultiSelect=e},getSelectAllState:function(){return i.selection.selectAll}}}};i.api.registerEventsFromObject(e.events),i.api.registerMethodsFromObject(e.methods)},defaultGridOptions:function(e){e.enableRowSelection=!1!==e.enableRowSelection,e.multiSelect=!1!==e.multiSelect,e.noUnselect=!0===e.noUnselect,e.modifierKeysToMultiSelect=!0===e.modifierKeysToMultiSelect,e.enableRowHeaderSelection=!1!==e.enableRowHeaderSelection,void 0===e.enableFullRowSelection&&(e.enableFullRowSelection=!e.enableRowHeaderSelection),e.enableFocusRowOnRowHeaderClick=!1!==e.enableFocusRowOnRowHeaderClick||!e.enableRowHeaderSelection,e.enableSelectRowOnFocus=!1!==e.enableSelectRowOnFocus,e.enableSelectAll=!1!==e.enableSelectAll,e.enableSelectionBatchEvent=!1!==e.enableSelectionBatchEvent,e.selectionRowHeaderWidth=angular.isDefined(e.selectionRowHeaderWidth)?e.selectionRowHeaderWidth:30,e.enableFooterTotalSelected=!1!==e.enableFooterTotalSelected,e.isRowSelectable=angular.isDefined(e.isRowSelectable)?e.isRowSelectable:angular.noop},toggleRowSelection:function(e,t,r,i,n){if(!1!==t.enableSelection){var o,a=t.isSelected;i||(a?1<(o=u.getSelectedRows(e)).length&&(a=!1,u.clearSelectedRows(e,r)):u.clearSelectedRows(e,r)),a&&n||(t.setSelected(!a),!0===t.isSelected&&(e.selection.lastSelectedRow=t),o=u.getSelectedRows(e),e.selection.selectAll=e.rows.length===o.length,e.api.selection.raise.rowSelectionChanged(t,r))}},shiftSelect:function(e,t,r,i){if(i){var n=0<u.getSelectedRows(e).length?e.renderContainers.body.visibleRowCache.indexOf(e.selection.lastSelectedRow):0,o=e.renderContainers.body.visibleRowCache.indexOf(t);if(o<n){var a=n;n=o,o=a}for(var l=[],s=n;s<=o;s++){var d=e.renderContainers.body.visibleRowCache[s];d&&(d.isSelected||!1===d.enableSelection||(d.setSelected(!0),e.selection.lastSelectedRow=d,u.decideRaiseSelectionEvent(e,d,l,r)))}u.decideRaiseSelectionBatchEvent(e,l,r)}},getSelectedRows:function(e){return e.rows.filter(function(e){return e.isSelected})},clearSelectedRows:function(t,r){var i=[];u.getSelectedRows(t).forEach(function(e){e.isSelected&&(e.setSelected(!1),u.decideRaiseSelectionEvent(t,e,i,r))}),t.selection.selectAll=!1,t.selection.selectedCount=0,u.decideRaiseSelectionBatchEvent(t,i,r)},decideRaiseSelectionEvent:function(e,t,r,i){e.options.enableSelectionBatchEvent?r.push(t):e.api.selection.raise.rowSelectionChanged(t,i)},decideRaiseSelectionBatchEvent:function(e,t,r){0<t.length&&e.api.selection.raise.rowSelectionChangedBatch(t,r)}};return u}),e.directive("uiGridSelection",["uiGridSelectionConstants","uiGridSelectionService","uiGridConstants",function(d,u,c){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){if(u.initializeGrid(i.grid),i.grid.options.enableRowHeaderSelection){var n={name:d.selectionRowHeaderColName,displayName:"",width:i.grid.options.selectionRowHeaderWidth,minWidth:10,cellTemplate:"ui-grid/selectionRowHeader",headerCellTemplate:"ui-grid/selectionHeaderCell",enableColumnResizing:!1,enableColumnMenu:!1,exporterSuppressExport:!0,allowCellFocus:!0};i.grid.addRowHeaderColumn(n,0)}var o=!1,a=function(e){return e.forEach(function(e){e.enableSelection=i.grid.options.isRowSelectable(e)}),e},l=function(){i.grid.options.isRowSelectable!==angular.noop&&!0!==o&&(i.grid.registerRowsProcessor(a,500),o=!0)};l();var s=i.grid.registerDataChangeCallback(l,[c.dataChange.OPTIONS]);e.$on("$destroy",s)},post:function(e,t,r,i){}}}}}]),e.directive("uiGridSelectionRowHeaderButtons",["$templateCache","uiGridSelectionService","gridUtil",function(e,a,l){return{replace:!0,restrict:"E",template:e.get("ui-grid/selectionRowHeaderButtons"),scope:!0,require:"^uiGrid",link:function(e,t,r,i){var n=i.grid;function o(e,t){if(t.stopPropagation(),t.shiftKey)a.shiftSelect(n,e,t,n.options.multiSelect);else if(t.ctrlKey||t.metaKey)a.toggleRowSelection(n,e,t,n.options.multiSelect,n.options.noUnselect);else if(e.groupHeader){a.toggleRowSelection(n,e,t,n.options.multiSelect,n.options.noUnselect);for(var r=0;r<e.treeNode.children.length;r++)a.toggleRowSelection(n,e.treeNode.children[r].row,t,n.options.multiSelect,n.options.noUnselect)}else a.toggleRowSelection(n,e,t,n.options.multiSelect&&!n.options.modifierKeysToMultiSelect,n.options.noUnselect);n.options.enableFocusRowOnRowHeaderClick&&e.setFocused(!e.isFocused)&&n.api.selection.raise.rowFocusChanged(e,t)}e.selectButtonClick=o,e.selectButtonKeyDown=function(e,t){32===t.keyCode&&(t.preventDefault(),o(e,t))},"ie"===l.detectBrowser()&&t.on("mousedown",function(e){(e.ctrlKey||e.shiftKey)&&(e.target.onselectstart=function(){return!1},window.setTimeout(function(){e.target.onselectstart=null},0))}),e.$on("$destroy",function(){t.off()})}}}]),e.directive("uiGridSelectionSelectAllButtons",["$templateCache","uiGridSelectionService",function(e,i){return{replace:!0,restrict:"E",template:e.get("ui-grid/selectionSelectAllButtons"),scope:!1,link:function(t){var r=t.col.grid;t.headerButtonKeyDown=function(e){32!==e.keyCode&&13!==e.keyCode||(e.preventDefault(),t.headerButtonClick(e))},t.headerButtonClick=function(e){r.selection.selectAll?(i.clearSelectedRows(r,e),r.options.noUnselect&&r.api.selection.selectRowByVisibleIndex(0,e),r.selection.selectAll=!1):r.options.multiSelect&&(r.api.selection.selectAllVisibleRows(e),r.selection.selectAll=!0)}}}}]),e.directive("uiGridViewport",function(){return{priority:-200,scope:!1,compile:function(e){var t=angular.element(e[0].querySelector(".ui-grid-canvas:not(.ui-grid-empty-base-layer-container)").children[0]),r="'ui-grid-row-selected': row.isSelected, 'ui-grid-row-focused': row.isFocused}",i=t.attr("ng-class");return r=i?i.slice(0,-1)+","+r:"{"+r,t.attr("ng-class",r),{pre:function(e,t,r,i){},post:function(e,t,r,i){}}}}}),e.directive("uiGridCell",["uiGridConstants","uiGridSelectionService",function(u,c){return{priority:-200,restrict:"A",require:"?^uiGrid",scope:!1,link:function(r,t,e,i){var n=0;i.grid.api.cellNav&&i.grid.api.cellNav.on.viewPortKeyDown(r,function(e,t){null!==t&&t.row===r.row&&t.col===r.col&&e.keyCode===u.keymap.SPACE&&"selectionRowHeaderCol"===r.col.colDef.name&&(e.preventDefault(),c.toggleRowSelection(r.grid,r.row,e,r.grid.options.multiSelect&&!r.grid.options.modifierKeysToMultiSelect,r.grid.options.noUnselect),r.$apply())});var o=function(e){"ui-grid-icon-minus-squared"!==e.target.className&&"ui-grid-icon-plus-squared"!==e.target.className&&(t.off("touchend",l),e.shiftKey?c.shiftSelect(r.grid,r.row,e,r.grid.options.multiSelect):e.ctrlKey||e.metaKey?c.toggleRowSelection(r.grid,r.row,e,r.grid.options.multiSelect,r.grid.options.noUnselect):r.grid.options.enableSelectRowOnFocus&&c.toggleRowSelection(r.grid,r.row,e,r.grid.options.multiSelect&&!r.grid.options.modifierKeysToMultiSelect,r.grid.options.noUnselect),r.row.setFocused(!r.row.isFocused),r.grid.api.selection.raise.rowFocusChanged(r.row,e),r.$apply(),window.setTimeout(function(){t.on("touchend",l)},300))},a=function(){n=(new Date).getTime(),t.off("click",o)},l=function(e){(new Date).getTime()-n<300&&o(e),window.setTimeout(function(){t.on("click",o)},300)};function s(){r.grid.options.enableRowSelection&&r.grid.options.enableFullRowSelection&&"selectionRowHeaderCol"!==r.col.colDef.name&&(t.addClass("ui-grid-disable-selection"),t.on("touchstart",a),t.on("touchend",l),t.on("click",o),r.registered=!0)}s();var d=r.grid.registerDataChangeCallback(function(){r.grid.options.enableRowSelection&&r.grid.options.enableFullRowSelection&&!r.registered?s():r.grid.options.enableRowSelection&&r.grid.options.enableFullRowSelection||!r.registered||r.registered&&(t.removeClass("ui-grid-disable-selection"),t.off("touchstart",a),t.off("touchend",l),t.off("click",o),r.registered=!1)},[u.dataChange.OPTIONS]);t.on("$destroy",d)}}}]),e.directive("uiGridGridFooter",["$compile","gridUtil",function(o,r){return{restrict:"EA",replace:!0,priority:-1e3,require:"^uiGrid",scope:!0,compile:function(){return{pre:function(i,n,e,t){t.grid.options.showGridFooter&&r.getTemplate("ui-grid/gridFooterSelectedItems").then(function(e){var t=angular.element(e),r=o(t)(i);angular.element(n[0].getElementsByClassName("ui-grid-grid-footer")[0]).append(r)})},post:function(e,t,r,i){}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.treeBase",["ui.grid"]);e.constant("uiGridTreeBaseConstants",{featureName:"treeBase",rowHeaderColName:"treeBaseRowHeaderCol",EXPANDED:"expanded",COLLAPSED:"collapsed",aggregation:{COUNT:"count",SUM:"sum",MAX:"max",MIN:"min",AVG:"avg"}}),e.service("uiGridTreeBaseService",["$q","uiGridTreeBaseConstants","gridUtil","GridRow","gridClassFactory","i18nService","uiGridConstants","rowSorter",function(e,a,t,r,i,n,o,l){var s={initializeGrid:function(r){r.treeBase={},r.treeBase.numberLevels=0,r.treeBase.expandAll=!1,r.treeBase.tree=[],s.defaultGridOptions(r.options),r.registerRowsProcessor(s.treeRows,410),r.registerColumnBuilder(s.treeBaseColumnBuilder),s.createRowHeader(r);var e={events:{treeBase:{rowExpanded:{},rowCollapsed:{}}},methods:{treeBase:{expandAllRows:function(){s.expandAllRows(r)},collapseAllRows:function(){s.collapseAllRows(r)},toggleRowTreeState:function(e){s.toggleRowTreeState(r,e)},expandRow:function(e,t){s.expandRow(r,e,t)},expandRowChildren:function(e){s.expandRowChildren(r,e)},collapseRow:function(e){s.collapseRow(r,e)},collapseRowChildren:function(e){s.collapseRowChildren(r,e)},getTreeExpandedState:function(){return{expandedState:s.getTreeState(r)}},setTreeState:function(e){s.setTreeState(r,e)},getRowChildren:function(e){return e.treeNode.children.map(function(e){return e.row})}}}};r.api.registerEventsFromObject(e.events),r.api.registerMethodsFromObject(e.methods)},defaultGridOptions:function(e){e.treeRowHeaderBaseWidth=e.treeRowHeaderBaseWidth||30,e.treeIndent=null!=e.treeIndent?e.treeIndent:10,e.showTreeRowHeader=!1!==e.showTreeRowHeader,e.showTreeExpandNoChildren=!1!==e.showTreeExpandNoChildren,e.treeRowHeaderAlwaysVisible=!1!==e.treeRowHeaderAlwaysVisible,e.treeCustomAggregations=e.treeCustomAggregations||{},e.enableExpandAll=!1!==e.enableExpandAll},treeBaseColumnBuilder:function(e,t,r){void 0!==e.customTreeAggregationFn&&(t.treeAggregationFn=e.customTreeAggregationFn),void 0!==e.treeAggregationType&&(t.treeAggregation={type:e.treeAggregationType},void 0!==r.treeCustomAggregations[e.treeAggregationType]?(t.treeAggregationFn=r.treeCustomAggregations[e.treeAggregationType].aggregationFn,t.treeAggregationFinalizerFn=r.treeCustomAggregations[e.treeAggregationType].finalizerFn,t.treeAggregation.label=r.treeCustomAggregations[e.treeAggregationType].label):void 0!==s.nativeAggregations()[e.treeAggregationType]&&(t.treeAggregationFn=s.nativeAggregations()[e.treeAggregationType].aggregationFn,t.treeAggregation.label=s.nativeAggregations()[e.treeAggregationType].label)),void 0!==e.treeAggregationLabel&&(void 0===t.treeAggregation&&(t.treeAggregation={}),t.treeAggregation.label=e.treeAggregationLabel),t.treeAggregationUpdateEntity=!1!==e.treeAggregationUpdateEntity,void 0===t.customTreeAggregationFinalizerFn&&(t.customTreeAggregationFinalizerFn=e.customTreeAggregationFinalizerFn)},createRowHeader:function(e){var t={name:a.rowHeaderColName,displayName:"",width:e.options.treeRowHeaderBaseWidth,minWidth:10,cellTemplate:"ui-grid/treeBaseRowHeader",headerCellTemplate:"ui-grid/treeBaseHeaderCell",enableColumnResizing:!1,enableColumnMenu:!1,exporterSuppressExport:!0,allowCellFocus:!0};t.visible=e.options.treeRowHeaderAlwaysVisible,e.addRowHeaderColumn(t,-100)},expandAllRows:function(t){t.treeBase.tree.forEach(function(e){s.setAllNodes(t,e,a.EXPANDED)}),t.treeBase.expandAll=!0,t.queueGridRefresh()},collapseAllRows:function(t){t.treeBase.tree.forEach(function(e){s.setAllNodes(t,e,a.COLLAPSED)}),t.treeBase.expandAll=!1,t.queueGridRefresh()},setAllNodes:function(t,e,r){void 0!==e.state&&e.state!==r&&((e.state=r)===a.EXPANDED?t.api.treeBase.raise.rowExpanded(e.row):t.api.treeBase.raise.rowCollapsed(e.row)),e.children&&e.children.forEach(function(e){s.setAllNodes(t,e,r)})},toggleRowTreeState:function(e,t){void 0===t.treeLevel||null===t.treeLevel||t.treeLevel<0||(t.treeNode.state===a.EXPANDED?s.collapseRow(e,t):s.expandRow(e,t,!1),e.queueGridRefresh())},expandRow:function(e,t,r){if(r){for(var i=[];t&&void 0!==t.treeLevel&&null!==t.treeLevel&&0<=t.treeLevel&&t.treeNode.state!==a.EXPANDED;)i.push(t),t=t.treeNode.parentRow;if(0<i.length){for(t=i.pop();t;)t.treeNode.state=a.EXPANDED,e.api.treeBase.raise.rowExpanded(t),t=i.pop();e.treeBase.expandAll=s.allExpanded(e.treeBase.tree),e.queueGridRefresh()}}else{if(void 0===t.treeLevel||null===t.treeLevel||t.treeLevel<0)return;t.treeNode.state!==a.EXPANDED&&(t.treeNode.state=a.EXPANDED,e.api.treeBase.raise.rowExpanded(t),e.treeBase.expandAll=s.allExpanded(e.treeBase.tree),e.queueGridRefresh())}},expandRowChildren:function(e,t){void 0===t.treeLevel||null===t.treeLevel||t.treeLevel<0||(s.setAllNodes(e,t.treeNode,a.EXPANDED),e.treeBase.expandAll=s.allExpanded(e.treeBase.tree),e.queueGridRefresh())},collapseRow:function(e,t){void 0===t.treeLevel||null===t.treeLevel||t.treeLevel<0||t.treeNode.state!==a.COLLAPSED&&(t.treeNode.state=a.COLLAPSED,e.treeBase.expandAll=!1,e.api.treeBase.raise.rowCollapsed(t),e.queueGridRefresh())},collapseRowChildren:function(e,t){void 0===t.treeLevel||null===t.treeLevel||t.treeLevel<0||(s.setAllNodes(e,t.treeNode,a.COLLAPSED),e.treeBase.expandAll=!1,e.queueGridRefresh())},allExpanded:function(e){var t=!0;return e.forEach(function(e){s.allExpandedInternal(e)||(t=!1)}),t},allExpandedInternal:function(e){if(e.children&&0<e.children.length){if(e.state===a.COLLAPSED)return!1;var t=!0;return e.children.forEach(function(e){s.allExpandedInternal(e)||(t=!1)}),t}return!0},treeRows:function(e){return 0===e.length?(s.updateRowHeaderWidth(this),e):(this.treeBase.tree=s.createTree(this,e),s.updateRowHeaderWidth(this),s.sortTree(this),s.fixFilter(this),s.renderTree(this.treeBase.tree))},updateRowHeaderWidth:function(e){var t=e.getColumn(a.rowHeaderColName),r=e.options.treeRowHeaderBaseWidth+e.options.treeIndent*Math.max(e.treeBase.numberLevels-1,0);t&&r!==t.width&&(t.width=r,e.queueRefresh());var i=!0;!1===e.options.showTreeRowHeader&&(i=!1),!1===e.options.treeRowHeaderAlwaysVisible&&e.treeBase.numberLevels<=0&&(i=!1),t&&t.visible!==i&&(t.visible=i,t.colDef.visible=i,e.queueGridRefresh())},renderTree:function(e){var t=[];return e.forEach(function(e){e.row.visible&&t.push(e.row),e.state===a.EXPANDED&&e.children&&0<e.children.length&&(t=t.concat(s.renderTree(e.children)))}),t},createTree:function(r,e){var i=-1,n=[];r.treeBase.tree=[],r.treeBase.numberLevels=0;var o=s.getAggregations(r);for(e.forEach(function(e){if(void 0!==e.entity.$$treeLevel&&e.treeLevel!==e.entity.$$treeLevel&&(e.treeLevel=e.entity.$$treeLevel),e.treeLevel<=i){for(;e.treeLevel<=i;){var t=n.pop();s.finaliseAggregations(t),i--}0<n.length?s.setCurrentState(n):a.EXPANDED}(void 0===e.treeLevel||null===e.treeLevel||e.treeLevel<0)&&e.visible&&s.aggregate(r,e,n),s.addOrUseNode(r,e,n,o),void 0!==e.treeLevel&&null!==e.treeLevel&&0<=e.treeLevel&&(n.push(e),i++,s.setCurrentState(n)),r.treeBase.numberLevels<e.treeLevel+1&&(r.treeBase.numberLevels=e.treeLevel+1)});0<n.length;){var t=n.pop();s.finaliseAggregations(t)}return r.treeBase.tree},addOrUseNode:function(e,t,r,i){var n=[];i.forEach(function(e){n.push(s.buildAggregationObject(e.col))});var o={state:a.COLLAPSED,row:t,parentRow:null,aggregations:n,children:[]};t.treeNode&&(o.state=t.treeNode.state),0<r.length&&(o.parentRow=r[r.length-1]),t.treeNode=o,0===r.length?e.treeBase.tree.push(o):r[r.length-1].treeNode.children.push(o)},setCurrentState:function(e){var t=a.EXPANDED;return e.forEach(function(e){e.treeNode.state===a.COLLAPSED&&(t=a.COLLAPSED)}),t},sortTree:function(e){e.columns.forEach(function(e){e.sort&&e.sort.ignoreSort&&delete e.sort.ignoreSort}),e.treeBase.tree=s.sortInternal(e,e.treeBase.tree)},sortInternal:function(t,e){var r=e.map(function(e){return e.row}),i=(r=l.sort(t,r,t.columns)).map(function(e){return e.treeNode});return i.forEach(function(e){e.state===a.EXPANDED&&e.children&&0<e.children.length&&(e.children=s.sortInternal(t,e.children))}),i},fixFilter:function(e){var t;e.treeBase.tree.forEach(function(e){e.children&&0<e.children.length&&(t=e.row.visible,s.fixFilterInternal(e.children,t))})},fixFilterInternal:function(e,t){return e.forEach(function(e){e.row.visible&&!t&&(s.setParentsVisible(e),t=!0),e.children&&0<e.children.length&&s.fixFilterInternal(e.children,t&&e.row.visible)&&(t=!0)}),t},setParentsVisible:function(e){for(;e.parentRow;)e.parentRow.visible=!0,e=e.parentRow.treeNode},buildAggregationObject:function(e){var t={col:e};return e.treeAggregation&&e.treeAggregation.type&&(t.type=e.treeAggregation.type),e.treeAggregation&&e.treeAggregation.label&&(t.label=e.treeAggregation.label),t},getAggregations:function(t){var r=[];return t.columns.forEach(function(e){void 0!==e.treeAggregationFn&&(r.push(s.buildAggregationObject(e)),t.options.showColumnFooter&&void 0===e.colDef.aggregationType&&e.treeAggregation&&(e.treeFooterAggregation=s.buildAggregationObject(e),e.aggregationType=s.treeFooterAggregationType))}),r},aggregate:function(n,o,e){0===e.length&&o.treeNode&&o.treeNode.aggregations&&o.treeNode.aggregations.forEach(function(e){if(void 0!==e.col.treeFooterAggregation){var t=n.getCellValue(o,e.col),r=Number(t);e.col.treeAggregationFn?e.col.treeAggregationFn(e.col.treeFooterAggregation,t,r,o):e.col.treeFooterAggregation.value=void 0}}),e.forEach(function(e,i){e.treeNode.aggregations&&e.treeNode.aggregations.forEach(function(e){var t=n.getCellValue(o,e.col),r=Number(t);e.col.treeAggregationFn(e,t,r,o),0===i&&void 0!==e.col.treeFooterAggregation&&(e.col.treeAggregationFn?e.col.treeAggregationFn(e.col.treeFooterAggregation,t,r,o):e.col.treeFooterAggregation.value=void 0)})})},nativeAggregations:function(){return{count:{label:n.get().aggregation.count,menuTitle:n.get().grouping.aggregate_count,aggregationFn:function(e,t,r){void 0===e.value?e.value=1:e.value++}},sum:{label:n.get().aggregation.sum,menuTitle:n.get().grouping.aggregate_sum,aggregationFn:function(e,t,r){isNaN(r)||(void 0===e.value?e.value=r:e.value+=r)}},min:{label:n.get().aggregation.min,menuTitle:n.get().grouping.aggregate_min,aggregationFn:function(e,t,r){void 0===e.value?e.value=t:null!=t&&(t<e.value||null===e.value)&&(e.value=t)}},max:{label:n.get().aggregation.max,menuTitle:n.get().grouping.aggregate_max,aggregationFn:function(e,t,r){void 0===e.value?e.value=t:null!=t&&(t>e.value||null===e.value)&&(e.value=t)}},avg:{label:n.get().aggregation.avg,menuTitle:n.get().grouping.aggregate_avg,aggregationFn:function(e,t,r){void 0===e.count?e.count=1:e.count++,isNaN(r)||(void 0===e.value||void 0===e.sum?(e.value=r,e.sum=r):(e.sum+=r,e.value=e.sum/e.count))}}}},finaliseAggregation:function(e,t){t.col.treeAggregationUpdateEntity&&void 0!==e&&void 0!==e.entity["$$"+t.col.uid]&&angular.extend(t,e.entity["$$"+t.col.uid]),"function"==typeof t.col.treeAggregationFinalizerFn&&t.col.treeAggregationFinalizerFn(t),"function"==typeof t.col.customTreeAggregationFinalizerFn&&t.col.customTreeAggregationFinalizerFn(t),void 0===t.rendered&&(t.rendered=t.label?t.label+t.value:t.value)},finaliseAggregations:function(e){null!=e&&void 0!==e.treeNode.aggregations&&e.treeNode.aggregations.forEach(function(r){if(s.finaliseAggregation(e,r),r.col.treeAggregationUpdateEntity){var i={};angular.forEach(r,function(e,t){r.hasOwnProperty(t)&&"col"!==t&&(i[t]=e)}),e.entity["$$"+r.col.uid]=i}})},treeFooterAggregationType:function(e,t){return s.finaliseAggregation(void 0,t.treeFooterAggregation),void 0===t.treeFooterAggregation.value||null===t.treeFooterAggregation.rendered?"":t.treeFooterAggregation.rendered}};return s}]),e.directive("uiGridTreeBaseRowHeaderButtons",["$templateCache","uiGridTreeBaseService",function(e,o){return{replace:!0,restrict:"E",template:e.get("ui-grid/treeBaseRowHeaderButtons"),scope:!0,require:"^uiGrid",link:function(e,t,r,i){var n=i.grid;e.treeButtonClass=function(e){if(n.options.showTreeExpandNoChildren&&-1<e.treeLevel||e.treeNode.children&&0<e.treeNode.children.length){if("expanded"===e.treeNode.state)return"ui-grid-icon-minus-squared";if("collapsed"===e.treeNode.state)return"ui-grid-icon-plus-squared"}},e.treeButtonClick=function(e,t){t.stopPropagation(),o.toggleRowTreeState(n,e,t)}}}}]),e.directive("uiGridTreeBaseExpandAllButtons",["$templateCache","uiGridTreeBaseService",function(e,i){return{replace:!0,restrict:"E",template:e.get("ui-grid/treeBaseExpandAllButtons"),scope:!1,link:function(e){var r=e.col.grid;e.headerButtonClass=function(){return 0<r.treeBase.numberLevels&&r.treeBase.expandAll?"ui-grid-icon-minus-squared":0<r.treeBase.numberLevels&&!r.treeBase.expandAll?"ui-grid-icon-plus-squared":void 0},e.headerButtonClick=function(e,t){r.treeBase.expandAll?i.collapseAllRows(r,t):i.expandAllRows(r,t)}}}}]),e.directive("uiGridViewport",function(){return{priority:-200,scope:!1,compile:function(e){var t=angular.element(e.children().children()[0]),r=t.attr("ng-class"),i="";return i=r?r.slice(0,-1)+",'ui-grid-tree-header-row': row.treeLevel > -1}":"{'ui-grid-tree-header-row': row.treeLevel > -1}",t.attr("ng-class",i),{pre:function(e,t,r,i){},post:function(e,t,r,i){}}}}})}(),function(){"use strict";var e=angular.module("ui.grid.treeView",["ui.grid","ui.grid.treeBase"]);e.constant("uiGridTreeViewConstants",{featureName:"treeView",rowHeaderColName:"treeBaseRowHeaderCol",EXPANDED:"expanded",COLLAPSED:"collapsed",aggregation:{COUNT:"count",SUM:"sum",MAX:"max",MIN:"min",AVG:"avg"}}),e.service("uiGridTreeViewService",["$q","uiGridTreeViewConstants","uiGridTreeBaseConstants","uiGridTreeBaseService","gridUtil","GridRow","gridClassFactory","i18nService","uiGridConstants",function(e,t,r,n,i,o,a,l,s){var d={initializeGrid:function(e,t){n.initializeGrid(e,t),e.treeView={},e.registerRowsProcessor(d.adjustSorting,60);var r={treeView:{}},i={treeView:{}};e.api.registerEventsFromObject(r),e.api.registerMethodsFromObject(i)},defaultGridOptions:function(e){e.enableTreeView=!1!==e.enableTreeView},adjustSorting:function(e){return this.columns.forEach(function(e){e.sort&&(e.sort.ignoreSort=!0)}),e}};return d}]),e.directive("uiGridTreeView",["uiGridTreeViewConstants","uiGridTreeViewService","$templateCache",function(e,n,t){return{replace:!0,priority:0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){!1!==i.grid.options.enableTreeView&&n.initializeGrid(i.grid,e)},post:function(e,t,r,i){}}}}}])}(),function(){"use strict";var e=angular.module("ui.grid.validate",["ui.grid"]);e.service("uiGridValidateService",["$sce","$q","$http","i18nService","uiGridConstants",function(n,u,e,o,t){var c={validatorFactories:{},setExternalFactoryFunction:function(e){c.externalFactoryFunction=e},clearExternalFactory:function(){delete c.externalFactoryFunction},getValidatorFromExternalFactory:function(e,t){return c.externalFactoryFunction(e,t).validatorFactory(t)},getMessageFromExternalFactory:function(e,t){return c.externalFactoryFunction(e,t).messageFunction(t)},setValidator:function(e,t,r){c.validatorFactories[e]={validatorFactory:t,messageFunction:r}},getValidator:function(e,t){if(c.externalFactoryFunction){var r=c.getValidatorFromExternalFactory(e,t);if(r)return r}if(!c.validatorFactories[e])throw"Invalid validator name: "+e;return c.validatorFactories[e].validatorFactory(t)},getMessage:function(e,t){if(c.externalFactoryFunction){var r=c.getMessageFromExternalFactory(e,t);if(r)return r}return c.validatorFactories[e].messageFunction(t)},isInvalid:function(e,t){return e["$$invalid"+t.name]},setInvalid:function(e,t){e["$$invalid"+t.name]=!0},setValid:function(e,t){delete e["$$invalid"+t.name]},setError:function(e,t,r){e["$$errors"+t.name]||(e["$$errors"+t.name]={}),e["$$errors"+t.name][r]=!0},clearError:function(e,t,r){e["$$errors"+t.name]&&r in e["$$errors"+t.name]&&delete e["$$errors"+t.name][r]},getErrorMessages:function(e,t){var r=[];return e["$$errors"+t.name]&&0!==Object.keys(e["$$errors"+t.name]).length&&Object.keys(e["$$errors"+t.name]).sort().forEach(function(e){r.push(c.getMessage(e,t.validators[e]))}),r},getFormattedErrors:function(e,t){var r="",i=c.getErrorMessages(e,t);if(i.length)return i.forEach(function(e){r+=e+"<br/>"}),n.trustAsHtml("<p><b>"+o.getSafeText("validate.error")+"</b></p>"+r)},getTitleFormattedErrors:function(e,t){var r="",i=c.getErrorMessages(e,t);if(i.length)return i.forEach(function(e){r+=e+"\n"}),n.trustAsHtml(o.getSafeText("validate.error")+"\n"+r)},runValidators:function(e,t,n,o,a){if(n!==o){if(void 0===t.name||!t.name)throw new Error("colDef.name is required to perform validation");c.setValid(e,t);var r=function(t,r,i){return function(e){e||(c.setInvalid(t,r),c.setError(t,r,i),a&&a.api.validate.raise.validationFailed(t,r,n,o))}},i=[];for(var l in t.validators){c.clearError(e,t,l);var s=c.getValidator(l,t.validators[l]),d=u.when(s(o,n,e,t)).then(r(e,t,l));i.push(d)}return u.all(i)}},createDefaultValidators:function(){c.setValidator("minLength",function(r){return function(e,t){return null==t||""===t||t.length>=r}},function(e){return o.getSafeText("validate.minLength").replace("THRESHOLD",e)}),c.setValidator("maxLength",function(r){return function(e,t){return null==t||""===t||t.length<=r}},function(e){return o.getSafeText("validate.maxLength").replace("THRESHOLD",e)}),c.setValidator("required",function(r){return function(e,t){return!r||!(null==t||""===t)}},function(){return o.getSafeText("validate.required")})},initializeGrid:function(e,n){n.validate={isInvalid:c.isInvalid,getErrorMessages:c.getErrorMessages,getFormattedErrors:c.getFormattedErrors,getTitleFormattedErrors:c.getTitleFormattedErrors,runValidators:c.runValidators};var t={events:{validate:{validationFailed:function(e,t,r,i){}}},methods:{validate:{isInvalid:function(e,t){return n.validate.isInvalid(e,t)},getErrorMessages:function(e,t){return n.validate.getErrorMessages(e,t)},getFormattedErrors:function(e,t){return n.validate.getFormattedErrors(e,t)},getTitleFormattedErrors:function(e,t){return n.validate.getTitleFormattedErrors(e,t)}}}};n.api.registerEventsFromObject(t.events),n.api.registerMethodsFromObject(t.methods),n.edit&&n.api.edit.on.afterCellEdit(e,function(e,t,r,i){n.validate.runValidators(e,t,r,i,n)}),c.createDefaultValidators()}};return c}]),e.directive("uiGridValidate",["gridUtil","uiGridValidateService",function(e,n){return{priority:0,replace:!0,require:"^uiGrid",scope:!1,compile:function(){return{pre:function(e,t,r,i){n.initializeGrid(e,i.grid)},post:function(e,t,r,i){}}}}}])}(),angular.module("ui.grid").run(["$templateCache",function(e){"use strict";e.put("ui-grid/ui-grid-filter",'<div class="ui-grid-filter-container" ng-style="col.extraStyle" ng-repeat="colFilter in col.filters" ng-class="{\'ui-grid-filter-cancel-button-hidden\' : colFilter.disableCancelFilterButton === true }"><div ng-if="colFilter.type !== \'select\'"><input type="text" class="ui-grid-filter-input ui-grid-filter-input-{{$index}}" ng-model="colFilter.term" ng-attr-placeholder="{{colFilter.placeholder || \'\'}}" aria-label="{{colFilter.ariaLabel || aria.defaultFilterLabel}}"><div role="button" class="ui-grid-filter-button" ng-click="removeFilter(colFilter, $index)" ng-if="!colFilter.disableCancelFilterButton" ng-disabled="colFilter.term === undefined || colFilter.term === null || colFilter.term === \'\'" ng-show="colFilter.term !== undefined && colFilter.term !== null && colFilter.term !== \'\'"><i class="ui-grid-icon-cancel" ui-grid-one-bind-aria-label="aria.removeFilter">&nbsp;</i></div></div><div ng-if="colFilter.type === \'select\'"><select class="ui-grid-filter-select ui-grid-filter-input-{{$index}}" ng-model="colFilter.term" ng-show="colFilter.selectOptions.length > 0" ng-attr-placeholder="{{colFilter.placeholder || aria.defaultFilterLabel}}" aria-label="{{colFilter.ariaLabel || \'\'}}" ng-options="option.value as option.label for option in colFilter.selectOptions"><option value=""></option></select><div role="button" class="ui-grid-filter-button-select" ng-click="removeFilter(colFilter, $index)" ng-if="!colFilter.disableCancelFilterButton" ng-disabled="colFilter.term === undefined || colFilter.term === null || colFilter.term === \'\'" ng-show="colFilter.term !== undefined && colFilter.term != null"><i class="ui-grid-icon-cancel" ui-grid-one-bind-aria-label="aria.removeFilter">&nbsp;</i></div></div></div>'),e.put("ui-grid/ui-grid-footer",'<div class="ui-grid-footer-panel ui-grid-footer-aggregates-row">\x3c!-- tfooter --\x3e<div class="ui-grid-footer ui-grid-footer-viewport"><div class="ui-grid-footer-canvas"><div class="ui-grid-footer-cell-wrapper" ng-style="colContainer.headerCellWrapperStyle()"><div role="row" class="ui-grid-footer-cell-row"><div ui-grid-footer-cell role="gridcell" ng-repeat="col in colContainer.renderedColumns track by col.uid" col="col" render-index="$index" class="ui-grid-footer-cell ui-grid-clearfix"></div></div></div></div></div></div>'),e.put("ui-grid/ui-grid-grid-footer",'<div class="ui-grid-footer-info ui-grid-grid-footer"><span>{{\'search.totalItems\' | t}} {{grid.rows.length}}</span> <span ng-if="grid.renderContainers.body.visibleRowCache.length !== grid.rows.length" class="ngLabel">({{"search.showingItems" | t}} {{grid.renderContainers.body.visibleRowCache.length}})</span></div>'),e.put("ui-grid/ui-grid-header",'<div role="rowgroup" class="ui-grid-header">\x3c!-- theader --\x3e<div class="ui-grid-top-panel"><div class="ui-grid-header-viewport"><div class="ui-grid-header-canvas"><div class="ui-grid-header-cell-wrapper" ng-style="colContainer.headerCellWrapperStyle()"><div role="row" class="ui-grid-header-cell-row"><div class="ui-grid-header-cell ui-grid-clearfix" ng-repeat="col in colContainer.renderedColumns track by col.uid" ui-grid-header-cell col="col" render-index="$index"></div></div></div></div></div></div></div>'),e.put("ui-grid/ui-grid-menu-button",'<div class="ui-grid-menu-button"><div role="button" ui-grid-one-bind-id-grid="\'grid-menu\'" class="ui-grid-icon-container" ng-click="toggleMenu()" aria-haspopup="true"><i class="ui-grid-icon-menu" ui-grid-one-bind-aria-label="i18n.aria.buttonLabel">&nbsp;</i></div><div ui-grid-menu menu-items="menuItems"></div></div>'),e.put("ui-grid/ui-grid-menu-header-item",'<li role="menuitem"><div class="ui-grid-menu-item" role="heading" aria-level="2" ng-show="itemShown()"><i aria-hidden="true">&nbsp; </i><span ng-bind="label()"></span></div></li>'),e.put("ui-grid/ui-grid-no-header",'<div class="ui-grid-top-panel"></div>'),e.put("ui-grid/ui-grid-row","<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\" ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' + col.uid + '-cell'\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\" ui-grid-cell></div>"),e.put("ui-grid/ui-grid",'<div ui-i18n="en" class="ui-grid">\x3c!-- TODO (c0bra): add "scoped" attr here, eventually? --\x3e<style ui-grid-style>.grid{{ grid.id }} {\n /* Styles for the grid */\n }\n\n .grid{{ grid.id }} .ui-grid-row, .grid{{ grid.id }} .ui-grid-cell, .grid{{ grid.id }} .ui-grid-cell .ui-grid-vertical-bar {\n height: {{ grid.options.rowHeight }}px;\n }\n\n .grid{{ grid.id }} .ui-grid-row:last-child .ui-grid-cell {\n border-bottom-width: {{ (((grid.getVisibleRowCount() * grid.options.rowHeight) < grid.getViewportHeight()) && \'1\') || \'0\' }}px;\n }\n\n {{ grid.verticalScrollbarStyles }}\n {{ grid.horizontalScrollbarStyles }}\n\n /*\n .ui-grid[dir=rtl] .ui-grid-viewport {\n padding-left: {{ grid.verticalScrollbarWidth }}px;\n }\n */\n\n {{ grid.customStyles }}</style><div class="ui-grid-contents-wrapper" role="grid"><div ui-grid-menu-button ng-if="grid.options.enableGridMenu"></div><div ng-if="grid.hasLeftContainer()" style="width: 0" ui-grid-pinned-container="\'left\'"></div><div ui-grid-render-container container-id="\'body\'" col-container-name="\'body\'" row-container-name="\'body\'" bind-scroll-horizontal="true" bind-scroll-vertical="true" enable-horizontal-scrollbar="grid.options.enableHorizontalScrollbar" enable-vertical-scrollbar="grid.options.enableVerticalScrollbar"></div><div ng-if="grid.hasRightContainer()" style="width: 0" ui-grid-pinned-container="\'right\'"></div><div ui-grid-grid-footer ng-if="grid.options.showGridFooter"></div><div ui-grid-column-menu ng-if="grid.options.enableColumnMenus"></div><div ng-transclude></div></div></div>'),e.put("ui-grid/uiGridCell",'<div class="ui-grid-cell-contents" title="TOOLTIP">{{COL_FIELD CUSTOM_FILTERS}}</div>'),e.put("ui-grid/uiGridColumnMenu",'<div class="ui-grid-column-menu"><div ui-grid-menu menu-items="menuItems">\x3c!-- <div class="ui-grid-column-menu">\n <div class="inner" ng-show="menuShown">\n <ul>\n <div ng-show="grid.options.enableSorting">\n <li ng-click="sortColumn($event, asc)" ng-class="{ \'selected\' : col.sort.direction == asc }"><i class="ui-grid-icon-sort-alt-up"></i> Sort Ascending</li>\n <li ng-click="sortColumn($event, desc)" ng-class="{ \'selected\' : col.sort.direction == desc }"><i class="ui-grid-icon-sort-alt-down"></i> Sort Descending</li>\n <li ng-show="col.sort.direction" ng-click="unsortColumn()"><i class="ui-grid-icon-cancel"></i> Remove Sort</li>\n </div>\n </ul>\n </div>\n </div> --\x3e</div></div>'),e.put("ui-grid/uiGridFooterCell",'<div class="ui-grid-cell-contents" col-index="renderIndex"><div>{{ col.getAggregationText() + ( col.getAggregationValue() CUSTOM_FILTERS ) }}</div></div>'),e.put("ui-grid/uiGridHeaderCell",'<div role="columnheader" ng-class="{ \'sortable\': sortable, \'ui-grid-header-cell-last-col\': isLastCol }" ui-grid-one-bind-aria-labelledby-grid="col.uid + \'-header-text \' + col.uid + \'-sortdir-text\'" aria-sort="{{col.sort.direction == asc ? \'ascending\' : ( col.sort.direction == desc ? \'descending\' : (!col.sort.direction ? \'none\' : \'other\'))}}"><div role="button" tabindex="0" ng-keydown="handleKeyDown($event)" class="ui-grid-cell-contents ui-grid-header-cell-primary-focus" col-index="renderIndex" title="TOOLTIP"><span class="ui-grid-header-cell-label" ui-grid-one-bind-id-grid="col.uid + \'-header-text\'">{{ col.displayName CUSTOM_FILTERS }}</span> <span ui-grid-one-bind-id-grid="col.uid + \'-sortdir-text\'" ui-grid-visible="col.sort.direction" aria-label="{{getSortDirectionAriaLabel()}}"><i ng-class="{ \'ui-grid-icon-up-dir\': col.sort.direction == asc, \'ui-grid-icon-down-dir\': col.sort.direction == desc, \'ui-grid-icon-blank\': !col.sort.direction }" title="{{isSortPriorityVisible() ? i18n.headerCell.priority + \' \' + ( col.sort.priority + 1 ) : null}}" aria-hidden="true"></i> <sub ui-grid-visible="isSortPriorityVisible()" class="ui-grid-sort-priority-number">{{col.sort.priority + 1}}</sub></span></div><div role="button" tabindex="0" ui-grid-one-bind-id-grid="col.uid + \'-menu-button\'" class="ui-grid-column-menu-button" ng-if="grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false" ng-click="toggleMenu($event)" ng-keydown="headerCellArrowKeyDown($event)" ui-grid-one-bind-aria-label="i18n.headerCell.aria.columnMenuButtonLabel" aria-haspopup="true"><i class="ui-grid-icon-angle-down" aria-hidden="true">&nbsp;</i></div><div ui-grid-filter></div></div>'),e.put("ui-grid/uiGridMenu",'<div class="ui-grid-menu" ng-show="shown"><style ui-grid-style>{{dynamicStyles}}</style><div class="ui-grid-menu-mid" ng-show="shownMid"><div class="ui-grid-menu-inner" ng-if="shown"><ul role="menu" class="ui-grid-menu-items"><li ng-repeat="item in menuItems" role="menuitem" ui-grid-menu-item ui-grid-one-bind-id="\'menuitem-\'+$index" action="item.action" name="item.title" active="item.active" icon="item.icon" shown="item.shown" context="item.context" template-url="item.templateUrl" leave-open="item.leaveOpen" screen-reader-only="item.screenReaderOnly"></li></ul></div></div></div>'),e.put("ui-grid/uiGridMenuItem",'<button type="button" class="ui-grid-menu-item" ng-click="itemAction($event, title)" ng-show="itemShown()" ng-class="{ \'ui-grid-menu-item-active\': active(), \'ui-grid-sr-only\': (!focus && screenReaderOnly) }" aria-pressed="{{active()}}" tabindex="0" ng-focus="focus=true" ng-blur="focus=false"><i ng-class="icon" aria-hidden="true">&nbsp; </i>{{ label() }}</button>'),e.put("ui-grid/uiGridRenderContainer","<div role=\"presentation\" ui-grid-one-bind-id-grid=\"containerId + '-grid-container'\" class=\"ui-grid-render-container\" ng-style=\"{ 'margin-left': colContainer.getMargin('left') + 'px', 'margin-right': colContainer.getMargin('right') + 'px' }\">\x3c!-- All of these dom elements are replaced in place --\x3e<div ui-grid-header></div><div ui-grid-viewport></div><div ng-if=\"colContainer.needsHScrollbarPlaceholder()\" class=\"ui-grid-scrollbar-placeholder\" ng-style=\"{height: colContainer.grid.scrollbarHeight + 'px'}\"></div><ui-grid-footer ng-if=\"grid.options.showColumnFooter\"></ui-grid-footer></div>"),e.put("ui-grid/uiGridViewport",'<div role="rowgroup" class="ui-grid-viewport" ng-style="colContainer.getViewportStyle()">\x3c!-- tbody --\x3e<div class="ui-grid-canvas"><div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by $index" class="ui-grid-row" ng-style="Viewport.rowStyle(rowRenderIndex)"><div role="row" ui-grid-row="row" row-render-index="rowRenderIndex"></div></div></div></div>'),e.put("ui-grid/cellEditor",'<div><form name="inputForm"><input type="INPUT_TYPE" ng-class="\'colt\' + col.uid" ui-grid-editor ng-model="MODEL_COL_FIELD"></form></div>'),e.put("ui-grid/dropdownEditor",'<div><form name="inputForm"><select ng-class="\'colt\' + col.uid" ui-grid-edit-dropdown ng-model="MODEL_COL_FIELD" ng-options="field[editDropdownIdLabel] as field[editDropdownValueLabel] CUSTOM_FILTERS for field in editDropdownOptionsArray"></select></form></div>'),e.put("ui-grid/fileChooserEditor",'<div><form name="inputForm"><input ng-class="\'colt\' + col.uid" ui-grid-edit-file-chooser type="file" id="files" name="files[]" ng-model="MODEL_COL_FIELD"></form></div>'),e.put("ui-grid/emptyBaseLayerContainer",'<div class="ui-grid-empty-base-layer-container ui-grid-canvas"><div class="ui-grid-row" ng-repeat="(rowRenderIndex, row) in grid.baseLayer.emptyRows track by $index" ng-style="Viewport.rowStyle(rowRenderIndex)"><div><div><div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name" class="ui-grid-cell {{ col.getColClass(false) }}"></div></div></div></div></div>'),e.put("ui-grid/expandableRow",'<div ui-grid-expandable-row ng-if="expandableRow.shouldRenderExpand()" class="expandableRow" style="float:left; margin-top: 1px; margin-bottom: 1px" ng-style="{width: (grid.renderContainers.body.getCanvasWidth()) + \'px\', height: row.expandedRowHeight + \'px\'}"></div>'),e.put("ui-grid/expandableRowHeader",'<div class="ui-grid-row-header-cell ui-grid-expandable-buttons-cell"><div class="ui-grid-cell-contents"><i class="clickable" ng-if="!(row.groupHeader==true || row.entity.subGridOptions.disableRowExpandable)" ng-class="{ \'ui-grid-icon-plus-squared\' : !row.isExpanded, \'ui-grid-icon-minus-squared\' : row.isExpanded }" ng-click="grid.api.expandable.toggleRowExpansion(row.entity, $event)"></i></div></div>'),e.put("ui-grid/expandableScrollFiller","<div ng-if=\"expandableRow.shouldRenderFiller()\" ng-class=\"{scrollFiller: true, scrollFillerClass:(colContainer.name === 'body')}\" ng-style=\"{ width: (grid.getViewportWidth()) + 'px', height: row.expandedRowHeight + 2 + 'px', 'margin-left': grid.options.rowHeader.rowHeaderWidth + 'px' }\">&nbsp;</div>"),e.put("ui-grid/expandableTopRowHeader",'<div class="ui-grid-row-header-cell ui-grid-expandable-buttons-cell"><div class="ui-grid-cell-contents"><span class="ui-grid-cell-empty" ng-if="!grid.options.showExpandAllButton"></span> <button type="button" class="ui-grid-icon-button clickable" ng-if="grid.options.showExpandAllButton" ng-class="{ \'ui-grid-icon-plus-squared\' : !grid.expandable.expandedAll, \'ui-grid-icon-minus-squared\' : grid.expandable.expandedAll }" ng-click="grid.api.expandable.toggleAllRows()"></button></div></div>'),e.put("ui-grid/csvLink",'<span class="ui-grid-exporter-csv-link-span"><a href="data:text/csv;charset=UTF-8,CSV_CONTENT" download="FILE_NAME">LINK_LABEL</a></span>'),e.put("ui-grid/importerMenuItem",'<li class="ui-grid-menu-item"><form><input class="ui-grid-importer-file-chooser" type="file" id="files" name="files[]"></form></li>'),e.put("ui-grid/importerMenuItemContainer","<div ui-grid-importer-menu-item></div>"),e.put("ui-grid/pagination",'<div class="ui-grid-pager-panel" ui-grid-pager ng-show="grid.options.enablePaginationControls"><div role="navigation" class="ui-grid-pager-container"><div class="ui-grid-pager-control"><button type="button" class="ui-grid-pager-first" ui-grid-one-bind-title="aria.pageToFirst" ui-grid-one-bind-aria-label="aria.pageToFirst" ng-click="pageFirstPageClick()" ng-disabled="cantPageBackward()"><div ng-class="grid.isRTL() ? \'last-triangle\' : \'first-triangle\'"><div ng-class="grid.isRTL() ? \'last-bar-rtl\' : \'first-bar\'"></div></div></button> <button type="button" class="ui-grid-pager-previous" ui-grid-one-bind-title="aria.pageBack" ui-grid-one-bind-aria-label="aria.pageBack" ng-click="pagePreviousPageClick()" ng-disabled="cantPageBackward()"><div ng-class="grid.isRTL() ? \'last-triangle prev-triangle\' : \'first-triangle prev-triangle\'"></div></button> <input type="number" ui-grid-one-bind-title="aria.pageSelected" ui-grid-one-bind-aria-label="aria.pageSelected" class="ui-grid-pager-control-input" ng-model="grid.options.paginationCurrentPage" min="1" max="{{ paginationApi.getTotalPages() }}" step="1" required> <span class="ui-grid-pager-max-pages-number" ng-show="paginationApi.getTotalPages() > 0"><abbr ui-grid-one-bind-title="paginationOf">/ </abbr>{{ paginationApi.getTotalPages() }} </span><button type="button" class="ui-grid-pager-next" ui-grid-one-bind-title="aria.pageForward" ui-grid-one-bind-aria-label="aria.pageForward" ng-click="pageNextPageClick()" ng-disabled="cantPageForward()"><div ng-class="grid.isRTL() ? \'first-triangle next-triangle\' : \'last-triangle next-triangle\'"></div></button> <button type="button" class="ui-grid-pager-last" ui-grid-one-bind-title="aria.pageToLast" ui-grid-one-bind-aria-label="aria.pageToLast" ng-click="pageLastPageClick()" ng-disabled="cantPageToLast()"><div ng-class="grid.isRTL() ? \'first-triangle\' : \'last-triangle\'"><div ng-class="grid.isRTL() ? \'first-bar-rtl\' : \'last-bar\'"></div></div></button></div><div class="ui-grid-pager-row-count-picker" ng-if="grid.options.paginationPageSizes.length > 1 && !grid.options.useCustomPagination"><select ui-grid-one-bind-aria-labelledby-grid="\'items-per-page-label\'" ng-model="grid.options.paginationPageSize" ng-options="o as o for o in grid.options.paginationPageSizes"></select><span ui-grid-one-bind-id-grid="\'items-per-page-label\'" class="ui-grid-pager-row-count-label">&nbsp;{{sizesLabel}}</span></div><span ng-if="grid.options.paginationPageSizes.length <= 1" class="ui-grid-pager-row-count-label">{{grid.options.paginationPageSize}}&nbsp;{{sizesLabel}}</span></div><div class="ui-grid-pager-count-container"><div class="ui-grid-pager-count"><span ng-show="grid.options.totalItems > 0">{{ 1 + paginationApi.getFirstRowIndex() }} <abbr ui-grid-one-bind-title="paginationThrough">- </abbr>{{ 1 + paginationApi.getLastRowIndex() }} {{paginationOf}} {{grid.options.totalItems}} {{totalItemsLabel}}</span></div></div></div>'),e.put("ui-grid/columnResizer",'<div ui-grid-column-resizer ng-if="grid.options.enableColumnResizing" class="ui-grid-column-resizer" col="col" position="right" render-index="renderIndex" unselectable="on"></div>'),e.put("ui-grid/gridFooterSelectedItems",'<span ng-if="grid.selection.selectedCount !== 0 && grid.options.enableFooterTotalSelected">({{"search.selectedItems" | t}} {{grid.selection.selectedCount}})</span>'),e.put("ui-grid/selectionHeaderCell",'<div>\x3c!-- <div class="ui-grid-vertical-bar">&nbsp;</div> --\x3e<div class="ui-grid-cell-contents" col-index="renderIndex"><ui-grid-selection-select-all-buttons ng-if="grid.options.enableSelectAll" role="checkbox" ng-model="grid.selection.selectAll"></ui-grid-selection-select-all-buttons></div></div>'),e.put("ui-grid/selectionRowHeader",'<div class="ui-grid-cell-contents ui-grid-disable-selection clickable"><ui-grid-selection-row-header-buttons></ui-grid-selection-row-header-buttons></div>'),e.put("ui-grid/selectionRowHeaderButtons",'<div class="ui-grid-selection-row-header-buttons ui-grid-icon-ok clickable" ng-class="{\'ui-grid-row-selected\': row.isSelected}" ng-click="selectButtonClick(row, $event)" ng-keydown="selectButtonKeyDown(row, $event)" role="checkbox" ng-model="row.isSelected">&nbsp;</div>'),e.put("ui-grid/selectionSelectAllButtons",'<div role="button" class="ui-grid-selection-row-header-buttons ui-grid-icon-ok" ng-class="{\'ui-grid-all-selected\': grid.selection.selectAll}" ng-click="headerButtonClick($event)" ng-keydown="headerButtonKeyDown($event)"></div>'),e.put("ui-grid/treeBaseExpandAllButtons",'<div class="ui-grid-tree-base-row-header-buttons" ng-class="headerButtonClass()" ng-click="headerButtonClick($event)"></div>'),e.put("ui-grid/treeBaseHeaderCell",'<div><div class="ui-grid-cell-contents" col-index="renderIndex"><ui-grid-tree-base-expand-all-buttons ng-if="grid.options.enableExpandAll"></ui-grid-tree-base-expand-all-buttons></div></div>'),e.put("ui-grid/treeBaseRowHeader",'<div class="ui-grid-cell-contents"><ui-grid-tree-base-row-header-buttons></ui-grid-tree-base-row-header-buttons></div>'),e.put("ui-grid/treeBaseRowHeaderButtons",'<div class="ui-grid-tree-base-row-header-buttons" ng-class="{\'ui-grid-tree-base-header\': row.treeLevel > -1 }" ng-click="treeButtonClick(row, $event)"><i ng-class="treeButtonClass(row)" ng-style="{\'padding-left\': grid.options.treeIndent * row.treeLevel + \'px\'}"></i> &nbsp;</div>'),e.put("ui-grid/cellTitleValidator",'<div class="ui-grid-cell-contents" ng-class="{invalid:grid.validate.isInvalid(row.entity,col.colDef)}" title="{{grid.validate.getTitleFormattedErrors(row.entity,col.colDef)}}">{{COL_FIELD CUSTOM_FILTERS}}</div>'),e.put("ui-grid/cellTooltipValidator",'<div class="ui-grid-cell-contents" ng-class="{invalid:grid.validate.isInvalid(row.entity,col.colDef)}" tooltip-html-unsafe="{{grid.validate.getFormattedErrors(row.entity,col.colDef)}}" tooltip-enable="grid.validate.isInvalid(row.entity,col.colDef)" tooltip-append-to-body="true" tooltip-placement="top" title="TOOLTIP">{{COL_FIELD CUSTOM_FILTERS}}</div>')}]);
faraday/server/www/script/ui-grid.woff less more
Binary diff not shown
+0
-48
faraday/server/www/scripts/admin/admin.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion">
5 <div class="faraday-header-border-fix">
6 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
7 <div id="reports-main" class="fila">
8 <div class="settings">
9 <div class="setting-header">
10 <div><h2>Settings</h2></div>
11 </div>
12 <div class="setting-body">
13 <div class="setting-sidebar col-sm-2">
14 <ul>
15 <li href="javascript:;" ng-class="{'active':on=='custom_fields'}"
16 ng-click="setItemPanel('custom_fields')">Custom fields
17 </li>
18 <li href="javascript:;" ng-class="{'active':on=='agents'}"
19 ng-click="setItemPanel('agents')">Agents (Beta)
20 </li>
21 </ul>
22 </div>
23
24 <div class="setting-container col-sm-10">
25 <div ng-switch="on">
26 <div ng-switch-when="custom_fields">
27 <div ng-controller="customFieldsCtrl" ng-include="'scripts/admin/customFields/partials/customFields.html'"></div>
28 </div>
29 <div ng-switch-when="agents">
30 <div ng-controller="agentsCtrl" ng-include="'scripts/admin/agents/partials/agents.html'"></div>
31 </div>
32
33
34 <div ng-switch-default>
35 <h1>Switch</h1>
36 <p>There's something wrong !</p>
37 </div>
38 </div>
39 </div>
40
41 </div>
42 </div>
43
44 </div>
45 </div>
46 </div>
47 </section><!-- #main -->
+0
-24
faraday/server/www/scripts/admin/admin.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('adminCtrl',
6 ['$scope', '$location', '$routeParams', function($scope, $location, $routeParams) {
7
8 var init = function () {
9 if ($routeParams.item !== undefined){
10 $scope.on = $routeParams.item;
11 }else{
12 $scope.on = "custom_fields";
13 }
14 };
15
16 $scope.setItemPanel = function (menuItem) {
17 $scope.on = menuItem;
18 var url = "/admin/" + menuItem;
19 $location.path(url);
20 };
21
22 init();
23 }]);
+0
-239
faraday/server/www/scripts/admin/agents/controllers/agents.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2019 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('agentsCtrl', [
6 '$scope',
7 'agentFact',
8 'workspacesFact',
9 'Notification',
10 '$routeParams',
11 '$uibModal',
12 function ($scope,
13 agentFact,
14 workspacesFact,
15 Notification,
16 $routeParams,
17 $uibModal
18 ) {
19 $scope.agentToken = {id: null, token: null};
20 $scope.workspace = null;
21 $scope.agents = [];
22 $scope.executors = [];
23 $scope.selectAll = false;
24 $scope.options = [];
25 $scope.disableExecute = false;
26 $scope.parameters_metadata = {};
27 $scope.data = {
28 selectedExecutor: null
29 };
30
31 $scope.init = function () {
32 getWorkspaces();
33 };
34
35
36 var getWorkspaces = function () {
37 workspacesFact.getWorkspaces().then(function (wss) {
38 $scope.workspaces = [];
39
40 wss.forEach(function (ws) {
41 if (ws.active && !ws.readonly) {
42 $scope.workspaces.push(ws);
43 }
44 });
45
46 $scope.workspace = $scope.workspaces[0].name;
47 $scope.workspaceData = $scope.workspaces[0];
48
49 getToken();
50 getAgents();
51 });
52 };
53
54
55 $scope.switchWorkspace = function (workspace) {
56 $scope.workspace = workspace;
57
58 workspacesFact.get(workspace).then(function (ws) {
59 $scope.workspaceData = ws
60 });
61
62 getToken();
63 getAgents();
64 };
65
66
67 var getToken = function () {
68 agentFact.getAgentToken($scope.workspace).then(
69 function (response) {
70 $scope.agentToken = response.data;
71 }, function (error) {
72 console.log(error);
73 });
74 };
75
76 var getAgents = function () {
77 agentFact.getAgents($scope.workspace).then(
78 function (response) {
79 $scope.agents = response.data
80 }, function (error) {
81 console.log(error);
82 });
83 };
84
85 $scope.selectAgent = function (agent) {
86 $scope.executors = [];
87 $scope.parameters_values = {};
88 agent.executors.forEach((executor) => {
89 let exec = {
90 id: executor.id,
91 name: executor.name,
92 parameters_metadata: [],
93 parameters_values: {}
94 };
95 let params = executor.parameters_metadata;
96 for (let [key, value] of Object.entries(params)) {
97 let parameter = { name: key, isRequired: value };
98 exec.parameters_metadata.push(parameter);
99 exec.parameters_values[key] = '';
100 }
101
102 $scope.executors.push(exec);
103 });
104 };
105
106 let removeAgentFromScope = function (agentId) {
107 for (var i = 0; i < $scope.agents.length; i++) {
108 if ($scope.agents[i].id === agentId) {
109 $scope.agents.splice(i, 1);
110 break;
111 }
112 }
113 };
114
115 $scope.refreshToken = function () {
116 agentFact.getNewAgentToken().then(
117 function (response) {
118 $scope.agentToken = response.data;
119 }, function (error) {
120 console.log(error);
121 });
122 };
123
124 $scope.runAgent = function (agentId) {
125 $scope.disableExecute = true;
126 let executorData = {
127 agent_id: agentId,
128 executor: $scope.data.selectedExecutor.name,
129 args: {}
130 };
131 for (let [key, value] of Object.entries($scope.data.selectedExecutor.parameters_values)) {
132 executorData.args[key] = value;
133 }
134 agentFact.runAgent($scope.workspace, agentId, executorData).then(
135 function (response) {
136 $('#selectExecutorModal-' + agentId).modal('toggle');
137 Notification.success("The Agent is running");
138 setInterval(function () {
139 $scope.disableExecute = false;
140 }, 2000);
141 }, function (error) {
142 console.log(error);
143 });
144 };
145
146 $scope.copyToClipboard = function () {
147 var copyElement = document.createElement("textarea");
148 copyElement.style.position = 'fixed';
149 copyElement.style.opacity = '0';
150 copyElement.textContent = decodeURI($scope.agentToken.token);
151 var body = document.getElementsByTagName('body')[0];
152 body.appendChild(copyElement);
153 copyElement.select();
154 document.execCommand('copy');
155 body.removeChild(copyElement);
156 Notification.success("Token copied to clipboard");
157 };
158
159 var _delete = function (agentId) {
160 var modal = $uibModal.open({
161 templateUrl: 'scripts/commons/partials/modalDelete.html',
162 controller: 'commonsModalDelete',
163 size: 'md',
164 resolve: {
165 msg: function () {
166 return "A agent will be deleted. This action cannot be undone. " +
167 "Are you sure you want to proceed?";
168 }
169 }
170 });
171
172 modal.result.then(function () {
173 agentFact.deleteAgent($scope.workspace, agentId).then(
174 function (response) {
175 removeAgentFromScope(agentId);
176 Notification.success("The Agent has been removed");
177 }, function (error) {
178 console.log(error);
179 });
180 });
181 };
182
183 $scope.removeAgent = function (agentId) {
184 _delete(agentId);
185 };
186
187 $scope.changeStatusAgent = function (agent) {
188 var oldStatus = agent.active;
189 agent.active = !agent.active;
190
191 var agentData = {
192 id: agent.id,
193 name: agent.name,
194 active: agent.active
195 };
196
197 agentFact.updateAgent($scope.workspace, agentData).then(
198 function (response) {
199 if (!response.data.active)
200 Notification.success("The Agent has been paused");
201 else
202 Notification.success("The Agent is active");
203 agent.status = response.data.status;
204 }, function (error) {
205 agent.active = oldStatus;
206 console.log(error);
207 });
208 };
209
210
211 $scope.toggleAgent = function (index) {
212 $scope.agents[index].checked = !$scope.agents[index].checked;
213 if (!$scope.agents[index].checked) {
214 $scope.selectAll = false;
215 } else {
216 $scope.selectAll = $scope.agents.filter(function (agent) {
217 return agent.checked === true
218 }).length === $scope.agents.length;
219 }
220 };
221
222 $scope.toggleAll = function () {
223 var checked = $scope.selectAll;
224 for (var i = 0; i < $scope.agents.length; i++) {
225 $scope.options[i] = checked;
226 $scope.agents[i].checked = checked;
227 $scope.agents[i].selected = checked;
228 }
229 };
230
231 var getCurrentSelection = function () {
232 return $scope.agents.filter(function (agent) {
233 return agent.selected === true
234 });
235 };
236
237 $scope.init();
238 }]);
+0
-162
faraday/server/www/scripts/admin/agents/partials/agents.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2019 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="row" style="overflow-x: hidden; padding: 10px; height: 675px">
5 <div class="panel panel-default custom-panel">
6 <div class="panel-body custom-panel-body">
7 <span class="agent-token-container"><code>{{agentToken.token}}</code> &nbsp;<span class="cursor"
8 title="Copy registration token to clipboard"
9 ng-click="copyToClipboard()"><i
10 class="fa fa-copy"></i></span></span>
11 <span class="glyphicon glyphicon-question-sign margin-right-15px"
12 title="To register a new agent you should enter the current token"></span>
13
14 <button type="button" class="btn btn-info"
15 title="A new token will be shown and the current token will be lost"
16 ng-click="refreshToken()">
17 <i class="fa fa-refresh"></i> New Token
18 </button>
19
20 <span class="control-wrapper" ng-if="">
21 <button type="button" class="btn btn-default"
22 title="{{workspaceData.readonly == false ? 'Tags' : 'Read-only. Workspace disabled'}}"
23 ng-click="agentsTags()"
24 ng-disabled="user.roles[0] === 'client' || workspaceData.readonly == true">
25 <span class="glyphicon glyphicon-tags"></span>
26 </button>
27 </span>
28
29
30 <span class="col-md-3">
31 <div ng-if="workspace" class="workspace-selector-wrapper inside-admin workflow-workspace-switcher">
32 <div class="switcher-wrapper inside-admin">
33 <div class="dropdown">
34 <button id="workspaceSwitcher" type="button"
35 class="btn btn-default dropdown-toggle workspace-switcher"
36 data-toggle="dropdown" title="Change current workspace">
37 <div class="img-wrapper">
38 <img src="images/ico-status-menu.svg" class="icon" alt="Workspace"/>
39 </div>
40 <div class="workspace-switcher-title-wrapper">
41 <div class="workspace-switcher-title">
42 <span class="title">
43 {{ workspace }}
44 </span>
45 <span class="caret-container">
46 <span class="caret"></span>
47 </span>
48 </div>
49 </div>
50 </button>
51 <ul class="dropdown-menu" role="menu" aria-labelledby="workspaceSwitcher" style="width: 100%;">
52 <li ng-repeat="ws in workspaces"><a href="javascript:;" class="ws"
53 ng-click="switchWorkspace(ws.name)">{{ws.name}}</a></li>
54 </ul>
55 </div>
56 </div>
57 </div>
58 </span>
59
60 </div>
61
62 </div>
63
64
65 <table id="agent-table" class="status-report-grid hosts-list table table-responsive">
66 <thead>
67 <tr class="ui-grid-header">
68 <th class="ui-grid-cell-contents ui-grid-header-cell">Name</th>
69 <th class="ui-grid-cell-contents ui-grid-header-cell">Status</th>
70 <th class="ui-grid-cell-contents ui-grid-header-cell">Token</th>
71 <th class="ui-grid-cell-contents ui-grid-header-cell"></th>
72 </tr>
73 </thead>
74 <tbody>
75 <tr ng-repeat="agent in agents">
76 <td class="ui-grid-cell-contents active-toggle">
77 {{agent.name}}
78 </td>
79 <td class="ui-grid-cell-contents active-toggle">
80 <span class="preview-tag" ng-class="{
81 'tag-green':agent.status == 'online',
82 'tag-yellow':agent.status=='offline',
83 'tag-red': agent.status=='paused'}">
84 {{agent.status |uppercase}}
85 </span>
86 </td>
87
88 <td class="ui-grid-cell-contents active-toggle">
89 {{agent.token}}
90 </td>
91
92 <td class="ui-grid-cell-contents active-toggle" selection-model-ignore="">
93 <button type="button" class="btn btn-info"
94 ng-click="selectAgent(agent)"
95 title="Run Agent"
96 data-toggle="modal" data-target="#selectExecutorModal-{{agent.id}}" ng-disabled="!agent.active || disableExecute || agent.status=='offline'">
97 Execute
98 </button>
99 <!--<button type="button" class="btn"
100 ng-class="{'btn-danger': agent.active, 'btn-success': !agent.active}"
101 title="{ {agent.active?'Pause Agent': 'Unpause
102 Agent'}}"
103 ng-click="changeStatusAgent(agent)"
104 ng-disabled="agent.status=='offline'">
105 <span ng-bind="agent.active ?'Pause':
106 'Unpause'"></span>
107 </button>-->
108 <button type="button" class="btn btn-danger" title="Remove Agent" ng-click="removeAgent(agent.id)">
109 Remove
110 </button>
111 </td>
112
113
114 </tr>
115 </tbody>
116 </table><!-- #hosts -->
117
118 <div class="no-info-overlay" ng-if="agents.length === 0" style="margin-bottom: 15px;top: -8px;">
119 <p class="no-info-text">
120 No registered agents
121 </p>
122 </div>
123
124 </div>
125
126 <div ng-repeat="agent in agents">
127 <div class="modal fade" id="selectExecutorModal-{{agent.id}}" tabindex="-1" role="dialog"
128 aria-labelledby="exampleModalLabel"
129 aria-hidden="true">
130 <div class="modal-dialog" role="document">
131 <div class="modal-content">
132 <div class="modal-header">
133 <h4 class="modal-title" id="selectExecutorModalLabel">Agent Executors</h4>
134 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
135 <span aria-hidden="true">&times;</span>
136 </button>
137 </div>
138 <form role="form" name="form">
139 <div class="modal-body">
140
141 <div class="form-group">
142 <label for="selectedExecutor">Select Executor</label>
143 <select class="form-control" ng-options="executor as executor.name for executor in executors track by executor.id" id="selectedExecutor" ng-model="data.selectedExecutor"></select>
144 </div>
145
146 <div class="var-item margin-top-65px row">
147 <div class="form-group col-md-6" ng-repeat="parameter in data.selectedExecutor.parameters_metadata" ng-class="{'has-error': form[$index].$invalid}">
148 <label for="paramName" ng-class="{'text-danger': form[$index].$invalid}">{{parameter.name}} <span ng-if="parameter.isRequired">*</span></label>
149 <input type="text" class="form-control" name="{{$index}}" id="paramName" placeholder="{{parameter.name}}" ng-model="data.selectedExecutor.parameters_values[parameter.name]" ng-required="parameter.isRequired">
150 </div>
151 </div>
152 </div>
153 <div class="modal-footer">
154 <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
155 <button class="btn btn-primary" ng-disabled="form.$invalid" ng-click="runAgent(agent.id)">Run</button>
156 </div>
157 </form>
158 </div>
159 </div>
160 </div>
161 </div>
+0
-90
faraday/server/www/scripts/admin/agents/providers/agents.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('agentFact', ['BASEURL', 'ServerAPI', '$http', '$q', function(BASEURL, ServerAPI, $http, $q) {
6 var agentFact = {};
7
8 agentFact.getAgentToken = function() {
9 var deferred = $q.defer();
10 ServerAPI.getAgentToken().then(function(response) {
11 deferred.resolve(response);
12 }, function (error) {
13 deferred.reject(error)
14 });
15 return deferred.promise;
16 };
17
18 agentFact.getNewAgentToken = function() {
19 var deferred = $q.defer();
20 $http.get(BASEURL + '_api/session').then(function(response){
21 var fd = new FormData();
22 fd.append('csrf_token', response.data.csrf_token);
23 $http.post(BASEURL + '_api/v2/agent_token/', fd, {
24 transformRequest: angular.identity,
25 withCredentials: false,
26 headers: {'Content-Type': undefined},
27 }).then(
28 function(tokenResponse) {
29 deferred.resolve(tokenResponse)
30 });
31 });
32
33 return deferred.promise;
34 };
35
36
37 agentFact.runAgent = function(wsName, agentId, executorData) {
38 var deferred = $q.defer();
39 $http.get(BASEURL +'_api/session').then(function(response){
40 let data = {
41 'csrf_token': response.data.csrf_token,
42 'executorData': executorData
43 };
44 var postUrl = BASEURL + '_api/v2/ws/' + wsName + '/agents/' + agentId + '/run/';
45 $http.post(postUrl, JSON.stringify(data), {
46 transformRequest: angular.identity,
47 withCredentials: false,
48 headers: {'Content-Type': 'application/json'}
49 }).then(
50 function(tokenResponse) {
51 deferred.resolve(tokenResponse)
52 });
53 });
54
55 return deferred.promise;
56 };
57
58 agentFact.getAgents = function(wsName) {
59 var deferred = $q.defer();
60 ServerAPI.getAgents(wsName).then(function(response) {
61 deferred.resolve(response);
62 }, function (error) {
63 deferred.reject(error)
64 });
65 return deferred.promise;
66 };
67
68 agentFact.deleteAgent = function(wsName, agentId) {
69 var deferred = $q.defer();
70 ServerAPI.deleteAgent(wsName, agentId).then(function(response) {
71 deferred.resolve(response);
72 }, function (error) {
73 deferred.reject(error)
74 });
75 return deferred.promise;
76 };
77
78 agentFact.updateAgent = function(wsName, agent) {
79 var deferred = $q.defer();
80 ServerAPI.updateAgent(wsName, agent).then(function(response) {
81 deferred.resolve(response);
82 }, function (error) {
83 deferred.reject(error)
84 });
85 return deferred.promise;
86 };
87
88 return agentFact;
89 }]);
+0
-244
faraday/server/www/scripts/admin/customFields/controllers/customFields.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('customFieldsCtrl',
6 ['$scope', 'customFieldFact', '$uibModal', 'commonsFact', function ($scope, customFieldFact, $uibModal, commonsFact) {
7
8 $scope.customFields = [];
9 $scope.selected_cf = {
10 field_display_name: "",
11 field_name: "",
12 field_metadata: [],
13 field_order: null,
14 field_type: null,
15 table_name: 'vulnerability'
16 };
17 $scope.isEditable = false;
18 $scope.data = {
19 newOption : ''
20 };
21
22 $scope.models = {
23 selected: null
24 };
25
26 var init = function () {
27 loadCustomFields();
28 };
29
30 var compareFunction = function (cf1, cf2) {
31 return cf1.field_order - cf2.field_order;
32 };
33
34
35 var errorHandler = function (error) {
36 if (typeof(error) === "object") {
37 if (error.status=== 409)
38 commonsFact.showMessage(error.data.object.field_display_name + " has the same field name: '" +
39 error.data.object.field_name + "'");
40 }
41 else if (typeof(error) === "string")
42 commonsFact.showMessage(error);
43 else
44 commonsFact.showMessage('Something bad happened');
45 };
46
47
48 $scope.insertCallback = function () {
49 var ids = [];
50 for (var i = 0; i < $scope.customFields.length; i++) {
51 if (ids.indexOf($scope.customFields[i].id) === -1) {
52 $scope.customFields[i].field_order = i;
53 customFieldFact.updateCustomField($scope.customFields[i]).then(function(){
54 if (i < $scope.customFields.length ) {
55 ids.push($scope.customFields[i].id);
56 }
57
58 $scope.clearSelection();
59 });
60 }
61 }
62 };
63
64
65 var loadCustomFields = function () {
66 customFieldFact.getCustomFields().then(
67 function (response) {
68 $scope.customFields = response.data.sort(compareFunction);
69 });
70 };
71
72
73 var getMaxOrder = function () {
74 if ($scope.customFields.length === 0) {
75 return -1;
76 }
77
78 var orders = [];
79 $scope.customFields.forEach(function (customField) {
80 orders.push(customField.field_order);
81 });
82
83 return Math.max.apply(null, orders) || 0;
84 };
85
86 $scope.normalizeName = function () {
87 if ($scope.selected_cf.field_name !== null) {
88 $scope.selected_cf.field_name = $scope.selected_cf.field_name.toLowerCase().replace(' ', '_');
89 }
90 };
91
92 $scope.addOption = function(){
93 if ( $scope.data.newOption !== ''){
94 $scope.selected_cf.field_metadata.push($scope.data.newOption);
95 $scope.data.newOption = '';
96 }
97 };
98
99 $scope.createCustomCustomField = function () {
100 $scope.selected_cf.table_name = 'vulnerability';
101
102 if ($scope.selected_cf.field_order === null)
103 $scope.selected_cf.field_order = getMaxOrder() + 1;
104
105 if(!$scope.selected_cf.field_metadata || $scope.selected_cf.field_metadata.length === 0){
106 $scope.selected_cf.field_metadata = null;
107 }
108
109 if ($scope.selected_cf.field_type === 'choice'){
110 $scope.selected_cf.field_metadata = JSON.stringify($scope.selected_cf.field_metadata)
111 }
112 customFieldFact.createCustomField($scope.selected_cf).then(
113 function (response) {
114 $scope.customFields.push(response.data);
115 $scope.clearSelection();
116 }, errorHandler);
117 };
118
119
120 $scope.updateCustomCustomField = function () {
121 if(!$scope.selected_cf.field_metadata || $scope.selected_cf.field_metadata.length === 0){
122 $scope.selected_cf.field_metadata = null;
123 }
124
125 if ($scope.selected_cf.field_type === 'choice'){
126 $scope.selected_cf.field_metadata = JSON.stringify($scope.selected_cf.field_metadata)
127 }
128
129 customFieldFact.updateCustomField($scope.selected_cf).then(
130 function (response) {
131 if (response) {
132 $scope.clearSelection();
133 loadCustomFields();
134 }
135 });
136 };
137
138 $scope._delete = function (customField) {
139 var modal = $uibModal.open({
140 templateUrl: 'scripts/commons/partials/modalDelete.html',
141 controller: 'commonsModalDelete',
142 size: 'lg',
143 resolve: {
144 msg: function () {
145 var msg = "A custom field will be deleted.";
146 msg += " This action cannot be undone. Are you sure you want to proceed?";
147 return msg;
148 }
149 }
150 });
151
152 modal.result.then(function () {
153 $scope.deleteCustomCustomField(customField.id);
154 });
155 };
156
157
158 $scope.deleteCustomCustomField = function (customFieldId) {
159 customFieldFact.deleteCustomField(customFieldId).then(
160 function (response) {
161 removeCustomField(customFieldId);
162 });
163 };
164
165 var removeCustomField = function (customFieldId) {
166 for (var i = 0; i < $scope.customFields.length; i++) {
167 if ($scope.customFields[i].id === customFieldId) {
168 $scope.customFields.splice(i, 1);
169 break;
170 }
171 }
172 };
173
174 $scope.setCustomField = function (cf) {
175 $scope.selected_cf = angular.copy(cf);
176 if (cf.field_type === 'choice'){
177 $scope.selected_cf.field_metadata = cf.field_metadata === null ? [] : JSON.parse(cf.field_metadata);
178 }
179 $scope.isEditable = true;
180 $scope.changeType(cf.field_type);
181
182 $scope.showSidePanel();
183 };
184
185 $scope.updateBtnTypeColor = function (type) {
186 var color = undefined;
187 switch (type) {
188 case "str":
189 color = '#2e97bd';
190 break;
191 case "list":
192 color = '#a1ce31';
193 break;
194 case "int":
195 color = '#932ebe';
196 break;
197 case "choice":
198 color = '#be2743';
199 break;
200 default:
201 color = '#AAAAAA';
202 break;
203 }
204
205 angular.element('#btn-chg-type').css('background-color', color);
206 angular.element('#caret-chg-type').css('background-color', color);
207 };
208
209 $scope.changeType = function (type) {
210 $scope.selected_cf.field_type = type;
211 $scope.updateBtnTypeColor(type);
212 };
213
214 $scope.clearSelection = function () {
215 $scope.selected_cf = {
216 field_display_name: "",
217 field_metadata: [],
218 field_name: "",
219 field_order: null,
220 field_type: null
221 };
222 $scope.updateBtnTypeColor(null);
223 $scope.isEditable = false;
224 };
225
226 $scope.showSidePanel = function () {
227 angular.element('#slide').addClass('show-slide');
228 angular.element('#main-panel').addClass('slice-main-panel');
229 };
230
231 $scope.hideSidePanel = function () {
232 angular.element('#slide').removeClass('show-slide');
233 angular.element('#main-panel').removeClass('slice-main-panel');
234 $scope.clearSelection();
235 };
236
237 $scope.new = function () {
238 $scope.clearSelection();
239 $scope.showSidePanel();
240 };
241
242 init();
243 }]);
+0
-134
faraday/server/www/scripts/admin/customFields/partials/customFields.html less more
0 <div class="header-btns row">
1 <button class="btn btn-success pull-right background-blue" ng-click="new()">New</button>
2 </div>
3
4 <div class="row" style="overflow-x: hidden">
5 <div id="main-panel" class="cf-container col-md-8" dnd-list="customFields"
6 dnd-effect-allowed="all"
7 dnd-inserted="insertCallback()">
8
9 <div class="alert alert-info" style="text-align: center" ng-if="customFields.length === 0">There isn't any
10 custom field created
11 </div>
12
13 <div class="row cf-item" ng-repeat="cf in customFields | orderBy:'field_order'"
14 dnd-draggable="cf"
15 dnd-moved="customFields.splice($index, 1)"
16 ng-class="{'selected': models.selected === item}">
17 <div class="col-md-10">
18 <h3 class="cf-display-name"> {{cf.field_display_name}}</h3>
19 <div class="cf-name"> {{cf.field_name}}</div>
20 <div class="cf-type type-int" ng-if="cf.field_type == 'int'">INTEGER</div>
21 <div class="cf-type type-list" ng-if="cf.field_type == 'list'">LIST</div>
22 <div class="cf-type type-str" ng-if="cf.field_type == 'str'">STRING</div>
23 <div class="cf-type type-choice" ng-if="cf.field_type == 'choice'">CHOICE</div>
24 </div>
25 <div class="cf-actions col-md-2">
26 <span class="cf-icon-action" ng-click="_delete(cf)"><i
27 class="fa fa-trash-o fa-2x"></i></span>
28 <span class="cf-icon-action" ng-click="setCustomField(cf)"><i class="fa fa-pencil fa-2x"></i></span>
29 <span class="cf-icon-action handle-move" style="cursor: move"><i
30 class="fa fa-arrows-alt fa-2x"
31 title="You can drag and drop each custom field to reorder"></i></span>
32 </div>
33 </div>
34 </div>
35
36 <div id="slide" class="col-md-4 cf-detail">
37 <h3><span ng-if="isEditable == true">Edit</span>
38 <span ng-if="isEditable == false">Create</span>
39 custom field
40 </h3><br>
41 <form name="form" role="form">
42 <div class="tab-pane-header">Display Name</div>
43 <div class="form-group">
44 <label class="sr-only control-label" for="cf_display_name">Display Name</label>
45 <input type="text" class="form-control" id="cf_display_name" placeholder="Display Name"
46 ng-model="selected_cf.field_display_name" required/>
47 </div><!-- .form-group -->
48
49 <div class="tab-pane-header">Name</div>
50 <div class="form-group">
51 <label class="sr-only control-label" for="cf_name">Name</label>
52 <input type="text" class="form-control" id="cf_name" placeholder="Name" ng-readonly="isEditable == true"
53 ng-model="selected_cf.field_name" ng-change="normalizeName()" required/>
54 </div><!-- .form-group -->
55
56 <div class="row" style="margin-top: 32px;">
57 <div class="btn-group col-md-6">
58 <div class="tab-pane-header">Type</div>
59 <button type="button" class="dropdown-toggle btn-change-property primary-btn"
60 data-toggle="dropdown"
61 id="btn-chg-type"
62 ng-disabled="isEditable == true">
63 <span ng-if="selected_cf.field_type == null">UNDEFINED</span>
64 <span ng-if="selected_cf.field_type == 'int'">INTEGER</span>
65 <span ng-if="selected_cf.field_type == 'list'">LIST</span>
66 <span ng-if="selected_cf.field_type == 'str'">STRING</span>
67 <span ng-if="selected_cf.field_type == 'choice'">CHOICE</span>
68 </button>
69 <button type="button" class="dropdown-toggle secondary-btn btn-change-property"
70 data-toggle="dropdown"
71 id="caret-chg-type"
72 title="Change type"
73 ng-disabled="isEditable == true">
74 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
75 </button>
76 <ul class="dropdown-menu dropdown-menu-right" role="menu">
77 <li>
78 <a class="ws"
79 ng-click="changeType(null)">UNDEFINED</a>
80 <a class="ws"
81 ng-click="changeType('str')">STRING</a>
82 <a class="ws"
83 ng-click="changeType('int')">INTEGER</a>
84 <a class="ws"
85 ng-click="changeType('list')">LIST</a>
86 <a class="ws"
87 ng-click="changeType('choice')">CHOICE</a>
88 </li>
89 </ul>
90 </div>
91
92 <div class="add-options col-md-12 margin-top-30px" ng-if="selected_cf.field_type == 'choice'">
93 <div class="form-group">
94 <div class="col-md-12">
95 <div class="tab-pane-header">Options</div>
96 <div class="input-group margin-bottom-sm">
97 <label class="sr-only" for="option">Options</label>
98 <input type="text" class="form-control" id="option" placeholder="Option"
99 ng-model="data.newOption"/>
100 <span class="input-group-addon cursor" ng-click="addOption()">
101 <i class="fa fa-plus-circle"></i>
102 </span>
103 </div>
104 </div>
105 <div class="col-md-12 reference" ng-repeat="option in selected_cf.field_metadata">
106 <div class="input-group margin-bottom-sm">
107 <label class="sr-only" for="vuln-refs-create">Options</label>
108 <input type="text" class="form-control" id="vuln-refs-create" placeholder="Option"
109 ng-model="option"
110 role="button"
111 readonly/>
112 <span class="input-group-addon cursor" ng-click="selected_cf.field_metadata.splice($index, 1)"><i
113 class="fa fa-minus-circle"></i></span>
114 </div>
115 </div>
116 </div><!-- .form-group -->
117 </div>
118 </div>
119
120 <div class="btn-tools">
121 <button type="reset" class="btn btn-default" ng-click="hideSidePanel()">Cancel</button>
122 <button class="btn btn-success" ng-if="isEditable == true"
123 ng-click="updateCustomCustomField()"
124 ng-disabled="form.$invalid || selected_cf.field_type == null">Save
125 </button>
126 <button class="btn btn-success" ng-if="isEditable == false"
127 ng-click="createCustomCustomField()"
128 ng-disabled="form.$invalid || selected_cf.field_type == null">Save
129 </button>
130 </div>
131 </form>
132 </div>
133 </div>
+0
-61
faraday/server/www/scripts/admin/customFields/providers/customFields.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('customFieldFact', ['BASEURL', 'ServerAPI', '$http', '$q', function (BASEURL, ServerAPI, $http, $q) {
6 var customFieldFact = {};
7
8 customFieldFact.getCustomFields = function () {
9 var deferred = $q.defer();
10 ServerAPI.getCustomFields().then(function (response) {
11 deferred.resolve(response)
12 }, errorHandler);
13 return deferred.promise;
14 };
15
16
17 errorHandler = function (response) {
18 if (typeof(response) == "object")
19 return $q.reject(response.data.reason.replace("file", "workspace"));
20 else if (typeof(response) == "string")
21 return $q.reject(response);
22 else
23 return $q.reject("Something bad happened");
24 };
25
26 customFieldFact.createCustomField = function (customField) {
27 var deferred = $q.defer();
28 ServerAPI.createCustomField(customField).then(function (response) {
29 deferred.resolve(response)
30 }, function (err) {
31 deferred.reject(err);
32 });
33 return deferred.promise;
34 };
35
36
37 customFieldFact.updateCustomField = function (customField) {
38 var deferred = $q.defer();
39 ServerAPI.updateCustomField(customField).then(function (data) {
40 customField._rev = data.rev;
41 deferred.resolve(customField);
42 }, function (err) {
43 deferred.reject(err);
44 });
45 return deferred.promise;
46 };
47
48 customFieldFact.deleteCustomField = function(customFieldId) {
49 var deferred = $q.defer();
50 ServerAPI.deleteCustomField(customFieldId).then(function(response) {
51 deferred.resolve(response);
52 }, function() {
53 deferred.reject();
54 });
55 return deferred.promise;
56 };
57
58
59 return customFieldFact;
60 }]);
+0
-394
faraday/server/www/scripts/app.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 'use strict';
5
6 $.ajaxSetup({
7 async: false
8 });
9
10 var faradayApp = angular.module('faradayApp', [
11 'ngRoute',
12 'selectionModel',
13 'ui.bootstrap',
14 'angularFileUpload',
15 'filter',
16 'angular-clipboard',
17 'ngCookies',
18 'cfp.hotkeys',
19 'chart.js',
20 'ui.grid',
21 'ui.grid.selection',
22 'ui.grid.grouping',
23 'ngSanitize',
24 'ui.grid.pagination',
25 'ui.grid.pinning',
26 'angularMoment',
27 'ui-notification',
28 'ui.grid.resizeColumns',
29 'angularSimplePagination',
30 'dndLists',
31 'angularFileUploadLib',
32 'rzTable',
33 'ui'
34 ])
35 .constant("BASEURL", (function() {
36 if (window.location.pathname === "/"){
37 var url = window.location.origin + "/";
38 } else {
39 var client_url_id = window.location.pathname;
40 var url = window.location.origin + client_url_id;
41 }
42 return url;
43 })())
44 .constant("APIURL", (function() {
45 if (window.location.pathname === "/"){
46 var url = window.location.origin + "/_api/v2/";
47 } else {
48 var client_url_id = window.location.pathname;
49 var url = window.location.origin + client_url_id + "_api/v2/";
50 }
51 return url;
52 })())
53 .constant("EASEOFRESOLUTION", (function() {
54 var resolutions = [
55 "trivial",
56 "simple",
57 "moderate",
58 "difficult",
59 "infeasible"
60 ];
61 return resolutions;
62 })())
63 .constant("SEVERITIES", (function() {
64 var severities = [
65 "critical",
66 "high",
67 "med",
68 "low",
69 "info",
70 "unclassified"
71 ];
72 return severities;
73 })())
74 .constant("EXPLOITATIONS", (function() {
75 var exploitations = [
76 "critical",
77 "high",
78 "med",
79 "low",
80 "info",
81 "unclassified"
82 ];
83 return exploitations;
84 })())
85 .constant("SERVICE_STATUSES", (function() {
86 var statuses = [
87 "open",
88 "closed",
89 "filtered"
90 ];
91 return statuses;
92 })())
93 .constant("STATUSES", (function() {
94 var statuses = [
95 "opened", // TODO migration: should we change this to "open"?
96 "closed",
97 "re-opened",
98 "risk-accepted"
99 ];
100 return statuses;
101 })());
102
103 faradayApp.config(['$routeProvider', '$uibTooltipProvider', 'BASEURL',
104 function($routeProvider, $uibTooltipProvider, BASEURL) {
105 $uibTooltipProvider.options({
106 appendToBody: true
107 });
108 $routeProvider.
109 when('/', {
110 redirectTo: "/workspaces"
111 }).
112 when('/dashboard/ws/:wsId', {
113 templateUrl: 'scripts/dashboard/partials/dashboard.html',
114 controller: 'dashboardCtrl',
115 title: 'Dashboard | '
116 }).
117 when('/dashboard/ws', {
118 templateUrl: 'scripts/workspaces/partials/list.html',
119 controller: 'workspacesCtrl',
120 title: 'Dashboard | '
121 }).
122 when('/dashboard', {
123 templateUrl: 'scripts/workspaces/partials/list.html',
124 controller: 'workspacesCtrl',
125 title: 'Dashboard | '
126 }).
127 when('/extras', {
128 templateUrl: 'scripts/extras/partials/extras.html',
129 title: 'Extras | '
130 }).
131 when('/help', {
132 templateUrl: 'scripts/help/partials/help.html',
133 title: 'Help | '
134 }).
135 when('/hosts/ws/:wsId/search/:search', {
136 templateUrl: 'scripts/hosts/partials/list.html',
137 controller: 'hostsCtrl',
138 title: 'Hosts | '
139 }).
140 when('/hosts/ws/:wsId/search', {
141 templateUrl: 'scripts/hosts/partials/list.html',
142 controller: 'hostsCtrl',
143 title: 'Hosts | '
144 }).
145 when('/hosts/ws/:wsId', {
146 templateUrl: 'scripts/hosts/partials/list.html',
147 controller: 'hostsCtrl',
148 title: 'Hosts | '
149 }).
150 when('/hosts/ws', {
151 templateUrl: 'scripts/workspaces/partials/list.html',
152 controller: 'workspacesCtrl',
153 title: 'Hosts | '
154 }).
155 when('/host/ws/:wsId/hid/:hidId/search/:search', {
156 templateUrl: 'scripts/services/partials/list.html',
157 controller: 'hostCtrl',
158 title: 'Host and services | '
159 }).
160 when('/host/ws/:wsId/hid/:hidId/search', {
161 templateUrl: 'scripts/services/partials/list.html',
162 controller: 'hostCtrl',
163 title: 'Host and services | '
164 }).
165 when('/hosts', {
166 templateUrl: 'scripts/workspaces/partials/list.html',
167 controller: 'workspacesCtrl',
168 title: 'Hosts | '
169 }).
170 when('/host/ws/:wsId/hid/:hidId', {
171 templateUrl: 'scripts/services/partials/list.html',
172 controller: 'hostCtrl',
173 title: 'Host and services | '
174 }).
175 when('/host/ws/:wsId/hid/:hidId/:edit', {
176 templateUrl: 'scripts/services/partials/list.html',
177 controller: 'hostCtrl',
178 title: 'Host and services | '
179 }).
180 when('/host/ws/:wsId/new', {
181 templateUrl: 'scripts/hosts/partials/new.html',
182 controller: 'newHostCtrl',
183 title: 'New host | '
184 }).
185 when('/host/ws/:wsId/', {
186 redirectTo: "/hosts/ws/:wsId/"
187 }).
188 when('/license/lid/:lidId', {
189 templateUrl: 'scripts/licenses/partials/license.html',
190 controller: 'licenseCtrl',
191 title: 'License | '
192 }).
193 when('/license', {
194 templateUrl: 'scripts/licenses/partials/list.html',
195 controller: 'licensesCtrl',
196 title: 'Licenses | '
197 }).
198 when('/licenses', {
199 templateUrl: 'scripts/licenses/partials/list.html',
200 controller: 'licensesCtrl',
201 title: 'Licenses | '
202 }).
203 when('/licenses/search/:search', {
204 templateUrl: 'scripts/licenses/partials/list.html',
205 controller: 'licensesCtrl',
206 title: 'Licenses | '
207 }).
208 when('/licenses/search', {
209 templateUrl: 'scripts/licenses/partials/list.html',
210 controller: 'licensesCtrl',
211 title: 'Licenses | '
212 }).
213 when('/status/ws/:wsId/groupby/:groupbyId', {
214 templateUrl: 'scripts/statusReport/partials/statusReport.html',
215 controller: 'statusReportCtrl',
216 title: 'Status Report | ',
217 resolve: {
218 workspaceData: function($route, workspacesFact){
219 return workspacesFact.get($route.current.params.wsId);
220 }
221 }
222 }).
223 when('/status/ws/:wsId/groupby/:groupbyId/search/:search', {
224 templateUrl: 'scripts/statusReport/partials/statusReport.html',
225 controller: 'statusReportCtrl',
226 title: 'Status Report | ',
227 resolve: {
228 workspaceData: function($route, workspacesFact){
229 return workspacesFact.get($route.current.params.wsId);
230 }
231 }
232 }).
233 when('/status/ws/:wsId/groupby/:groupbyId/search', {
234 templateUrl: 'scripts/statusReport/partials/statusReport.html',
235 controller: 'statusReportCtrl',
236 title: 'Status Report | ',
237 resolve: {
238 workspaceData: function($route, workspacesFact){
239 return workspacesFact.get($route.current.params.wsId);
240 }
241 }
242 }).
243 when('/status/ws/:wsId/search/:search*\/', {
244 templateUrl: 'scripts/statusReport/partials/statusReport.html',
245 controller: 'statusReportCtrl',
246 title: 'Status Report | ',
247 resolve: {
248 workspaceData: function($route, workspacesFact){
249 return workspacesFact.get($route.current.params.wsId);
250 }
251 }
252 }).
253 when('/status/ws/:wsId/search', {
254 templateUrl: 'scripts/statusReport/partials/statusReport.html',
255 controller: 'statusReportCtrl',
256 title: 'Status Report | ',
257 resolve: {
258 workspaceData: function($route, workspacesFact){
259 return workspacesFact.get($route.current.params.wsId);
260 }
261 }
262 }).
263 when('/status/ws/:wsId', {
264 templateUrl: 'scripts/statusReport/partials/statusReport.html',
265 controller: 'statusReportCtrl',
266 title: 'Status Report | ',
267 resolve: {
268 workspaceData: function($route, workspacesFact){
269 return workspacesFact.get($route.current.params.wsId);
270 }
271 }
272 }).
273 when('/status/ws', {
274 templateUrl: 'scripts/workspaces/partials/list.html',
275 controller: 'workspacesCtrl',
276 title: 'Status Report | ',
277 resolve: {
278 workspaceData: function($route, workspacesFact){
279 return workspacesFact.get($route.current.params.wsId);
280 }
281 }
282 }).
283 when('/status', {
284 templateUrl: 'scripts/workspaces/partials/list.html',
285 controller: 'workspacesCtrl',
286 title: 'Status Report | '
287 }).
288 when('/workspaces', {
289 templateUrl: 'scripts/workspaces/partials/list.html',
290 controller: 'workspacesCtrl',
291 title: 'Workspaces | '
292 }).
293 when('/comparison', {
294 templateUrl: 'scripts/commons/partials/commercial.html',
295 controller: 'commercialCtrl'
296 }).
297 when('/webshell', {
298 templateUrl: 'scripts/commons/partials/commercial.html',
299 controller: 'commercialCtrl'
300 }).
301 when('/executive', {
302 templateUrl: 'scripts/commons/partials/commercial.html',
303 controller: 'commercialCtrl',
304 title: 'Executive Report | '
305 }).
306 when('/workflows', {
307 templateUrl: 'scripts/commons/partials/commercial.html',
308 controller: 'commercialCtrl',
309 title: 'Workflows | '
310 }).
311 when('/scheduling', {
312 templateUrl: 'scripts/commons/partials/commercial.html',
313 controller: 'commercialCtrl',
314 title: 'Scheduling | '
315 }).
316 when('/login', {
317 templateUrl: 'scripts/auth/partials/login.html',
318 controller: 'loginCtrl',
319 title: 'Login | '
320 }).
321 when('/users', {
322 templateUrl: 'scripts/commons/partials/commercial.html',
323 controller: 'commercialCtrl',
324 title: 'Users | '
325 }).
326 when('/credentials', {
327 templateUrl: 'scripts/credentials/partials/list.html',
328 controller: 'credentialsCtrl',
329 title: 'Credentials | '
330 }).
331 when('/credentials/ws', {
332 templateUrl: 'scripts/workspaces/partials/list.html',
333 controller: 'workspacesCtrl',
334 title: 'Credentials | '
335 }).
336 when('/credentials/ws/:wsId', {
337 templateUrl: 'scripts/credentials/partials/list.html',
338 controller: 'credentialsCtrl',
339 title: 'Credentials | '
340 }).
341 when('/credentials/ws/:wsId/hid/:hId', {
342 templateUrl: 'scripts/credentials/partials/list.html',
343 controller: 'credentialsCtrl',
344 title: 'Credentials | '
345 }).
346 when('/credentials/ws/:wsId/sid/:sId', {
347 templateUrl: 'scripts/credentials/partials/list.html',
348 controller: 'credentialsCtrl',
349 title: 'Credentials | '
350 }).
351 when('/vulndb', {
352 templateUrl: 'scripts/vulndb/partials/vulndb.html',
353 controller: 'vulnModelsCtrl',
354 title: 'Vulnerabilities | '
355 }).
356 when('/data_analysis', {
357 templateUrl: 'scripts/commons/partials/commercial.html',
358 controller: 'commercialCtrl'
359 }).
360 when('/taskgroup', {
361 templateUrl: 'scripts/commons/partials/commercial.html',
362 controller: 'commercialCtrl',
363 title: 'Methodologies | '
364 }).
365 when('/forbidden', {
366 templateUrl: 'scripts/auth/partials/forbidden.html',
367 title: ' Forbidden | '
368 }).
369 when('/workspace-worth/ws/:wsId', {
370 templateUrl: 'scripts/dashboard/partials/vulns-by-price.html',
371 controller: 'vulnsByPriceCtrl',
372 title: ' Workspace worth | '
373 }).
374 when('/admin', {
375 templateUrl: 'scripts/admin/admin.html',
376 controller: 'adminCtrl',
377 title: ' Admin | '
378 }).
379 when('/admin/:item', {
380 templateUrl: 'scripts/admin/admin.html',
381 controller: 'adminCtrl',
382 title: ' Admin | '
383 }).
384 otherwise({redirectTo:'/'});
385 }]);
386
387 faradayApp.run(['$location', '$rootScope', 'loginSrv', function($location, $rootScope, loginSrv) {
388 $rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
389 if(current.hasOwnProperty('$$route')) {
390 $rootScope.title = current.$$route.title;
391 }
392 });
393 }]);
+0
-50
faraday/server/www/scripts/attachments/providers/attachments.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('attachmentsFact', ['BASEURL', '$http', '$q', function(BASEURL, $http, $q) {
6 var attachmentsFact = {};
7
8 // receives an array of File objects
9 // returns an array of promises
10 attachmentsFact.loadAttachments = function(files) {
11 var deferred = $q.defer(),
12 promises = [],
13 tmp = {};
14 for(var name in files) {
15 if(files.hasOwnProperty(name)) {
16 var file = files[name];
17 file.name = name;
18 promises.push(attachmentsFact.loadAttachment(file));
19 }
20 }
21 $q.all(promises).then(function(attachments) {
22 attachments.forEach(function(attachment) {
23 tmp[attachment.filename] = attachment.value;
24 });
25 deferred.resolve(tmp);
26 });
27
28 return deferred.promise;
29 };
30
31 // receives a File object
32 // returns a promise
33 attachmentsFact.loadAttachment = function(file) {
34 var deferred = $q.defer(),
35 filename = encodeURIComponent(file.name),
36 filetype = file.type.replace("/", "\/"),
37 fileReader = new FileReader();
38 fileReader.readAsDataURL(file);
39 fileReader.onloadend = function (readerEvent) {
40 result = readerEvent.target.result;
41 result = result.slice(result.indexOf(',')+1);
42 deferred.resolve({"filename": filename, "value": {"content_type": filetype, "data": result}});
43 };
44
45 return deferred.promise;
46 };
47
48 return attachmentsFact;
49 }]);
+0
-37
faraday/server/www/scripts/auth/controllers/forgotPassword.js less more
0 angular.module('faradayApp').controller('forgotPasswordCtrl', ['$modalInstance', '$scope', 'AccountSrv',
1 function($modalInstance, $scope, AccountSrv) {
2
3 $scope.cancel = function() {
4 $modalInstance.dismiss('cancel');
5 };
6
7 $scope.data;
8
9 init = function () {
10 $scope.data = {
11 "email": "",
12 "recover":{
13 "valid" : false,
14 "not_found": false
15 }
16 };
17 };
18
19 $scope.recover = function(){
20 if ($scope.data.email){
21 loginSrv.recover($scope.data.email).then(function(result){
22 $scope.data.recover.valid = true;
23 $scope.data.recover.not_found = false;
24 //$modalInstance.close();
25 }, function(){
26 $scope.errorMessage = "Invalid email";
27 $scope.data.recover.valid = false;
28 $scope.data.recover.not_found = true;
29 });
30 } else {
31 $scope.errorMessage = "Email user is required";
32 }
33 };
34
35 init();
36 }]);
+0
-117
faraday/server/www/scripts/auth/controllers/login.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('loginCtrl', ['$scope', '$location', '$cookies', 'loginSrv', 'BASEURL' ,'$uibModal',
6 function($scope, $location, $cookies, loginSrv, BASEURL, $uibModal) {
7
8 $scope.data = {
9 "user": null,
10 "pass": null,
11 "remember": false
12 };
13
14 $scope.errorLoginFlag = false;
15
16 $scope.checkResetError = function(){
17 if($scope.errorLoginFlag == true)
18 $scope.errorMessage = "";
19 };
20
21 $scope.login = function(){
22 if ($scope.data.user && $scope.data.pass){
23 loginSrv.login($scope.data.user, $scope.data.pass, $scope.data.remember).then(function(user){
24 var currentUrl = "/workspaces";
25 if($cookies.currentUrl != undefined) {
26 currentUrl = $cookies.currentUrl;
27 }
28 $location.path(currentUrl);
29 }, function(){
30 $scope.errorMessage = "Invalid user or password";
31 $scope.errorLoginFlag = true;
32 });
33 } else {
34 $scope.errorMessage = "Every field is required";
35 $scope.errorLoginFlag = true;
36 }
37 };
38
39 $scope.$on('$routeChangeSuccess', function(){
40 loginSrv.isAuthenticated().then(function(auth){
41 if(auth) $location.path('/');
42 });
43 });
44
45 $scope._forgotPassword = function () {
46 var modal = $uibModal.open({
47 templateUrl: 'scripts/auth/partials/forgotPassword.html',
48 controller: 'forgotPasswordCtrl',
49 size: ''
50 });
51
52 modal.result.then(function () {
53 debugger;
54 });
55 };
56
57
58 }]);
59
60 angular.module('faradayApp')
61 .controller('loginBarCtrl', ['$scope', '$location', '$cookies','loginSrv', '$uibModal', 'BASEURL', function($scope, $location, $cookies,loginSrv,$uibModal, BASEURL) {
62 $scope.user = null;
63 $scope.auth = loginSrv.isAuth();
64
65 $scope.$watch(loginSrv.isAuth, function(newValue) {
66 loginSrv.getUser().then(function(user){
67 $scope.user = user;
68 $scope.auth = newValue;
69 });
70 });
71
72 $scope.getUser = function(){
73 return $scope.user;
74 };
75
76 $scope.loginPage = function(){
77 $location.path('/login');
78 };
79
80 $scope.logout = function(){
81 loginSrv.logout().then(function(){
82 $location.path('/login');
83 $cookies.currentUrl = "/workspaces";
84 });
85 };
86
87 $scope.changePasswordModal = function(){
88 $scope.base_url = BASEURL;
89 $scope.modal = $uibModal.open({
90 templateUrl: 'scripts/auth/partials/changePassword.html',
91 controller: 'resetPassword',
92 size: 'lg'
93 });
94 }
95
96 }]);
97
98 angular.module('faradayApp')
99 .controller('loginBackgroundCtrl', ['$scope', '$location', '$cookies', function($scope, $location, $cookies) {
100 $scope.component = "";
101 $scope.isLogin = true;
102
103 $scope.updateComponent = function() {
104 if($location.path() == "") {
105 $scope.component = "home";
106 } else {
107 $scope.component = $location.path().split("/")[1];
108 }
109 $cookies.currentComponent = $scope.component;
110 $scope.isLogin = $scope.component == "login";
111 };
112
113 $scope.$on('$locationChangeSuccess', function() {
114 $scope.updateComponent();
115 });
116 }]);
+0
-51
faraday/server/www/scripts/auth/controllers/resetPassword.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('resetPassword', ['$modalInstance', '$scope', 'AccountSrv',
6 function($modalInstance, $scope, AccountSrv) {
7
8 // Change Password Modal controller
9
10 $scope.data;
11
12 init = function () {
13 $scope.data = {
14 "current": "",
15 "newPassword": "",
16 "newPasswordRepeat": ""
17 };
18 };
19
20 $scope.open = function($event, isStart) {
21 $event.preventDefault();
22 $event.stopPropagation();
23 };
24
25 $scope.ok = function(){
26 AccountSrv.changePassword($scope.data).then(
27 function(response, statusText, xhrObj){
28 $modalInstance.close()
29 }, function(xhrObj, textStatus, err) {
30 if (xhrObj.data.response.errors.password != undefined) {
31 $scope.form.current.$setValidity("current", false);
32 }
33 if (xhrObj.data.response.errors.new_password_confirm != undefined) {
34 $scope.form.password.$setValidity("password", true);
35 $scope.form.passRepeat.$setValidity("passRepeat", false);
36 }
37 });
38 };
39
40 $scope.resetError = function() {
41 $scope.form.current.$setValidity('current', true);
42
43 }
44
45 $scope.cancel = function() {
46 $modalInstance.dismiss('cancel');
47 };
48
49 init();
50 }]);
+0
-21
faraday/server/www/scripts/auth/directives/compareTo.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 // http://odetocode.com/blogs/scott/archive/2014/10/13/confirm-password-validation-in-angularjs.aspx
4 angular.module('faradayApp')
5 .directive('compareTo', [function() {
6 return {
7 require: "ngModel",
8 scope: {
9 otherModelValue: "=compareTo"
10 },
11 link: function(scope, element, attributes, ngModel) {
12 ngModel.$validators.compareTo = function(modelValue) {
13 return modelValue == scope.otherModelValue;
14 };
15 scope.$watch("otherModelValue", function() {
16 ngModel.$validate();
17 });
18 }
19 };
20 }]);
+0
-69
faraday/server/www/scripts/auth/partials/changePassword.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3 <form name="form" novalidate >
4 <div class="modal-header">
5 <div class="modal-button">
6 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid">Change</button>
7 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
8 </div>
9 <h3 class="modal-title">Change password {{user.name}}</h3>
10 </div>
11 <div class="modal-body">
12 <div class="form-horizontal">
13 <div ng-if="error_message">
14 <div class="alert alert-danger alert-dismissible" role="alert">
15 <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
16 <h5>{{error_message}}</h5>
17 </div> <!-- .alert -->
18 </div> <!-- ng-if -->
19 <h5>Please type current password</h5>
20 <div class="form-group">
21 <div class="col-md-6">
22 <label class="sr-only" for="user-pass">Current Password</label>
23 <input type="password" class="form-control" id="user-currentpass" name="current" placeholder="Password" ng-model="data.current" ng-change="resetError()" />
24 </div>
25
26 </div>
27 <div class="alert alert-danger target_not_selected" role="alert" ng-show="form.current.$invalid && form.current.$dirty">
28 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
29 <span class="sr-only">Error:</span>
30 <button type="button" class="close" data-dismiss="alert"><span area-hidden="true">&times;</span><span class="sr-only">Close</span></button>
31 Invalid Password
32 </div>
33 <h5>New password (must be at least 8 characters long) </h5>
34 <div class="form-group">
35 <div class="col-md-6">
36 <label class="sr-only" for="user-pass">Password</label>
37 <input type="password" class="form-control" id="user-pass" name="password" placeholder="Password" ng-model="data.newPassword" ng-pattern="/^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[\d\W]).*$/" />
38 </div>
39 <div class="col-md-6" ng-class="{'has-error': form.passRepeat.$invalid }">
40 <label class="sr-only" for="user-pass-repeat">Repeat password</label>
41 <input type="password" class="form-control" id="user-pass-repeat" name="passRepeat" placeholder="Repeat password" ng-model="data.newPasswordRepeat" ng-pattern="/^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[\d\W]).*$/" ng-required="data.newPassword" compare-to="data.newPassword" />
42 </div>
43 </div>
44 <div ng-if="form.password.$invalid">
45 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="">
46 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
47 <span class="sr-only">Error:</span>
48 <button type="button" class="close" data-dismiss="alert"><span area-hidden="true">&times;</span><span class="sr-only">Close</span></button>
49 Password must be at least 8 characters long. It must contain at least one uppercase letter and one of the following: numbers (0-9) or special characters ( ~!@#$%^&*_-+=`|\(){}[]:;"'<>,.?/ )
50 </div>
51 </div>
52 <div ng-if="!form.newPassword.$invalid && form.newPasswordRepeat.$invalid">
53 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="">
54 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
55 <span class="sr-only">Error:</span>
56 <button type="button" class="close" data-dismiss="alert"><span area-hidden="true">&times;</span><span class="sr-only">Close</span></button>
57 Passwords don't match
58 </div>
59 </div>
60 </div>
61 </div><!-- .modal-body -->
62 <div class="modal-footer">
63 <div class="modal-button">
64 <button class="btn btn-success" ng-disabled="form.$invalid" ng-click="ok()">Change</button>
65 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
66 </div>
67 </div>
68 </form>
+0
-16
faraday/server/www/scripts/auth/partials/forbidden.html less more
0 <section id="main" class="seccion">
1 <div class="faraday-header-border-fix">
2 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
3 <div id="reports-main" class="fila clearfix">
4 <div class="centrado">
5 <img src="images/logo-faraday.svg" class="faraday-iso"/>
6 <div class="home-list">
7 <h1>Forbidden</h1>
8 </div>
9 </div>
10 <div class="forbidden-error">
11 <h3>You don't have the permissions or It is either read-protected (readonly workspace)</h3>
12 </div>
13 </div>
14 </div><!-- #reports-main --></div><!-- .right-main -->
15 </section><!-- #main -->
+0
-41
faraday/server/www/scripts/auth/partials/forgotPassword.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3 <form name="form" novalidate >
4 <div class="modal-header">
5 <h3 class="modal-title">Recover password</h3>
6 </div>
7 <div class="modal-body">
8 <div class="row">
9 <div class="col-md-10 col-md-offset-1">
10 <div ng-if="data.recover.valid">
11 <div class="alert alert-success target_not_selected" role="alert" ng-hide="">
12 <span class="sr-only">Success!</span>
13 A recovery email has been sent to {{data.email}}.
14 </div>
15 </div>
16 <div ng-if="data.recover.not_found">
17 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="">
18 <span class="sr-only">Error!</span>
19 The email {{data.email}} is invalid.
20 </div>
21 </div>
22
23 <div class="form-input margin-top-10px">
24 <label>
25 <input type="email" required id="email" ng-model="data.email" ng-keyup="$event.keyCode == 13 && recover()" ng-class="{'has-error': errorMessage !== undefined }">
26 <span class="placeholder">Please enter your email for recovery instructions</span>
27 </label>
28 </div>
29 <p class="font-xs font-bold fg-red pull-left margin-top-18px">{{errorMessage}}</p>
30 </div>
31 </div>
32
33 </div><!-- .modal-body -->
34 <div class="modal-footer">
35 <div class="modal-button">
36 <button class="btn btn-success" ng-disabled="form.$invalid" ng-click="recover()">Recover</button>
37 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
38 </div>
39 </div>
40 </form>
+0
-41
faraday/server/www/scripts/auth/partials/login.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3 <div id="login-main" class="">
4 <div id="login-container" class="">
5 <section id="main" class="">
6 <div id="form-signin">
7 <img src="images/logo-faraday.svg" class="height-39px"/>
8 <h3 class="clear-margin-bottom margin-top-22px">Sign in</h3>
9 <div class="form-input margin-top-30px">
10 <label>
11 <input id="username" ng-model="data.user" ng-change="checkResetError()" ng-keyup="$event.keyCode == 13 && login()" ng-class="{'has-error': errorMessage !== undefined }" required>
12 <span class="placeholder">Enter your username</span>
13 </label>
14 </div>
15 <div class="form-input margin-top-30px">
16 <label>
17 <input id="password" type="password" ng-model="data.pass" ng-change="checkResetError()" ng-keyup="$event.keyCode == 13 && login()" ng-class="{'has-error': errorMessage !== undefined }" required>
18 <span class="placeholder">
19 Password
20 <div class="frd-icon frd-icon-lock pull-right"></div>
21 </span>
22 </label>
23 </div>
24 <div class="form-input margin-top-30px">
25 <label class="remember-me">
26 <span class="">
27 Remember me
28 </span>
29 <input id="remember" type="checkbox" ng-model="data.remember" ng-change="checkResetError()">
30 </label>
31 </div>
32 <p class="font-xs font-bold fg-red pull-left margin-top-18px">{{errorMessage}}</p>
33 </div><!-- .form-signin -->
34 <button class="btn-frd btn-xl bg-blue btn-block" style="background-color: #00a8e1" type="submit" ng-click="login()">Login</button>
35 </section>
36 </div>
37 <div id="footer-login">
38 <p class="normal-size fg-white">Faraday Community - <a class="fg-white" href="https://www.faradaysec.com">faradaysec.com</a></p>
39 </div>
40 </div>
+0
-22
faraday/server/www/scripts/auth/services/account.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp').
5 factory('AccountSrv', ["BASEURL", 'ServerAPI', function(BASEURL, ServerAPI){
6 return {
7 changePassword: function(data) {
8 api_data = {
9 "new_password": data.newPassword,
10 "new_password_confirm": data.newPasswordRepeat,
11 "password": data.current
12 }
13 return ServerAPI.changePassword(api_data);
14 }
15 }
16 }]);
17
18 angular.module('faradayApp').
19 config(['$httpProvider', function($httpProvider) {
20 $httpProvider.interceptors.push('AuthInterceptor');
21 }]);
+0
-37
faraday/server/www/scripts/auth/services/interceptor.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp').
5 factory('AuthInterceptor', ['$q', '$location', '$cookies', 'loginSrv',
6 function($q, $location, $cookies, loginSrv){
7 return {
8 response: function(response){
9 return response;
10 },
11
12 responseError: function(response) {
13 if(response.status === 401){
14 var deferred = $q.defer();
15 loginSrv.isAuthenticated().then(function(auth){
16 if(!auth) {
17 $location.path('/login');
18 $cookies.currentComponent;
19 }
20 return deferred.reject(response);
21 });
22 return deferred.promise;
23 }else if (response.status === 403) {
24 $location.path('/forbidden');
25 return $q.reject(response);
26 }else{
27 return $q.reject(response);
28 }
29 }
30 }
31 }]);
32
33 angular.module('faradayApp').
34 config(['$httpProvider', function($httpProvider) {
35 $httpProvider.interceptors.push('AuthInterceptor');
36 }]);
+0
-121
faraday/server/www/scripts/auth/services/login.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .service('loginSrv', ['BASEURL', '$q', '$cookies', function(BASEURL, $q, $cookies) {
6
7 loginSrv = {
8 is_authenticated: false,
9 user_obj: null,
10 last_time_checked: new Date(0),
11
12 login: function(user, pass, remember){
13 var deferred = $q.defer();
14 $.ajax({
15 type: 'POST',
16 url: BASEURL + '_api/login',
17 data: JSON.stringify({"email": user, "password": pass, "remember": remember}),
18 dataType: 'json',
19 contentType: 'application/json'
20 })
21 .done(function(){
22 $.getJSON(BASEURL + '_api/session', function(data) {
23 loginSrv.user_obj = data;
24 loginSrv.last_time_checked = new Date();
25 loginSrv.is_authenticated = true;
26 deferred.resolve(loginSrv.user_obj);
27 });
28 })
29 .fail(function(){
30 loginSrv.is_authenticated = false;
31 loginSrv.user_obj = null;
32 deferred.reject();
33 });
34 return deferred.promise;
35 },
36
37 _check: function(deferred) {
38 $.getJSON(BASEURL + '_api/session', function(data) {
39 loginSrv.user_obj = data;
40 loginSrv.is_authenticated = true;
41 loginSrv.last_time_checked = new Date();
42 deferred.resolve(loginSrv.is_authenticated);
43 }).fail(function(){
44 loginSrv.user_obj = null;
45 loginSrv.is_authenticated = false;
46 loginSrv.last_time_checked = new Date();
47 deferred.resolve(loginSrv.is_authenticated);
48 });
49 },
50
51 isAuthenticated: function(){
52 var deferred = $q.defer();
53 var seconds = (new Date() - loginSrv.last_time_checked) / 1000;
54 if (seconds > 1){
55 //more than one second since checked for last time
56 loginSrv._check(deferred);
57 } else {
58 deferred.resolve(loginSrv.is_authenticated);
59 }
60 return deferred.promise;
61 },
62
63 isAuth: function(){
64 return loginSrv.is_authenticated;
65 },
66
67 getUser: function(){
68 var deferred = $q.defer();
69 $.getJSON(BASEURL + '_api/session', function(data) {
70 loginSrv.user_obj = data;
71 deferred.resolve(loginSrv.user_obj);
72 })
73 .fail(function(){
74 deferred.reject();
75 });
76 return deferred.promise;
77 },
78
79 logout: function(){
80 var deferred = $q.defer();
81 var callback = function(){
82 loginSrv.is_authenticated = false;
83 loginSrv.user_obj = null;
84 deferred.resolve();
85 }
86 $cookies.remove('remember_token');
87 $.ajax({
88 url: BASEURL + '_api/logout',
89 type: 'GET',
90 success: callback,
91 error: callback
92 });
93 return deferred.promise;
94 },
95
96 recover: function(email){
97 var deferred = $q.defer();
98
99 $.ajax({
100 type: 'POST',
101 url: BASEURL + '_api/auth/forgot_password',
102 data: JSON.stringify({"email": email}),
103 dataType: 'json',
104 contentType: 'application/json'
105 })
106 .done(function(data){
107 deferred.resolve(data);
108 })
109 .fail(function(){
110 deferred.reject();
111 });
112
113 return deferred.promise;
114 }
115 }
116
117 loginSrv.isAuthenticated();
118
119 return loginSrv;
120 }]);
+0
-25
faraday/server/www/scripts/commons/controllers/commercialCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('commercialCtrl',
6 ['$scope', '$location',
7 function($scope, $location) {
8 loginSrv.isAuthenticated().then(function(auth){
9 if(!auth) {
10 $location.path('/login');
11 }
12 });
13 if ($location.path().split("/")[1] === "executive") {
14 $scope.header = "executive report";
15 } else if ($location.path().split("/")[1] === "comparison") {
16 $scope.header = "workspace comparison";
17 } else if ($location.path().split("/")[1] === "communication") {
18 $scope.header = "chat";
19 } else if ($location.path().split("/")[1] === "data_analysis") {
20 $scope.header = "data analysis";
21 } else {
22 $scope.header = $location.path().split("/")[1];
23 }
24 }]);
+0
-166
faraday/server/www/scripts/commons/controllers/headerCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('headerCtrl', [
6 '$scope',
7 '$routeParams',
8 '$location',
9 '$cookies',
10 'dashboardSrv',
11 'workspacesFact',
12 'vulnsManager',
13 '$uibModal',
14 function ($scope,
15 $routeParams,
16 $location,
17 $cookies,
18 dashboardSrv,
19 workspacesFact,
20 vulnsManager,
21 $uibModal) {
22
23 $scope.confirmed = ($cookies.get('confirmed') == undefined) ? false : JSON.parse($cookies.get('confirmed'));
24 $scope.confirmed ? $cookies.put('filterConfirmed', "Confirmed"): $cookies.put('filterConfirmed', "All");
25
26 $scope.showSwitcher = function() {
27 var noSwitcher = [
28 "", "home", "login", "index", "workspaces", "users", "licenses",
29 "taskgroup", "executive", // Only for white versions!!
30 "vulndb", "comparison", "webshell", "help", "forbidden", "data_analysis"
31 ];
32 return noSwitcher.indexOf($scope.component) < 0;
33 };
34
35 // Ugly, ugly, ugly hack
36 $scope.vulnsNum = vulnsManager.getVulnsNum($routeParams.wsId);
37 $scope.totalVulns = vulnsManager.getTotalVulns($routeParams.wsId);
38 $scope.logo_url = "images/logo-faraday-blanco.svg";
39 setInterval(function(){
40 $scope.vulnsNum = vulnsManager.getVulnsNum($routeParams.wsId);
41 $scope.totalVulns = vulnsManager.getTotalVulns($routeParams.wsId);
42 $scope.$apply();
43 }, 500)
44
45 $scope.toggleConfirmed = function() {
46 $scope.confirmed = !$scope.confirmed;
47 dashboardSrv.setConfirmed($scope.confirmed);
48 dashboardSrv.updateData();
49 };
50
51 $scope.updateWorkspace = function(ws, wsName, finally_){
52 if(typeof(ws.duration.start_date) == "number") {
53 start_date = ws.duration.start_date;
54 } else if(ws.duration.start_date) {
55 start_date = ws.duration.start_date.getTime();
56 } else {start_date = "";}
57 if(typeof(ws.duration.end_date) == "number") {
58 end_date = ws.duration.end_date;
59 } else if(ws.duration.end_date) {
60 end_date = ws.duration.end_date.getTime();
61 } else {end_date = "";}
62 duration = {'start_date': start_date, 'end_date': end_date};
63 workspace = {
64 "_id": ws._id,
65 "_rev": ws._rev,
66 "children": ws.children,
67 "customer": ws.customer,
68 "description": ws.description,
69 "duration": duration,
70 "name": ws.name,
71 "scope": ws.scope,
72 "type": ws.type
73 };
74 workspacesFact.update(workspace, wsName).then(function(workspace) {
75 if (finally_) finally_(workspace);
76 $location.path($scope.location + "/ws/" + workspace.name);
77 }, function(error){
78 if (finally_) finally_(workspace);
79 var modal = $uibModal.open({
80 templateUrl: 'scripts/commons/partials/modalKO.html',
81 controller: 'commonsModalKoCtrl',
82 resolve: {
83 msg: function() {
84 if (error.status == 409){
85 return "A workspace with that name already exists";
86 }
87 return error;
88 }
89 }
90 });
91 });
92 };
93
94 $scope.editWorkspace = function() {
95 if($scope.workspace !== undefined) {
96 var workspace;
97 var index = -1;
98 $scope.workspaces.forEach(function(w, i) {
99 if(w.name === $scope.workspace) {
100 workspace = w;
101 index = i;
102 }
103 });
104
105 // copy pasted from server/www/scripts/workspaces/controllers/workspaces.js
106 // it makes scope work properly (i think)
107 workspace.scope = workspace.scope.map(function(scope){
108 if(scope.key === undefined)
109 return {key: scope};
110 return scope;
111 });
112 if (workspace.scope.length == 0) workspace.scope.push({key: ''});
113
114 var oldName = $scope.workspace;
115 var modal = $uibModal.open({
116 templateUrl: 'scripts/workspaces/partials/modalEdit.html',
117 backdrop : 'static',
118 controller: 'workspacesModalEdit',
119 size: 'lg',
120 resolve: {
121 ws: function() {
122 return workspace;
123 }
124 }
125 });
126
127 modal.result.then(function(workspace) {
128 // The API expects list of strings in scope
129 // var old_scope = workspace.scope;
130 workspace.scope = workspace.scope.map(function(scope){
131 return scope.key;
132 }).filter(Boolean);
133
134 $scope.updateWorkspace(workspace, oldName, function(workspace){
135 // workspace.scope = old_scope;
136 $scope.workspaces[index] = angular.copy(workspace);
137 });
138 });
139 }
140 };
141
142 getWorkspaces = function() {
143 workspacesFact.getWorkspaces().then(function(wss) {
144 // $scope.workspacesNames = [];
145 $scope.workspaces = [];
146
147 wss.forEach(function(ws){
148 // $scope.workspacesNames.push(ws.name);
149 $scope.workspaces.push(ws);
150 });
151 });
152 };
153
154 init = function(name) {
155 $scope.location = $location.path().split('/')[1];
156 $scope.workspace = $routeParams.wsId;
157 if($routeParams.wsId)
158 vulnsManager.loadVulnsCounter($routeParams.wsId);
159
160 getWorkspaces();
161
162 };
163
164 init();
165 }]);
+0
-14
faraday/server/www/scripts/commons/controllers/homeCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('homeCtrl',
6 ['$location', 'loginSrv',
7 function($location, loginSrv) {
8 loginSrv.isAuthenticated().then(function(auth){
9 if(!auth) {
10 $location.path('/login');
11 }
12 });
13 }]);
+0
-214
faraday/server/www/scripts/commons/controllers/modal.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('commonsModalDelete', ['$scope', '$modalInstance', 'msg', function($scope, $modalInstance, msg) {
6 $scope.msg = msg;
7
8 $scope.ok = function() {
9 $modalInstance.close();
10 };
11
12 $scope.cancel = function() {
13 $modalInstance.dismiss('cancel');
14 };
15 }]);
16
17 angular.module('faradayApp')
18 .controller('commonsModalKoCtrl', ['$scope', '$modalInstance', 'msg', function($scope, $modalInstance, msg) {
19 $scope.msg = msg;
20
21 $scope.ok = function() {
22 $modalInstance.close();
23 };
24 }]);
25
26 angular.module('faradayApp')
27 .controller('commonsModalEditString', ['$scope', '$modalInstance', 'msg', function($scope, $modalInstance, msg) {
28 $scope.msg = msg;
29 $scope.data = {property: ''};
30
31 $scope.ok = function() {
32 $modalInstance.close($scope.data.property);
33 };
34
35 $scope.cancel = function() {
36 $modalInstance.dismiss();
37 }
38 }]);
39 angular.module('faradayApp')
40 .controller('commonsModalEditOptions', ['$scope', '$modalInstance', 'msg', 'options', function($scope, $modalInstance, msg, options) {
41 $scope.msg = msg;
42 $scope.options = options;
43 $scope.data = {property: ''};
44
45 $scope.ok = function() {
46 $modalInstance.close($scope.data.property);
47 };
48
49 $scope.cancel = function() {
50 $modalInstance.dismiss();
51 }
52 }]);
53 angular.module('faradayApp')
54 .controller('commonsModalEditArray', ['$scope', '$modalInstance', 'msg', function($scope, $modalInstance, msg) {
55 $scope.msg = msg;
56 $scope.data = {property: []};
57 $scope.new_value = "";
58
59 $scope.newValue = function() {
60 if ($scope.new_value != "") {
61 // we need to check if the ref already exists
62 if ($scope.data.property.filter(function(ref) {return ref.value === $scope.new_value}).length == 0) {
63 $scope.data.property.push({value: $scope.new_value});
64 $scope.new_value = "";
65 }
66 }
67 }
68
69 $scope.ok = function() {
70 // add the ref in new_ref, if there's any
71 $scope.newValue();
72 // convert refs to an array of strings
73 var values = [];
74 $scope.data.property.forEach(function(val) {
75 values.push(val.value);
76 });
77 $scope.data.property = values;
78
79 $modalInstance.close($scope.data.property);
80 };
81
82 $scope.cancel = function() {
83 $modalInstance.dismiss();
84 }
85 }]);
86 angular.module('faradayApp')
87 .controller('commonsModalEditObject', ['$scope', '$modalInstance', 'msg', 'options', function($scope, $modalInstance, msg, options) {
88 var data = [];
89 $scope.msg = msg;
90 $scope.options = options;
91 $scope.data = {};
92 $scope.impact = {
93 add: [],
94 del: []
95 };
96
97 $scope.addImpact = function(key) {
98 if($scope.impact.add.indexOf(key) === -1 && $scope.impact.del.indexOf(key) === -1) {
99 $scope.impact.add.push(key);
100 }
101 };
102
103 $scope.delImpact = function(key) {
104 if($scope.impact.del.indexOf(key) === -1 && $scope.impact.add.indexOf(key) === -1) {
105 $scope.impact.del.push(key);
106 }
107 };
108
109 $scope.del_backImpact = function(key) {
110 var i = $scope.impact.del.indexOf(key);
111 if(i != -1) {
112 $scope.impact.del.splice(i, 1);
113 }
114 };
115
116 $scope.add_backImpact = function(key) {
117 var i = $scope.impact.add.indexOf(key);
118 if(i != -1) {
119 $scope.impact.add.splice(i, 1);
120 }
121 };
122
123 $scope.ok = function() {
124 for(opt in $scope.options){
125 if($scope.impact.add.indexOf(opt) != -1) {
126 $scope.data[opt] = true;
127 }
128 if($scope.impact.del.indexOf(opt) != -1) {
129 $scope.data[opt] = false;
130 }
131 }
132 $modalInstance.close($scope.data);
133 };
134
135 $scope.cancel = function() {
136 $modalInstance.dismiss();
137 }
138 }]);
139 angular.module('faradayApp')
140 .controller('commonsModalEditCWE', ['$scope', '$modalInstance', 'msg', 'vulnModelsManager', function($scope, $modalInstance, msg, vulnModelsManager) {
141 $scope.cweList = [];
142 vulnModelsManager.get().then(function(data) {
143 $scope.cweList = data;
144 });
145 $scope.cweLimit = 5;
146 $scope.cwe_filter = "";
147 $scope.msg = msg;
148
149 $scope.data = {
150 name: "",
151 desc: "",
152 resolution: "",
153 refs: []
154 };
155
156 $scope.new_ref = "";
157
158 $scope.populate = function(item) {
159 for (var key in $scope.data) {
160 if (key != "refs" && item.hasOwnProperty(key) && $scope.data.hasOwnProperty(key)) {
161 $scope.data[key] = item[key];
162 }
163 }
164 // convert refs to an array of objects
165 var refs = [];
166 item.refs.forEach(function(ref) {
167 refs.push({value: ref});
168 });
169 $scope.data.refs = refs;
170 };
171
172 $scope.ok = function() {
173 if($scope.formCWE.$valid) {
174 // add the ref in new_ref, if there's any
175 $scope.newReference();
176 // convert refs to an array of strings
177 var refs = [];
178 $scope.data.refs.forEach(function(ref) {
179 refs.push(ref.value);
180 });
181 $scope.data.refs = refs;
182
183 $modalInstance.close($scope.data);
184 }
185 };
186
187 $scope.newReference = function() {
188 if ($scope.new_ref != "") {
189 // we need to check if the ref already exists
190 if ($scope.data.refs.filter(function(ref) {return ref.value === $scope.new_ref}).length == 0) {
191 $scope.data.refs.push({value: $scope.new_ref});
192 $scope.new_ref = "";
193 }
194 }
195 }
196
197 $scope.cancel = function() {
198 $modalInstance.dismiss();
199 }
200 }]);
201
202 angular.module('faradayApp')
203 .controller('commonsModalExploitsCtrl',
204 ['$scope', '$modalInstance', 'msg',
205 function($scope, $modalInstance, msg) {
206
207 $scope.objsCve = msg;
208
209 $scope.ok = function() {
210 $modalInstance.close();
211 };
212
213 }]);
+0
-61
faraday/server/www/scripts/commons/directives/angular-simple-pagination.js less more
0 'use strict';
1
2 angular.module('angularSimplePagination', []).directive('simplePagination', SimplePagination);
3
4 function SimplePagination() {
5 return {
6 restrict: 'E',
7 scope: {
8 currentPage: '=',
9 offset: '=',
10 pageLimit: '=',
11 pageLimits: '=',
12 total: '=',
13 onUpdate: '&'
14 },
15 bindToController: true,
16 controller: SimplePaginationController,
17 controllerAs: 'pagination',
18 template: '\n <div class="simple-pagination">\n <p class="simple-pagination__items">Showing {{pagination.pageLimit}} out of {{pagination.total}}</p>\n <p>\n <button ng-click="pagination.previousPage()" ng-disabled="pagination.currentPage <= 0" class="simple-pagination__button simple-pagination__button--prev">\n &#10094;\n </button>\n <span class="simple-pagination__pages">{{pagination.currentPage + 1}} of {{pagination.getTotalPages()}}</span>\n <button ng-click="pagination.nextPage()" ng-disabled="pagination.currentPage === (pagination.getTotalPages() - 1)" class="simple-pagination__button simple-pagination__button--next">\n &#10095;\n </button>\n </p>\n <p class="simple-pagination__page-limit">\n <span class="simple-pagination__page-limit__option" ng-repeat="limit in pagination.pageLimits" ng-if="limit < pagination.total">\n <a href="" ng-click="pagination.setItemsPerPages(limit)" ng-class="{\'active\': pagination.isCurrentPageLimit(limit)}">{{limit}}</a>\n </span>\n <span>\n <a href="" ng-click="pagination.setItemsPerPages(pagination.total)" ng-class="{\'active\': pagination.isCurrentPageLimit(pagination.total)}">All</a>\n </span>\n </p>\n </div>\n '
19 };
20 }
21
22 function SimplePaginationController() {
23 var self = this;
24
25 self.currentPage = self.currentPage || 0;
26 self.pageLimit = self.pageLimit || self.pageLimits[0];
27
28 self.setItemsPerPages = function (max) {
29 self.pageLimit = max >= self.total ? self.total : max;
30 self.currentPage = 0;
31 self.offset = 0;
32 invokeCallback();
33 };
34
35 self.nextPage = function () {
36 self.currentPage += 1;
37 self.offset = self.currentPage * self.pageLimit;
38 invokeCallback();
39 };
40
41 self.previousPage = function () {
42 self.currentPage -= 1;
43 self.offset = self.currentPage * self.pageLimit;
44 invokeCallback();
45 };
46
47 self.getTotalPages = function () {
48 return Math.ceil(self.total / self.pageLimit);
49 };
50
51 self.isCurrentPageLimit = function (value) {
52 return self.pageLimit == value;
53 };
54
55 function invokeCallback() {
56 if (self.onUpdate) {
57 self.onUpdate();
58 }
59 }
60 }
+0
-102
faraday/server/www/scripts/commons/directives/contenteditable.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 /**
5 * @see http://docs.angularjs.org/guide/concepts
6 * @see http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController
7 * @see https://github.com/angular/angular.js/issues/528#issuecomment-7573166
8 */
9
10 angular.module('faradayApp')
11 .directive('contenteditable', ['$timeout', function($timeout) { return {
12 restrict: 'A',
13 require: '?ngModel',
14 link: function(scope, element, attrs, ngModel) {
15 // don't do anything unless this is actually bound to a model
16 if (!ngModel) {
17 return
18 }
19
20 // options
21 var opts = {}
22 angular.forEach([
23 'stripBr',
24 'noLineBreaks',
25 'selectNonEditable',
26 'moveCaretToEndOnChange',
27 ], function(opt) {
28 var o = attrs[opt]
29 opts[opt] = o && o !== 'false'
30 })
31
32 // view -> model
33 element.bind('input', function(e) {
34 scope.$apply(function() {
35 var html, html2, rerender
36 html = element.html()
37 rerender = false
38 if (opts.stripBr) {
39 html = html.replace(/<br>$/, '')
40 }
41 if (opts.noLineBreaks) {
42 html2 = html.replace(/<div>/g, '').replace(/<br>/g, '').replace(/<\/div>/g, '')
43 if (html2 !== html) {
44 rerender = true
45 html = html2
46 }
47 }
48 ngModel.$setViewValue(html)
49 if (rerender) {
50 ngModel.$render()
51 }
52 if (html === '') {
53 // the cursor disappears if the contents is empty
54 // so we need to refocus
55 $timeout(function(){
56 element[0].blur()
57 element[0].focus()
58 })
59 }
60 })
61 })
62
63 // model -> view
64 var oldRender = ngModel.$render
65 ngModel.$render = function() {
66 var el, el2, range, sel
67 if (!!oldRender) {
68 oldRender()
69 }
70 element.html(ngModel.$viewValue || '')
71 if (opts.moveCaretToEndOnChange) {
72 el = element[0]
73 range = document.createRange()
74 sel = window.getSelection()
75 if (el.childNodes.length > 0) {
76 el2 = el.childNodes[el.childNodes.length - 1]
77 range.setStartAfter(el2)
78 } else {
79 range.setStartAfter(el)
80 }
81 range.collapse(true)
82 sel.removeAllRanges()
83 sel.addRange(range)
84 }
85 }
86 if (opts.selectNonEditable) {
87 element.bind('click', function(e) {
88 var range, sel, target
89 target = e.toElement
90 if (target !== this && angular.element(target).attr('contenteditable') === 'false') {
91 range = document.createRange()
92 sel = window.getSelection()
93 range.setStartBefore(target)
94 range.setEndAfter(target)
95 sel.removeAllRanges()
96 sel.addRange(range)
97 }
98 })
99 }
100 }
101 }}]);
+0
-26
faraday/server/www/scripts/commons/directives/file.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 /**
5 * @see http://docs.angularjs.org/guide/concepts
6 * @see http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController
7 * @see https://github.com/angular/angular.js/issues/528#issuecomment-7573166
8 */
9
10
11 angular.module('faradayApp')
12 .directive('validFile',function(){
13 return {
14 require:'ngModel',
15 link:function(scope,el,attrs,ngModel){
16 //change event is fired when file is selected
17 el.bind('change',function(){
18 scope.$apply(function(){
19 ngModel.$setViewValue(el.val());
20 ngModel.$render();
21 });
22 });
23 }
24 }
25 });
+0
-19
faraday/server/www/scripts/commons/directives/fileModel.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp').directive('fileModel', ['$parse', function ($parse) {
5 return {
6 restrict: 'A',
7 link: function(scope, element, attrs) {
8 var model = $parse(attrs.fileModel);
9 var modelSetter = model.assign;
10
11 element.bind('change', function(){
12 scope.$apply(function(){
13 modelSetter(scope, element[0].files[0]);
14 });
15 });
16 }
17 };
18 }]);
+0
-23
faraday/server/www/scripts/commons/directives/osintLink.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 /**
5 * @see http://docs.angularjs.org/guide/concepts
6 * @see http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController
7 * @see https://github.com/angular/angular.js/issues/528#issuecomment-7573166
8 */
9
10 // TODO: Refactor to don't do one request to the server for each host
11 // TODO: urlencode query
12
13 angular.module('faradayApp')
14 .directive('osintLink', ['indexFact', function(indexFact){
15 return {
16 scope: {
17 query: '=query',
18 osint: '=osint'
19 },
20 templateUrl: 'scripts/commons/partials/osintLink.html'
21 }
22 }]);
+0
-10
faraday/server/www/scripts/commons/filters/decodeURIComponent.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .filter('decodeURIComponent', function() {
6 return function(x) {
7 return decodeURIComponent(x);
8 };
9 });
+0
-10
faraday/server/www/scripts/commons/filters/encodeURIComponent.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .filter('encodeURIComponent', function() {
6 return function(x) {
7 return encodeURIComponent(x);
8 };
9 });
+0
-18
faraday/server/www/scripts/commons/filters/getByProperty.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 // returns index of object in collection if found or -1
5 angular.module('faradayApp')
6 .filter('getByProperty', function() {
7 return function(propertyName, propertyValue, collection) {
8 var len = collection.length;
9
10 for(var i = 0; i < len; i++) {
11 if(collection[i][propertyName] == propertyValue) {
12 return i;
13 }
14 }
15 return -1;
16 }
17 });
+0
-10
faraday/server/www/scripts/commons/filters/integer.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp').
5 filter('integer', function() {
6 return function(input) {
7 return parseInt(input);
8 }
9 });
+0
-38
faraday/server/www/scripts/commons/filters/markdown.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4
5 angular.module('faradayApp').filter('markdown', function (BASEURL) {
6 var evidenceRender = function () {
7 // This could be a lot more simple code, but
8 // we found a bug on filename with spaces and we need to espape it.
9 // take a look to the history of this extension to see the simple version of this code
10 var ws_index = window.location.href.split('/').indexOf('ws');
11 var workspace = window.location.href.split('/')[ws_index + 1];
12 var evidenceExtension = {
13 type: 'lang',
14 filter: function(text, converter) {
15 var regex = /\(evidence\:(\w+)\:(\d+)\:([a-zA-Z0-9\s_\\.\-\(:]+\.\w+)\)/g;
16 var matches = text.match(regex);
17 var markdown = text;
18 var filename;
19 for (var evidence_index in matches) {
20 filename = escape(matches[evidence_index].split(':')[3].slice(0, -1));
21 evidence = matches[evidence_index].replace(regex, '![$1 With Id $2 Evidence ](' + BASEURL + '_api/v2/ws/' + workspace + '/vulns/$2/attachment/' + filename + '/ =500x281)');
22 console.log(evidence);
23 markdown = markdown.replace(matches[evidence_index], evidence);
24 }
25 return markdown;
26 }
27 };
28 return [evidenceExtension];
29 }
30
31 return function (md) {
32 var converter = new showdown.Converter({extensions: ['table', evidenceRender]});
33 converter.setOption('tables', 'true');
34 converter.setOption('tasklists', 'true');
35 return converter.makeHtml(md);
36 }
37 });
+0
-71
faraday/server/www/scripts/commons/filters/orderObjectBy.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 //Filter to order by field, when you have and object
5 angular.module('faradayApp')
6 .filter('orderObjectBy', ['SEVERITIES',
7 function(SEVERITIES) {
8 return function(items, field, reverse) {
9 var filtered = [];
10 angular.forEach(items, function(item) {
11 filtered.push(item);
12 });
13 filtered.sort(compareItems(field));
14 if(reverse) filtered.reverse();
15 return filtered;
16 };
17
18 function compareItems(field) {
19 return function(a, b) {
20 var res;
21 if(field === 'metadata.create_time') {
22 var arrayField = field.split(".");
23 a = a[arrayField[0]][arrayField[1]];
24 b = b[arrayField[0]][arrayField[1]];
25 } else {
26 a = a[field];
27 b = b[field];
28 }
29 if(typeof(a) == "string" && typeof(b) == "string") {
30 a = a.toLowerCase();
31 b = b.toLowerCase();
32 }
33 res = (a > b || typeof(b) == "undefined" ? 1 : -1);
34 if(field == 'impact'){
35 res = compareImpact(a, b);
36 }
37 if(field == 'severity') {
38 res = compareSeverities(a, b);
39 }
40 return res;
41 }
42 }
43
44 function compareImpact(a, b) {
45 var contA = 0, contB = 0;
46 for(key in a){
47 if(a.hasOwnProperty(key)){
48 if(a[key]){
49 contA = contA + 1;
50 }
51 }
52 }
53 for(key in b){
54 if(b.hasOwnProperty(key)){
55 if(b[key]){
56 contB = contB + 1;
57 }
58 }
59 }
60 return (contA > contB ? 1 : -1);
61 }
62
63 function compareSeverities(a, b) {
64 var res = 1;
65 if(SEVERITIES.indexOf(a) > SEVERITIES.indexOf(b)) {
66 res = -1;
67 }
68 return res;
69 }
70 }]);
+0
-11
faraday/server/www/scripts/commons/filters/removeLinebreaks.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 // removes line breaks \n from text
5
6 angular.module('faradayApp')
7 .filter('removeLinebreaks',function(){
8 return function(text){
9 return text?text.replace(/\n/g, ' '):'';
10 }});
+0
-10
faraday/server/www/scripts/commons/filters/startFrom.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('filter', []).filter('startFrom', function() {
5 return function(input, start) {
6 start = +start; //parse to int
7 return input.slice(start);
8 }
9 });
+0
-91
faraday/server/www/scripts/commons/partials/commercial.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion clearfix">
5 <div class="faraday-header-border-fix"></div>
6 <div class="left-main-without-pagination">
7 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
8 <div id="reports-main" class="fila clearfix">
9 <div class="button-control col-md-4 col-sm-4 col-xs-4" id="btn_bar">
10 <div class="control-wrapper control-new">&nbsp;</div>
11 <table class="col-md-9" ng-if="component == 'executive' || component == 'comparison' || component == 'data_analysis'">
12 <thead>
13 <tr>
14 <th class="col-md-1" style="border-left: 1px solid rgb(221, 221, 221); padding-left: 12px;">
15 <a href="#/executive" class="status-report" ng-class="{'navigation-active' : component == 'executive'}" style="color: black !important; font-weight: bold; font-size: 15px;">
16 Report
17 </a>
18 </th>
19 <th class="col-md-1">
20 <a href="#/comparison" class="workspaces" ng-class="{'navigation-active' : component == 'comparison'}" style="color: black !important; font-weight: bold; font-size: 15px;">
21 Comparison
22 </a>
23 <div class="flex-spacer"></div>
24 </th>
25 <th class="col-md-2" style = "border-right: 1px solid rgb(221, 221, 221); padding-right: 12px">
26 <a href="#/data_analysis" class="workspaces" ng-class="{'navigation-active' : component == 'data_analysis'}" style="color: black !important; font-weight: bold; font-size: 15px;">
27 Data Analysis
28 </a>
29 <div class="flex-spacer"></div>
30 </th>
31 </tr>
32 </thead>
33 </table>
34 <table class="col-md-9" ng-if="component == 'scheduling' || component == 'vulndb'">
35 <thead>
36 <tr>
37 <th class="col-md-1">
38 <a href="#/scheduling" class="workspaces" ng-class="{'navigation-active' : component == 'scheduling'}" style="color: black !important; font-weight: bold; font-size: 15px;">
39 Scheduling
40 </a>
41 <div class="flex-spacer"></div>
42 </th>
43 <th class="col-md-2" style = "border-right: 1px solid rgb(221, 221, 221); padding-right: 12px">
44 <a href="#/vulndb" class="workspaces" ng-class="{'navigation-active' : component == 'vulndb'}" style="color: black !important; font-weight: bold; font-size: 15px;">
45 KB
46 </a>
47 <div class="flex-spacer"></div>
48 </th>
49 </tr>
50 </thead>
51 </table>
52 <table class="col-md-9" ng-if="component == 'taskgroup'">
53 <thead>
54 <tr>
55 <th class="col-md-2" style="border-left: 1px solid rgb(221, 221, 221); padding-left: 12px;">
56 <a href="#/status/ws/{{workspace}}" class="status-report" ng-class="{'navigation-active' : component == 'status'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Vulns" tooltip-placement="right">
57 Vulns
58 </a>
59 </th>
60 <th class="col-md-2">
61 <a href="#/hosts/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'hosts'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Hosts" tooltip-placement="right">
62 Hosts
63 </a>
64 <div class="flex-spacer"></div>
65 </th>
66 <th class="col-md-2">
67 <a href="#/credentials/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'credentials'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Credentials" tooltip-placement="right">
68 Credentials
69 </a>
70 <div class="flex-spacer"></div>
71 </th>
72 <th class="col-md-2" style = "border-right: 1px solid rgb(221, 221, 221); padding-right: 12px">
73 <a href="#/taskgroup" class="executive-report" ng-class="{'navigation-active' : component == 'taskgroup'}" style="color: black !important; font-weight: bold; font-size: 15px;">
74 Tasks
75 </a>
76 <div class="flex-spacer"></div>
77 </th>
78 </tr>
79 </thead>
80 </table>
81 </div>
82 <div class="jumbotron" ng-class="{ 'jumbotron-font':header === 'workspace comparison' }">
83 <h1><b>Welcome to the <span style="text-transform: capitalize;">{{header}}</span> panel!</b></h1>
84 <br><br><br><br>
85 <p>This feature belongs to our commercial versions.
86 <br>
87 For more information, please contact us at <span class="bold">[email protected]</span> or visit <a href="https://www.faradaysec.com">www.faradaysec.com</a>!</p>
88 </div><!-- .jumbotron -->
89 </div><!-- #reports-main --></div><!-- .right-main -->
90 </section><!-- #main -->
+0
-23
faraday/server/www/scripts/commons/partials/editArray.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header">
5 <h5>{{msg}}</h5>
6 </div>
7 <div class="modal-body">
8 <div class="form-group editArray">
9 <div class="input-group margin-bottom-sm">
10 <input type="text" class="form-control" ng-model="new_value"/>
11 <span class="input-group-addon cursor" ng-click="newValue()"><i class="fa fa-plus-circle"></i></span>
12 </div>
13 <div class="input-group margin-bottom-sm reference" ng-repeat="v in data.property">
14 <input type="text" class="form-control" ng-model="v.value" disabled/>
15 <span class="input-group-addon cursor" ng-click="data.property.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
16 </div>
17 </div>
18 </div>
19 <div class="modal-footer editArray">
20 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
21 <button class="btn btn-success" ng-click="ok()">OK</button>
22 </div>
+0
-42
faraday/server/www/scripts/commons/partials/editCWE.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="formCWE">
5 <div class="modal-header">
6 <h5>{{msg}}</h5>
7 </div>
8 <div class="modal-body">
9 <div class="form-group">
10 <h5>Search vulnerability template database by typing in the field below</h5>
11 <input type="text" ng-model="cwe_selected" class="form-control input-sm" placeholder="Search for vulnerability template" uib-typeahead="cwe as cwe.name for cwe in cweList | filter:{name: $viewValue} | limitTo:10" typeahead-on-select="populate($item, $model, $label)">
12 </div>
13 <div class="form-group">
14 <h5>Name</h5>
15 <input type="text" ng-model="data.name" class="form-control input-sm" placeholder="Name" required/>
16 </div>
17 <div class="form-group">
18 <h5>Description</h5>
19 <textarea ng-model="data.desc" class="form-control" placeholder="Description" required></textarea>
20 </div>
21 <div class="form-group">
22 <h5>Resolution</h5>
23 <textarea ng-model="data.resolution" class="form-control" placeholder="Resolution"></textarea>
24 </div>
25 <div class="form-group editArray">
26 <h5>References</h5>
27 <div class="input-group margin-bottom-sm">
28 <input type="text" class="form-control" placeholder="Reference" ng-model="new_ref"/>
29 <span class="input-group-addon cursor" ng-click="newReference()"><i class="fa fa-plus-circle"></i></span>
30 </div>
31 <div class="input-group margin-bottom-sm reference" ng-repeat="reference in data.refs">
32 <input type="text" class="form-control" placeholder="Reference" ng-model="reference.value"/>
33 <span class="input-group-addon cursor" ng-click="data.refs.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
34 </div>
35 </div>
36 </div>
37 <div class="modal-footer">
38 <button class="btn btn-success" ng-click="ok()" ng-disabled="formCWE.$invalid">OK</button>
39 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
40 </div>
41 </form>
+0
-38
faraday/server/www/scripts/commons/partials/editObject.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header" hotkey="{enter:ok}">
5 <h5>{{msg}}</h5>
6 </div>
7 <div class="modal-body">
8 <div class="row">
9 <div class="col-md-4">
10 <h2 class="ws-label"><span class="label label-default" title="All Impacts">All Impacts</span></h2>
11 <div class="ws-list">
12 <a class="ws-link" ng-repeat="(key, value) in options" style="height:35px">
13 <p class="label label-primary ws-name" style="cursor:default;">
14 <span class="glyphicon glyphicon-ok impact-ok cursor" ng-click="addImpact(key)"></span>{{key}}
15 <span class="glyphicon glyphicon-remove impact-del cursor" ng-click="delImpact(key)"></span>
16 </p>
17 </a>
18 </div><!-- .ws-list -->
19 </div>
20 <div class="col-md-4">
21 <h2 class="ws-label"><span class="label label-default" title="Will add">Will add</span></h2>
22 <div ng-repeat="add in impact.add" class="normal-size" style="cursor: pointer;">
23 <h4><span class="label label-success" ng-click="add_backImpact(add)">{{add}}</span></h4>
24 </div><!-- .normal-size -->
25 </div>
26 <div class="col-md-4">
27 <h2 class="ws-label"><span class="label label-default" title="Will delete">Will delete</span></h2>
28 <div ng-repeat="del in impact.del" class="normal-size" style="cursor: pointer;">
29 <h4><span class="label label-danger" ng-click="del_backImpact(del)">{{del}}</span></h4>
30 </div><!-- .normal-size -->
31 </div>
32 </div>
33 </div>
34 <div class="modal-footer">
35 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
36 <button class="btn btn-success" ng-click="ok()">OK</button>
37 </div>
+0
-22
faraday/server/www/scripts/commons/partials/editOptions.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header" hotkey="{enter:ok}">
5 <h5>{{msg}}</h5>
6 </div>
7 <div class="modal-body change-padding-to-margin">
8 <div class="form-group" style="min-height: 18px">
9 <div class="col-md-12 form-group severities">
10 <button type="button" class="btn btn-default dropdown-toggle color-{{data.property}}" data-toggle="dropdown" title="Change severity">
11 {{data.property || 'Edit property'}} <span class="caret"></span>
12 </button>
13 <ul id="nav" class="dropdown-menu dropdown-menu-left" role="menu">
14 <li ng-repeat="o in options"><a href="" class="ws color-{{o}}" ng-click="data.property = o">{{o}}</a></li>
15 </ul><!-- WS navigation -->
16 </div>
17 </div>
18 <div class="modal-footer">
19 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
20 <button class="btn btn-success" ng-disabled="!data.property" ng-click="ok()">OK</button>
21 </div>
+0
-16
faraday/server/www/scripts/commons/partials/editString.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form hotkey="{enter:ok}">
5 <div class="modal-header">
6 <h5>{{msg}}</h5>
7 </div>
8 <div class="modal-body">
9 <input type="text" ng-model="data.property" class="form-control"/>
10 </div>
11 <div class="modal-footer">
12 <button class="btn btn-success" ng-click="ok()">OK</button>
13 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
14 </div>
15 </form>
+0
-14
faraday/server/www/scripts/commons/partials/editText.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header" hotkey="{enter:ok}">
5 <h5>{{msg}}</h5>
6 </div>
7 <div class="modal-body">
8 <textarea class="form-control" ng-model="data.property"></textarea>
9 </div>
10 <div class="modal-footer">
11 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
12 <button class="btn btn-success" ng-click="ok()">OK</button>
13 </div>
+0
-74
faraday/server/www/scripts/commons/partials/header.html less more
0 <div class="faraday-page-header" class="clearfix">
1 <div class="head">
2 <a href="#/workspaces" class="ws-dashboard" uib-tooltip="{{version}}" tooltip-placement="bottom" style="margin-right: 20px;">
3 <img class="" style="margin: 0.5rem;" src="{{logo_url}}" alt="Faraday home | WS Dashboard"/>
4 </a>
5 </div>
6 <div class="workspace-selector-wrapper">
7 <div ng-if="showSwitcher() && workspace" class="switcher-wrapper">
8 <div class="dropdown">
9 <button id="workspaceSwitcher" type="button" class="btn btn-default dropdown-toggle workspace-switcher" data-toggle="dropdown" title="Change current workspace">
10 <div class="workspace-switcher-title-wrapper">
11 <div class="workspace-switcher-title">
12 <span class="title">
13 {{ workspace }}
14 </span>
15 <span class="caret-container">
16 <span class="caret"></span>
17 </span>
18 </div>
19 <span class="subtitle">
20 {{vulnsNum}}/{{totalVulns}} vulns
21 </span>
22 </div>
23 </button>
24 <ul class="dropdown-menu" role="menu" aria-labelledby="workspaceSwitcher">
25 <li ng-repeat="ws in workspaces | filter:{active:true}"><a href="#/{{location}}/ws/{{ws.name}}" class="ws" >{{ws.name}}</a></li>
26 </ul>
27 </div>
28 </div>
29 </div>
30 <div>
31 <div class="wrapper">
32 <div ng-controller="navigationCtrl" ng-include="'scripts/navigation/partials/topBar.html'"></div>
33 </div>
34 </div>
35 <div class="controls-wrapper">
36 <button ng-if="workspace" id="refresh" type="button" class="btn" title="Refresh current workspace" onclick="location.reload()">
37 <span class="glyphicon glyphicon-refresh"></span>
38 </button>
39 <button ng-if="showSwitcher() && workspace" type="button" class="btn" title="Edit current workspace" ng-click="editWorkspace()">
40 <span class="glyphicon glyphicon-cog"></span>
41 </button>
42 <span ng-if="location === 'dashboard' && workspace" class="control-wrapper filter-wrapper">
43 <button type="button" class="btn confirm-button" title="{{ confirmed === true ? 'All vulns' : 'Confirmed vulns' }}" ng-click="toggleConfirmed()">
44 <img ng-src="{{ confirmed === true ? 'images/icon-toolbar-confirmed-on.svg' : 'images/icon-toolbar-confirmed-off.svg'}}" class="confirm-icon" ng-style="{ 'opacity': (confirmed === true) ? '1' : '0.7' }" />
45 </button>
46 </span>
47 </div>
48 <div class="flex-spacer"></div>
49 <div class="user-menu-wrapper">
50 <div ng-controller="loginBarCtrl">
51 <div class="btn-group dropdown" ng-if="auth" uib-dropdown="" is-open="status.isopen">
52 <button id="single-button" type="button" class="btn btn-default dropdown-toggle user-dropdown" uib-dropdown-toggle="" ng-disabled="disabled" aria-haspopup="true" aria-expanded="true">
53 <span>{{user.name}} </span>
54 <i class="glyphicon glyphicon-user"></i>
55 <span class="caret"></span>
56 </button>
57 <ul class="dropdown-menu dropdown-menu-right overall" uib-dropdown-menu="" role="menu" aria-labelledby="single-button">
58 <li role="menuitem"><a href="#/workspaces">Workspaces</a></li>
59 <li role="menuitem"><a href="#/users">Users</a></li>
60 <li role="menuitem"><a href="#/licenses">Licenses</a></li>
61 <hr class="hr_divider"></hr>
62 <li role="menuitem"><a href="" ng-click="changePasswordModal()">Change password</a></li>
63 <li role="menuitem"><a href="#/admin">Settings</a></li>
64 <li role="menuitem"><a href="" ng-click="logout()">Logout</a></li>
65 <hr class="hr_divider"></hr>
66 <li role="menuitem"><a href="#/help">Help</a></li>
67 <li role="menuitem"><a href="#/extras">Extras</a></li>
68 <li role="menuitem"><a href="" ng-click="about()">About</a></li>
69 </ul>
70 </div>
71 </div>
72 </div>
73 </div>
+0
-106
faraday/server/www/scripts/commons/partials/home.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion clearfix">
5 <div class="faraday-header-border-fix"></div>
6 <div class="left-main"><div id="reports-main" class="fila clearfix">
7 <h2 class="ws-label">
8 <span id="ws-name" class="label label-default"
9 title="Current workspace">Welcome to Faraday!</span><!-- WS name -->
10 </h2><!-- .ws-label -->
11 <div class="reports">
12 <div class="reports">
13 <div class="ws-list home-list corporate clearfix">
14 <a href="#/dashboard" class="ws-link item animated flipInX">
15 <img src="images/ico-dashboard.svg" />
16 <span class="ws-name">Dashboard</span>
17 <small>
18 Gain insight into your project.<br/>
19 <strong>Visualise the progress</strong>
20 </small>
21 </a>
22 <a href="#/status" class="ws-link item animated flipInX">
23 <img src="images/ico-status.svg" />
24 <span class="ws-name">Status Report</span>
25 <small>
26 All the vulnerabilities in one place.<br/>
27 <strong>Manage findings</strong>
28 </small>
29 </a>
30 <a href="#/hosts" class="ws-link item animated flipInX">
31 <img src="images/ico-hosts.svg" />
32 <span class="ws-name">Hosts</span>
33 <small>
34 Hosts and Services CRUD<br/>
35 <strong>Manage your hosts</strong>
36 </small>
37 </a>
38 <a href="#/credentials" class="ws-link item animated flipInX">
39 <img src="images/ico-credentials.svg" />
40 <span class="ws-name">Credentials</span>
41 <small>
42 <br>Create and edit credentials</br>
43 <strong>Manage your credentials</strong>
44 </small>
45 </a>
46 <a href="#/executive" class="ws-link item animated flipInX">
47 <img src="images/ico-executive.svg" />
48 <span class="ws-name">Executive Report</span>
49 <small>
50 Export project to a word file.<br/>
51 <strong>Manage reports</strong>
52 </small>
53 </a>
54 <a href="#/taskgroup" class="ws-link item animated flipInX">
55 <img src="images/ico-tasks.svg" />
56 <span class="ws-name">Tasks</span>
57 <small>
58 Control all your tasks.<br/>
59 <strong>Plan your Job</strong>
60 </small>
61 </a>
62 <a href="#/comparison" class="ws-link item animated flipInX">
63 <img src="images/ico-workspace-comparison.svg" />
64 <span class="ws-name">Workspace Comparison</span>
65 <small>
66 Compare two workspaces.<br/>
67 <strong>Differences between projects</strong>
68 </small>
69 </a>
70 <a href="#/webshell" class="ws-link item animated flipInX">
71 <img src="images/ico-web-shell.svg" />
72 <span class="ws-name">Web Shell</span>
73 <small>
74 Run commands directly from your.<br/>
75 <strong>UI Web</strong>
76 </small>
77 </a>
78 <a href="#/vulndb" class="ws-link item animated flipInX">
79 <img src="images/ico-vulnerability-templates.svg" />
80 <span class="ws-name">Vuln Templates</span>
81 <small>
82 Add consistency to your workspaces.<br/>
83 <strong>Manage your vuln templates</strong>
84 </small>
85 </a>
86 <a href="#/data_analysis" class="ws-link item animated flipInX">
87 <img src="images/ico-data-analysis.svg" />
88 <span class="ws-name">Data analysis</span>
89 <small>
90 Analyze historic data.<br/>
91 <strong>View trends from projects</strong>
92 </small>
93 </a>
94 <a href="#/admin" class="ws-link item animated flipInX">
95 <i class="fa fa-cogs fa-4x" style="color: #b3b4b5;margin-bottom: 5px;"></i>
96 <span class="ws-name">Admin panel</span>
97 <small>
98 Configure your preferences<br/>
99 <strong>Access to your settings</strong>
100 </small>
101 </a>
102 </div><!-- .ws-list -->
103 </div><!-- .reports -->
104 </div><!-- #reports-main --></div><!-- .right-main -->
105 </section>
+0
-23
faraday/server/www/scripts/commons/partials/modalAbout.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header">
5 <h4 class="modal-title"><img src="images/faraday-iso.svg" height="30" style="display: inline; padding: 5px; vertical-align:middle;"> About Faraday</h4>
6 </div>
7 <div class="modal-body">
8 <h2>Faraday <b>{{version}}</b> <small>by <a href="https://faradaysec.com">FaradaySEC</a></small></h2>
9 <br/>
10 <h5>The collaborative penetration test environment the world needed!</h5>
11 </div><!-- .modal-body -->
12 <div class="modal-footer container-fluid" style="text-align: center;">
13 <div class="col-md-4">
14 <a href="https://medium.com/faraday/faraday-changelog-cd35dfcf37dd" target="_blank">What's new</a>
15 </div>
16 <div class="col-md-4">
17 <a href="http://github.com/infobyte/faraday/blob/master/AUTHORS" target="_blank">Authors</a>
18 </div>
19 <div class="col-md-4">
20 <a href="https://support.faradaysec.com/" target="_blank">Documentation</a>
21 </div>
22 </div>
+0
-14
faraday/server/www/scripts/commons/partials/modalDelete.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header" hotkey="{enter:ok}">
5 <h3 class="modal-title">Bulk deletion</h3>
6 </div>
7 <div class="modal-body">
8 <h5>{{msg}}</h5>
9 </div><!-- .modal-body -->
10 <div class="modal-footer">
11 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
12 <button class="btn btn-success" ng-click="ok()">OK</button>
13 </div>
+0
-61
faraday/server/www/scripts/commons/partials/modalExtras.html less more
0 <div class="modal-header">
1 <h4 class="modal-title"><img src="images/faraday-iso.svg" height="30"
2 style="display: inline; padding: 5px; vertical-align:middle;"> Extras</h4>
3 </div>
4 <div class="modal-body">
5 <h4>Want to level up your Faraday usage? You can download any of the following enhancers to connect with your
6 instance:</h4>
7 <br/>
8
9 Faraday CLI
10 <br/>
11 Link: <a
12 href="https://github.com/infobyte/faraday-cli" target="_blank">https://github.com/infobyte/faraday-cli</a>
13 <br/>
14 Use Faraday directly from your favorite terminal. This is a common replacement for our GTK Client.
15
16 <br/><br/>
17
18 Agent Dispatcher
19 <br/>
20 Link: <a href="https://github.com/infobyte/faraday_agent_dispatcher" target="_blank">https://github.com/infobyte/faraday_agent_dispatcher</a>
21 <br/>
22 Integrate Faraday with your scanning tools and automate all your scans. Our Dispatcher allows you to create custom
23 integrations for your instance.
24
25 <br/><br/>
26
27 Faraday Client
28 <br/>
29 DEB Link: <a href="https://storage.googleapis.com/faraday-community/faraday-client_amd64.deb" target="_blank">https://storage.googleapis.com/faraday-community/faraday-client_amd64.deb</a>
30 <br/>
31 RPM Link: <a href="https://storage.googleapis.com/faraday-community/faraday-client_amd64.rpm" target="_blank">https://storage.googleapis.com/faraday-community/faraday-client_amd64.rpm</a>
32 <br/>
33 Run commands directly from our GTK Client and get all results imported automatically into your instance.
34
35 <br/><br/>
36
37 Methodology Templates
38 <br/>
39 Link: <a href="https://github.com/infobyte/faraday_templates/tree/master/methodologies" target="_blank">https://github.com/infobyte/faraday_templates/tree/master/methodologies</a>
40 <br/>
41 Common security methodologies ready to be used within your Faraday projects.
42
43 <br/><br/>
44
45 Vulnerability KB Templates (CWE)
46 <br/>
47 Link: <a href="https://github.com/infobyte/faraday_templates/tree/master/vulnerability_templates" target="_blank">https://github.com/infobyte/faraday_templates/tree/master/vulnerability_templates</a>
48 <br/>
49 Populate your Faraday KB with default CWE information.
50
51 <br/><br/>
52
53 Burp Extender
54 <br/>
55 Link: <a href="https://portswigger.net/bappstore/82f3cbaea46c4f158fd85bbccc90c31c" target="_blank">https://portswigger.net/bappstore/82f3cbaea46c4f158fd85bbccc90c31c</a>
56 <br/>
57 Send findings directly from Burp into your Faraday instance. Automatically populate your project or choose exactly what you want to share.
58
59 <br/><br/>
60 </div>
+0
-13
faraday/server/www/scripts/commons/partials/modalKO.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header">
5 <h3 class="modal-title"><span class="glyphicon glyphicon-exclamation-sign"></span>Oops!</h3>
6 </div>
7 <div class="modal-body">
8 <h5 class="line-breaks">{{ msg }}</h5>
9 </div><!-- .modal-body -->
10 <div class="modal-footer">
11 <button class="btn btn-success" ng-click="ok()">OK</button>
12 </div>
+0
-13
faraday/server/www/scripts/commons/partials/modalOK.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header">
5 <h3 class="modal-title"><span class="glyphicon glyphicon-ok"></span>Great!</h3>
6 </div>
7 <div class="modal-body">
8 <h5 class="line-breaks">{{ msg }}</h5>
9 </div><!-- .modal-body -->
10 <div class="modal-footer">
11 <button class="btn btn-success" ng-click="ok()">OK</button>
12 </div>
+0
-3
faraday/server/www/scripts/commons/partials/osintLink.html less more
0 <a href="//{{osint.host}}{{osint.prefix}}{{query}}{{osint.suffix}}" uib-tooltip="Search in {{osint.label}}" target="_blank">
1 <img ng-src="{{osint.icon}}" height="15px" width="15px" />
2 </a>
+0
-48
faraday/server/www/scripts/commons/partials/workspaces.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3 <section id="main" class="seccion clearfix">
4 <div class="faraday-header-border-fix">
5 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
6 <div id="reports-main" class="fila clearfix">
7 <div class="jumbotron">
8 <h1><b>Welcome!</b></h1>
9 <p ng-if="workspaces.length > 0">These are your available workspaces</p>
10 </div><!-- .jumbotron -->
11 <div class="reports normal-size">
12 <table ng-if="workspaces.length > 0" class="table-v3 licenses-list table table-responsive">
13 <thead>
14 <tr class="ui-grid-header">
15 <th class="ui-grid-cell-contents ui-grid-header-cell">Read only</th>
16 <th class="ui-grid-cell-contents ui-grid-header-cell">Name</th>
17 <th class="ui-grid-cell-contents ui-grid-header-cell">Vulns</th>
18 <th class="ui-grid-cell-contents ui-grid-header-cell">Hosts</th>
19 <th class="ui-grid-cell-contents ui-grid-header-cell">Services</th>
20 </tr>
21 </thead>
22 <tbody>
23 <tr ng-repeat="ws in workspaces | filter:{active:true}">
24 <td class="ui-grid-cell-contents active-toggle">
25 <div class="toogle-img-container">
26 <span ng-click="readonlyToggle(ws)" class="active-toggle-container" ng-class="{ disabled:ws.readonly === false }" uib-tooltip="{{(ws.readonly === false) ? 'Workspace with all permissions' : 'Workspace read only'}}" tooltip-placement="right">
27 <img ng-src="{{ (ws.readonly == true) ? 'images/icon-list-confirmed.svg' : 'images/icon-list-notconfirmed.svg'}}" class="confirm-icon" ng-style="{ 'opacity': (ws.readonly === true) ? '1' : '0.7' }" />
28 </span>
29 </div>
30 </td>
31 <td class="ui-grid-cell-contents">
32 <span class="onhover upsize" ng-click="redirect(ws.name)">
33 <b>{{ws.name}}</b>
34 </span>
35 </td>
36 <td ng-bind="objects[ws.name]['total_vulns']" class="ui-grid-cell-contents"></td>
37 <td ng-bind="objects[ws.name]['hosts']" class="ui-grid-cell-contents"></td>
38 <td ng-bind="objects[ws.name]['services']" class="ui-grid-cell-contents"></td>
39 </tr>
40 </tbody>
41 </table>
42 <div ng-if="workspaces.length == 0">
43 No workspaces found, please create a new one <a href="#/workspaces" class="ws" >here</a>
44 </div>
45 </div><!-- .reports -->
46 </div><!-- #reports-main --></div><!-- .right-main -->
47 </section>
+0
-383
faraday/server/www/scripts/commons/providers/commons.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('commonsFact',
6 ['$uibModal',
7 function($uibModal) {
8 var commonsFact = {};
9
10 // receives a dictionary of files whose keys are names
11 // returns a dictionary whose keys are names and values are strings - the names of the icons
12 commonsFact.loadIcons = function(files) {
13 var icons = {},
14 type = "";
15
16 for(var name in files) {
17 // first lets load the type prop
18 if(files[name].hasOwnProperty("type")) {
19 type = files[name].type.toLowerCase();
20 } else {
21 type = name.slice(-3);
22 }
23 if(type == "application/pdf" || type == "pdf") {
24 icons[name] = "fa-file-pdf-o";
25 } else if(type.split("/")[0] == "image" || type == "jpg" || type == "peg" || type == "png") {
26 icons[name] = "fa-file-image-o";
27 } else if(type == "application/msword" || type == "text/plain" || type == "txt" || type == "doc") {
28 icons[name] = "fa-file-text-o";
29 } else {
30 icons[name] = "fa-file-o";
31 }
32 };
33
34 return icons;
35 };
36
37 commonsFact.arrayToObject = function(array){
38 var arrayOfObjects = [];
39 if (array != undefined){
40 array.forEach(function(r){
41 arrayOfObjects.push({key:r});
42 });
43 }
44 return arrayOfObjects;
45 }
46
47 commonsFact.objectToArray = function(object){
48 var res = {};
49 var array = [];
50 object.forEach(function(r){
51 array.push(r.key);
52 });
53 array = array.filter(Boolean);
54 return array;
55 }
56
57 commonsFact.htmlentities = function(string, quote_style, charset, double_encode) {
58 var hash_map = commonsFact.translationtable('HTML_ENTITIES', quote_style), symbol = '';
59 string = string == null ? '' : string + '';
60
61 if (!hash_map) {
62 return false;
63 }
64
65 if (quote_style && quote_style === 'ENT_QUOTES') {
66 hash_map["'"] = '&#039;';
67 }
68
69 if ( !! double_encode || double_encode == null) {
70 for (symbol in hash_map) {
71 if (hash_map.hasOwnProperty(symbol)) {
72 string = string.split(symbol)
73 .join(hash_map[symbol]);
74 }
75 }
76 } else {
77 string = string.replace(/([\s\S]*?)(&(?:#\d+|#x[\da-f]+|[a-zA-Z][\da-z]*);|$)/g, function (ignore, text, entity) {
78 for (symbol in hash_map) {
79 if (hash_map.hasOwnProperty(symbol)) {
80 text = text.split(symbol)
81 .join(hash_map[symbol]);
82 }
83 }
84 return text + entity;
85 });
86 }
87 return string;
88 };
89
90 commonsFact.translationtable = function(table, quote_style) {
91 var entities = {},
92 hash_map = {},
93 decimal;
94 var constMappingTable = {},
95 constMappingQuoteStyle = {};
96 var useTable = {},
97 useQuoteStyle = {};
98
99 // Translate arguments
100 constMappingTable[0] = 'HTML_SPECIALCHARS';
101 constMappingTable[1] = 'HTML_ENTITIES';
102 constMappingQuoteStyle[0] = 'ENT_NOQUOTES';
103 constMappingQuoteStyle[2] = 'ENT_COMPAT';
104 constMappingQuoteStyle[3] = 'ENT_QUOTES';
105
106 useTable = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
107 useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() :
108 'ENT_COMPAT';
109
110 if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
111 throw new Error('Table: ' + useTable + ' not supported');
112 }
113
114 entities['38'] = '&amp;';
115 if (useTable === 'HTML_ENTITIES') {
116 entities['160'] = '&nbsp;';
117 entities['161'] = '&iexcl;';
118 entities['162'] = '&cent;';
119 entities['163'] = '&pound;';
120 entities['164'] = '&curren;';
121 entities['165'] = '&yen;';
122 entities['166'] = '&brvbar;';
123 entities['167'] = '&sect;';
124 entities['168'] = '&uml;';
125 entities['169'] = '&copy;';
126 entities['170'] = '&ordf;';
127 entities['171'] = '&laquo;';
128 entities['172'] = '&not;';
129 entities['173'] = '&shy;';
130 entities['174'] = '&reg;';
131 entities['175'] = '&macr;';
132 entities['176'] = '&deg;';
133 entities['177'] = '&plusmn;';
134 entities['178'] = '&sup2;';
135 entities['179'] = '&sup3;';
136 entities['180'] = '&acute;';
137 entities['181'] = '&micro;';
138 entities['182'] = '&para;';
139 entities['183'] = '&middot;';
140 entities['184'] = '&cedil;';
141 entities['185'] = '&sup1;';
142 entities['186'] = '&ordm;';
143 entities['187'] = '&raquo;';
144 entities['188'] = '&frac14;';
145 entities['189'] = '&frac12;';
146 entities['190'] = '&frac34;';
147 entities['191'] = '&iquest;';
148 entities['192'] = '&Agrave;';
149 entities['193'] = '&Aacute;';
150 entities['194'] = '&Acirc;';
151 entities['195'] = '&Atilde;';
152 entities['196'] = '&Auml;';
153 entities['197'] = '&Aring;';
154 entities['198'] = '&AElig;';
155 entities['199'] = '&Ccedil;';
156 entities['200'] = '&Egrave;';
157 entities['201'] = '&Eacute;';
158 entities['202'] = '&Ecirc;';
159 entities['203'] = '&Euml;';
160 entities['204'] = '&Igrave;';
161 entities['205'] = '&Iacute;';
162 entities['206'] = '&Icirc;';
163 entities['207'] = '&Iuml;';
164 entities['208'] = '&ETH;';
165 entities['209'] = '&Ntilde;';
166 entities['210'] = '&Ograve;';
167 entities['211'] = '&Oacute;';
168 entities['212'] = '&Ocirc;';
169 entities['213'] = '&Otilde;';
170 entities['214'] = '&Ouml;';
171 entities['215'] = '&times;';
172 entities['216'] = '&Oslash;';
173 entities['217'] = '&Ugrave;';
174 entities['218'] = '&Uacute;';
175 entities['219'] = '&Ucirc;';
176 entities['220'] = '&Uuml;';
177 entities['221'] = '&Yacute;';
178 entities['222'] = '&THORN;';
179 entities['223'] = '&szlig;';
180 entities['224'] = '&agrave;';
181 entities['225'] = '&aacute;';
182 entities['226'] = '&acirc;';
183 entities['227'] = '&atilde;';
184 entities['228'] = '&auml;';
185 entities['229'] = '&aring;';
186 entities['230'] = '&aelig;';
187 entities['231'] = '&ccedil;';
188 entities['232'] = '&egrave;';
189 entities['233'] = '&eacute;';
190 entities['234'] = '&ecirc;';
191 entities['235'] = '&euml;';
192 entities['236'] = '&igrave;';
193 entities['237'] = '&iacute;';
194 entities['238'] = '&icirc;';
195 entities['239'] = '&iuml;';
196 entities['240'] = '&eth;';
197 entities['241'] = '&ntilde;';
198 entities['242'] = '&ograve;';
199 entities['243'] = '&oacute;';
200 entities['244'] = '&ocirc;';
201 entities['245'] = '&otilde;';
202 entities['246'] = '&ouml;';
203 entities['247'] = '&divide;';
204 entities['248'] = '&oslash;';
205 entities['249'] = '&ugrave;';
206 entities['250'] = '&uacute;';
207 entities['251'] = '&ucirc;';
208 entities['252'] = '&uuml;';
209 entities['253'] = '&yacute;';
210 entities['254'] = '&thorn;';
211 entities['255'] = '&yuml;';
212 }
213
214 if (useQuoteStyle !== 'ENT_NOQUOTES') {
215 entities['34'] = '&quot;';
216 }
217 if (useQuoteStyle === 'ENT_QUOTES') {
218 entities['39'] = '&#39;';
219 }
220 entities['60'] = '&lt;';
221 entities['62'] = '&gt;';
222
223 // ascii decimals to real symbols
224 for (decimal in entities) {
225 if (entities.hasOwnProperty(decimal)) {
226 hash_map[String.fromCharCode(decimal)] = entities[decimal];
227 }
228 }
229
230 return hash_map;
231 };
232
233 commonsFact.addPresentationParams = function(url, page, page_size, filter, sort, sort_direction) {
234 var param_conn = '?';
235
236 if(page !== null && page_size !== null && page !== undefined && page_size !== undefined){
237 url = url + param_conn + 'page=' + page + '&page_size=' + page_size;
238 param_conn = '&';
239 }
240
241 if(filter !== undefined) {
242 for(var param in filter) {
243 if (filter.hasOwnProperty(param)) {
244 url = url + param_conn + encodeURIComponent(param) + '=' + encodeURIComponent(filter[param]);
245 param_conn = '&';
246 }
247 }
248 }
249
250 if(sort && sort_direction) {
251 url = url + param_conn + 'sort=' + sort;
252 param_conn = '&';
253 url = url + param_conn + 'sort_dir=' + sort_direction;
254 }
255
256 return url;
257 };
258
259 commonsFact.showMessage = function(msg, success) {
260 if (! success) { var success = false }
261 if (success) {
262 var templateUrl = 'scripts/commons/partials/modalOK.html';
263 } else {
264 var templateUrl = 'scripts/commons/partials/modalKO.html';
265 }
266 var modal = $uibModal.open({
267 templateUrl: templateUrl,
268 controller: 'commonsModalKoCtrl',
269 resolve: {
270 msg: function() {
271 return msg;
272 },
273 }
274 });
275 }
276
277 commonsFact.errorDialog = function(message) {
278 $uibModal.open(config = {
279 templateUrl: 'scripts/commons/partials/modalKO.html',
280 controller: 'commonsModalKoCtrl',
281 size: 'sm',
282 resolve: {
283 msg: function() {
284 return message;
285 }
286 }
287 });
288 };
289
290 commonsFact.parseSearchURL = function(searchParams) {
291 var i = -1, searchFilter = {}, searchTerms = searchParams.split("&");
292
293 searchTerms.forEach(function(term) {
294 i = term.indexOf("=");
295 if(i > 0) {
296 var filterField = decodeURIComponent(term.slice(0, i));
297 var filterValue = decodeURIComponent(term.slice(i+1));
298 searchFilter[filterField] = filterValue;
299 }
300 });
301
302 return trimSearchFilter(searchFilter);
303 };
304
305 commonsFact.parseSearchExpression = function(searchExpression) {
306 var i = -1;
307 var searchFilter = {};
308 var lastFilterField = "search";
309 var expressionTerms = searchExpression.split(" ");
310 var excludedConnectorsList = ["and"];
311
312 expressionTerms.forEach(function(term) {
313 i = term.indexOf(":");
314 if (i > 0) {
315 var filterField = term.slice(0, i);
316 var filterValueChunk = term.slice(i+1);
317 searchFilter[filterField] = filterValueChunk;
318 lastFilterField = filterField;
319 } else {
320 if (!searchFilter.hasOwnProperty(lastFilterField)) {
321 searchFilter[lastFilterField] = term;
322 } else {
323 if(excludedConnectorsList.indexOf(term.toLowerCase()) === -1){
324 searchFilter[lastFilterField] += ' ' + term;
325 }
326 }
327 }
328 });
329
330 return trimSearchFilter(searchFilter);
331 };
332
333 var trimSearchFilter = function(searchFilter) {
334 for (var filter in searchFilter) {
335 if (searchFilter.hasOwnProperty(filter)) {
336 searchFilter[filter] = searchFilter[filter].trim();
337 }
338 }
339 return searchFilter;
340 };
341
342 commonsFact.searchFilterToExpression = function(searchFilter) {
343 var searchExpression = "";
344
345 if (searchFilter.hasOwnProperty("search")) {
346 searchExpression += searchFilter.search;
347 }
348
349 var index = 0;
350 for (var filter in searchFilter) {
351 if (searchFilter.hasOwnProperty(filter)) {
352 if (filter !== "search") {
353 if (searchExpression !== "") {
354 searchExpression += " ";
355 }
356 if (index > 0)
357 searchExpression += ' and ';
358 searchExpression += filter + ":" + searchFilter[filter];
359 }
360 }
361 index ++;
362 }
363
364 return searchExpression.trim();
365 };
366
367 commonsFact.searchFilterToURLParams = function(searchFilter) {
368 var searchURLParams = "";
369 for (var filter in searchFilter) {
370 if (searchFilter.hasOwnProperty(filter)) {
371 if (searchFilter[filter] != "") {
372 var paramName = encodeURIComponent(filter);
373 var paramValue = encodeURIComponent(searchFilter[filter]);
374 searchURLParams += "&" + paramName + "=" + paramValue;
375 }
376 }
377 }
378 return searchURLParams.slice(1);
379 };
380
381 return commonsFact;
382 }]);
+0
-732
faraday/server/www/scripts/commons/providers/server.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file "doc/LICENSE" for the license information
3
4 // "use strict"; // Elm? Where we"re going we don"t need Elm.
5
6 // TODO: handle errors
7 angular.module("faradayApp")
8 .factory("ServerAPI", ["BASEURL", "$http", "$q", "APIURL",
9 function (BASEURL, $http, $q, APIURL) {
10 var ServerAPI = {};
11 var FILTER_URL = BASEURL + "_api/filter/";
12
13 var createGetRelatedUrl = function (wsName, objectType, objectId, relatedObjectType) {
14 var objectName = ((objectName) ? "/" + objectType : "");
15 return get_url = APIURL + "ws/" + wsName + "/" + objectType + "/" + objectId + "/" + relatedObjectType + "/";
16 };
17
18 var createGetUrl = function (wsName, objectName, objectId) {
19 var objectName = ((objectName) ? "/" + objectName : "");
20 if (typeof objectId == 'string' || typeof objectId == "number") {
21 objectName = objectName + "/" + objectId;
22 }
23
24 return APIURL + "ws/" + wsName + objectName + "/";
25 };
26
27 // create GET URL for objects that do not belong to a workspace
28 var createNonWorkspacedGetUrl = function (objectName, objectId) {
29 if (typeof objectId == 'string' || typeof objectId == "number") {
30 objectName = objectName + "/" + objectId;
31 }
32
33 return APIURL + objectName + "/";
34 };
35
36 var createNewGetUrl = function (wsName, objectId, objectType) {
37 return APIURL + "ws/" + wsName + "/" + objectType + "/" + objectId;
38 }
39
40 var createPostUrl = function (wsName, objectId, objectType) {
41 return APIURL + "ws/" + wsName + "/" + objectType + "/";
42 };
43
44 // create POST URL for objects that do not belong to a workspace
45 var createNonWorkspacedPostUrl = function (objectId, objectType) {
46 return APIURL + objectType + "/";
47 };
48
49 var createPutUrl = function (wsName, objectId, objectType) {
50 return APIURL + "ws/" + wsName + "/" + objectType + "/" + objectId + "/";
51 };
52
53 // create PUT URL for objects that do not belong to a workspace
54 var createNonWorkspacedPutUrl = function (objectId, objectType) {
55 return APIURL + objectType + "/" + objectId + "/";
56 };
57
58 var createDbUrl = function (wsName) {
59 wsName = wsName || "";
60 return APIURL + "ws/" + wsName + (wsName ? "/" : "");
61 }
62
63 var createDeleteUrl = createPutUrl;
64
65 var createNonWorkspacedDeleteUrl = createNonWorkspacedPutUrl;
66
67 var serverComm = function (method, url, data) {
68 var success = function (response) {
69 return response;
70 };
71 var error = function (err) {
72 return $q.reject(err);
73 };
74
75 // return a promise :)
76 if (method === 'GET' || method === 'DELETE') {
77 return $http({method: method, url: url, params: data}).then(success).catch(error);
78 } else {
79 return $http({method: method, url: url, data: data}).then(success).catch(error);
80 }
81 };
82
83 var get = function (url, data) {
84 return serverComm("GET", url, data);
85 };
86
87 var send_data = function (url, data, is_update, method) {
88 // undefined is just evil...
89 if (typeof is_update === "undefined") {
90 var is_update = false;
91 }
92 return serverComm(method, url, data);
93 };
94
95 // delete is a reserved keyword
96 // just set rev_provided to false if you're deleting a database :)
97 var _delete = function (url, rev_provided) {
98 // never let undefined win
99 if (typeof rev_provided === "undefined") {
100 var rev_provided = false;
101 }
102 var deferred = $q.defer();
103 var data = {};
104 return serverComm("DELETE", url, data);
105 };
106
107 var modHost = function (createOrUpdate, wsName, host) {
108 if (typeof host.description === "undefined") {
109 host.description = ""
110 }
111 ;
112 if (typeof host.owner === "undefined") {
113 host.owner = ""
114 }
115 ;
116 if (typeof host.owned === "undefined") {
117 host.owned = false
118 }
119 ;
120 if (typeof host.os === "undefined") {
121 host.os = ""
122 }
123 ;
124 return createOrUpdate(wsName, host._id, host, 'hosts');
125 }
126
127 var modService = function (createOrUpdate, wsName, service) {
128 if (typeof service.owned === "undefined") {
129 service.owned = false
130 }
131 ;
132 if (typeof service.owner === "undefined") {
133 service.owner = ""
134 }
135 ;
136 if (typeof service.protocol === "undefined") {
137 service.protocol = ""
138 }
139 ;
140 if (typeof service.status === "undefined") {
141 service.status = ""
142 }
143 ;
144 if (typeof service.version === "undefined") {
145 service.version = ""
146 }
147 ;
148 return createOrUpdate(wsName, service._id, service, 'services');
149 }
150
151 var modVuln = function (createOrUpdate, wsName, vuln) {
152 if (typeof vuln.owner === "undefined") {
153 vuln.owner = ""
154 }
155 ;
156 if (typeof vuln.description === "undefined") {
157 vuln.description = ""
158 }
159 ;
160 if (typeof vuln.protocol === "undefined") {
161 vuln.protocol = ""
162 }
163 ;
164 if (typeof vuln.status === "undefined") {
165 vuln.status = ""
166 }
167 ;
168 if (typeof vuln.version === "undefined") {
169 vuln.version = ""
170 }
171 ;
172 if (typeof vuln.confirmed === "undefined") {
173 vuln.confirmed = false
174 }
175 ;
176 if (typeof vuln.data === "undefined") {
177 vuln.data = ""
178 }
179 ;
180 if (typeof vuln.severity === "undefined") {
181 vuln.severity = "info"
182 }
183 ;
184 if (typeof vuln.resolution === "undefined") {
185 vuln.resolution = ""
186 }
187 ;
188 return createOrUpdate(wsName, vuln._id, vuln, 'vulns');
189 }
190
191 var modVulnWeb = function (createOrUpdate, wsName, vulnWeb) {
192 if (typeof vulnWeb.owner === "undefined") {
193 vulnWeb.owner = ""
194 }
195 ;
196 if (typeof vulnWeb.description === "undefined") {
197 vulnWeb.description = ""
198 }
199 ;
200 if (typeof vulnWeb.protocol === "undefined") {
201 vulnWeb.protocol = ""
202 }
203 ;
204 if (typeof vulnWeb.status === "undefined") {
205 vulnWeb.status = ""
206 }
207 ;
208 if (typeof vulnWeb.version === "undefined") {
209 vulnWeb.version = ""
210 }
211 ;
212 if (typeof vulnWeb.confirmed === "undefined") {
213 vulnWeb.confirmed = false
214 }
215 ;
216 if (typeof vulnWeb.data === "undefined") {
217 vulnWeb.data = ""
218 }
219 ;
220 if (typeof vulnWeb.severity === "undefined") {
221 vulnWeb.severity = "info"
222 }
223 ;
224 if (typeof vulnWeb.resolution === "undefined") {
225 vulnWeb.resolution = ""
226 }
227 ;
228 if (typeof vulnWeb.params === "undefined") {
229 vulnWeb.params = ""
230 }
231 ;
232 return createOrUpdate(wsName, vulnWeb._id, vulnWeb);
233 }
234
235 var modVulnerabilityTemplate = function (createOrUpdate, vulnerabilityTemplate) {
236
237 var data_name = 'vulnerability_template';
238 if (typeof vulnerabilityTemplate.cwe === "undefined") {
239 vulnerabilityTemplate.cwe = ""
240 }
241 ;
242 if (typeof vulnerabilityTemplate.description === "undefined") {
243 vulnerabilityTemplate.description = ""
244 }
245 ;
246 if (typeof vulnerabilityTemplate.exploitation === "undefined") {
247 vulnerabilityTemplate.exploitation = "informational"
248 }
249 ;
250 if (typeof vulnerabilityTemplate.name === "undefined") {
251 vulnerabilityTemplate.name = ""
252 }
253 ;
254 if (typeof vulnerabilityTemplate.references === "undefined") {
255 vulnerabilityTemplate.references = ""
256 }
257 ;
258 if (typeof vulnerabilityTemplate.resolution === "undefined") {
259 vulnerabilityTemplate.resolution = ""
260 }
261 ;
262 vulnerabilityTemplate.type = data_name;
263 return createOrUpdate(vulnerabilityTemplate._id, vulnerabilityTemplate, data_name);
264 }
265
266 var modNote = function (createOrUpdate, wsName, note) {
267 if (typeof note.owner === "undefined") {
268 note.owner = ""
269 }
270 ;
271 if (typeof note.description === "undefined") {
272 note.description = ""
273 }
274 ;
275 return createOrUpdate(weName, note._id, note);
276 }
277
278 var modCustomField = function (createOrUpdate, wsName, customField) {
279 return createOrUpdate(wsName, customField._id, customField);
280 }
281
282 var modCredential = function (createOrUpdate, wsName, credential) {
283 if (typeof credential.owner === "undefined") {
284 credential.owner = ""
285 }
286 ;
287 if (typeof credential.description === "undefined") {
288 credential.description = ""
289 }
290 ;
291 return createOrUpdate(wsName, credential.id, credential, 'credential');
292 }
293
294 var modCommand = function (createOrUpdate, wsName, command) {
295 return createOrUpdate(wsName, command._id, command);
296 }
297
298 var createObject = function (wsName, id, data, collectionName) {
299 var postUrl = createPostUrl(wsName, id, collectionName);
300 return send_data(postUrl, data, false, "POST");
301 }
302
303 var createNonWorkspacedObject = function (id, data, collectionName) {
304 var postUrl = createNonWorkspacedPostUrl(id, collectionName);
305 return send_data(postUrl, data, false, "POST");
306 };
307
308 var updateObject = function (wsName, id, data, collectionName) {
309 var postUrl = createPutUrl(wsName, id, collectionName);
310 return send_data(postUrl, data, true, "PUT");
311 }
312
313 var updateNonWorkspacedObject = function (id, data, collectionName) {
314 var postUrl = createNonWorkspacedPutUrl(id, collectionName);
315 return send_data(postUrl, data, true, "PUT");
316 };
317
318 var saveInServer = function (wsName, objectId, data, collectionName) {
319 var postUrl = createPostUrl(wsName, objectId, collectionName);
320 return send_data(postUrl, data, false, "PUT");
321 }
322
323 var saveNonWorkspacedInServer = function (objectId, data, collectionName) {
324 var postUrl = createNonWorkspacedPostUrl(objectId, collectionName);
325 return send_data(postUrl, data, false, "PUT");
326 };
327
328 var updateInServer = function (wsName, objectId, data, collectionName) {
329 var postUrl = createPostUrl(wsName, objectId, collectionName);
330 return send_data(postUrl, objectId, true, "PUT");
331 }
332
333 var updateNonWorkspacedInServer = function (objectId, data, collectionName) {
334 var postUrl = createPostUrl(objectId, collectionName);
335 return send_data(postUrl, objectId, true, "PUT");
336 };
337
338 ServerAPI.getHost = function (wsName, objId) {
339 var url = createGetUrl(wsName, 'hosts', objId);
340 return get(url);
341 }
342
343 ServerAPI.getHosts = function (wsName, data) {
344 var url = createGetUrl(wsName, 'hosts');
345 return get(url, data);
346 }
347
348 ServerAPI.getVulns = function (wsName, data) {
349 var getUrl = createGetUrl(wsName, 'vulns');
350 return get(getUrl, data);
351 }
352
353 ServerAPI.getFilteredVulns = function (wsName, jsonOptions) {
354 var getUrl = createGetUrl(wsName, 'vulns');
355 return get(getUrl + 'filter?q=' + jsonOptions);
356 }
357
358 ServerAPI.getVulnerabilityTemplate = function (objId) {
359 var url = createNonWorkspacedGetUrl('vulnerability_template', objId);
360 return get(url);
361 }
362
363 ServerAPI.getVulnerabilityTemplates = function (data) {
364 var url = createNonWorkspacedGetUrl('vulnerability_template');
365 return get(url);
366 }
367
368 ServerAPI.getService = function (wsName, objId) {
369 var getUrl = createGetUrl(wsName, 'services', objId);
370 return get(getUrl);
371 }
372
373 ServerAPI.getServices = function (wsName, data) {
374 var getUrl = createGetUrl(wsName, 'services');
375 return get(getUrl, data);
376 }
377
378 ServerAPI.getAgents = function (wsName, data) {
379 var getUrl = createGetUrl(wsName, 'agents');
380 return get(getUrl);
381 }
382
383 ServerAPI.getNotes = function (wsName, data) {
384 var getUrl = createGetUrl(wsName, 'notes');
385 return get(getUrl, data);
386 }
387
388 ServerAPI.getCredentials = function (wsName, data, objId) {
389 var getUrl = createGetUrl(wsName, 'credential', objId);
390 return get(getUrl, data);
391 }
392
393 ServerAPI.getCommands = function (wsName, data, onlyLastCommands) {
394 var getUrl = createGetUrl(wsName, 'commands') + (onlyLastCommands ? '?page_size=10&page=1' : '');
395 return get(getUrl, data);
396 }
397
398 ServerAPI.getActivityFeed = function (wsName, data, onlyLastActivities) {
399 var getUrl = createGetUrl(wsName, 'activities') + (onlyLastActivities ? '?page_size=15&page=1' : '');
400 return get(getUrl, data);
401 }
402
403 ServerAPI.getWorkspacesNames = function () {
404 return get(APIURL + "ws/");
405 }
406
407 ServerAPI.getWorkspaces = function () {
408 return get(APIURL + "ws/");
409 }
410
411 ServerAPI.getWorkspace = function (wsName) {
412 var getUrl = createDbUrl(wsName);
413 return get(getUrl);
414 }
415
416 ServerAPI.getCustomFields = function () {
417 return get(APIURL + "custom_fields_schema/");
418 }
419
420 ServerAPI.activateWorkspace = function (wsName) {
421 var putUrl = APIURL + "ws/" + wsName + "/activate/";
422 return send_data(putUrl, undefined, false, "PUT");
423 }
424
425 ServerAPI.deactivateWorkspace = function (wsName) {
426 var putUrl = APIURL + "ws/" + wsName + "/deactivate/";
427 return send_data(putUrl, undefined, false, "PUT");
428 }
429
430 ServerAPI.readOnlyToogle = function (wsName) {
431 var putUrl = APIURL + "ws/" + wsName + "/change_readonly/";
432 return send_data(putUrl, undefined, false, "PUT");
433 }
434
435
436 ServerAPI.getWorkspaceSummary = function (wsName, confirmed) {
437
438 var getUrl = createGetUrl(wsName);
439 var payload = {};
440
441 if (confirmed !== undefined) {
442 payload.confirmed = confirmed;
443 }
444
445 return get(getUrl, payload);
446 }
447
448 ServerAPI.getObj = function (wsName, objID, objectType) {
449 var getUrl = createNewGetUrl(wsName, objID, objectType) + "/";
450 return get(getUrl);
451 }
452
453 var getCount = function (wsName, object) {
454 var deferred = $q.defer();
455 ServerAPI.getWorkspaceSummary(wsName).then(
456 function (response) {
457 deferred.resolve(response.data.stats[object]);
458 }, function (error) {
459 deferred.reject(error);
460 })
461 return deferred.promise;
462 }
463
464 ServerAPI.getHostCount = function (wsName) {
465 return getCount(wsName, 'hosts');
466 }
467
468 ServerAPI.getServiceCount = function (wsName) {
469 return getCount(wsName, 'services');
470 }
471
472 ServerAPI.getServicesBy = function (wsName, what) {
473 var url = createGetUrl(wsName, 'services') + 'count/';
474 return get(url, {"group_by": what})
475 }
476
477 ServerAPI.getServicesByName = function (wsName) {
478 return ServerAPI.getServicesBy(wsName, 'name');
479 }
480
481 ServerAPI.getServicesByHost = function (wsName, hostId) {
482 var url = createGetRelatedUrl(wsName, 'hosts', hostId, 'services');
483 return get(url);
484 }
485
486 ServerAPI.getVulnsBySeverity = function (wsName, confirmed) {
487
488 var url = createGetUrl(wsName, 'vulns') + 'count/';
489 var payload = {'group_by': 'severity'}
490
491 if (confirmed !== undefined) {
492 payload.confirmed = confirmed;
493 }
494
495 return get(url, payload)
496 }
497
498 ServerAPI.getVulnsGroupedBy = function (wsName, groupBy, confirmed) {
499 var url = createGetUrl(wsName, 'vulns') + 'count/';
500 var payload = {'group_by': groupBy}
501 if (confirmed) {
502 payload.confirmed = confirmed;
503 }
504
505 return get(url, payload)
506 }
507
508 ServerAPI.createHost = function (wsName, host) {
509 return modHost(createObject, wsName, host);
510 }
511
512 ServerAPI.updateHost = function (wsName, host) {
513 return modHost(updateObject, wsName, host);
514 }
515
516 ServerAPI.createService = function (wsName, service) {
517 return modService(createObject, wsName, service);
518 }
519
520 ServerAPI.updateService = function (wsName, service) {
521 return modService(updateObject, wsName, service);
522 }
523
524 ServerAPI.createVuln = function (wsName, vuln) {
525 return modVuln(createObject, wsName, vuln)
526 }
527
528 ServerAPI.updateVuln = function (wsName, vuln) {
529 return modVuln(updateObject, wsName, vuln);
530 }
531
532 ServerAPI.createVulnWeb = function (wsName, vulnWeb) {
533 return modVulnWeb(createObject, wsName, vulnWeb);
534 }
535
536 ServerAPI.updateVulnWeb = function (wsName, vulnWeb) {
537 return modVulnWeb(updateObject, wsName, vulnWeb);
538 }
539
540 ServerAPI.createVulnerabilityTemplate = function (vulnerabilityTemplate) {
541 return modVulnerabilityTemplate(createNonWorkspacedObject, vulnerabilityTemplate);
542 };
543
544 ServerAPI.bulkCreateVulnerabilityTemplate = function (vulns) {
545 var bulkCreateURL = APIURL + 'vulnerability_template/bulk_create/';
546 return send_data(bulkCreateURL, vulns, false, "POST");
547 };
548
549 ServerAPI.updateVulnerabilityTemplate = function (vulnerabilityTemplate) {
550 return modVulnerabilityTemplate(updateNonWorkspacedObject, vulnerabilityTemplate);
551 };
552
553 ServerAPI.createNote = function (wsName, note) {
554 return modNote(createObject, wsName, note);
555 }
556
557 ServerAPI.updateNote = function (wsName, note) {
558 return modNote(updateObject, wsName, note);
559 }
560
561 ServerAPI.createCustomField = function (customField) {
562 var postUrl = createNonWorkspacedGetUrl('custom_fields_schema');
563 return send_data(postUrl, customField, false, "POST");
564 }
565
566 ServerAPI.updateCustomField = function (customField) {
567 var postUrl = createNonWorkspacedGetUrl('custom_fields_schema', customField.id);
568 return send_data(postUrl, customField, true, "PUT");
569 }
570
571 ServerAPI.createCredential = function (wsName, credential) {
572 return modCredential(createObject, wsName, credential);
573 }
574
575 ServerAPI.updateCredential = function (wsName, credential) {
576 return modCredential(updateObject, wsName, credential);
577 }
578
579 ServerAPI.createCommand = function (wsName, command) {
580 return modCommand(createObject, wsName, command);
581 }
582
583 ServerAPI.updateCommand = function (wsName, command) {
584 return modCommand(updateObject, wsName, command);
585 }
586
587 ServerAPI.createDB = function (wsName) {
588 var dbUrl = BASEURL + wsName;
589 return put(dbUrl);
590 }
591
592 ServerAPI.deleteHost = function (wsName, hostId, rev) {
593 var deleteUrl = createDeleteUrl(wsName, hostId, 'hosts');
594 if (typeof rev === "undefined") {
595 return _delete(deleteUrl, false)
596 }
597 else {
598 return _delete(deleteUrl, true);
599 }
600 }
601
602 ServerAPI.deleteService = function (wsName, serviceId) {
603 var deleteUrl = createDeleteUrl(wsName, serviceId, 'services');
604 if (typeof rev === "undefined") {
605 return _delete(deleteUrl, false)
606 }
607 else {
608 return _delete(deleteUrl, true);
609 }
610 }
611
612 ServerAPI.exportCsv = function (wsName, jsonOptions) {
613 if(jsonOptions){
614 let url = APIURL + "ws/" + wsName + "/vulns/export_csv";
615 return get(url + '?q=' + jsonOptions);
616 }else{
617 let url = APIURL + "ws/" + wsName + "/vulns/export_csv/";
618 return get(url);
619 }
620 }
621
622 ServerAPI.deleteVuln = function (wsName, vulnId, rev) {
623 var deleteUrl = createDeleteUrl(wsName, vulnId, 'vulns');
624 if (typeof rev === "undefined") {
625 return _delete(deleteUrl, false)
626 }
627 else {
628 return _delete(deleteUrl, true);
629 }
630 }
631
632 ServerAPI.deleteVulnerabilityTemplate = function (vulnId, rev) {
633 var deleteUrl = createNonWorkspacedDeleteUrl(vulnId, 'vulnerability_template');
634 if (typeof rev === "undefined") {
635 return _delete(deleteUrl, false)
636 }
637 else {
638 return _delete(deleteUrl, true);
639 }
640 }
641
642 ServerAPI.deleteNote = function (wsName, noteId, rev) {
643 var deleteUrl = createDeleteUrl(wsName, noteId, rev);
644 if (typeof rev === "undefined") {
645 return _delete(deleteUrl, false)
646 }
647 else {
648 return _delete(deleteUrl, true);
649 }
650 }
651
652 ServerAPI.deleteCustomField = function (customFieldId, rev) {
653 var deleteUrl = createNonWorkspacedDeleteUrl(customFieldId, 'custom_fields_schema');
654 if (typeof rev === "undefined") {
655 return _delete(deleteUrl, false)
656 }
657 else {
658 return _delete(deleteUrl, true);
659 }
660 }
661
662 ServerAPI.deleteCredential = function (wsName, credentialId, rev) {
663 var deleteUrl = createDeleteUrl(wsName, credentialId, 'credential');
664 if (typeof rev === "undefined") {
665 return _delete(deleteUrl, false)
666 }
667 else {
668 return _delete(deleteUrl, true);
669 }
670 }
671
672 ServerAPI.deleteCommand = function (wsName, commandId, rev) {
673 var deleteUrl = createDeleteUrl(wsName, commandId, rev);
674 if (typeof rev === "undefined") {
675 return _delete(deleteUrl, false)
676 }
677 else {
678 return _delete(deleteUrl, true);
679 }
680 }
681
682 ServerAPI.createWorkspace = function (wsName, data) {
683 var dbUrl = createDbUrl();
684 return send_data(dbUrl, data, true, "POST");
685 }
686
687 ServerAPI.updateWorkspace = function (workspace, wsName) {
688 var putUrl = createDbUrl(wsName || workspace.name);
689 return send_data(putUrl, workspace, true, "PUT");
690 }
691
692 ServerAPI.deleteWorkspace = function (wsName) {
693 var dbUrl = createDbUrl(wsName);
694 return _delete(dbUrl, false);
695 }
696
697 ServerAPI.changePassword = function (data) {
698 var url = BASEURL + "_api/change";
699 return serverComm('POST', url, data);
700 }
701
702 ServerAPI.getExploits = function (cveId) {
703 return get(APIURL + 'vulners/exploits/' + cveId);
704 }
705
706 ServerAPI.deleteAgent = function (wsName, agentId, rev) {
707 var deleteUrl = createDeleteUrl(wsName, agentId, 'agents');
708 if (typeof rev === "undefined") {
709 return _delete(deleteUrl, false)
710 }
711 else {
712 return _delete(deleteUrl, true);
713 }
714 };
715
716 ServerAPI.updateAgent = function (wsName, agent) {
717 var putUrl = createPutUrl(wsName, agent.id, 'agents');
718 return send_data(putUrl, agent, true, "PUT");
719 };
720
721 ServerAPI.getAgentToken = function () {
722 var getUrl = createNonWorkspacedGetUrl('agent_token');
723 return get(getUrl);
724 };
725
726 ServerAPI.getTools = function(hid, ws){
727 return get(APIURL + 'ws/' + ws + '/hosts/' + hid + '/tools_history/');
728 }
729
730 return ServerAPI;
731 }]);
+0
-6
faraday/server/www/scripts/config/.gitignore less more
0 # Faraday Penetration Test IDE
1 # Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 # See the file 'doc/LICENSE' for the license information
3
4 # Ignore config file
5 config.json
+0
-21
faraday/server/www/scripts/config/services/config.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('configSrv', ['$http', 'BASEURL', function($http, BASEURL) {
6
7 var p = $http.get(BASEURL + '_api/config')
8 .then(function(conf) {
9 configSrv.faraday_version = conf.data.ver;
10 configSrv.show_vulns_by_price = conf.data.show_vulns_by_price;
11 });
12
13 configSrv = {
14 faraday_version: null,
15 promise: p,
16 show_vulns_by_price: false
17 }
18
19 return configSrv;
20 }]);
+0
-348
faraday/server/www/scripts/credentials/controllers/credentials.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2017 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 "use strict";
5
6 angular.module('faradayApp')
7 .controller('credentialsCtrl', [
8 '$scope',
9 '$filter',
10 '$q',
11 '$uibModal',
12 '$routeParams',
13 '$window',
14 'commonsFact',
15 'credential',
16 'ServerAPI',
17 'workspacesFact',
18 'vulnsManager',
19 function ($scope,
20 $filter,
21 $q,
22 $uibModal,
23 $routeParams,
24 $window,
25 commonsFact,
26 credential,
27 ServerAPI,
28 workspacesFact,
29 vulnsManager) {
30
31 $scope.workspace;
32 $scope.workspaces;
33 $scope.credentials = [];
34 // Contains: type of parent(Host or Service), id(Couchid and internal id) of that and name of host and/or name of service(For show in view)
35 $scope.parentObject = new Object();
36
37 // table stuff
38 $scope.reverse;
39 $scope.search;
40 $scope.selectall_credentials;
41 $scope.sort_field;
42
43 var getParent = function() {
44
45 var deferred = $q.defer();
46
47 // Host is our parent.
48 if($routeParams.hId !== undefined){
49
50 // Load all host information needed.
51 $scope.parentObject.parent_type = 'Host';
52 $scope.parentObject.id = $routeParams.hId;
53
54 ServerAPI.getObj($scope.workspace, $scope.parentObject.id, 'hosts').then(function (response) {
55 $scope.parentObject.nameHost = response['data']['name'];
56 deferred.resolve();
57 });
58 }
59
60 // Service is our parent.
61 if($routeParams.sId !== undefined){
62
63 // Load all service information needed.
64 $scope.parentObject.parent_type = 'Service';
65 $scope.parentObject.id = $routeParams.sId;
66
67 ServerAPI.getObj($scope.workspace, $scope.parentObject.id, 'services').then(function (response) {
68 $scope.parentObject.nameService = response['data']['name'];
69
70 // and also, load all host information needed.
71 var hostId = response['data']['host_id'];
72
73 ServerAPI.getObj($scope.workspace, hostId, 'hosts').then(function (response) {
74 $scope.parentObject.nameHost = response['data']['name'];
75 deferred.resolve();
76 });
77 });
78 }
79 // We dont have parent, resolve promise.
80 deferred.resolve();
81 return deferred.promise;
82 };
83
84 var loadCredentials = function (credentials){
85 credentials.forEach(function(cred){
86
87 var object = new credential(cred.value, cred.value.parent, cred.value.parent_type);
88 object.getParentName($scope.workspace).then(function(response){
89 object.target = response;
90 });
91 $scope.credentials.push(object);
92
93 });
94 };
95
96 var getAndLoadCredentials = function() {
97
98 // Load all credentials, we dont have a parent.
99 if($scope.parentObject.parent_type === undefined){
100 ServerAPI.getCredentials($scope.workspace).then(function(response){
101 loadCredentials(response.data.rows);
102 });
103 }
104 else {
105 // Load all credentials, filtered by host internal id or service internal id.
106 if ($scope.parentObject.parent_type === 'Host')
107 var data = {'host_id': $scope.parentObject.id};
108 else if ($scope.parentObject.parent_type === 'Service')
109 var data = {'service_id': $scope.parentObject.id};
110
111 ServerAPI.getCredentials($scope.workspace, data).then(function(response){
112 loadCredentials(response.data.rows);
113 });
114 }
115 };
116
117 var init = function() {
118
119 // table stuff
120 $scope.selectall_credentials = false;
121 $scope.sort_field = "end";
122 $scope.reverse = true;
123
124 // Load all workspaces to list 'choose workspace'
125 workspacesFact.list().then(function(wss) {
126 $scope.workspaces = wss;
127 });
128
129 $scope.workspace = $routeParams.wsId;
130
131 // load current workspace data
132 workspacesFact.get($scope.workspace).then(function(response) {
133 $scope.workspaceData = response;
134 });
135
136 getParent().then(function(){
137 getAndLoadCredentials();
138 });
139
140 // Make the workspace vuln counter work
141 if(typeof $scope.workspace !== 'undefined'){
142 vulnsManager.loadVulnsCounter($scope.workspace);
143 }
144 };
145
146 var removeFromView = function(credential){
147 $scope.credentials.forEach(function(item, index){
148 if (item._id === credential._id)
149 $scope.credentials.splice(index, 1);
150 });
151 };
152
153 // Delete to server.
154 var remove = function(credentialsToDelete) {
155
156 var confirmations = [];
157
158 credentialsToDelete.forEach(function(credToDelete) {
159 var deferred = $q.defer();
160
161 $scope.credentials.forEach(function(credentialLocal){
162 if(credentialLocal._id == credToDelete._id){
163 credentialLocal.delete($scope.workspace).then(function(resp) {
164 deferred.resolve(resp);
165 removeFromView(credentialLocal);
166 }, function(message) {
167 deferred.reject(message);
168 });
169 confirmations.push(deferred);
170 }
171 });
172 });
173 return $q.all(confirmations);
174 };
175
176 var createCredential = function(credentialData, parent_id, parent_type){
177 // Add parent id, create credential and save to server.
178 try {
179 // If parent_id is undefined, assign host or service to credential from modal
180 if(parent_id === undefined){
181 credentialData.targetsArray.forEach(function(target) {
182 if(target.type === "Service") {
183 // Since it is not possible to get the host's IP from target if it is a service,
184 // credentialData.hostsIp contains the host's IPs of every target that is a service.
185 // To get the host's Ip, use the host's ID
186 credentialData.target = credentialData.hostsIp[target.host_id] + "/" + target.name;
187 } else {
188 credentialData.target = target.ip;
189 }
190
191 parent_id = target.id;
192 parent_type = target.type;
193
194 var credentialObj = new credential(credentialData, parent_id, parent_type);
195
196 credentialObj.create($scope.workspace).then(function(){
197 $scope.credentials.push(credentialObj);
198 }, function(){
199 console.log('Error creating credential.');
200 });
201
202 });
203 } else {
204 var credentialObj = new credential(credentialData, parent_id, parent_type);
205
206 credentialObj.create($scope.workspace).then(function(){
207 $scope.credentials.push(credentialObj);
208 }, function(){
209 console.log('Error creating credential.');
210 });
211 }
212 } catch (error) {
213 console.log(error);
214 }
215 };
216
217 var editCredential = function(credentialEdited, idCredentialEdited){
218 $scope.credentials.forEach(function(item, index){
219 if (item._id === idCredentialEdited){
220 item.name = credentialEdited.name;
221 item.username = credentialEdited.username;
222 item.password = credentialEdited.password;
223 item.update($scope.workspace);
224 }
225 });
226 };
227
228 // Binded to New button.
229 $scope.new = function() {
230 var modal = $uibModal.open({
231 templateUrl: 'scripts/credentials/partials/modalNewEdit.html',
232 backdrop : 'static',
233 controller: 'modalNewEditCredentialCtrl',
234 size: 'lg',
235 resolve: {
236 title: function(){
237 return 'New credential';
238 },
239 credential: function(){
240 return undefined;
241 }
242 }
243 });
244 modal.result
245 .then(function(data) {
246 createCredential(data, $scope.parentObject.id, $scope.parentObject.parent_type);
247 });
248 };
249
250 // Binded to Edit button.
251 $scope.edit = function() {
252
253 var credentialToEdit = $scope.selectedCredentials()[0];
254
255 var modal = $uibModal.open({
256 templateUrl: 'scripts/credentials/partials/modalNewEdit.html',
257 backdrop : 'static',
258 controller: 'modalNewEditCredentialCtrl',
259 size: 'lg',
260 resolve: {
261 title: function(){
262 return 'Edit credential';
263 },
264 credential: function(){
265 return credentialToEdit;
266 }
267 }
268 });
269
270 modal.result
271 .then(function(data) {
272 editCredential(data, credentialToEdit._id);
273 });
274 };
275
276 // Binded to Delete button, internal logic.
277 $scope.delete = function() {
278 var selected = $scope.selectedCredentials();
279
280 var message = "A credential will be deleted";
281 if(selected.length > 1) {
282 message = selected.length + " credentials will be deleted";
283 }
284 message = message.concat(". This operation cannot be undone. Are you sure you want to proceed?");
285 $uibModal.open({
286 templateUrl: 'scripts/commons/partials/modalDelete.html',
287 controller: 'commonsModalDelete',
288 size: 'lg',
289 resolve: {
290 msg: function() {
291 return message;
292 }
293 }
294 }).result.then(function() {
295 remove(selected);
296 }, function() {
297 //dismised, do nothing
298 });
299 };
300
301 $scope.selectedCredentials = function() {
302 var selected = [];
303
304 $filter('filter')($scope.credentials, $scope.search).forEach(function(credential) {
305 if(credential.selected === true) {
306 selected.push(credential);
307 }
308 });
309
310 return selected;
311 };
312
313 $scope.checkAll = function() {
314 $scope.selectall_credentials = !$scope.selectall_credentials;
315
316 var tmp_credentials = $filter('filter')($scope.credentials, $scope.search);
317 tmp_credentials.forEach(function(credential) {
318 credential.selected = $scope.selectall_credentials;
319 });
320 };
321
322 $scope.clearSearch = function() {
323 $scope.search = '';
324 }
325
326 // toggles sort field and order
327 $scope.toggleSort = function(field) {
328 $scope.toggleSortField(field);
329 $scope.toggleReverse();
330 };
331
332 // toggles column sort field
333 $scope.toggleSortField = function(field) {
334 $scope.sort_field = field;
335 };
336
337 // toggle column sort order
338 $scope.toggleReverse = function() {
339 $scope.reverse = !$scope.reverse;
340 };
341
342 $scope.reloadPage = function() {
343 $window.location.reload();
344 };
345
346 init();
347 }]);
+0
-146
faraday/server/www/scripts/credentials/controllers/modalNewEditCredentialCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2017 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 "use strict";
5
6 angular.module('faradayApp')
7 .controller('modalNewEditCredentialCtrl',
8 ['$scope', '$modalInstance', 'title', 'credential', 'targetFactCred', '$routeParams',
9 function($scope, $modalInstance, title, credential, targetFactCred, $routeParams) {
10 $scope.title = title;
11 $scope.workspace = $routeParams.wsId;
12 $scope.targets = [];
13 $scope.credentialData = {
14 'name': '',
15 'username': '',
16 'password': '',
17 'target': '',
18 'hostsIp': {},
19 'targetsArray': []
20 };
21
22 $scope.total_rows = 0;
23 $scope.pageSize = 5;
24 $scope.currentPage = 1;
25 $scope.newCurrentPage = {};
26 $scope.targetFilter = {};
27 $scope.activeSearch;
28
29 var init = function(){
30 if(credential !== undefined){
31 $scope.credentialData.name = credential.name;
32 $scope.credentialData.username = credential.username;
33 $scope.credentialData.password = credential.password;
34 }
35
36 targetFactCred.getTargets($scope.workspace, $scope.currentPage, $scope.pageSize).then(function(targets){
37 $scope.targets = targets.hosts;
38 $scope.total_rows = targets.total;
39 });
40 };
41
42 $scope.ok = function() {
43 $modalInstance.close($scope.credentialData);
44 };
45
46 $scope.cancel = function() {
47 $modalInstance.dismiss('cancel');
48 };
49
50 $scope.invalidSubmit = function() {
51 if($scope.showTargets() === true){
52 if($scope.credentialData.targetsArray.length > 0) {
53 return false;
54 } else {
55 return true;
56 }
57 } else {
58 return false;
59 }
60 };
61
62 $scope.showTargets = function() {
63 // Don't show targets in modal:
64 // If Credential creation from hosts/services tab
65 // If user wants to create credential and not edit it
66 if(($routeParams.hId === undefined && $routeParams.sId === undefined) && title === 'New credential'){
67 return true;
68 }
69 else {
70 return false;
71 }
72 };
73
74 $scope.filterTargets = function() {
75 var filter = {ip: $scope.targetFilter.ip};
76 targetFactCred.getTargets($scope.workspace, $scope.currentPage, $scope.pageSize, filter).then(function(targets){
77 $scope.targets = targets.hosts;
78 $scope.activeSearch = true;
79 });
80 };
81
82 $scope.clearFilterTargets = function() {
83 $scope.activeSearch = false;
84 targetFactCred.getTargets($scope.workspace, $scope.currentPage, $scope.pageSize).then(function(targets){
85 $scope.targets = targets.hosts;
86 $scope.targetFilter = {};
87 });
88 };
89
90 $scope.assignTarget = function(target, hostIp) {
91 // Receive hostIp as parameter because if target
92 // is Service, it does not have hostIp
93 var index = -1;
94 var array = $.grep($scope.credentialData.targetsArray, function(item, i){
95 index = i;
96 return item.id === target.id && item.type === target.type;
97 });
98
99 if(array.length > 0) {
100 // Remove target selection
101 $scope.credentialData.targetsArray.splice(index, 1);
102 } else {
103 $scope.credentialData.targetsArray.push(target);
104
105 // Since it is not possible to obtain the hostIp from target if it is a service,
106 // credentialData.hostsIp contains the host's id with its IP if target is service
107 if(target.type === "Service")
108 $scope.credentialData.hostsIp[target.host_id] = hostIp;
109 }
110 };
111
112 $scope.updatePaginator = function(isNext, toGo) {
113 if (isNext === true)
114 $scope.currentPage = $scope.currentPage + 1;
115 else if (toGo) {
116 $scope.currentPage = toGo;
117 } else {
118 $scope.currentPage = $scope.currentPage - 1;
119 }
120
121 targetFactCred.getTargets($scope.workspace, $scope.currentPage, $scope.pageSize).then(function(targets){
122 $scope.targets = targets.hosts;
123 });
124
125 };
126
127 $scope.go = function() {
128 $scope.currentPage = 1;
129 if($scope.newCurrentPage.value <= (parseInt($scope.total_rows/$scope.pageSize) + 1) && $scope.newCurrentPage.value > 0) {
130 $scope.currentPage = $scope.newCurrentPage.value;
131 }
132
133 $scope.updatePaginator(false, $scope.currentPage);
134 };
135
136 $scope.isEmpty = function(obj) {
137 for(var key in obj) {
138 if(obj.hasOwnProperty(key))
139 return false;
140 }
141 return true;
142 };
143
144 init();
145 }]);
+0
-114
faraday/server/www/scripts/credentials/partials/list.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2017 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion clearfix">
5 <div class="faraday-header-border-fix"></div>
6 <div class="left-main-without-pagination">
7 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
8 <div id="reports-main" class="fila clearfix">
9 <div class="reports col-md-12 col-sm-12 col-xs-12">
10 <div class="button-control justify-flex-start col-md-12 col-sm-12 col-xs-12">
11 <div class="control-wrapper control-new">
12 <button id="new" type="button" class="btn btn-success btn-new" ng-title="{{workspaceData.readonly == false? 'New credential' : 'Read-only. Workspace disabled'}}" ng-click="new()" ng-disabled="workspaceData.readonly == true">
13 New
14 </button>
15 </div>
16 <table>
17 <thead>
18 <tr>
19 <th class="col-s-1" style="border-left: 1px solid rgb(221, 221, 221); padding-left: 12px;">
20 <a href="#/status/ws/{{workspace}}" class="status-report" ng-class="{'navigation-active' : component == 'status'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Vulns" tooltip-placement="right">
21 Vulns
22 </a>
23 </th>
24 <th class="col-s-1">
25 <a href="#/hosts/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'hosts'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Hosts" tooltip-placement="right">
26 Hosts
27 </a>
28 <div class="flex-spacer"></div>
29 </th>
30 <th class="col-s-1">
31 <a href="#/credentials/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'credentials'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Credentials" tooltip-placement="right">
32 Credentials
33 </a>
34 <div class="flex-spacer"></div>
35 </th>
36 <th class="col-md-1" style = "border-right: 1px solid rgb(221, 221, 221); padding-right: 12px">
37 <a href="#/taskgroup" class="executive-report" ng-class="{'navigation-active' : component == 'taskgroup'}" style="color: black !important; font-weight: bold; font-size: 15px;">
38 Tasks
39 </a>
40 <div class="flex-spacer"></div>
41 </th>
42 </tr>
43 </thead>
44 </table>
45 <div class="control-wrapper control-edit">
46 <button type="button" class="btn edit" title="{{workspaceData.readonly == false ? 'Edit selected credentials' : 'Read-only. Workspace disabled'}}" ng-disabled="selectedCredentials().length != 1 || workspaceData.readonly == true" ng-click="edit()">
47 <img src="images/icon-toolbar-edit.svg" class="edit-icon" />
48 </button>
49 </div>
50 <div class="control-wrapper">
51 <button id="delete" type="button" class="btn" title="{{workspaceData.readonly == false ? 'Delete selected credentials' : 'Read-only. Workspace disabled'}}" ng-disabled="selectedCredentials().length == 0 || workspaceData.readonly == true" ng-click="delete()">
52 <img src="images/icon-toolbar-delete.svg" class="delete-icon" />
53 </button>
54 </div>
55 <div class="control-wrapper search-wrapper">
56 <form role="form">
57 <div class="form-group">
58 <div class="input-group">
59 <span class="input-group-addon glyphicon-btn glyphicon glyphicon-remove" ng-if="search && search != 'confirmed=true'" style="cursor: pointer" ng-click="clearSearch()"></span>
60 <input type="text" class="form-control" placeholder="Enter keywords" ng-model="search" />
61 <span class="input-group-addon glyphicon-btn">
62 <img src="images/icon-toolbar-searchbar-loupe.svg" class="search-icon" />
63 </span>
64 </div>
65 </div>
66 </form>
67 </div>
68 </div>
69 </div>
70 </div>
71 <div class="reports col-md-12 col-sm-12 col-xs-12">
72 <table ng-if="credentials.length > 0" class="table-v3 licenses-list table table-responsive">
73 <thead>
74 <tr class="ui-grid-header">
75 <th class="ui-grid-cell-contents checkbox-select ui-grid-header-cell">
76 <input type="checkbox" ng-model="selectall" ng-click="checkAll()"/>
77 </th>
78 <th ng-if="!parentObject.parent_type" class="ui-grid-cell-contents ui-grid-header-cell">
79 <span ng-click="toggleSort('target')">Target</span>
80 </th>
81 <th class="ui-grid-cell-contents ui-grid-header-cell">
82 <span ng-click="toggleSort('name')">Name</span>
83 </th>
84 <th class="ui-grid-cell-contents ui-grid-header-cell">
85 <span ng-click="toggleSort('username')">Username</span>
86 </th>
87 <th class="ui-grid-cell-contents ui-grid-header-cell">
88 <span ng-click="toggleSort('password')">Password</span>
89 </th>
90 </tr>
91 </thead>
92 <tbody>
93 <tr ng-repeat="credential in credentials | filter:search | orderBy:sort_field:reverse"
94 selection-model selection-model-type="checkbox"
95 selection-model-mode="multiple-additive"
96 selection-model-selected-class="multi-selected"
97 selection-model-on-change="selectedCredentials()">
98 <td class="ui-grid-cell-contents checkbox-select">
99 <input type="checkbox" name="{{credential._id}}"/>
100 </td>
101 <td class="ui-grid-cell-contents" ng-if="!parentObject.parent_type"> {{credential.target}} </td>
102 <td class="ui-grid-cell-contents">{{credential.name}}</td>
103 <td class="ui-grid-cell-contents">{{credential.username}}</td>
104 <td class="ui-grid-cell-contents">{{credential.password}}</td>
105 </tr>
106 </tbody>
107 </table>
108 <h3 ng-if="credentials.length == 0">
109 No credentials found in this workspace
110 </h3>
111 </div>
112 </div>
113 </section>
+0
-113
faraday/server/www/scripts/credentials/partials/modalNewEdit.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2017 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <h3 class="modal-title">{{title}}</h3>
7 </div>
8 <div class="modal-body">
9 <div class="form-horizontal">
10 <div class="form-group" ng-if="showTargets()">
11 <div class="col-md-12">
12 <h5>
13 Target
14 </h5>
15 <div class="form-group">
16 <form name="formSearch" role="form">
17 <div class="col-md-8">
18 <div class="form-group input-accordion">
19 <input type="text" ng-model="targetFilter.ip" class="form-control input-sm"
20 placeholder="Search targets" ng-change="currentPage = 1">
21 <span class="btn btn-danger" id="btn_clear_search"
22 ng-if="!isEmpty(targetFilter) && activeSearch === true"
23 ng-click="clearFilterTargets()">
24 <i class="fa fa-times"></i>
25 </span>
26 </div>
27 </div>
28 <div class="col-md-2">
29 <div class="form-group">
30 <button type="submit" class="btn btn-success btn-xs background-blue" title="Search targets"
31 ng-click="filterTargets()" style="height: 30px!important; float: left;"
32 ng-disabled="isEmpty(targetFilter)">
33 Search
34 </button>
35 </div>
36 </div>
37 </form>
38 </div>
39
40 <uib-accordion close-others="true">
41 <uib-accordion-group is-open="isopen"
42 ng-repeat="host in targets"
43 template-url="scripts/statusReport/partials/accordion-group.html"
44 is-disabled="host.services.length < 1">
45 <uib-accordion-heading>
46 <a ng-click="assignTarget(host, host.ip)" ng-class="{'multi-selected': credentialData.targetsArray.indexOf(host) >= 0}">{{host.name}} ({{host.hostnames[0]}})</a>
47 </uib-accordion-heading>
48 <div class="panel-body" ng-repeat="service in host.services">
49 <a ng-model="service" ng-click="assignTarget(service, host.ip)" ng-class="{'multi-selected': credentialData.targetsArray.indexOf(service) >= 0}">{{service.name}} {{service.ports}}</a>
50 </div>
51 </uib-accordion-group>
52 </uib-accordion>
53
54 <div class="showPagination" ng-if="total_rows > pageSize">
55 <div class="form-group">
56 <ul class="pagination">
57 <li>
58 <a ng-hide="currentPage <= 1"
59 ng-click="updatePaginator()">
60 <span aria-hidden="true">&laquo;</span>
61 <span class="sr-only">Previous</span>
62 </a>
63 </li>
64 <li><a>{{currentPage}}/{{ ((total_rows / pageSize) | integer) + 1}}</a></li>
65 <li>
66 <a ng-hide="currentPage > ((total_rows / pageSize) | integer)"
67 ng-click="updatePaginator(true)">
68 <span aria-hidden="true">&raquo;</span>
69 <span class="sr-only">Next</span>
70 </a>
71 </li>
72 </ul>
73 <ng-form name="goToPage">
74 <div class="col-md-2">
75 <input type="number" class="form-control" ng-maxlength="((total_rows / pageSize) | integer)"
76 ng-model="newCurrentPage.value" ng-change="newCurrentPage"placeholder="Go to page"/>
77 </div>
78 <button type="submit" class="btn btn-danger background-blue" ng-click="go()">GO</button>
79 </ng-form>
80 </div>
81 </div>
82 <div class="alert alert-danger target_not_selected" role="alert"
83 ng-hide="credentialData.targetsArray.length > 0">
84 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
85 <span class="sr-only">Error:</span>
86 There is no target selected
87 </div>
88 </div>
89 </div>
90 <div class="col-md-12 custom-divider"></div>
91 <div class="tab-pane-header">Credential</div>
92 <div class="form-group">
93
94 <div class="col-md-3" ng-class="{'has-error': form.nameCredential.$invalid}">
95 <input type="text" class="form-control" id="nameCredential" name="nameCredential" placeholder="Name" ng-model="credentialData.name"/>
96 </div>
97 <div class="col-md-3" ng-class="{'has-error': form.usernameCredential.$invalid}">
98 <input type="text" class="form-control" id="usernameCredential" name="usernameCredential" placeholder="Username" ng-model="credentialData.username" required/>
99 </div>
100 <div class="col-md-3" ng-class="{'has-error': form.passwordCredential.$invalid}">
101 <input type="text" class="form-control" id="passwordCredential" name="passwordCredential" placeholder="Password" ng-model="credentialData.password"/>
102 </div>
103 </div>
104 </div>
105 </div>
106 <div class="modal-footer">
107 <div class="modal-button">
108 <button class="btn btn-success" ng-disabled="form.$invalid || invalidSubmit()" ng-click="ok()">OK</button>
109 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
110 </div>
111 </div>
112 </form>
+0
-165
faraday/server/www/scripts/credentials/providers/credential.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2017 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 "use strict";
5
6 angular.module('faradayApp')
7 .factory('credential', ['ServerAPI', '$q',
8 function(ServerAPI, $q) {
9
10 // All credentials need this properties minimum for build object.
11 var _credentialFields = {
12 'name': 'string',
13 'username': 'string',
14 'password': 'string',
15 'type': 'string',
16 };
17
18 // Only this properties will be saved to server.
19 var _credentialFieldsSaveToServer = {
20 'id': 'integer',
21 'name': 'string',
22 'username': 'string',
23 'metadata': 'string',
24 'password': 'string',
25 'type': 'string',
26 'parent_type': 'string',
27 'parent': 'string'
28 };
29
30 var Credential;
31 Credential = function(data, parent, parent_type){
32 if(data) {
33 this.set(data, parent, parent_type);
34 }
35 };
36
37 Credential.prototype = {
38 // Build object.
39 set: function(data, parent, parent_type) {
40
41 data.type = 'Cred';
42 data.parent_type = parent_type;
43 data.parent = parent;
44 if(data.metadata === undefined)
45 data.metadata = '';
46
47 _checkFieldsOk(data);
48 angular.extend(this, data);
49 },
50
51 // Find object in server and build that.
52 load: function(ws, id){
53
54 var deferred = $q.defer();
55 var self = this;
56
57 ServerAPI.getObj(ws, id, 'credential').then(function(response){
58 angular.extend(self, response.data);
59 deferred.resolve();
60 });
61
62 return deferred.promise;
63 },
64
65 // Delete object object in server.
66 delete: function(ws) {
67 return ServerAPI.deleteCredential(ws, this._id, this._rev);
68 },
69
70 // Update object in server.
71 update: function(ws) {
72 var self = this;
73 self.metadata = updateMetadata(self.metadata);
74 if(!self.id) self.id = self._id;
75
76 return ServerAPI.updateCredential(ws, buildObjectServer(self));
77 },
78
79 // Create object in server.
80 create: function(ws) {
81 var self = this;
82 self.metadata = generateCreateMetadata();
83
84 return ServerAPI.createCredential(ws, buildObjectServer(self)).
85 then(function(credential_data) {
86 self._id = credential_data.data.id
87 });
88 },
89
90 getParentName: function(ws){
91
92 var deferred = $q.defer();
93
94 var result = this.parent;
95 var hostIdToSearch = undefined;
96 var serviceIdToSearch = undefined;
97
98 //Parent is Host
99 if (result.parent_type === 'Host'){
100 hostIdToSearch = result[0];
101
102 ServerAPI.getObj(ws, hostIdToSearch).then(function(response){
103 deferred.resolve(response.data.name);
104 });
105 }
106
107 //Parent is Service
108 else if (result.lparent_type == 'Service'){
109 hostIdToSearch = result[0];
110 serviceIdToSearch = result.parent;
111
112 ServerAPI.getObj(ws, hostIdToSearch).then(function(responseHost){
113 ServerAPI.getObj(ws, serviceIdToSearch).then(function(responseService){
114 deferred.resolve(responseHost.data.name + '/' + responseService.data.name);
115 });
116 });
117 }
118
119 return deferred.promise;
120 }
121 };
122
123 // Check object to construct have all fields and also, type of they are OK.
124 // All fields in _credentialFields should are in object.
125 var _checkFieldsOk = function(credential){
126
127 Object.keys(_credentialFields).forEach(function(key, index) {
128 // Credential dont have property or type of property in credential dont same.
129 if(!credential.hasOwnProperty(key) || typeof(credential[key]) !== _credentialFields[key])
130 throw 'Credential-Invalid fields: Invalid fields in credential creation: ' + key;
131 });
132 };
133
134 // Build a credential object with only properties specified in _credentialFieldsSaveToServer (properties to save in server).
135 var buildObjectServer = function(credential){
136
137 var serverObject = {};
138 Object.keys(_credentialFieldsSaveToServer).forEach(function(key, index) {
139 if(credential.hasOwnProperty(key))
140 serverObject[key] = credential[key];
141 });
142 return serverObject;
143 };
144
145 var generateCreateMetadata = function() {
146
147 return {
148 'update_time': new Date().getTime(),
149 'update_user': '',
150 'update_action': 0,
151 'creator': 'UI Web',
152 'create_time': new Date().getTime(),
153 'update_controller_action': '',
154 'owner': ''
155 };
156 };
157
158 var updateMetadata = function(metadata) {
159 metadata['update_time'] = new Date().getTime();
160 return metadata;
161 };
162
163 return Credential;
164 }]);
+0
-41
faraday/server/www/scripts/credentials/providers/targetCred.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('targetFactCred', ['BASEURL', '$q', 'hostsManager', 'servicesManager', function(BASEURL, $q, hostsManager, servicesManager) {
6 var targetFactCred = {};
7
8 targetFactCred.getTargets = function(workspace, page, page_size, filter, sort, sort_direction) {
9 var deferred = $q.defer();
10 var res = {hosts: [], total: 0};
11 var hosts_dict = {};
12 hostsManager.getHosts(workspace, page, page_size, filter, sort, sort_direction).then(function(resp) {
13 resp.hosts.forEach(function(host) {
14 host.hostnames = host.hostnames || [];
15 host.services = [];
16 hosts_dict[host._id] = host;
17 res.hosts.push(host);
18 });
19
20 res.total = resp.total;
21
22 servicesManager.getServices(workspace).then(function(services) {
23 services.forEach(function(service) {
24 host_id = service.host_id
25 if (hosts_dict.hasOwnProperty(host_id)) {
26 hosts_dict[host_id].services.push(service);
27 }
28 });
29 }, function(err) {deferred.reject(err)});
30
31 deferred.resolve(res);
32
33 }, function(err) {deferred.reject(err)});
34
35 return deferred.promise;
36 };
37
38 return targetFactCred;
39 }]);
40
+0
-105
faraday/server/www/scripts/csv/providers/csv.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('csvService', function() {
6 var csvService = {};
7
8 csvService.generator = function(properties, values, ws) {
9 var values = angular.copy(values);
10 var obj_content = "",
11 aProperties = [];
12 if (ws === null) {
13 var title = 'Vulnerability Model CSV'
14 } else {
15 var title = "SR-" + ws
16 }
17
18 // Add confirmed to CSV fields
19 aProperties.push("confirmed");
20 for(key in properties) {
21 if(properties.hasOwnProperty(key)) {
22 if(properties[key] === true) {
23 aProperties.push(key);
24 }
25 }
26 }
27 values.forEach(function(v) {
28 aProperties.forEach(function(prop) {
29 object = {};
30 if(typeof(v[prop]) === "object") v[prop] = parseObject(v[prop]);
31 if(typeof(v[prop]) != "undefined" && v[prop] != null && typeof(v[prop]) != "number" && prop != "confirmed") {
32 object[prop] = cleanCSV(v[prop]);
33 }else{
34 object[prop] = "";
35 }
36
37 if(prop === "_id") object[prop] = v[prop].toString();
38 if(prop === "confirmed") object[prop] = v[prop].toString();
39 if(prop === "date") object[prop] = parseDate(new Date(v["metadata"]["create_time"]));
40 if(prop === "creator") object[prop] = excelEscape(v["metadata"]["creator"]);
41 if(prop === "web") {
42 if(v.type === "Vulnerability") {
43 object[prop] = false;
44 } else {
45 object[prop] = true;
46 }
47 }
48 obj_content += "\"" + object[prop] + "\",";
49 });
50 obj_content = obj_content.substring(0, obj_content.length - 1);
51 obj_content += "\n";
52 });
53 var content = JSON.stringify(aProperties).replace(/\[|\]/g,"") + "\n" + obj_content;
54 var csvObj = {
55 "content": content,
56 "extension": "csv",
57 "title": title,
58 "type": "text/csv"
59 };
60
61 return csvObj;
62 };
63
64 cleanCSV = function(field) {
65 return excelEscape(field.replace(/\"/g, "\"\""));
66 };
67
68 parseObject = function(object) {
69 if (object === null || object === undefined) return "";
70 var parsedData = "";
71 if(object.length === undefined) {
72 for(key in object){
73 if(object.hasOwnProperty(key)) {
74 parsedData += key + ":" + object[key] + "\n";
75 }
76 }
77 } else {
78 object.forEach(function(obj, k) {
79 parsedData += obj + "\n";
80 });
81 }
82 parsedData = parsedData.substring(0, parsedData.length - 1);
83 return excelEscape(parsedData);
84 };
85
86 parseDate = function(date) {
87 var d = new Date(date);
88 return excelEscape(d.getMonth()+1 +"/" + d.getDate() + "/" + d.getFullYear());
89 };
90
91 excelEscape = function(data){
92 // Patch possible formula injection attacks
93 // See https://www.contextis.com/resources/blog/comma-separated-vulnerabilities/ for more info.
94 if(data.startsWith('=') || data.startsWith('+')
95 || data.startsWith('-')
96 || data.startsWith('@')){
97 return "'" + data
98 }else{
99 return data
100 }
101 }
102
103 return csvService;
104 });
+0
-124
faraday/server/www/scripts/d3/directives/bar.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('d3Bars', ['d3Service', '$routeParams',
6 function(d3Service, $routeParams) {
7 return {
8 restrict: 'EA',
9 scope: {
10 data: '='
11 },
12 link: function(scope, ele, attrs) {
13 d3Service.d3().then(function(d3) {
14
15 var margin = {
16 "top": parseInt(attrs.marginTop) || 20,
17 "right": parseInt(attrs.marginRight) || 20,
18 "bottom": parseInt(attrs.marginBottom) || 30,
19 "left": parseInt(attrs.marginLeft) || 40
20 }
21
22 var barHeight = parseInt(attrs.barHeight) || 20,
23 barPadding = parseInt(attrs.barPadding) || 5,
24 width = parseInt(attrs.svgWitdh) || 160,
25 height = parseInt(attrs.svgHeight) || 149;
26
27 scope.$watch('data', function(newData) {
28 scope.render(newData);
29 }, true);
30
31 scope.render = function(data) {
32
33 // remove existing treemap container, if any
34 d3.select("#bar_container").remove();
35
36 if (!data || data.length == 0) return;
37
38 var svg = d3.select(ele[0])
39 .append("div")
40 .attr("class", "box")
41 .attr("id", "bar_container")
42 .append("svg")
43 .attr("width", width)
44 .attr("height", height)
45 .append("g")
46 .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
47
48 var color = d3.scale.category20b();
49 var x = d3.scale.ordinal()
50 .rangeRoundBands([0, width - margin.left - margin.right], .1);
51
52 var y = d3.scale.linear()
53 .range([height - margin.top - margin.bottom, 0]);
54
55 var xAxis = d3.svg.axis()
56 .scale(x)
57 .orient("bottom");
58 var yAxis = d3.svg.axis()
59 .scale(y)
60 .orient("left")
61 .ticks(5);
62
63 x.domain(data.map(function(d) { return d.key; }));
64 y.domain([0, d3.max(data, function(d) { return d.value; })]);
65
66 svg.selectAll('.bar')
67 .data(data)
68 .enter()
69 .append('rect')
70 .attr("class", function(d) { return "id-" + d.key + " bar"; })
71 .attr("x", function(d) { return x(d.key); })
72 .attr("y", function(d) { return y(d.value - 0.5); })
73 .style("fill", function(d) { return color(Math.random()*55); })
74 .attr("height", function(d) { return height - margin.top - margin.bottom - y(d.value); })
75 .attr("width", 30)
76 .style('opacity', 0)
77 .on('mouseover', function(d) {
78 workspace = $routeParams.wsId;
79 var hurl = "/" + workspace + "/_design/hosts/_view/hosts";
80 hosts = get_obj(hurl);
81 var name = hosts[d.key].name;
82 var element = document.getElementById("barText");
83 var colored = document.createElement('div');
84 colored.style = "background-color:" + d.color; // Color is safe (its value is in a whitelist)
85 colored.innerText = name;
86 while (element.firstChild) {
87 // https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript
88 element.removeChild(element.firstChild);
89 }
90 element.appendChild(colored);
91 element.appendChild(document.createTextNode(d.value));
92 })
93 .on('mouseenter', function(d) {
94 var line = d3.select('.id-'+d.key)
95 .style("opacity", 1);
96 })
97 .on('mouseleave', function(d) {
98 document.getElementById("barText").innerHTML = "";
99 var line = d3.select('.id-'+d.key)
100 .style("opacity", 0.8);
101 })
102 .transition()
103 .duration(1250)
104 .style('opacity', 0.8);
105
106 function get_obj(ourl) {
107 var ls = {};
108 $.ajax({
109 dataType: "json",
110 url: ourl,
111 async: false,
112 success: function(data) {
113 $.each(data.rows, function(n, obj){
114 ls[obj.key] = obj.value;
115 });
116 }
117 });
118 return ls;
119 }
120 };
121 });
122 }}
123 }]);
+0
-132
faraday/server/www/scripts/d3/directives/cake.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('d3Cake', ['d3Service',
6 function(d3Service) {
7 return {
8 restrict: 'EA',
9 scope: {
10 data: '='
11 },
12 link: function(scope, ele, attrs) {
13 d3Service.d3().then(function(d3) {
14
15 var margin = {
16 "top": parseInt(attrs.marginTop) || 28,
17 "right": parseInt(attrs.marginRight) || 10,
18 "bottom": parseInt(attrs.marginBottom) || 10,
19 "left": parseInt(attrs.marginLeft) || 10
20 }
21
22 var width = parseInt(attrs.cakeWitdh) || 160,
23 height = parseInt(attrs.cakeHeight) || 149,
24 radius = parseInt(attrs.cakeRadius) || Math.min(width, height) / 2;
25
26 // Breadcrumb dimensions: width, height, spacing, width of tip/tail.
27 var b = {
28 w: 75, h: 30, s: 3, t: 10
29 };
30
31 scope.$watch('data', function(newData) {
32 scope.render(newData);
33 }, true);
34
35 scope.render = function(data) {
36
37 // remove existing treemap container, if any
38 d3.select("#chart").remove();
39 d3.select("#sequence").remove();
40
41 if (!data || data.length == 0) return;
42
43 // we need to make a copy of the data, because the treemap is going to change it
44 // and we have a watcher for that data to re-render the treemap, so we can enter
45 // in a recursion loop
46 var data_cp = {};
47 angular.copy(data, data_cp);
48
49 var totalSize = 0;
50
51 var vis = d3.select(ele[0])
52 .append("div")
53 .attr("class", "box")
54 .attr("id", "chart")
55 .append("svg:svg")
56 .attr("class", "box")
57 .attr("width", width)
58 .attr("height", height)
59 .append("svg:g")
60 .attr("id", "container")
61 .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
62
63 var partition = d3.layout.partition()
64 .size([2 * Math.PI , radius * radius])
65 .value(function(d) { return d.value; });
66
67 var arc = d3.svg.arc()
68 .startAngle(function(d) { return d.x; })
69 .endAngle(function(d) { return d.x + d.dx; })
70 .innerRadius(function(d) { return Math.sqrt(d.y); })
71 .outerRadius(function(d) { return Math.sqrt(radius); });
72
73 // Bounding circle underneath the sunburst, to make it easier to detect
74 // when the mouse leaves the parent g.
75 vis.append("svg:circle")
76 .attr("r", radius)
77 .style("opacity", 0);
78
79 // For efficiency, filter nodes to keep only those large enough to see.
80 var nodes = partition.nodes(data_cp)
81 .filter(function(d) {
82 return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
83 });
84
85 var path = vis.data([data_cp]).selectAll("path")
86 .data(nodes)
87 .enter().append("svg:path")
88 .attr("display", function(d) { return d.depth ? null : "none"; })
89 .attr("d", arc)
90 .attr("fill-rule", "evenodd")
91 .attr("class", function(d) {
92 var key = "";
93 if(d.key) {
94 key = "cake-" + d.key;
95 }
96 return key;
97 })
98 .style("fill", function(d) {return d.color; })
99 .style("stroke-width", "0.5")
100 .style("opacity", 0)
101 .on('mouseover', function(d) {
102 var element = document.getElementById("cakeText");
103 var colored = document.createElement('div');
104 colored.style = "background-color:" + d.color; // Color is safe (its value is in a whitelist)
105 colored.innerText = d.key;
106 while (element.firstChild) {
107 // https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript
108 element.removeChild(element.firstChild);
109 }
110 element.appendChild(colored);
111 element.appendChild(document.createTextNode(d.value));
112 })
113 .on('mouseenter', function(d) {
114 var slice = d3.select('.cake-'+d.key)
115 .style("opacity", 1);
116 })
117 .on('mouseleave', function(d) {
118 var slice = d3.select('.cake-'+d.key)
119 .style("opacity", 0.8);
120 document.getElementById("cakeText").innerHTML = "";
121 })
122 .transition()
123 .duration(1250)
124 .style('opacity', 0.8);
125
126 // Get total size of the tree = value of root node from partition.
127 totalSize = path.node().__data__.value;
128 };
129 });
130 }}
131 }]);
+0
-139
faraday/server/www/scripts/d3/directives/stackedbar.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('d3HorizontalStackedBar', ['d3Service', '$window', '$compile',
6 function(d3Service, $window, $compile) {
7 return {
8 restrict: 'EA',
9 scope: {
10 data: '=data'
11 },
12 link: function(scope, ele, attrs) {
13 d3Service.d3().then(function(d3) {
14 // update scope when changes occur
15 scope.$watch('data', function(newData) {
16 if(newData != undefined) scope.render(newData);
17 }, true);
18
19 // redraw graphic when resize occurs
20 angular.element($window).on('resize', function(e) {
21 if(scope.data != undefined) scope.render(scope.data);
22 });
23
24 }); // d3Service.d3()
25
26 scope.render = function(data) {
27 d3.select('.stackedbars').selectAll('svg').remove();
28
29 var margins = {
30 top: 5,
31 left: 15,
32 right: 5,
33 bottom: 5
34 };
35
36 // get parent width to calculate graphic width
37 var pwidth = ele.parent().width(),
38 width = pwidth * 0.9,
39 height = 30 - margins.top - margins.bottom;
40
41 var dataset = data.map(function(d) {
42 return [{
43 k: d.key,
44 c: d.color,
45 y: d.amount,
46 x: 0
47 }];
48 });
49
50 stack = d3.layout.stack();
51 stack(dataset);
52
53 var dataset = dataset.map(function (group) {
54 return group.map(function (d) {
55 // Invert the x and y values, and y0 becomes x0
56 return {
57 k: d.k,
58 c: d.c,
59 x: d.y,
60 y: d.x,
61 x0: d.y0
62 };
63 });
64 }),
65 svg = d3.select(".stackedbars")
66 .append('svg')
67 .attr('width', width + margins.left + margins.right)
68 .attr('height', height + margins.top + margins.bottom)
69 .append('g')
70 .attr('transform', 'translate(' + margins.left + ',' + margins.top + ')'),
71 xMax = d3.max(dataset, function (group) {
72 return d3.max(group, function (d) {
73 return d.x + d.x0;
74 });
75 }),
76 xScale = d3.scale.linear()
77 .domain([0, xMax])
78 .range([0, width]),
79 months = dataset[0].map(function (d) {
80 return d.y;
81 }),
82 yScale = d3.scale.ordinal()
83 .domain(months)
84 .rangeRoundBands([0, height], .1),
85 xAxis = d3.svg.axis()
86 .scale(xScale)
87 .orient('bottom'),
88 yAxis = d3.svg.axis()
89 .scale(yScale)
90 .orient('left'),
91 groups = svg.selectAll('g')
92 .data(dataset)
93 .enter()
94 .append('g')
95 .style('fill', function (d, i) {
96 return d[0].c;
97 }),
98 rects = groups.selectAll('rect')
99 .data(function (d) {
100 return d;
101 })
102 .enter()
103 .append('rect')
104 .attr('x', function (d) {
105 return xScale(d.x0);
106 })
107 .attr('y', function (d, i) {
108 return yScale(d.y);
109 })
110 .attr('height', function (d) {
111 return yScale.rangeBand();
112 })
113 .attr('width', function (d) {
114 return xScale(d.x);
115 })
116 .attr('tooltip-append-to-body', true)
117 .attr('uib-tooltip', function(d) {
118 return d.k + " sums $" + d.x;
119 })
120 .attr('class', function(d) {
121 return "sb-" + d.k;
122 })
123 .style('opacity', 0.8)
124 .on('mouseenter', function(d) {
125 var line = d3.select('.sb-'+d.k)
126 .style("opacity", 1);
127 })
128 .on('mouseleave', function(d) {
129 var line = d3.select('.sb-'+d.k)
130 .style("opacity", 0.8);
131 });
132
133 ele.removeAttr("d3-horizontal-stacked-bar");
134 $compile(ele)(scope);
135 }; // scope.render definition
136 }
137 };
138 }]);
+0
-123
faraday/server/www/scripts/d3/directives/treemap.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('d3Treemap', ['d3Service',
6 function(d3Service) {
7 return {
8 restrict: 'EA',
9 scope: {
10 data: '='
11 },
12 link: function(scope, ele, attrs) {
13 d3Service.d3().then(function(d3) {
14
15 var margin = {
16 "top": parseInt(attrs.marginTop) || 28,
17 "right": parseInt(attrs.marginRight) || 10,
18 "bottom": parseInt(attrs.marginBottom) || 10,
19 "left": parseInt(attrs.marginLeft) || 10
20 }
21
22 function position() {
23 this.style("left", function(d) { return d.x + "px"; })
24 .style("top", function(d) { return d.y + "px"; })
25 .style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; })
26 .style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; });
27 }
28
29 scope.$watch('data', function(newData) {
30 scope.render(newData);
31 }, true);
32
33 scope.render = function(data) {
34 //remove existing treemap container, if any
35 d3.select(ele[0]).select("#treemap_container").remove();
36
37 if (!data || data.length == 0) return;
38
39 var width = data.width || 160,
40 height = data.height || 133;
41
42 var div = d3.select(ele[0])
43 .append("div")
44 .attr("class", "treemap")
45 .attr("id", "treemap_container")
46 .style("position", "relative")
47 .style("width", width + "px")
48 .style("height", height + "px")
49 .style("left", margin.left + "px")
50 .style("top", margin.top + "px");
51
52 // we need to make a copy of the data, because the treemap is going to change it
53 // and we have a watcher for that data to re-render the treemap, so we can enter
54 // in a recursion loop
55 var data_cp = {};
56 angular.copy(data, data_cp);
57
58 var treemap = d3.layout.treemap()
59 .size([width - margin.left - margin.right, height - margin.top - margin.bottom])
60 .sticky(true)
61 .value(function(d) {return d.count});
62
63 function nameToClassSafeName(name) {
64 // Remove non alphanumeric characters to safely use the (modified)
65 // name as a class name
66 return name.replace(/[^0-9a-zA-Z]/g, '');
67 }
68
69 var node = div.datum(data_cp).selectAll(".node")
70 .data(treemap.nodes)
71 .enter().append("div")
72 .attr("class", function(d) {
73 var ret = "node treemap-tooltip";
74 if(d.name) ret += " tm-" + nameToClassSafeName(d.name);
75 return ret;
76 })
77 .call(position)
78 .style("background", function(d) { return d.color; })
79 .style('opacity', 0)
80 .text(function(d, i) {
81 if(data.width){
82 var total = d3.sum(data.children, function(d){return d.count;});
83 return (d.name+ " ( " + d3.round(100* d.count / total, 1) + "% " + ")" ) ;
84 }
85 })
86 .on('mouseover', function(d){
87 if(typeof(d.name) === 'undefined') return; // I don't know why this happens
88 if (!data.width){
89 var element = document.getElementById("treemapText");
90 //.innerHTML = "<div style='background-color:" + d.color + "'>" + d.name + '</div>' + d.count;
91 }else{
92 var element = document.getElementById("treemapTextModel");
93 }
94 var colored = document.createElement('div');
95 colored.style = "background-color:" + d.color; // Color is safe (its value is in a whitelist)
96 colored.innerText = d.name;
97 while (element.firstChild) {
98 // https://stackoverflow.com/questions/3955229/remove-all-child-elements-of-a-dom-node-in-javascript
99 element.removeChild(element.firstChild);
100 }
101 element.appendChild(colored);
102 element.appendChild(document.createTextNode(d.count));
103 })
104 .on('mouseenter', function(d) {
105 if(typeof(d.name) === 'undefined') return; // I don't know why this happens
106 var line = d3.select('.tm-'+nameToClassSafeName(d.name))
107 .style("opacity", 1);
108 })
109 .on('mouseleave', function(d) {
110 if(typeof(d.name) === 'undefined') return; // I don't know why this happens
111 var line = d3.select('.tm-'+nameToClassSafeName(d.name))
112 .style("opacity", 0.8);
113 document.getElementById("treemapText").innerHTML = "";
114 })
115 .transition()
116 .duration(1250)
117 .style('opacity', 0.8);
118
119 };
120 });
121 }}
122 }]);
+0
-32
faraday/server/www/scripts/d3/providers/d3.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('d3Service', ['BASEURL', '$document', '$q', '$rootScope',
6 function(BASEURL, $document, $q, $rootScope) {
7 var d = $q.defer();
8 function onScriptLoad() {
9 // Load client in the browser
10 $rootScope.$apply(function() { d.resolve(window.d3); });
11 }
12 // Create a script tag with d3 as the source
13 // and call our onScriptLoad callback when it
14 // has been loaded
15 var scriptTag = $document[0].createElement('script');
16 scriptTag.type = 'text/javascript';
17 scriptTag.async = true;
18 scriptTag.src = 'script/d3.v3.min.js';
19 scriptTag.onreadystatechange = function () {
20 if (this.readyState == 'complete') onScriptLoad();
21 }
22 scriptTag.onload = onScriptLoad;
23
24 var s = $document[0].getElementsByTagName('body')[0];
25 s.appendChild(scriptTag);
26
27 return {
28 d3: function() { return d.promise; }
29 };
30 }
31 ]);
+0
-85
faraday/server/www/scripts/dashboard/controllers/activityFeedCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 'use strict';
5
6 angular.module('faradayApp')
7 .controller('activityFeedCtrl',
8 ['$scope', '$routeParams', 'dashboardSrv',
9 function ($scope, $routeParams, dashboardSrv) {
10
11 var vm = this;
12 vm.commands = [];
13
14 // Get last 15 commands
15 var init = function () {
16
17 $scope.settings = {
18 currentPage: 0,
19 offset: 0,
20 pageLimit: 5,
21 pageLimits: ['3', '5', '10', '20', '30', '50', '80', '100']
22 };
23
24 if ($routeParams.wsId !== undefined) {
25 $scope.workspace = $routeParams.wsId;
26
27 collapse();
28
29 dashboardSrv.getActivityFeed($scope.workspace)
30 .then(function (response) {
31 vm.commands = response.activities;
32 });
33 }
34 };
35
36 $scope.toggleExpanded = function () {
37 if ($scope.isExpanded) {
38 collapse();
39 } else {
40 expand();
41 }
42 };
43
44 var collapse = function () {
45 $scope.settings.pageLimit = 5;
46 $scope.isExpanded = false;
47 $scope.hideEmpty = true;
48 angular.element('#first-row-panel').css('display', 'inherit');
49 angular.element('#activities-container-row').addClass('mt-md');
50 };
51
52 var expand = function () {
53 $scope.settings.pageLimit = 15;
54 $scope.isExpanded = true;
55 $scope.hideEmpty = false;
56 angular.element('#first-row-panel').css('display', 'none');
57 angular.element('#activities-container-row').removeClass('mt-md');
58 };
59
60 $scope.isEmpty = function (cmd) {
61 return cmd.hosts_count === 0 && cmd.services_count === 0 && cmd.vulnerabilities_count === 0;
62 };
63
64 $scope.getValidCount = function () {
65 var count = 0;
66 for(var i = 0; i < vm.commands.length; i++){
67 if (!$scope.isEmpty(vm.commands[i])) count ++
68 }
69 return count;
70 };
71
72 $scope.fitStringInTooltip = function (string) {
73 /**
74 * Summary: split string to fit it into tooltip.
75 * */
76 if (string.length >= 18)
77 return string.substring(0, 18) + ' ' + string.substring(18)
78 else
79 return string
80 };
81
82 dashboardSrv.registerCallback(init);
83 init();
84 }]);
+0
-51
faraday/server/www/scripts/dashboard/controllers/commandsCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('commandsCtrl',
6 ['$scope', '$routeParams', 'dashboardSrv',
7 function($scope, $routeParams, dashboardSrv) {
8
9 $scope.commands;
10 $scope.cmdSortField = "date";
11 $scope.cmdSortReverse = true;
12
13 init = function() {
14 if($routeParams.wsId != undefined) {
15 $scope.workspace = $routeParams.wsId;
16
17 dashboardSrv.getCommands($scope.workspace)
18 .then(function(commands) {
19 $scope.commands = commands;
20 });
21 }
22
23 $scope.settings = {
24 currentPage: 0,
25 offset: 0,
26 pageLimit: 5,
27 pageLimits: ['5', '10', '20', '30', '50', '80', '100']
28 };
29 };
30
31 // toggles sort field and order
32 $scope.cmdToggleSort = function(field) {
33 $scope.cmdToggleSortField(field);
34 $scope.cmdToggleReverse();
35 };
36
37 // toggles column sort field
38 $scope.cmdToggleSortField = function(field) {
39 $scope.cmdSortField = field;
40 };
41
42 // toggle column sort order
43 $scope.cmdToggleReverse = function() {
44 $scope.cmdSortReverse = !$scope.cmdSortReverse;
45 }
46
47 dashboardSrv.registerCallback(init);
48
49 init();
50 }]);
+0
-161
faraday/server/www/scripts/dashboard/controllers/compoundCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('compoundCtrl', [
6 '$scope',
7 '$location',
8 '$route',
9 '$routeParams',
10 '$uibModal',
11 'hostsManager',
12 'workspacesFact',
13 'dashboardSrv',
14 function ($scope,
15 $location,
16 $route,
17 $routeParams,
18 $uibModal,
19 hostsManager,
20 workspacesFact,
21 dashboardSrv) {
22
23 init = function() {
24 // hosts list
25 $scope.hosts = [];
26 $scope.totalHosts = 0;
27 // current workspace
28 $scope.workspace = $routeParams.wsId;
29
30 $scope.sortField = "services";
31 $scope.sortDirection = "desc";
32 $scope.reverse = true;
33
34 // load all workspaces
35 workspacesFact.list().then(function(wss) {
36 $scope.workspaces = wss;
37 });
38
39 // paging
40 $scope.pageSize = 10;
41 $scope.currentPage = 1;
42 $scope.newCurrentPage = 1;
43 $scope.newPageSize = $scope.pageSize;
44
45 loadHosts();
46 };
47
48 var loadHosts = function() {
49 hostsManager.getHosts(
50 $scope.workspace, $scope.currentPage,
51 $scope.pageSize, $scope.expression,
52 $scope.sortField, $scope.sortDirection)
53 .then(function(batch) {
54 $scope.hosts = batch.hosts;
55 $scope.totalHosts = batch.total;
56 $scope.loadedVulns = true;
57 $scope.loadIcons();
58 })
59 .catch(function(e) {
60 console.log(e);
61 });
62 };
63
64 $scope.loadIcons = function() {
65 $scope.hosts.forEach(function(host) {
66 // load icons into object for HTML
67 // maybe this part should be directly in the view somehow
68 // or, even better, in a CSS file
69 oss = ["windows", "cisco", "router", "osx", "apple","linux", "unix"];
70 oss.forEach(function(os){
71 if(host.os.toLowerCase().indexOf(os) != -1) {
72 host.icon = os;
73 if(os == "unix") {
74 host.icon = "linux";
75 } else if(os == "apple") {
76 host.icon = "osx";
77 }
78 }
79 });
80 });
81 };
82
83 $scope.go = function() {
84 $scope.pageSize = $scope.newPageSize;
85 $scope.currentPage = 1;
86 if ($scope.newCurrentPage <= $scope.pageCount() && $scope.newCurrentPage > 0 &&
87 !isNaN(parseInt($scope.newCurrentPage))) {
88 $scope.currentPage = $scope.newCurrentPage;
89 }
90 loadHosts();
91 };
92
93 // toggles sort field and order
94 $scope.toggleSort = function(field) {
95 if ($scope.sortField != field) {
96 $scope.sortDirection = "desc";
97 } else {
98 $scope.toggleReverse();
99 }
100 $scope.sortField = field;
101 loadHosts();
102 };
103
104 // toggle column sort order
105 $scope.toggleReverse = function() {
106 if ($scope.sortDirection == "asc") {
107 $scope.sortDirection = "desc";
108 } else {
109 $scope.sortDirection = "asc";
110 }
111 }
112
113 // paging
114 $scope.prevPage = function() {
115 $scope.currentPage -= 1;
116 loadHosts();
117 };
118
119 $scope.prevPageDisabled = function() {
120 return $scope.currentPage <= 1;
121 };
122
123 $scope.nextPage = function() {
124 $scope.currentPage += 1;
125 loadHosts();
126 };
127
128 $scope.nextPageDisabled = function() {
129 return $scope.currentPage >= $scope.pageCount();
130 };
131
132 $scope.pageCount = function() {
133 return Math.ceil($scope.totalHosts / $scope.pageSize);
134 };
135
136 $scope.showServices = function(host) {
137 if ($scope.workspace != undefined){
138 var modal = $uibModal.open({
139 templateUrl: 'scripts/dashboard/partials/modal-services-by-host.html',
140 controller: 'summarizedCtrlServicesModal',
141 size: 'lg',
142 resolve: {
143 host: function() {
144 return host
145 },
146 workspace: function() {
147 return $scope.workspace;
148 },
149 osint: function() {
150 return $scope.osint;
151 }
152 }
153 });
154 }
155 };
156
157 dashboardSrv.registerCallback(loadHosts);
158
159 init();
160 }]);
+0
-55
faraday/server/www/scripts/dashboard/controllers/dashboard.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('dashboardCtrl',[
6 '$scope',
7 '$filter',
8 '$route',
9 '$routeParams',
10 '$location',
11 'dashboardSrv',
12 'workspacesFact',
13 'vulnsManager',
14 'configSrv',
15 function($scope,
16 $filter,
17 $route,
18 $routeParams,
19 $location,
20 dashboardSrv,
21 workspacesFact,
22 vulnsManager,
23 configSrv) {
24
25 $scope.props = dashboardSrv.props;
26
27 init = function() {
28 //current workspace
29 $scope.workspace = $routeParams.wsId;
30 $scope.showVulnCost = configSrv.show_vulns_by_price;
31 $scope.workspaces = [];
32
33 workspacesFact.list().then(function(wss) {
34 $scope.workspaces = wss;
35 });
36
37 dashboardSrv.setConfirmedFromCookie();
38 dashboardSrv.startTimer();
39 };
40
41 $scope.navigate = function(route) {
42 $location.path(route);
43 };
44
45 $scope.$on('$destroy', function(){
46 dashboardSrv.stopTimer();
47 })
48
49 $scope.reload = function() {
50 dashboardSrv.updateData();
51 }
52
53 init();
54 }]);
+0
-48
faraday/server/www/scripts/dashboard/controllers/lastVulnsCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('lastVulnsCtrl',
6 ['$scope', '$routeParams', 'dashboardSrv', 'vulnsManager',
7 function($scope, $routeParams, dashboardSrv, vulnsManager) {
8 $scope.vulns;
9 $scope.workspace;
10
11 init = function() {
12 if($routeParams.wsId != undefined) {
13 $scope.workspace = $routeParams.wsId;
14
15 $scope.loadData();
16
17 $scope.$watch(function() {
18 return dashboardSrv.props.confirmed;
19 }, function(newValue, oldValue) {
20 if (oldValue != newValue)
21 $scope.loadData();
22 }, true);
23 }
24
25 $scope.settings = {
26 currentPage: 0,
27 offset: 0,
28 pageLimit: 5,
29 pageLimits: ['3', '5', '10', '20', '30', '50', '80', '100']
30 };
31 };
32
33 $scope.loadData = function() {
34 var filter = {};
35 if (dashboardSrv.props.confirmed) {
36 filter.confirmed = true;
37 }
38 vulnsManager.getVulns($scope.workspace, 0, 5, filter, "date", "desc")
39 .then(function(res) {
40 $scope.vulns = res.vulnerabilities;
41 });
42 };
43
44 dashboardSrv.registerCallback($scope.loadData);
45
46 init();
47 }]);
+0
-47
faraday/server/www/scripts/dashboard/controllers/servicesCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('servicesCtrl',
6 ['$scope', '$uibModal', '$routeParams', 'dashboardSrv',
7 function($scope, $uibModal, $routeParams, dashboardSrv) {
8 $scope.servicesCount;
9 $scope.workspace;
10
11 init = function() {
12 if($routeParams.wsId != undefined) {
13 $scope.workspace = $routeParams.wsId;
14
15 dashboardSrv.getServicesCount($scope.workspace)
16 .then(function(services) {
17 $scope.servicesCount = services;
18 });
19 }
20 };
21
22 $scope.showHosts = function(srv_name) {
23 if($scope.workspace != undefined) {
24 var modal = $uibModal.open({
25 templateUrl: 'scripts/dashboard/partials/modal-hosts-by-service.html',
26 controller: 'summarizedCtrlHostsModal',
27 size: 'lg',
28 resolve: {
29 srv_name: function() {
30 return srv_name;
31 },
32 workspace: function() {
33 return $scope.workspace;
34 },
35 osint: function() {
36 return $scope.osint;
37 }
38 }
39 });
40 }
41 };
42
43 dashboardSrv.registerCallback(init);
44
45 init();
46 }]);
+0
-53
faraday/server/www/scripts/dashboard/controllers/summarizedCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('summarizedCtrl',
6 ['$scope', '$routeParams', 'dashboardSrv',
7 function($scope, $routeParams, dashboardSrv) {
8
9 $scope.objectsCount = [];
10 $scope.workspace;
11
12 init = function() {
13 if($routeParams.wsId != undefined) {
14 $scope.workspace = $routeParams.wsId;
15 $scope.loadData();
16
17 $scope.$watch(function() {
18 return dashboardSrv.props.confirmed;
19 }, function(newValue, oldValue) {
20 if (oldValue != newValue)
21 $scope.loadData();
22 }, true);
23 }
24 };
25
26 // Used to set the order ob the items
27 countFields = ['hosts', 'credentials', 'services', 'std_vulns',
28 'total_vulns', 'web_vulns']
29
30 $scope.loadData = function() {
31 dashboardSrv.getObjectsCount($scope.workspace)
32 .then(function(obj_count) {
33 $scope.objectsCount = [];
34 // for (var property in obj_count) {
35 countFields.forEach(function(property){
36 if (obj_count.hasOwnProperty(property) && obj_count[property] > 0) {
37 var tmp_obj = {};
38 tmp_obj["value"] = obj_count[property];
39 if (property === "std_vulns")
40 property = "vulns";
41 // replace underscores for spaces
42 tmp_obj["key"] = property.replace("_", " ");
43 $scope.objectsCount.push(tmp_obj);
44 }
45 });
46 });
47 };
48
49 dashboardSrv.registerCallback($scope.loadData);
50
51 init();
52 }]);
+0
-70
faraday/server/www/scripts/dashboard/controllers/summarizedCtrlHostsModal.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('summarizedCtrlHostsModal',
6 ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', 'srv_name', 'osint',
7 function($scope, $modalInstance, dashboardSrv, workspace, srv_name, osint) {
8
9 $scope.osint = osint;
10 $scope.sortField = 'name';
11 $scope.sortReverse = false;
12 $scope.clipText = "Copy names to Clipboard";
13 $scope.workspace = workspace
14
15 // toggles sort field and order
16 $scope.toggleSort = function(field) {
17 $scope.toggleSortField(field);
18 $scope.toggleReverse();
19 };
20
21 // toggles column sort field
22 $scope.toggleSortField = function(field) {
23 $scope.sortField = field;
24 };
25
26 // toggle column sort order
27 $scope.toggleReverse = function() {
28 $scope.sortReverse = !$scope.sortReverse;
29 }
30
31 dashboardSrv.getHostsByServicesName(workspace, srv_name).then(function(hosts){
32 $scope.name = srv_name;
33 $scope.hosts = hosts;
34 $scope.clip = "";
35 $scope.hosts.forEach(function(h, index, array){
36 let port = $scope.getPort(h.service_summaries);
37 $scope.hosts[index].port = port;
38 if(index === array.length -1)
39 $scope.clip += h.name + ":" + port;
40 else
41 $scope.clip += h.name + ":" + port + " - ";
42 });
43 });
44
45 $scope.messageCopied = function(){
46 $scope.clipText = "Copied!";
47 }
48
49 $scope.ok = function(){
50 $modalInstance.close();
51 }
52
53 $scope.getPort = function(summaries){
54
55 let port = "";
56
57 summaries.forEach(function(summarie){
58 let summarieSplited = summarie.split(" ");
59
60 if(summarieSplited[1] == $scope.name){
61 let index = summarieSplited[0].indexOf("/");
62
63 port = summarieSplited[0].substring(1, index);
64 }
65 })
66
67 return port;
68 }
69 }]);
+0
-41
faraday/server/www/scripts/dashboard/controllers/summarizedCtrlServicesModal.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('summarizedCtrlServicesModal',
6 ['$scope', '$modalInstance', 'dashboardSrv', 'workspace', 'host', 'osint', 'ServerAPI',
7 function($scope, $modalInstance, dashboardSrv, workspace, host, osint, ServerAPI) {
8
9 $scope.host = host
10 $scope.sortField = 'port';
11 $scope.sortReverse = false;
12 $scope.osint = osint;
13 $scope.workspace = workspace
14
15 // toggles sort field and order
16 $scope.toggleSort = function(field) {
17 $scope.toggleSortField(field);
18 $scope.toggleReverse();
19 };
20
21 // toggles column sort field
22 $scope.toggleSortField = function(field) {
23 $scope.sortField = field;
24 };
25
26 // toggle column sort order
27 $scope.toggleReverse = function() {
28 $scope.sortReverse = !$scope.sortReverse;
29 }
30
31 ServerAPI.getServicesByHost(workspace, host._id).then(function(response){
32 $scope.name = host.name;
33 $scope.services = response.data;
34 });
35
36 $scope.ok = function(){
37 $modalInstance.close();
38 }
39
40 }]);
+0
-27
faraday/server/www/scripts/dashboard/controllers/topHostsCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('topHostsCtrl',
6 ['$scope', '$routeParams', 'dashboardSrv',
7 function($scope, $routeParams, dashboardSrv) {
8
9 $scope.topHosts;
10 $scope.workspace;
11
12 init = function() {
13 if($routeParams.wsId != undefined) {
14 $scope.workspace = $routeParams.wsId;
15 }
16
17 dashboardSrv.getTopHosts($scope.workspace)
18 .then(function(topHosts) {
19 $scope.topHosts = topHosts;
20 });
21 };
22
23 dashboardSrv.registerCallback(init);
24
25 init();
26 }]);
+0
-42
faraday/server/www/scripts/dashboard/controllers/topServicesCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('topServicesCtrl',
6 ['$scope', '$routeParams', '$uibModal', 'dashboardSrv',
7 function($scope, $routeParams, $uibModal, dashboardSrv) {
8
9 $scope.topServices;
10 $scope.workspace;
11
12 init = function() {
13 if($routeParams.wsId != undefined) {
14 $scope.workspace = $routeParams.wsId;
15
16 dashboardSrv.getTopServices($scope.workspace)
17 .then(function(services) {
18 $scope.topServices = {"children": services};
19 });
20 }
21 };
22
23 $scope.treemap = function(data) {
24 if(data !== undefined && data != {}) {
25 var modal = $uibModal.open({
26 templateUrl: 'scripts/dashboard/partials/modal-treemap.html',
27 controller: 'treemapModalCtrl',
28 size: 'lg',
29 resolve: {
30 workspace: function() {
31 return $scope.workspace;
32 }
33 }
34 });
35 }
36 };
37
38 dashboardSrv.registerCallback(init);
39
40 init();
41 }]);
+0
-18
faraday/server/www/scripts/dashboard/controllers/treemapModalCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('treemapModalCtrl',
6 ['$scope', '$modalInstance', 'dashboardSrv', 'workspace',
7 function($scope, $modalInstance, dashboardSrv, workspace) {
8
9 dashboardSrv.getTopServices(workspace)
10 .then(function(res) {
11 $scope.treemapDataModel = {"children": res, "height":300, "width": 500};
12 });
13
14 $scope.ok = function() {
15 $modalInstance.close();
16 }
17 }]);
+0
-68
faraday/server/www/scripts/dashboard/controllers/vulnsByPriceCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('vulnsByPriceCtrl',
6 ['$scope', '$routeParams', 'dashboardSrv', 'SEVERITIES',
7 function($scope, $routeParams, dashboardSrv, SEVERITIES) {
8
9 $scope.vulnPrices;
10 $scope.vulns;
11 $scope.workspace;
12 $scope.workspaceWorth = 0;
13
14 init = function() {
15 if($routeParams.wsId != undefined) {
16 $scope.workspace = $routeParams.wsId;
17 $scope.vulnPrices = dashboardSrv.vulnPrices;
18
19 $scope.loadData();
20
21 $scope.$watch('vulnPrices', function(ps) {
22 if($scope.vulns != undefined) {
23 $scope.generateVulnPrices($scope.vulns, $scope.vulnPrices);
24 $scope.workspaceWorth = $scope.sumProperty($scope.vulns, "amount");
25 }
26 }, true);
27
28 $scope.$watch(function() {
29 return dashboardSrv.props.confirmed;
30 }, function(newValue, oldValue) {
31 if (oldValue != newValue)
32 $scope.loadData();
33 }, true);
34 }
35 };
36
37 $scope.generateVulnPrices = function(vulns, prices) {
38 vulns.forEach(function(vuln) {
39 vuln.amount = vuln.value * prices[vuln.key];
40 });
41 };
42
43 $scope.loadData = function() {
44 dashboardSrv.getVulnsWorth($scope.workspace)
45 .then(function(vulns) {
46 $scope.vulns = vulns;
47 $scope.generateVulnPrices($scope.vulns, $scope.vulnPrices);
48 $scope.workspaceWorth = $scope.sumProperty($scope.vulns, "amount");
49 });
50 };
51
52 $scope.sumProperty = function(data, prop) {
53 var total = 0;
54
55 for(var d in data) {
56 if(data.hasOwnProperty(d)) {
57 if(data[d][prop] !== undefined) total += parseInt(data[d][prop]);
58 }
59 }
60
61 return total;
62 };
63
64 dashboardSrv.registerCallback($scope.loadData);
65
66 init();
67 }]);
+0
-40
faraday/server/www/scripts/dashboard/controllers/vulnsBySeverityCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('vulnsBySeverityCtrl',
6 ['$scope', '$routeParams', 'dashboardSrv', 'SEVERITIES',
7 function($scope, $routeParams, dashboardSrv, SEVERITIES) {
8
9 $scope.vulns = {};
10 $scope.workspace;
11
12 init = function() {
13 if($routeParams.wsId != undefined) {
14 $scope.workspace = $routeParams.wsId;
15
16 $scope.loadData();
17
18 $scope.$watch(function() {
19 return dashboardSrv.props.confirmed;
20 }, function(newValue, oldValue) {
21 if (oldValue != newValue)
22 $scope.loadData();
23 }, true);
24 }
25 };
26
27 $scope.loadData = function() {
28 dashboardSrv.getVulnerabilitiesCount($scope.workspace)
29 .then(function(vulns) {
30 SEVERITIES.forEach(function(severity) {
31 $scope.vulns[severity] = vulns[severity] || 0;
32 });
33 });
34 };
35
36 dashboardSrv.registerCallback($scope.loadData);
37
38 init();
39 }]);
+0
-52
faraday/server/www/scripts/dashboard/controllers/vulnsByStatusCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('vulnsByStatusCtrl',
6 ['$scope', '$routeParams', 'dashboardSrv',
7 function($scope, $routeParams, dashboardSrv) {
8
9 $scope.workspace = null;
10
11 init = function() {
12 if($routeParams.wsId != undefined) {
13 $scope.workspace = $routeParams.wsId;
14 $scope.loadData();
15
16 $scope.$watch(function() {
17 return dashboardSrv.props.confirmed;
18 }, function(newValue, oldValue) {
19 if (oldValue != newValue)
20 $scope.loadData();
21 }, true);
22 }
23 };
24
25 $scope.loadData = function(){
26 dashboardSrv.getVulnerabilitiesGroupedBy($scope.workspace, 'status', dashboardSrv.props.confirmed)
27 .then(function(vulnsByStatus) {
28 $scope.data = {key: [], value: [], colors: [], options: {maintainAspectRatio: false, animateRotate: true}};
29 $scope.loaded = true;
30
31 vulnerabilityColors = {
32 'open': '#e77273',
33 'closed': '#bddd72',
34 're-opened': '#e7d174',
35 'risk-accepted': '#7aabd9'
36 };
37
38 vulnsByStatus.forEach(function(vuln, index) {
39 $scope.data.value.push(vuln.count);
40 $scope.data.key.push(vuln.status);
41
42 $scope.data.colors.push(vulnerabilityColors[vuln.status]);
43 });
44
45 $scope.loaded = true;
46 });
47 }
48
49 dashboardSrv.registerCallback($scope.loadData);
50 init();
51 }]);
+0
-51
faraday/server/www/scripts/dashboard/controllers/vulnsPiechartCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('vulnsPiechartCtrl',
6 ['$scope', '$routeParams', 'dashboardSrv', 'SEVERITIES',
7 function($scope, $routeParams, dashboardSrv, SEVERITIES) {
8
9 $scope.data;
10 $scope.loaded = false;
11 $scope.workspace;
12
13 init = function() {
14 if($routeParams.wsId != undefined) {
15 $scope.workspace = $routeParams.wsId;
16
17 $scope.loadData(true);
18
19 $scope.$watch(function() {
20 return dashboardSrv.props.confirmed;
21 }, function(newValue, oldValue) {
22 if (oldValue != newValue)
23 $scope.loadData(true);
24 }, true);
25 }
26 };
27
28 $scope.loadData = function(animated) {
29 dashboardSrv.getVulnerabilitiesCount($scope.workspace)
30 .then(function(vulns) {
31 $scope.data = {key: [], value: [], colors: [], options: {maintainAspectRatio: false, animateRotate: animated}};
32 $scope.loaded = true;
33 SEVERITIES.forEach(function(severity, index) {
34 if(severity != "unclassified" && vulns[severity] != undefined) {
35 $scope.data.value.push(vulns[severity]);
36 $scope.data.key.push(severity);
37 $scope.data.colors.push(dashboardSrv.vulnColors[index]);
38 }
39 });
40 // angular.copy(tmp, $scope.data);
41 //
42 });
43 };
44
45 dashboardSrv.registerCallback(function (){
46 $scope.loadData(false);
47 });
48
49 init();
50 }]);
+0
-56
faraday/server/www/scripts/dashboard/controllers/workspaceProgressCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('workspaceProgressCtrl',
6 ['$scope', '$routeParams', 'workspacesFact', 'dashboardSrv',
7 function($scope, $routeParams, workspacesFact, dashboardSrv) {
8
9 $scope.workspace;
10 $scope.wsDuration;
11 $scope.wsEnd;
12 $scope.wsStart;
13 $scope.wsProgress;
14
15 init = function() {
16 if($routeParams.wsId != undefined) {
17 $scope.workspace = $routeParams.wsId;
18
19 workspacesFact.getDuration($scope.workspace)
20 .then(function(duration) {
21 $scope.wsDuration = duration;
22 $scope.wsProgress = $scope.calculateProgress($scope.wsDuration);
23 $scope.wsStart = $scope.wsDuration.start;
24 $scope.wsEnd = $scope.wsDuration.end;
25 });
26 }
27 };
28
29 $scope.calculateProgress = function(duration) {
30 var partial = 0,
31 progress = 0,
32 today = new Date(),
33 total = 0;
34
35 if(!duration.start || !duration.end) {
36 progress = null;
37 } else {
38 today = today.getTime();
39 partial = today - duration.start;
40 total = duration.end - duration.start;
41
42 if(today > duration.end) {
43 progress = 100;
44 } else if(duration.start < today && today <= duration.end && total > 0) {
45 progress = Math.round(partial * 100 / total);
46 }
47 }
48
49 return progress;
50 };
51
52 dashboardSrv.registerCallback(init);
53
54 init();
55 }]);
+0
-86
faraday/server/www/scripts/dashboard/partials/activityFeed.html less more
0 <article class='panel left-big-box' ng-controller="activityFeedCtrl as activityFeed">
1 <header>
2 <h2>Activity Feed
3 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Faraday feed"></span>
4
5 <span class="pull-right" ng-show="!isExpanded && activityFeed.commands.length > 5">
6 <img src="images/icon_viewmore.svg" class="feed-icon"/>
7 <a href="javascript:;" ng-click="toggleExpanded()" >View more</a>
8 </span>
9
10 <span class="pull-right" ng-show="isExpanded">
11 <img src="images/icon_viewless.svg" class="feed-icon"/>
12 <a href="javascript:;" ng-click="toggleExpanded()" >View less</a>
13 </span>
14
15 <!--TODO: Change icon-->
16 <span class="pull-right margin-right-15px" ng-show="isExpanded && !hideEmpty">
17 <!--<img src="images/icon_viewless.svg" class="feed-icon"/> -->
18 <a href="javascript:;" ng-click="hideEmpty = true" >Hide empty</a>
19 </span>
20
21 <!--TODO: Change icon-->
22 <span class="pull-right margin-right-15px" ng-show="isExpanded && hideEmpty">
23 <!--<img src="images/icon_viewless.svg" class="feed-icon"/>-->
24 <a href="javascript:;" ng-click="hideEmpty = false" >Show empty</a>
25 </span>
26
27
28 </h2>
29
30
31 </header>
32 <div ng-if="activityFeed.commands.length === 0 || (getValidCount() === 0 && hideEmpty == true)" class="no-info-overlay">
33 <p class="no-info-text">No activities found yet.</p>
34 </div>
35 <div class="ph-xl">
36 <table id="commands" ng-if="activityFeed.commands.length > 0" class="tablesorter table table-striped">
37 <tbody>
38 <tr ng-repeat="cmd in activityFeed.commands | orderBy : '-date' | limitTo:settings.pageLimit:settings.offset"
39 ng-show="!isEmpty(cmd) || !hideEmpty">
40 <td align="left" ng-class="{'hide-border-top':$first}">
41 <span ng-if="cmd.import_source == 'report'">
42 <img src="images/icon_terminal.svg" class="feed-icon"/>
43 </span>
44 <span ng-if="cmd.import_source == 'shell'">
45 <img src="images/icon_terminal.svg" class="feed-icon"/>
46 </span>
47
48 <b class="capitalize fg-blue">{{cmd.creator || Anonymous}}</b>
49 <span ng-if="cmd.import_source == 'shell'"
50 uib-tooltip="{{ cmd.command + ' ' + cmd.params}}"><span class="little-gray">ran</span> <strong>{{cmd.command}}</strong></span>
51 <span ng-if="cmd.import_source == 'report'"
52 uib-tooltip="Import {{ cmd.command + ': ' + cmd.params}}">imported <strong>{{cmd.tool == 'unknown' ? cmd.command : cmd.tool}}</strong> report</span>
53 <span ng-if="cmd.import_source == 'agent'">
54 <b class="fg-blue">{{cmd.tool}}</b>
55 agent ran
56 <span uib-tooltip="{{ fitStringInTooltip(cmd.params) }}"><strong>{{cmd.command}}</strong></span>
57 executor
58 </span>
59 <span class="little-gray"> and found</span>
60 <span ng-if="cmd.hosts_count == 0 && cmd.services_count == 0 && cmd.vulnerabilities_count == 0 "> <strong>nothing</strong></span>
61 <span ng-if="cmd.hosts_count != 0 || cmd.services_count != 0 || cmd.vulnerabilities_count != 0 ">: </span>
62 <span ng-if="cmd.hosts_count > 0">{{cmd.hosts_count}} {{cmd.hosts_count == 1 ? 'host' : 'hosts'}}</span>
63 <span ng-if="cmd.hosts_count != 0 && cmd.services_count != 0 && cmd.vulnerabilities_count != 0">, </span>
64 <span ng-if="(cmd.hosts_count != 0 && cmd.services_count != 0 && cmd.vulnerabilities_count == 0) || (cmd.hosts_count != 0 && cmd.services_count == 0 && cmd.vulnerabilities_count != 0)"> & </span>
65 <span ng-if="cmd.services_count > 0">{{cmd.services_count}} {{cmd.services_count == 1 ? 'service' : 'services'}}</span>
66 <span ng-if="(cmd.hosts_count != 0 && cmd.services_count != 0 && cmd.vulnerabilities_count != 0) || (cmd.hosts_count == 0 && cmd.services_count != 0 && cmd.vulnerabilities_count != 0)"> & </span>
67 <span ng-if="cmd.vulnerabilities_count > 0"><a
68 ng-click="navigate('/status/ws/' + workspace + '/search/command_id=' + cmd._id)"> {{cmd.vulnerabilities_count}} {{cmd.vulnerabilities_count == 1 ? 'vulnerability' : 'vulnerabilities'}}</a></span>
69 <span ng-if="cmd.criticalIssue > 0">- {{cmd.criticalIssue}} {{cmd.criticalIssue == 1 ? 'is' : 'are'}} rated as <b>Critical</b>.</span>
70 <span class="small-size fg-light-gray" am-time-ago="cmd.date" am-preprocess="utc"/>
71 </td>
72 </tr>
73 </tbody>
74 </table>
75
76 <simple-pagination ng-if="isExpanded == true && hideEmpty == false"
77 current-page="settings.currentPage"
78 offset="settings.offset"
79 page-limit="settings.pageLimit"
80 page-limits="settings.pageLimits"
81 total="activityFeed.commands.length">
82 </simple-pagination>
83
84 </div>
85 </article>
+0
-1
faraday/server/www/scripts/dashboard/partials/barChart.html less more
0 <canvas id="bar" class="chart chart-bar" chart-data="[topHosts.value]" chart-labels="topHosts.key" chart-series="topHosts.key" chart-legend="false" chart-options="topHosts.options"></canvas>
+0
-49
faraday/server/www/scripts/dashboard/partials/commands-list.html less more
0 <article class='panel' ng-controller="commandsCtrl">
1 <header>
2 <h2>Commands History
3 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Shows current WS executed commands"></span>
4 </h2>
5 </header>
6 <div ng-if="commands.length === 0" class="no-info-overlay">
7 <p class="no-info-text">No commands found yet.</p>
8 </div>
9 <div class="ph-xl">
10 <table id="" ng-if="commands.length > 0" class="tablesorter table table-striped last-vuln text-left">
11 <thead>
12 <tr>
13 <th class="text-left"><span ng-click="cmdToggleSort('creator')">By</span></th>
14 <th class="text-left"><span ng-click="cmdToggleSort('command')">Command</span></th>
15 <th class="text-left"><span ng-click="cmdToggleSort('date')">Start Date</span></th>
16 <th class="text-left"><span ng-click="cmdToggleSort('duration')">Duration</span></th>
17 </tr>
18 </thead>
19 <tbody>
20 <tr ng-repeat="cmd in commands | limitTo:settings.pageLimit:settings.offset | orderObjectBy:cmdSortField:cmdSortReverse track by $index ">
21 <td>
22 <b><p uib-tooltip="{{cmd.ip}}">{{cmd.creator}}</p></b>
23 </td>
24 <td class="wrapword">
25 <span ng-if="cmd.import_source == 'report'">Import {{(cmd.tool == 'unknown' ? cmd.command : cmd.tool)}}</span>
26 <span ng-if="cmd.import_source == 'shell'">{{cmd.command + ' ' + cmd.params}}</span>
27 <span ng-if="cmd.import_source == 'agent'">
28 <p class="responsive_agent_command">
29 {{cmd.tool + ' executor: ' + cmd.command + ' ' + cmd.params}}
30 </p>
31 </span>
32 </td>
33 <td am-time-ago="cmd.date" am-preprocess="utc"></td>
34 <td ng-bind="cmd.duration || 'undefined'"></td>
35 </tr>
36 </tbody>
37 </table>
38
39 <simple-pagination
40 current-page="settings.currentPage"
41 offset="settings.offset"
42 page-limit="settings.pageLimit"
43 page-limits="settings.pageLimits"
44 total="commands.length">
45 </simple-pagination>
46
47 </div>
48 </article>
+0
-36
faraday/server/www/scripts/dashboard/partials/compound.html less more
0 <article class='panel' ng-controller="compoundCtrl">
1 <header>
2 <h2><a href="#/hosts/ws/{{workspace}}">Hosts</a>
3 <span class="glyphicon glyphicon-info-sign" uib-tooltip="All hosts, each one showing its service count and operating system. By clicking on a host IP you can access a list with all of its services"></span>
4 </h2>
5 </header>
6 <div ng-if="hosts.length === 0" class="no-info-overlay">
7 <p class="no-info-text">No hosts found yet.</p>
8 </div>
9 <div class="ph-xl">
10 <table id="hosts" ng-if="hosts.length > 0" class="tablesorter table table-striped text-left">
11 <thead>
12 <tr>
13 <th class="text-left"><span ng-click="toggleSort('name')">Host</span></th>
14 <th class="text-left"><span ng-click="toggleSort('services')">Services</span></th>
15 <th class="text-left"><span ng-click="toggleSort('os')">OS</span></th>
16 </tr>
17 </thead>
18 <tbody>
19 <tr ng-repeat="host in hosts | limitTo:5">
20 <td class="">
21 <a href="" class="host" ng-click="showServices(host)">{{host.name}}</a>
22 <a href="//www.shodan.io/search?query={{host.ip}}" uib-tooltip="Search in shodan" target="_blank">
23 <img ng-src="/images/shodan.png" height="15px" width="15px" />
24 </a>
25 </td>
26 <td class="">{{host.services}}</td>
27 <td class="">
28 <img ng-if="host.icon != undefined" ng-src="images/{{host.icon}}.png" uib-tooltip="{{host.os}}"/>
29 <span ng-if="host.icon == undefined" class="fa fa-laptop pl-xs" uib-tooltip="{{host.os}}"></span>
30 </td>
31 </tr>
32 </tbody>
33 </table>
34 </div>
35 </article>
+0
-64
faraday/server/www/scripts/dashboard/partials/dashboard.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion clearfix dashboard">
5 <div class="faraday-header-border-fix">
6 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
7 <div class="row ph-xl m0">
8 <div class="col-lg-6 col-md-6 col-sm-12 col-xs-12 ">
9 <div class="row" id="first-row-panel">
10 <div class="col-lg-4 col-md-4 col-sm-12 col-xs-12 pl0 pr-sm">
11 <div ng-include="'scripts/dashboard/partials/workspace-progress.html'"></div>
12 </div>
13 <div class="col-lg-4 col-md-4 col-sm-12 col-xs-12 ph-sm">
14 <div ng-include="'scripts/dashboard/partials/vulns-piechart.html'"></div>
15 </div>
16 <div class="col-lg-4 col-md-4 col-sm-12 col-xs-12 ph-sm">
17 <div ng-include="'scripts/dashboard/partials/vulns-by-status.html'"></div>
18 </div>
19 </div>
20 <div class="row mt-md" id="activities-container-row" ng-if="showVulnCost">
21 <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 pl0 pr-sm">
22 <div ng-include="'scripts/dashboard/partials/vulns-by-price.html'"></div>
23 </div>
24 </div>
25 <div class="row mt-md" id="activities-container-row">
26 <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 pl0 pr-sm">
27 <div ng-include="'scripts/dashboard/partials/activityFeed.html'"></div>
28 </div>
29 </div>
30 <div class="row">
31 <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 pl0 pr-sm">
32 <div ng-include="'scripts/dashboard/partials/last-vulns.html'"></div>
33 </div>
34 </div>
35 </div>
36 <div class="col-lg-6 col-md-6 col-sm-12 col-xs-12 ">
37 <div class="row">
38 <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 ph-sm">
39 <div ng-include="'scripts/dashboard/partials/vulns-by-severity.html'"></div>
40 </div>
41 </div>
42 <div class="row">
43 <div class="col-lg-6 col-md-6 col-sm-12 col-xs-12 ph-sm">
44 <div ng-include="'scripts/dashboard/partials/services.html'"></div>
45 </div>
46 <div class="col-lg-6 col-md-6 col-sm-12 col-xs-12 ph-sm">
47 <div ng-include="'scripts/dashboard/partials/summarized.html'"></div>
48 </div>
49 </div>
50 <div class="row mt-md">
51 <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 ph-sm">
52 <div ng-include="'scripts/dashboard/partials/compound.html'"></div>
53 </div>
54 </div>
55 <div class="row">
56 <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 ph-sm">
57 <div ng-include="'scripts/dashboard/partials/commands-list.html'"></div>
58 </div>
59 </div>
60 </div>
61 </div>
62 </div><!-- .right-main -->
63 </section>
+0
-44
faraday/server/www/scripts/dashboard/partials/last-vulns.html less more
0 <article class='panel left-big-box' ng-controller="lastVulnsCtrl" id="last-vuln-panel">
1 <header>
2 <h2>Last Vulnerabilities
3 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Last vulnerabilities added"></span>
4 </h2>
5 </header>
6 <div ng-if="vulns.length === 0" class="no-info-overlay">
7 <p class="no-info-text">No vulnerabilities found yet.</p>
8 </div>
9 <div class="ph-xl">
10 <table ng-if="vulns.length > 0" class="tablesorter table table-striped last-vuln text-left">
11 <thead>
12 <tr>
13 <th class="text-left"><span>Severity</span></th>
14 <th class="text-left"><span>Target</span></th>
15 <th class="text-left"><span>Name</span></th>
16 <th class="text-left"><span>Owner</span></th>
17 <th class="text-left"><span>Date</span></th>
18 </tr>
19 </thead>
20 <tbody>
21 <tr ng-repeat="vuln in vulns | limitTo:settings.pageLimit:settings.offset">
22 <td><a href="" ng-click="navigate('/status/ws/'+workspace+'/search/severity='+vuln.severity)"><span class="label vuln fondo-{{vuln.severity}}">{{vuln.severity | uppercase}}</span></a></td>
23 <td>
24 <a href="" ng-click="navigate('/status/ws/'+workspace+'/search/target='+vuln.target)">{{vuln.target}}</a>
25 </td>
26 <td class="wrapword"><a href="" ng-click="navigate('/status/ws/'+workspace+'/search/name='+vuln.name)">{{vuln.name}}</a></td>
27
28 <td><a href="" ng-click="navigate('/status/ws/'+workspace+'/search/owner='+vuln.owner)">{{vuln.owner}}</a></td>
29 <td><span am-time-ago="vuln.metadata.create_time" am-preprocess="utc"></span></td>
30 </tr>
31 </tbody>
32 </table>
33
34 <simple-pagination
35 current-page="settings.currentPage"
36 offset="settings.offset"
37 page-limit="settings.pageLimit"
38 page-limits="settings.pageLimits"
39 total="vulns.length">
40 </simple-pagination>
41
42 </div>
43 </article>
+0
-55
faraday/server/www/scripts/dashboard/partials/modal-hosts-by-service.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header" hotkey="{enter:ok}">
5 <h3 ng-style="{'word-wrap': 'break-word'}">Hosts for {{name}} ({{hosts.length}} total)</h3>
6 </div>
7
8 <div class="modal-body">
9 <table class="table-v3 services-list table table-responsive">
10 <thead>
11 <tr class="ui-grid-header">
12 <th class="ui-grid-cell-contents ui-grid-header-cell">
13 <span href="" ng-click="toggleSort('name')">Name</span>
14 </th>
15 <th class="ui-grid-cell-contents ui-grid-header-cell">
16 <span href="" ng-click="toggleSort('hostnames')">Hostnames</span>
17 </th>
18 <th class="ui-grid-cell-contents ui-grid-header-cell">
19 <span href="" ng-click="toggleSort('os')">OS</span>
20 </th>
21 <th class="ui-grid-cell-contents ui-grid-header-cell">
22 <span href="" ng-click="toggleSort('versions')">Versions</span>
23 </th>
24 </tr>
25 </thead>
26 <tbody>
27 <tr class="ui-grid-row" ng-repeat="host in hosts | orderBy:sortField:sortReverse">
28 <td class="ui-grid-cell-contents">
29 <a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}" class="ng-binding" ng-click="ok()">{{host.name}}:{{host.port}}</a>
30 </td>
31 <td class="ui-grid-cell-contents" ng-if="host.hostnames.length > 0">
32 <span ng-repeat="hostname in host.hostnames">{{hostname}}&nbsp;<br></span>
33 </td>
34 <td class="ui-grid-cell-contents" ng-if="host.hostnames.length == 0">
35 <span>-</span>
36 </td>
37 <td class="ui-grid-cell-contents">
38 {{host.os}}
39 </td>
40 <td class="ui-grid-cell-contents">
41 <span ng-repeat="version in host.versions | unique">{{version}}&nbsp;</span>
42 </td>
43 </tr>
44 </tbody>
45 </table>
46 <div class="modal-footer">
47 <div class="col-md-6" style="padding: 0px">
48 <button class="btn btn-danger pull-left" clipboard supported="supported" text="clip" on-copied="messageCopied()" ng-disabled="clipText === 'Copied!'">{{clipText}}</button>
49 </div>
50 <div class="col-md-6 btn-group" style="padding: 0px">
51 <button class="btn btn-success pull-right" ng-click="ok()" id="buttonAtRight">OK</button>
52 </div>
53 </div>
54 </div>
+0
-63
faraday/server/www/scripts/dashboard/partials/modal-services-by-host.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header" hotkey="{enter:ok}">
5 <h3>Services for <a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}" class="ng-binding" ng-click="ok()">{{name}} </a>({{services.length}} total)</h3>
6 </div>
7
8 <div class="modal-body">
9 <table class="table-v3 services-list table table-responsive" style="margin-top: 15px">
10 <thead>
11 <tr class="ui-grid-header">
12 <th class="ui-grid-cell-contents ui-grid-header-cell">
13 <span ng-click="toggleSort('name')">Name</span>
14 </th>
15 <th class="ui-grid-cell-contents ui-grid-header-cell">
16 <span href="" ng-click="toggleSort('version')">Version</span>
17 </th>
18 <th class="ui-grid-cell-contents ui-grid-header-cell">
19 <span href="" ng-click="toggleSort('port')">Port</span>
20 </th>
21 <th class="ui-grid-cell-contents ui-grid-header-cell">
22 <span href="" ng-click="toggleSort('protocol')">Protocol</span>
23 </th>
24 <th class="ui-grid-cell-contents ui-grid-header-cell">
25 <span href="" ng-click="toggleSort('status')">Status</span>
26 </th>
27 </tr>
28 </thead>
29 <tbody>
30 <tr class="ui-grid-row" ng-repeat="srv in services | orderBy:sortField:sortReverse">
31 <td class="ui-grid-cell-contents">
32 {{srv.name}}
33 </td>
34 <td class="ui-grid-cell-contents">
35 {{srv.version}}
36 </td>
37 <td class="ui-grid-cell-contents">
38 {{srv.ports.toString().replace("[]", "")}}
39 <osint-link query="srv.ports.toString().replace('[]', '')" osint="osint"></osint-link>
40 </td>
41 <td class="ui-grid-cell-contents">
42 {{srv.protocol}}
43 </td>
44 <td class="ui-grid-cell-contents">
45 {{srv.status}}
46 </td>
47 </tr>
48 </tbody>
49 <div class="col md-12" style="border-top:0px solid #e5e5e5">
50 <div>
51 <i class="fa fa-laptop"></i><span> OS: {{host.os | limitTo: 40}}</span>
52 <div class="pull-right">
53 <i class="glyphicon glyphicon-user"></i> Created by {{host.metadata.owner}} <span am-time-ago="host.metadata.create_time"></span>
54
55 </div>
56 </div>
57 </div><!-- .col md-12 -->
58 </table>
59 </div>
60 <div class="modal-footer">
61 <button class="btn btn-success" ng-click="ok()">OK</button>`
62 </div>
+0
-18
faraday/server/www/scripts/dashboard/partials/modal-treemap.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header" hotkey="{enter:ok}">
5 <h3>Top Services {{hola}}</h3>
6 </div>
7
8 <div class="modal-body">
9 <article class='panel'>
10 <span id="treemapTextModel"></span>
11 <d3-treemap data="treemapDataModel"></d3-treemap>
12 </article>
13 </div>
14
15 <div class="modal-footer">
16 <button class="btn btn-success" ng-click="ok()">OK</button>
17 </div>
+0
-30
faraday/server/www/scripts/dashboard/partials/services.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div id='byservices' ng-controller="servicesCtrl">
5 <article class='panel m0'>
6 <header>
7 <h2>Services report
8 <span class="glyphicon glyphicon-info-sign" uib-tooltip="All services for current WS ordered by host amount"></span>
9 </h2>
10 </header>
11 <div ng-if="servicesCount.length === 0" class="no-info-overlay">
12 <p class="no-info-text">No services found yet.</p>
13 </div>
14 <div class='main' ng-class="{'height-auto': servicesCount.length === 0}">
15 <div class='box'>
16 <div ng-repeat="srv in servicesCount" class="columna unquinto services">
17 <article class="dato2">
18 <span href="" ng-click="showHosts(srv.name)">
19 <section>
20 <div class="nro">{{srv.count}}</div>
21 <div class="txt texto-blanco" ng-style="{'word-wrap': 'break-word'}">{{srv.name}}</div>
22 </section>
23 </span>
24 </article>
25 </div>
26 </div>
27 </div>
28 </article>
29 </div>
+0
-37
faraday/server/www/scripts/dashboard/partials/summarized.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div id='summarized' ng-controller="summarizedCtrl">
5 <div>
6 <article class='panel m0'>
7 <header>
8 <h2>Workspace summarized report
9 <span class="glyphicon glyphicon-info-sign" uib-tooltip="WS overview - hosts, services and vulnerabilites counts"></span>
10 </h2>
11 </header>
12 <div ng-if="objectsCount.length === 0" class="no-info-overlay">
13 <p class="no-info-text">Not enough data to generate summarized report yet.</p>
14 </div>
15 <div class='main' ng-class="{'height-auto': objectsCount.length === 0}">
16 <div class='box'>
17 <div ng-repeat="obj in objectsCount" class="columna unquinto">
18 <article class="dato2">
19 <div ng-switch on="obj.key">
20 <div class="nro" ng-switch-when="total vulns"><a href="#/status/ws/{{workspace}}">{{obj.value}}</a></div>
21 <div class="nro" ng-switch-when="hosts"><a href="#/hosts/ws/{{workspace}}">{{obj.value}}</a></div>
22 <div class="nro" ng-switch-when="web vulns"><a href="#/status/ws/{{workspace}}/search/type=VulnerabilityWeb">{{obj.value}}</a></div>
23 <div class="nro" ng-switch-when="vulns"><a href="#/status/ws/{{workspace}}/search/type=Vulnerability">{{obj.value}}</a></div>
24 <div class="nro" ng-switch-when="credentials"><a href="#/credentials/ws/{{workspace}}">{{obj.value}}</a></div>
25 <!--#/status/ws/cscan/search/severity=high -->
26 <div class="nro" ng-switch-default>{{obj.value}}</div>
27 </div>
28 <div class="txt texto-blanco">{{obj.key}}</div>
29 </section>
30 </article>
31 </div>
32 </div>
33 </div>
34 </article>
35 </div>
36 </div>
+0
-22
faraday/server/www/scripts/dashboard/partials/top-hosts.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div ng-controller="topHostsCtrl">
5 <article id='bar' class='panel'>
6 <header>
7 <h2>Top Hosts
8 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Top 3 hosts with the largest quantity of services"></span>
9 </h2>
10 </header>
11 <span id="barText"></span>
12 <div ng-if="topHosts == undefined || topHosts.length < 3" class="alert alert-info alert-dismissible">
13 <button type="button" class="close" data-dismiss="alert">
14 <span aria-hidden="true">&times;</span>
15 <span class="sr-only">Close</span>
16 </button>
17 <p>At least 3 hosts needed to show this visualization</p>
18 </div>
19 <div id="bar" ng-include="'scripts/dashboard/partials/barChart.html'" ng-if="topHosts != undefined || topHosts.length > 3"></div>
20 </article>
21 </div>
+0
-23
faraday/server/www/scripts/dashboard/partials/top-services.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div ng-controller="topServicesCtrl">
5 <article id='treemap' class='panel m0'>
6 <header>
7 <h2>
8 <a class="treemap-view" href="" ng-disabled="{{nodata}}" ng-click="treemap(topServices)">Top Services</a>
9 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Top 5 services with the largest quantity of hosts"></span>
10 </h2>
11 </header>
12 <span id="treemapText"></span>
13 <div ng-if="topServices == undefined || topServices.length < 5" class="alert alert-info alert-dismissible">
14 <button type="button" class="close" data-dismiss="alert">
15 <span aria-hidden="true">&times;</span>
16 <span class="sr-only">Close</span>
17 </button>
18 <p>At least 5 services needed to show this visualization</p>
19 </div>
20 <d3-treemap data="topServices"></d3-treemap>
21 </article>
22 </div>
+0
-25
faraday/server/www/scripts/dashboard/partials/vulns-by-price.html less more
0 <article id="vulns-by-price" class="panel" ng-controller="vulnsByPriceCtrl">
1 <header>
2 <h2>
3 Workspace's worth
4 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Total net worth of Workspace, according to current vulnerabilities prices"></span>
5 </h2>
6 </header>
7 <div ng-if="workspaceWorth === 0" class="no-info-overlay">
8 <p class="no-info-text">No vulnerabilities found yet.</p>
9 </div>
10 <div class="main" ng-if="workspaceWorth > 0">
11 <div class="center-lg-6"><h4><i class="fa fa-money"></i> {{workspaceWorth | currency}} total</h4></div>
12 <div d3-horizontal-stacked-bar data="vulns" class="stackedbars"></div>
13 <div id="vulns-by-price-reference" class="center-lg-6">
14 <ul class="label-list">
15 <li ng-repeat="(severity, price) in vulnPrices" uib-tooltip="Click on number to edit price">
16 <span class="label vuln fondo-{{severity}}">
17 {{severity}} $
18 <span contenteditable="true" ng-model="vulnPrices[severity]"></span>
19 </span>
20 </li>
21 </ul>
22 </div><!-- #vulns-by-price-reference .center-lg-6 -->
23 </div>
24 </article>
+0
-25
faraday/server/www/scripts/dashboard/partials/vulns-by-severity.html less more
0 <article id='vulns' class='panel' ng-controller="vulnsBySeverityCtrl">
1 <!-- <header>
2 <h2>
3 <a href="#/status/ws/{{workspace}}" class="status-report">Vulnerabilities</a>
4 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Vulnerabilities count arranged by severity"></span>
5 </h2>
6 </header> -->
7 <div ng-if="vulns == undefined || vulns.length == 0" class="alert alert-info alert-dismissible no-margin-bottom">
8 <button type="button" class="close" data-dismiss="alert">
9 <span aria-hidden="true">&times;</span>
10 <span class="sr-only">Close</span>
11 </button>
12 <p>No vulnerabilities found yet.</p>
13 </div>
14 <div class='main box'>
15 <div ng-repeat="(severity, count) in vulns" class="bg-white col-lg-2 col-md-2 col-sm-2 col-xs-3 cursor m0 p0" ng-class="{'border-right': $last === false}">
16 <article class="dato2 bg-white" ng-click="navigate('/status/ws/'+workspace+'/search/severity='+severity)">
17 <section style="padding:10px;">
18 <div class="nro text-{{severity}}">{{count}}</div>
19 <div class="txt text-{{severity}}">{{severity}}</div>
20 </section>
21 </article>
22 </div>
23 </div>
24 </article>
+0
-20
faraday/server/www/scripts/dashboard/partials/vulns-by-status.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div ng-controller="vulnsByStatusCtrl">
5 <article id='vulnsByStatus' class='small-widget-height panel m0' ng-class="{'height-auto': loaded === true && data.key.length === 0}">
6 <header>
7 <h2>
8 Vulnerabilities by status
9 </h2>
10 </header>
11 <div ng-if="loaded && data.key.length === 0" class="no-info-overlay">
12 <p class="no-info-text">No vulnerabilities found yet.</p>
13 </div>
14 <div id="doughnut" ng-if="loaded && data.key.length !== 0">
15 <canvas id="doughnut" class="chart chart-doughnut" chart-data="data.value" chart-labels="data.key"
16 chart-colours="data.colors" chart-options="data.options"></canvas>
17 </div>
18 </article>
19 </div>
+0
-21
faraday/server/www/scripts/dashboard/partials/vulns-piechart.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div ng-controller="vulnsPiechartCtrl">
5 <article id='cake' class='panel m0' ng-class="{'height-auto': loaded === true && data.value.length === 0}">
6 <header>
7 <h2>Vulnerabilities
8 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Vulnerability distribution for current WS"></span>
9 </h2>
10 </header>
11 <span id="cakeText"></span>
12 <div ng-if="loaded && data.value.length === 0" class="no-info-overlay">
13 <p class="no-info-text">No vulnerabilities found yet.</p>
14 </div>
15 <div id="doughnut" ng-if="loaded && data.value.length !== 0">
16 <canvas id="doughnut" class="chart chart-doughnut" chart-data="data.value" chart-labels="data.key"
17 chart-colours="data.colors" chart-options="data.options"></canvas>
18 </div>
19 </article>
20 </div>
+0
-30
faraday/server/www/scripts/dashboard/partials/workspace-progress.html less more
0 <article class="small-widget-height panel m0" id="workspace-progress" ng-controller="workspaceProgressCtrl">
1 <header>
2 <h2>
3 Workspace progress
4 <span class="glyphicon glyphicon-info-sign" uib-tooltip="Workspace progress according to Scope dates"></span>
5 </h2>
6 </header>
7 <div class="ph-xl">
8 <div ng-if="!wsProgress" class="alert alert-info alert-dismissible no-margin-bottom">
9 <button type="button" class="close" data-dismiss="alert">
10 <span aria-hidden="true">&times;</span>
11 <span class="sr-only">Close</span>
12 </button>
13 <p>Start date and end date are required</p>
14 </div><!-- ng-if -->
15 <div id="workspace-progress-reference" ng-if="wsProgress">
16 <uib-progressbar value="wsProgress" class="progress-bar-light-blue progress-bar-tall">{{wsProgress}}%</uib-progressbar>
17 </div><!-- #workspace-progress-reference .center-lg-6 -->
18 <div>
19 <div class="dashboard-label-wrapper">
20 <span class="label label-gray" ng-if="wsStart">Start date: {{wsStart | amUtc | amDateFormat:'MM/DD/YYYY'}}</span>
21 <span class="label label-gray" ng-if="!wsStart">The workspace doesn't have a start date</span>
22 </div>
23 <div class="dashboard-label-wrapper">
24 <span class="label label-gray" ng-if="wsEnd">End date: {{wsEnd | amUtc | amDateFormat:'MM/DD/YYYY'}}</span>
25 <span class="label label-gray" ng-if="!wsEnd">The workspace doesn't have an end date</span>
26 </div>
27 </div>
28 </div>
29 </article>
+0
-424
faraday/server/www/scripts/dashboard/providers/dashboard.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('dashboardSrv', [
6 'BASEURL',
7 'SEVERITIES',
8 '$cookies',
9 '$q',
10 '$http',
11 '$interval',
12 'hostsManager',
13 'ServerAPI',
14 function (BASEURL,
15 SEVERITIES,
16 $cookies,
17 $q,
18 $http,
19 $interval,
20 hostsManager,
21 ServerAPI) {
22
23 var dashboardSrv = {};
24
25 dashboardSrv._getView = function(url) {
26 var deferred = $q.defer();
27
28 $http.get(url).then(function(response) {
29 res = response.data.rows;
30 deferred.resolve(res);
31 }, function() {
32 deferred.reject();
33 });
34
35 return deferred.promise;
36 };
37
38 dashboardSrv.props = {};
39 dashboardSrv.setConfirmedFromCookie = function() {
40 dashboardSrv.props["confirmed"] = ($cookies.get('confirmed') == undefined) ? false : JSON.parse($cookies.get('confirmed'));
41 }
42
43 dashboardSrv.setConfirmed = function(val) {
44 if(val == undefined) {
45 val = ($cookies.get('confirmed') == undefined) ? false : !JSON.parse($cookies.get('confirmed'));
46 }
47
48 dashboardSrv.props["confirmed"] = val;
49 $cookies.put('confirmed', val);
50
51 val ? $cookies.put('filterConfirmed', "Confirmed"): $cookies.put('filterConfirmed', "All");
52 };
53
54 dashboardSrv.vulnPrices = {
55 "critical": "5000",
56 "high": "3000",
57 "med": "1000",
58 "low": "500",
59 "info": "0",
60 "unclassified": "0"
61 };
62
63 dashboardSrv.vulnColors = [
64 "#932EBE", // critical
65 "#e77273", // high
66 "#e7d174", // med
67 "#bddd72", // low
68 "#7aabd9", // info
69 "#999999" // unclassified
70 ];
71
72 dashboardSrv.getTopHosts = function(ws, colors) {
73 var deferred = $q.defer();
74
75 hostsManager.getHosts(ws, 0, 3, null, "services", "desc")
76 .then(function(res) {
77 var hosts = res.hosts;
78 if(hosts.length == 3) {
79 var tmp = {key:[], colors:[], value:[]};
80
81 if(colors == undefined) {
82 colors = ["rgb(57, 59, 121)", "rgb(82, 84, 163)", "rgb(107, 110, 207)"];
83 }
84
85 tmp.options = {
86 showScale : false,
87 maintainAspectRatio: false
88 };
89
90 hosts.forEach(function(host) {
91 tmp.colors.push(colors.shift());
92 tmp.value.push(host.services);
93 tmp.key.push(host.name);
94 });
95
96 deferred.resolve(tmp);
97 } else {
98 deferred.reject("Not enough hosts");
99 }
100 }, function() {
101 deferred.reject("Unable to get Services count for Top Hosts");
102 });
103
104 return deferred.promise;
105 };
106
107 // this is really not the count
108 // does some weird grouping too
109 dashboardSrv.getServicesCount = function(ws) {
110 var deferred = $q.defer();
111 ServerAPI.getServicesByName(ws)
112 .then(function(res) {
113 var tmp =[];
114 res.data.groups.sort(function(a, b) {
115 return b.count - a.count;
116 });
117 deferred.resolve(res.data.groups);
118 }, function() {
119 deferred.reject("Unable to get Services Count");
120 });
121
122 return deferred.promise;
123 };
124
125 dashboardSrv.getServicesByCommandId = function(ws, command_id) {
126 var deferred = $q.defer();
127 ServerAPI.getServices(ws, {"command_id": command_id})
128 .then(function(res) {
129 deferred.resolve(res.data);
130 }, function() {
131 deferred.reject("Unable to get Services");
132 });
133
134 return deferred.promise;
135 };
136
137
138 dashboardSrv.getTopServices = function(ws, colors) {
139 var deferred = $q.defer();
140
141 dashboardSrv.getServicesCount(ws)
142 .then(function(res) {
143 if(res.length > 4) {
144 var tmp = [];
145
146 if(colors == undefined) {
147 colors = ["#FA5882", "#FF0040", "#B40431", "#610B21", "#2A0A1B"];
148 }
149
150 res.slice(0, 5).forEach(function(srv) {
151 srv.color = colors.shift();
152 tmp.push(srv);
153 });
154 deferred.resolve(tmp);
155 }
156 }, function() {
157 deferred.reject("Unable to get Top Services");
158 });
159
160 return deferred.promise;
161 };
162
163 dashboardSrv.getVulnsByCommandId = function(ws, command_id) {
164 var deferred = $q.defer();
165 ServerAPI.getVulns(ws, {"command_id": command_id})
166 .then(function(res) {
167 deferred.resolve(res.data);
168 }, function() {
169 deferred.reject("Unable to get Vulnerabilities");
170 });
171
172 return deferred.promise;
173 };
174
175 dashboardSrv.getVulnsWorth = function(ws) {
176 var deferred = $q.defer();
177
178 dashboardSrv.getVulnerabilitiesCount(ws)
179 .then(function(vulns) {
180 var vs = [];
181
182 SEVERITIES.forEach(function(severity, ind) {
183 var amount = 0,
184 value = 0;
185
186 if(vulns[severity] != undefined) {
187 amount = dashboardSrv.vulnPrices[severity] * vulns[severity];
188 value = vulns[severity];
189 }
190
191 vs.push({
192 "amount": amount,
193 "color": dashboardSrv.vulnColors[ind],
194 "key": severity,
195 "value": value
196 });
197 });
198
199 deferred.resolve(vs);
200 });
201 return deferred.promise;
202 };
203
204 dashboardSrv.getVulnerabilitiesCount = function(ws) {
205 var deferred = $q.defer();
206
207 var confirmed = undefined;
208
209 if (dashboardSrv.props['confirmed']) {
210 confirmed = true;
211 }
212
213 ServerAPI.getVulnsBySeverity(ws, confirmed)
214 .then(function(res) {
215 var vs = {};
216 res.data.groups.forEach(function(vuln) {
217 vs[vuln.severity] = vuln.count;
218 });
219
220 deferred.resolve(vs);
221 }, function() {
222 deferred.reject("Unable to get Vulnerabilities count");
223 });
224
225 return deferred.promise;
226 };
227
228 dashboardSrv.getVulnerabilitiesGroupedBy = function(ws, groupBy, confirmed) {
229 var deferred = $q.defer();
230
231 ServerAPI.getVulnsGroupedBy(ws, groupBy, confirmed)
232 .then(function(res) {
233 deferred.resolve(res.data.groups);
234 }, function() {
235 deferred.reject("Unable to get Vulnerabilities");
236 });
237
238 return deferred.promise;
239 };
240
241 dashboardSrv.getObjectsCount = function(ws) {
242 var deferred = $q.defer();
243 // Confirmed empty = All vulns
244 var confirmed = undefined;
245
246 if (dashboardSrv.props['confirmed']) {
247 confirmed = true;
248 }
249
250 ServerAPI.getWorkspaceSummary(ws, confirmed)
251 .then(function(res) {
252 delete res.data.stats["interfaces"];
253 deferred.resolve(res.data.stats);
254 }, function() {
255 deferred.reject("Unable to get Objects count");
256 });
257
258 return deferred.promise;
259 };
260
261 dashboardSrv.getActivityFeed = function(ws) {
262 var deferred = $q.defer();
263
264 ServerAPI.getActivityFeed(ws, undefined, true).then(function(res) {
265 deferred.resolve(res.data);
266 }, function() {
267 deferred.reject();
268 });
269
270 return deferred.promise;
271 };
272
273 dashboardSrv.getCommands = function(ws) {
274 var deferred = $q.defer();
275
276 ServerAPI.getCommands(ws, undefined, true)
277 .then(function(res) {
278 var tmp = [];
279 res.data.commands.forEach(function(cmd) {
280 var _cmd = cmd.value;
281 _cmd.user = _cmd.user || "unknown";
282 _cmd.hostname = _cmd.hostname || "unknown";
283 _cmd.ip = _cmd.ip || "0.0.0.0";
284 if(_cmd.duration == "In progress") {
285 _cmd.duration = "In progress";
286 } else if (_cmd.duration == "Not started") {
287 _cmd.duration = "Not started";
288 } else if(_cmd.duration != undefined) {
289 _cmd.duration = _cmd.duration.toFixed(2) + "s";
290 }
291 _cmd.date = _cmd.itime;
292 tmp.push(_cmd);
293 });
294
295 deferred.resolve(tmp);
296 }, function() {
297 deferred.reject();
298 });
299
300 return deferred.promise;
301 };
302
303 dashboardSrv.getHosts = function(ws) {
304 var deferred = $q.defer();
305 ServerAPI.getHosts(ws)
306 .then(function(res) {
307 var tmp = [];
308 res.data.rows.forEach(function(host) {
309 var _host = host.value;
310 _host["id"] = host.key;
311 tmp.push(_host);
312 });
313 deferred.resolve(tmp);
314 }, function() {
315 deferred.reject();
316 });
317 return deferred.promise;
318 };
319
320 dashboardSrv.getHostsCountByCommandId = function(ws, command_id) {
321
322 var deferred = $q.defer();
323
324 ServerAPI.getHosts(ws, {"command_id": command_id })
325 .then(function(res) {
326 deferred.resolve(res.data);
327 }, function() {
328 deferred.reject();
329 });
330 return deferred.promise;
331 };
332
333 dashboardSrv.getHost = function(ws, host_id) {
334 var deferred = $q.defer();
335 ServerAPI.getHost(ws, host_id)
336 .then(function(res) {
337 if (res.rows == 1) {
338 deferred.resolve(res.data);
339 } else {
340 deferred.reject("More than one object found by ID");
341 }
342 }, function() {
343 deferred.reject();
344 });
345 return deferred.promise;
346 };
347
348 dashboardSrv.getServicesByHost = function(ws, host_id) {
349
350 var deferred = $q.defer();
351 ServerAPI.getServicesByHost(ws, host_id).then(function(res){
352 deferred.resolve(res.data);
353 }, function(){
354 deferred.reject();
355 });
356 return deferred.promise;
357 }
358
359 dashboardSrv.getHostsByServicesName = function(ws, srv_name) {
360 var deferred = $q.defer();
361 hostsManager.getHosts(ws, null, null, {"service": srv_name}, "name", "desc")
362 .then(function(res) {
363 deferred.resolve(res.hosts);
364 }, function() {
365 deferred.reject();
366 });
367 return deferred.promise;
368 };
369
370 dashboardSrv.getName = function(ws, id) {
371 var deferred = $q.defer();
372
373 ServerAPI.getObj(ws, id)
374 .then(function(response){
375 res = response.data.name;
376 deferred.resolve(res);
377 }, function(){
378 deferred.reject();
379 });
380
381 return deferred.promise;
382 };
383
384
385 dashboardSrv.accumulate = function(_array, key, value, accum) {
386 _array.forEach(function(obj) {
387 if(obj.key == key) {
388 if(obj[accum] === undefined) obj[accum] = 0;
389 obj[accum] += value;
390 }
391 });
392 };
393
394 var timer = undefined;
395
396 dashboardSrv.startTimer = function() {
397 timer = $interval(function(){
398 dashboardSrv.updateData();
399 }, 60000)
400 }
401 dashboardSrv._callbacks = [];
402
403 dashboardSrv.registerCallback = function(callback) {
404 dashboardSrv._callbacks.push(callback);
405 }
406
407 dashboardSrv.stopTimer = function() {
408 dashboardSrv._callbacks = [];
409 if (angular.isDefined(timer)) {
410 $interval.cancel(timer);
411 timer = undefined;
412 }
413 }
414
415 dashboardSrv.updateData = function() {
416 for (var i = 0; i < dashboardSrv._callbacks.length; i++) {
417 var callback = dashboardSrv._callbacks[i];
418 callback();
419 }
420 }
421
422 return dashboardSrv;
423 }]);
+0
-61
faraday/server/www/scripts/extras/partials/extras.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion">
5 <div class="faraday-header-border-fix">
6 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
7 <div id="reports-main" class="fila">
8 <h2 class="ws-label">
9 <span id="ws-name" title="Help">Extras</span>
10 </h2><!-- .ws-label -->
11 <div class="reports col-md-10 col-sm-10 col-xs-12">
12 Want to level up your Faraday usage? You can download any of the following enhancers to connect with
13 your instance:
14 <br/><br/>
15
16 <a href="https://github.com/infobyte/faraday-cli" target="_blank">Faraday CLI</a>
17 <br>
18 Use Faraday directly from your favorite terminal. This is a common replacement for our GTK Client.
19 <br><br>
20
21 <a href="https://github.com/infobyte/faraday_agent_dispatcher" target="_blank">Agent Dispatcher</a>
22 <br>
23 Integrate Faraday with your scanning tools and automate all your scans. Our Dispatcher allows you to
24 create custom integrations for your instance.
25 <br><br>
26
27 Faraday Client
28 <br>
29 <a href="https://storage.googleapis.com/faraday-community/faraday-client_amd64.deb" target="_blank">DEB
30 Link</a>
31 <br>
32 <a href="https://storage.googleapis.com/faraday-community/faraday-client_amd64.rpm" target="_blank">RPM
33 Link</a>
34 <br>
35 Run commands directly from our GTK Client and get all results imported automatically into your instance.
36 <br><br>
37
38 <a href="https://github.com/infobyte/faraday_templates/tree/master/methodologies" target="_blank">Methodology
39 Templates</a>
40 <br>
41 Common security methodologies ready to be used within your Faraday projects.
42 <br><br>
43
44 <a href="https://github.com/infobyte/faraday_templates/tree/master/vulnerability_templates"
45 target="_blank">Vulnerability KB Templates (CWE)</a>
46 <br>
47 Populate your Faraday KB with default CWE information.
48 <br><br>
49
50 <a href="https://portswigger.net/bappstore/82f3cbaea46c4f158fd85bbccc90c31c" target="_blank">Burp
51 Extender</a>
52 <br>
53 Send findings directly from Burp into your Faraday instance. Automatically populate your project or
54 choose exactly what you want to share.
55 <br><br>
56
57 </div><!-- .reports -->
58 </div><!-- #reports-main -->
59 </div><!-- .right-main -->
60 </section><!-- #main -->
+0
-46
faraday/server/www/scripts/fileExporter/directives/download.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 // file export
6 .directive('fileExporter',
7 ['$parse', '$click', '$blob', '$log', '$timeout',
8 function($parse, $click, $blob, $log, $timeout) {
9 return {
10 compile: function($element, attr) {
11 var fn = $parse(attr.fileExporter);
12
13 return function(scope, element, attr) {
14
15 element.on('click', function(event) {
16 fn(scope).then(function (res){
17 var a_href, content, extension, title, type, url, _ref;
18 _ref = res;
19 content = _ref.content, extension = _ref.extension, title = _ref.title, type = _ref.type;
20
21 if (!(content != null) && !(extension != null) && !(title != null) && !(type != null)) {
22 $log.warn("Invalid content, extension, title or type in file exporter : ", content, extension, title, type);
23 return;
24 }
25
26 title = $blob.sanitizeFileName(title, extension);
27 type = $blob.sanitizeFileType(type);
28 url = $blob.fileToURL(content, type);
29
30 element.append("<a download=\"" + title + "\" href=\"" + url + "\"></a>");
31 a_href = element.find('a')[0];
32
33 $click.on(a_href);
34
35 //Delay is necesary only for old versions of firefox browser.
36 //Ref: https://stackoverflow.com/questions/30694453/blob-createobjecturl-download-not-working-in-firefox-but-works-when-debugging
37 $timeout(function() {$blob.revoke(url);}, 1000);
38
39 element[0].removeChild(a_href);
40 });
41 });
42 };
43 }
44 };
45 }]);
+0
-32
faraday/server/www/scripts/fileExporter/providers/blob.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('$blob', function() {
6 return {
7 fileToURL: function(content, t) {
8 var blob;
9 blob = new Blob([content], {type: t});
10 return (window.URL || window.webkitURL).createObjectURL(blob);
11 },
12 sanitizeFileName: function(name, extension) {
13 var nameRegExp = new RegExp("^[A-Za-z0-9_-]+$");
14 var extRegExp = new RegExp("^[A-Za-z]+$");
15 if(nameRegExp.test(name) && extRegExp.test(extension)) {
16 return "Faraday-" + name + "." + extension;
17 }
18 throw new Error("Invalid title or extension for file: " + name + "." + extension);
19 },
20 sanitizeFileType: function(type) {
21 var patt = new RegExp("^[a-z]+/[a-z+.-]+$");
22 if(patt.test(type)) {
23 return name;
24 }
25 throw new Error("Invalid type for file: " + type);
26 },
27 revoke: function(url) {
28 return (window.URL || window.webkitURL).revokeObjectURL(url);
29 }
30 };
31 });
+0
-14
faraday/server/www/scripts/fileExporter/providers/click.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('$click', function() {
6 return {
7 on: function(element) {
8 var e = document.createEvent("MouseEvent");
9 e.initMouseEvent("click", false, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
10 element.dispatchEvent(e);
11 }
12 };
13 });
+0
-46
faraday/server/www/scripts/help/partials/help.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion">
5 <div class="faraday-header-border-fix">
6 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
7 <div id="reports-main" class="fila">
8 <h2 class="ws-label">
9 <span id="ws-name" title="Help">Quick help</span>
10 </h2><!-- .ws-label -->
11 <div class="reports col-md-10 col-sm-10 col-xs-12">
12 We strongly recommend that every Faraday user starts by reading our <a href="https://support.faradaysec.com" target="_blank">official documentation</a>.
13 <br/><br/>
14 If after reading it you are still in the need of some assistance then we have some recommendations:
15 <br/><br/>
16 <div class="reports col-md-10 col-sm-10 col-xs-12"><ul>
17 <li>
18 * Maybe someone already had this question before, have you tried the <a href="https://support.faradaysec.com/portal/en/kb/articles/faqs" target="_blank">frequently asked questions</a> part of our docs?
19 </li>
20 <li>
21 * Not a question but a problem, it could help to take a look at the <a href="https://support.faradaysec.com/portal/en/kb/articles/troubleshooting-intro" target="_blank">troubleshooting page</a>
22 </li>
23 <!--<li>
24 * We also have a bunch of interesting <a href="TODO refill" target="_blank">video demos</a> that may help
25 </li>-->
26 <li>
27 * <a href="https://github.com/infobyte/faraday/issues" target="_blank">Open a ticket</a>
28 </li>
29 </ul></div><!-- .reports .col-md-10 .col-sm-10 .col-xs-12 -->
30 <br/><br/><br/><br/><br/>
31 Still can't fix it? You can reach us and find other Faraday users on:
32 <br/><br/>
33 <div class="reports col-md-10 col-sm-10 col-xs-12"><ul>
34 <li>
35 * User support - <a href="https://support.faradaysec.com" target="_blank">support.faradaysec.com</a>
36 </li>
37 <li>
38 * Twitter - <a href="https://twitter.com/faradaysec" target="_blank">twitter.com/faradaysec</a>
39 </li>
40 </ul></div><!-- .reports .col-md-10 .col-sm-10 .col-xs-12 -->
41 <br/><br/><br/><br/>
42 More info about Faraday at <a href="https://faradaysec.com" target="_blank">faradaysec.com</a>
43 </div><!-- .reports -->
44 </div><!-- #reports-main --></div><!-- .right-main -->
45 </section><!-- #main -->
+0
-531
faraday/server/www/scripts/hosts/controllers/host.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('hostCtrl', [
6 '$scope',
7 '$cookies',
8 '$filter',
9 '$location',
10 '$route',
11 '$routeParams',
12 '$uibModal',
13 '$q',
14 'hostsManager',
15 'workspacesFact',
16 'dashboardSrv',
17 'servicesManager',
18 'commonsFact',
19 function ($scope,
20 $cookies,
21 $filter,
22 $location,
23 $route,
24 $routeParams,
25 $uibModal,
26 $q,
27 hostsManager,
28 workspacesFact,
29 dashboardSrv,
30 servicesManager,
31 commons) {
32
33 loadHosts = function(){
34 hostsManager.getHost($routeParams.hidId, $scope.workspace, true)
35 .then(function(host) {
36 hostsManager.getTools($routeParams.hidId, $scope.workspace)
37 .then(function(tools){
38 host.tools = tools;
39 $scope.host = host;
40 $scope.host.hostnames = $scope.host.hostnames.map(function(hostname){
41 return {key: hostname}
42 });
43 $scope.hostName = host.ip; // User can edit $scope.host.name but not $scope.hostName
44 $scope.loadIcons();
45 workspacesFact.get($scope.workspace).then(function(response) {
46 $scope.workspaceData = response;
47 });
48 $scope.loadMac();
49 })
50 });
51 };
52
53 loadServices = function(){
54 // services by host
55 var hostId = $routeParams.hidId;
56 dashboardSrv.getServicesByHost($scope.workspace, hostId)
57 .then(function(services) {
58 $scope.services = services;
59
60 $scope.services.forEach(function(service) {
61 service.uri = encodeURIComponent(encodeURIComponent("(" + service.ports + "/" + service.protocol + ") " + service.name));
62 });
63
64 $scope.loadedServices = true;
65
66 return services;
67 })
68 .catch(function(e) {
69 console.log(e);
70 });
71 };
72
73 init = function() {
74 $scope.selectall_service = false;
75 // current workspace
76 $scope.workspace = $routeParams.wsId;
77 //ID of current host
78 var hostId = $routeParams.hidId;
79
80 $scope.services = [];
81 $scope.sortField = "ports";
82 $scope.reverse = false;
83 $scope.editing = ($routeParams.edit == 'edit');
84 $scope.showServices = true;
85 $scope.creating = false;
86
87 $scope.loadedServices = false;
88
89 // load all workspaces
90 workspacesFact.list()
91 .then(function(wss) {
92 $scope.workspaces = wss;
93 });
94
95 // current host and its services
96 loadHosts();
97 loadServices(hostId);
98
99 $scope.pageSize = 10;
100 $scope.toolPageSize = 10;
101 $scope.currentPage = 1;
102 $scope.newCurrentPage = 1;
103 $scope.currentToolPage = 1;
104 $scope.newCurrentToolPage = 1;
105
106 if(!isNaN(parseInt($cookies.pageSize))) $scope.pageSize = parseInt($cookies.pageSize);
107 $scope.newPageSize = $scope.pageSize;
108 $scope.newToolPageSize = $scope.toolPageSize;
109
110 // current search
111 $scope.search = $routeParams.search;
112 $scope.searchParams = "";
113 $scope.expression = {};
114 if($scope.search != "" && $scope.search != undefined && $scope.search.indexOf("=") > -1) {
115 // search expression for filter
116 $scope.expression = $scope.decodeSearch($scope.search);
117 // search params for search field, which shouldn't be used for filtering
118 $scope.searchParams = $scope.stringSearch($scope.expression);
119 }
120 };
121
122 $scope.selectedServices = function() {
123 selected = [];
124
125 tmp_services = filter($scope.services);
126 tmp_services.forEach(function(service) {
127 if(service.selected === true) {
128 selected.push(service);
129 }
130 });
131 return selected;
132 };
133
134 $scope.newHostnames = function($event){
135 $scope.host.hostnames.push({key:''});
136 $event.preventDefault();
137 }
138
139 $scope.ok = function() {
140 var date = new Date(),
141 timestamp = date.getTime()/1000.0;
142
143 // The API expects list of strings in hostnames
144 var old_hostnames = $scope.host.hostnames;
145 $scope.host.hostnames = $scope.host.hostnames.map(function(hostname){
146 return hostname.key
147 }).filter(Boolean);
148
149 $scope.hostdata = $scope.host;
150 $scope.hostdata.metadata['update_time'] = timestamp;
151 $scope.hostdata.metadata['update_user'] = "UI Web";
152
153 hostsManager.updateHost($scope.host, $scope.hostdata,
154 $scope.workspace).then(function(){
155 $scope.host.hostnames = old_hostnames;
156 $scope.hostnames = old_hostnames;
157 $location.path('/host/ws/' + $scope.workspace + '/hid/' + $scope.host._id);
158 }, function(){
159 $scope.host.hostnames = old_hostnames;
160 });
161 };
162
163 $scope.cancel = function(){
164 $scope.editing = false;
165 loadHosts();
166 };
167
168 $scope.toggleEdit = function(){
169 $scope.editing = !$scope.editing;
170 };
171
172
173 // changes the URL according to search params
174 $scope.searchFor = function(search, params) {
175 var url = "/host/ws/" + $routeParams.wsId + "/hid/" + $routeParams.hidId;
176
177 if(search && params != "" && params != undefined) {
178 url += "/search/" + $scope.encodeSearch(params);
179 }
180
181 $location.path(url);
182 };
183
184 $scope.go = function() {
185 if ($scope.newPageSize === undefined)
186 $scope.newPageSize = 1;
187 $scope.pageSize = $scope.newPageSize;
188 $cookies.pageSize = $scope.pageSize;
189 $scope.currentPage = 1;
190 if ($scope.newCurrentPage <= $scope.pageCount() && $scope.newCurrentPage > 0 &&
191 !isNaN(parseInt($scope.newCurrentPage))) {
192 $scope.currentPage = $scope.newCurrentPage;
193 }
194 };
195
196 // encodes search string in order to send it through URL
197 $scope.encodeSearch = function(search) {
198 var i = -1,
199 encode = "",
200 params = search.split(" "),
201 chunks = {};
202
203 params.forEach(function(chunk) {
204 i = chunk.indexOf(":");
205 if(i > 0) {
206 chunks[chunk.slice(0, i)] = chunk.slice(i+1);
207 } else {
208 if(!chunks.hasOwnProperty("free")) {
209 chunks.free = "";
210 }
211 chunks.free += " ".concat(chunk);
212 }
213 });
214
215 if(chunks.hasOwnProperty("free")) {
216 chunks.free = chunks.free.slice(1);
217 }
218
219 for(var prop in chunks) {
220 if(chunks.hasOwnProperty(prop)) {
221 if(chunks.prop != "") {
222 encode += "&" + encodeURIComponent(prop) + "=" + encodeURIComponent(chunks[prop]);
223 }
224 }
225 }
226 return encode.slice(1);
227 };
228
229 // decodes search parameters to object in order to use in filter
230 $scope.decodeSearch = function(search) {
231 var i = -1,
232 decode = {},
233 params = search.split("&");
234
235 params.forEach(function(param) {
236 i = param.indexOf("=");
237 decode[decodeURIComponent(param.slice(0,i))] = decodeURIComponent(param.slice(i+1));
238 });
239
240 if(decode.hasOwnProperty("free")) {
241 decode['$'] = decode.free;
242 delete decode.free;
243 }
244
245 return decode;
246 };
247
248 // converts current search object to string to be displayed in search field
249 $scope.stringSearch = function(obj) {
250 var search = "";
251
252 for(var prop in obj) {
253 if(obj.hasOwnProperty(prop)) {
254 if(search != "") {
255 search += " ";
256 }
257 if(prop == "$") {
258 search += obj[prop];
259 } else {
260 search += prop + ":" + obj[prop];
261 }
262 }
263 }
264
265 return search;
266 };
267
268 $scope.new = function() {
269 var modal = $uibModal.open({
270 templateUrl: 'scripts/services/partials/modalNew.html',
271 backdrop : 'static',
272 controller: 'serviceModalNew',
273 size: 'lg',
274 resolve: {
275 host: function() {
276 return $scope.host;
277 }
278 }
279 });
280
281 modal.result.then(function(data) {
282 loadServices();
283 });
284 };
285
286 $scope.update = function(services, data) {
287 //hostId
288 loadServices();
289 };
290
291 $scope.edit = function() {
292 if($scope.selectedServices().length > 0) {
293 var modal = $uibModal.open({
294 templateUrl: 'scripts/services/partials/modalEdit.html',
295 backdrop : 'static',
296 controller: 'serviceModalEdit',
297 size: 'lg',
298 resolve: {
299 service: function() {
300 return $scope.selectedServices();
301 },
302 workspace: function () {
303 return $scope.workspaceData;
304 }
305 }
306 });
307
308 modal.result.then(function(data) {
309 $scope.update($scope.selectedServices(), data);
310 });
311 } else {
312 $uibModal.open(config = {
313 templateUrl: 'scripts/commons/partials/modalKO.html',
314 controller: 'commonsModalKoCtrl',
315 size: 'sm',
316 resolve: {
317 msg: function() {
318 return 'No services were selected to edit';
319 }
320 }
321 });
322 }
323 };
324
325 $scope.delete = function() {
326 var selected = $scope.selectedServices();
327
328 if(selected.length == 0) {
329 $uibModal.open(config = {
330 templateUrl: 'scripts/commons/partials/modalKO.html',
331 controller: 'commonsModalKoCtrl',
332 size: 'sm',
333 resolve: {
334 msg: function() {
335 return 'No services were selected to delete';
336 }
337 }
338 })
339 } else {
340 var message = "A service will be deleted";
341 if(selected.length > 1) {
342 message = selected.length + " services will be deleted";
343 }
344 message = message.concat(" along with all of its children. This operation cannot be undone. Are you sure you want to proceed?");
345 $uibModal.open(config = {
346 templateUrl: 'scripts/commons/partials/modalDelete.html',
347 controller: 'commonsModalDelete',
348 size: 'lg',
349 resolve: {
350 msg: function() {
351 return message;
352 }
353 }
354 }).result.then(function() {
355 $scope.remove(selected);
356 }, function() {
357 //dismised, do nothing
358 });
359 }
360 };
361
362 $scope.deleteHost = function(){
363 var message = "A host will be deleted along with all of its children. This operation cannot be undone. Are you sure you want to proceed?";
364 $uibModal.open({
365 templateUrl: 'scripts/commons/partials/modalDelete.html',
366 controller: 'commonsModalDelete',
367 size: 'lg',
368 resolve: {
369 msg: function() {
370 return message;
371 }
372 }
373 }).result.then(function() {
374 $scope.removeHost($scope.host._id);
375 }, function() {
376 //dismised, do nothing
377 });
378 };
379
380 $scope.removeHost = function(id) {
381 hostsManager.deleteHost(id, $scope.workspace).then(function() {
382 $location.path('/hosts/ws/' + $scope.workspace);
383 }, function(message) {
384 console.log(message);
385 });
386 };
387
388 $scope.remove = function(services) {
389 //removes services from host
390 services.forEach(function(service) {
391 servicesManager.deleteServices(service, $scope.workspace).then(function() {
392 var index = -1;
393 for(var i=0; i < $scope.services.length; i++) {
394 if($scope.services[i]._id === service.id) {
395 index = i;
396 break;
397 }
398 }
399 $scope.services.splice(index, 1);
400 }, function(message) {
401 console.log(message);
402 });
403 });
404 };
405
406 $scope.checkAllServices = function() {
407 $scope.selectall_service = !$scope.selectall_service;
408
409 tmp_services = filter($scope.services);
410 tmp_services.forEach(function(service) {
411 service.selected = $scope.selectall_service;
412 });
413 };
414
415 // toggles sort field and order
416 $scope.toggleSort = function(field) {
417 $scope.toggleSortField(field);
418 $scope.toggleReverse();
419 };
420
421 // toggles column sort field
422 $scope.toggleSortField = function(field) {
423 $scope.sortField = field;
424 };
425
426 // toggle column sort order
427 $scope.toggleReverse = function() {
428 $scope.reverse = !$scope.reverse;
429 }
430
431 filter = function(data) {
432 // this is going to be replaced by a server query
433 var tmp_data = $filter('orderBy')(data, $scope.sortField, $scope.reverse);
434 tmp_data = $filter('filter')(tmp_data, $scope.expression);
435 tmp_data = tmp_data.splice($scope.pageSize * ($scope.currentPage - 1), $scope.pageSize);
436 return tmp_data;
437 };
438
439 // paging
440
441 $scope.prevPage = function() {
442 $scope.currentPage -= 1;
443 };
444
445 $scope.prevPageDisabled = function() {
446 return $scope.currentPage <= 1;
447 };
448
449 $scope.nextPage = function() {
450 $scope.currentPage += 1;
451 };
452
453 $scope.nextPageDisabled = function() {
454 return $scope.currentPage >= $scope.pageCount();
455 };
456
457 $scope.pageCount = function() {
458 var tmp_services = $filter('orderBy')($scope.services, $scope.sortField, $scope.reverse);
459 tmp_services = $filter('filter')(tmp_services, $scope.expression);
460 return Math.ceil(tmp_services.length / $scope.pageSize);
461 };
462
463 $scope.toolPageCount = function() {
464 if($scope.host && $scope.host.tools)
465 return Math.ceil($scope.host.tools.length / $scope.toolPageSize);
466 else
467 return false;
468 };
469
470 $scope.goTools = function() {
471 if ($scope.newToolPageSize === undefined)
472 $scope.newToolPageSize = 1;
473 $scope.toolPageSize = $scope.newToolPageSize;
474 $cookies.toolPageSize = $scope.toolPageSize;
475 $scope.currentToolPage = 1;
476 if ($scope.newCurrentToolPage <= $scope.toolPageCount() && $scope.newCurrentToolPage > 0 &&
477 !isNaN(parseInt($scope.newCurrentToolPage))) {
478 $scope.currentToolPage = $scope.newCurrentToolPage;
479 }
480 };
481
482 $scope.prevToolPage = function() {
483 $scope.currentToolPage -= 1;
484 };
485
486 $scope.nextToolPage = function() {
487 $scope.currentToolPage += 1;
488 };
489
490 $scope.prevToolPageDisabled = function() {
491 return $scope.currentToolPage <= 1;
492 };
493
494 $scope.nextToolPageDisabled = function() {
495 return $scope.currentToolPage >= $scope.toolPageCount();
496 };
497
498 $scope.loadIcons = function() {
499 var host = $scope.host;
500 // load icons into object for HTML
501 // maybe this part should be directly in the view somehow
502 // or, even better, in a CSS file
503 var oss = ["windows", "cisco", "router", "osx", "apple","linux", "unix", "unknown"];
504 oss.forEach(function(os){
505 if(host.os.toLowerCase().indexOf(os) != -1) {
506 host.icon = os;
507 if(os == "unix") {
508 host.icon = "linux";
509 } else if(os == "apple") {
510 host.icon = "osx";
511 }
512 }
513 });
514 };
515
516 $scope.loadMac = function() {
517 var host = $scope.host;
518 var mac_vendor = [""];
519 mac_vendor.forEach(function(mac){
520 if(host.mac == "00:00:00:00:00:00" || host.mac == ""){
521 host.mac = "-";
522 host.mac_vendor = "-";
523 } else {
524 host.mac_vendor = oui(host.mac);
525 }
526 });
527 };
528
529 init();
530 }]);
+0
-489
faraday/server/www/scripts/hosts/controllers/hosts.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('hostsCtrl', [
6 '$scope',
7 '$cookies',
8 '$filter',
9 '$location',
10 '$route',
11 '$routeParams',
12 '$uibModal',
13 'hostsManager',
14 'workspacesFact',
15 'commonsFact',
16 'credential',
17 '$http',
18 'BASEURL',
19 function ($scope,
20 $cookies,
21 $filter,
22 $location,
23 $route,
24 $routeParams,
25 $uibModal,
26 hostsManager,
27 workspacesFact,
28 commonsFact,
29 credential,
30 $http,
31 BASEURL) {
32
33 var init = function() {
34 $scope.selectall_hosts = false;
35 // hosts list
36 $scope.hosts = [];
37 $scope.totalHosts = 0;
38 $scope.columns = {
39 "id": false,
40 "ip": true,
41 "search_in_shodan": true,
42 "description": false,
43 "hostnames": false,
44 "services": false,
45 "mac": false,
46 "vendor": false,
47 "service_count": true,
48 "vuln_count": true,
49 "credential_count": true,
50 "os": true,
51 "owned": true,
52 "create_time": true,
53 "last_modified": true,
54 "owner": true
55 }
56 if($cookies.get('HColumns')) {
57 preferences = JSON.parse($cookies.get('HColumns'))
58 angular.extend($scope.columns, preferences);
59 }
60 // current workspace
61 $scope.workspace = $routeParams.wsId;
62
63 // load current workspace data
64 workspacesFact.get($scope.workspace).then(function(response) {
65 $scope.workspaceData = response;
66 });
67
68 $scope.sortField = "vulns";
69 $scope.sortDirection = "desc";
70 $scope.reverse = true;
71
72 // load all workspaces
73 workspacesFact.list().then(function(wss) {
74 $scope.workspaces = wss;
75 });
76
77 // paging
78 $scope.pageSize = 100;
79 $scope.currentPage = 1;
80 $scope.newCurrentPage = 1;
81
82 if(!isNaN(parseInt($cookies.pageSize))) $scope.pageSize = parseInt($cookies.pageSize);
83 $scope.newPageSize = $scope.pageSize;
84
85 parseSearchQuery();
86
87 loadHosts();
88
89 };
90
91 var parseSearchQuery = function() {
92 $scope.search = $routeParams.search;
93 $scope.searchParams = "";
94 $scope.expression = {};
95
96 if($scope.search != "" && $scope.search != undefined && $scope.search.indexOf("=") > -1) {
97 $scope.expression = commonsFact.parseSearchURL($scope.search);
98 $scope.searchParams = commonsFact.searchFilterToExpression($scope.expression);
99 }
100 };
101
102 var loadHosts = function() {
103 $scope.loading = true;
104 hostsManager.getHosts(
105 $scope.workspace, $scope.currentPage,
106 $scope.pageSize, $scope.expression,
107 $scope.sortField, $scope.sortDirection)
108 .then(function(batch) {
109 $scope.loading = false;
110 $scope.hosts = batch.hosts;
111 $scope.totalHosts = batch.total;
112 $scope.loadedVulns = true;
113 $scope.loadIcons();
114 $scope.loadMac();
115 })
116 .catch(function(e) {
117 $scope.loading = false;
118 console.log(e);
119 });
120 };
121
122 var createCredential = function(credentialData, parent_id){
123
124 // Add parent id, create credential and save to server.
125 try {
126 var credentialObj = new credential(credentialData, parent_id);
127 credentialObj.create($scope.workspace);
128 } catch (error) {
129 console.log(error);
130 }
131 };
132
133 $scope.loadIcons = function() {
134 $scope.hosts.forEach(function(host) {
135 // load icons into object for HTML
136 // maybe this part should be directly in the view somehow
137 // or, even better, in a CSS file
138 var oss = ["windows", "cisco", "router", "osx", "apple","linux", "unix"];
139 oss.forEach(function(os){
140 if(host.os.toLowerCase().indexOf(os) != -1) {
141 host.icon = os;
142 if(os == "unix") {
143 host.icon = "linux";
144 } else if(os == "apple") {
145 host.icon = "osx";
146 }
147 }
148 });
149 });
150 };
151
152 $scope.loadMac = function() {
153 $scope.hosts.forEach(function(host) {
154 var mac_vendor = [""];
155 mac_vendor.forEach(function(mac){
156 if(host.mac == "00:00:00:00:00:00" || host.mac == ""){
157 host.mac = "-";
158 host.mac_vendor = "-";
159 } else {
160 host.mac_vendor = oui(host.mac);
161 }
162 });
163 });
164 };
165 // changes the URL according to search params
166 $scope.searchFor = function(search, params) {
167 // TODO: It would be nice to find a way for changing
168 // the url without reloading the controller
169 var url = "/hosts/ws/" + $routeParams.wsId;
170
171 if(search && params != "" && params != undefined) {
172 var filter = commonsFact.parseSearchExpression(params);
173 var URLParams = commonsFact.searchFilterToURLParams(filter);
174 url += "/search/" + URLParams;
175 }
176
177 $location.path(url);
178 };
179
180 $scope.go = function() {
181 if ($scope.newPageSize === undefined)
182 $scope.newPageSize = 1;
183 $scope.pageSize = $scope.newPageSize;
184 $cookies.pageSize = $scope.pageSize;
185 $scope.currentPage = 1;
186 if ($scope.newCurrentPage <= $scope.pageCount() && $scope.newCurrentPage > 0 &&
187 !isNaN(parseInt($scope.newCurrentPage))) {
188 $scope.currentPage = $scope.newCurrentPage;
189 }
190 loadHosts();
191 };
192
193 $scope.remove = function(ids) {
194 ids.forEach(function(id) {
195 hostsManager.deleteHost(id, $scope.workspace).then(function() {
196 var index = -1;
197 for(var i=0; i < $scope.hosts.length; i++) {
198 if($scope.hosts[i]._id === id) {
199 index = i;
200 break;
201 }
202 }
203 $scope.hosts.splice(index, 1);
204 $scope.totalHosts--;
205 }, function(message) {
206 console.log(message);
207 });
208 });
209 };
210
211 $scope.delete = function() {
212 var selected = [];
213 $scope.selectedHosts().forEach(function(select) {
214 selected.push(select._id);
215 });
216
217 if(selected.length == 0) {
218 $uibModal.open({
219 templateUrl: 'scripts/commons/partials/modalKO.html',
220 controller: 'commonsModalKoCtrl',
221 size: 'sm',
222 resolve: {
223 msg: function() {
224 return 'No hosts were selected to delete';
225 }
226 }
227 })
228 } else {
229 var message = "A host will be deleted";
230 if(selected.length > 1) {
231 message = selected.length + " hosts will be deleted";
232 }
233 message = message.concat(" along with all of its children. This operation cannot be undone. Are you sure you want to proceed?");
234 $uibModal.open({
235 templateUrl: 'scripts/commons/partials/modalDelete.html',
236 controller: 'commonsModalDelete',
237 size: 'lg',
238 resolve: {
239 msg: function() {
240 return message;
241 }
242 }
243 }).result.then(function() {
244 $scope.remove(selected);
245 }, function() {
246 //dismised, do nothing
247 });
248 }
249 };
250
251 $scope.insert = function(hostdata, credentialData) {
252
253 hostsManager.createHost(hostdata, $scope.workspace).then(function(host) {
254 if(credentialData.name && credentialData.username && credentialData.password){
255 createCredential(credentialData, hostdata._id);
256 host.credentials = 1;
257 }
258 $scope.hosts.push(host);
259 $scope.loadIcons();
260 $scope.loadMac();
261
262 }, function(message) {
263 $uibModal.open({
264 templateUrl: 'scripts/commons/partials/modalKO.html',
265 controller: 'commonsModalKoCtrl',
266 size: 'sm',
267 resolve: {
268 msg: function() {
269 return message;
270 }
271 }
272 });
273 });
274 }
275
276 $scope.new = function() {
277 $location.path('/host/ws/' + $scope.workspace + '/new');
278 };
279
280 $scope.update = function(host, hostdata) {
281 hostsManager.updateHost(host, hostdata, $scope.workspace).then(function() {
282 // load icons in case an operating system changed
283 $scope.loadIcons();
284 $scope.loadMac();
285 loadHosts();
286 }, function(message){
287 console.log(message);
288 });
289 };
290
291 $scope.edit = function() {
292 if($scope.selectedHosts().length == 1) {
293 var hostId = $scope.selectedHosts()[0]._id;
294 $location.path('/host/ws/' + $scope.workspace + '/hid/' + hostId + '/edit');
295 } else {
296 $uibModal.open({
297 templateUrl: 'scripts/commons/partials/modalKO.html',
298 controller: 'commonsModalKoCtrl',
299 size: 'sm',
300 resolve: {
301 msg: function() {
302 return 'No hosts were selected to edit';
303 }
304 }
305 });
306 }
307 };
308
309 $scope.selectedHosts = function() {
310 var selected = [];
311 $scope.hosts.forEach(function(host) {
312 if(host.selected === true) {
313 selected.push(host);
314 }
315 });
316 return selected;
317 };
318
319 $scope.checkAll = function() {
320 $scope.selectall_hosts = !$scope.selectall_hosts;
321 $scope.hosts.forEach(function(host) {
322 host.selected = $scope.selectall_hosts;
323 });
324 };
325
326 $scope.hasDisabledFields = function(){
327 return Object.values($scope.columns).some(function(show){
328 return !show
329 });
330 };
331
332 $scope.toggleShow = function(column) {
333 $scope.columns[column] = !$scope.columns[column];
334 $cookies.put('HColumns', JSON.stringify($scope.columns));
335 };
336
337 // toggles sort field and order
338 $scope.toggleSort = function(field) {
339 if ($scope.sortField != field) {
340 $scope.sortDirection = "desc";
341 } else {
342 $scope.toggleReverse();
343 }
344 $scope.sortField = field;
345 loadHosts();
346 };
347
348 // toggle column sort order
349 $scope.toggleReverse = function() {
350 if ($scope.sortDirection == "asc") {
351 $scope.sortDirection = "desc";
352 } else {
353 $scope.sortDirection = "asc";
354 }
355 }
356
357 // paging
358 $scope.prevPage = function() {
359 $scope.currentPage -= 1;
360 loadHosts();
361 };
362
363 $scope.prevPageDisabled = function() {
364 return $scope.currentPage <= 1;
365 };
366
367 $scope.nextPage = function() {
368 $scope.currentPage += 1;
369 loadHosts();
370 };
371
372 $scope.nextPageDisabled = function() {
373 return $scope.currentPage >= $scope.pageCount();
374 };
375
376 $scope.pageCount = function() {
377 return Math.ceil($scope.totalHosts / $scope.pageSize);
378 };
379
380 $scope.copyToClipboard = function(ip){
381 var elem = document.getElementsByName(ip)[0];
382
383 var targetId = "_hiddenCopyText_";
384 var isInput = elem.tagName === "INPUT" || elem.tagName === "TEXTAREA";
385 var origSelectionStart, origSelectionEnd;
386 if (isInput) {
387 target = elem;
388 origSelectionStart = elem.selectionStart;
389 origSelectionEnd = elem.selectionEnd;
390 } else {
391 target = document.getElementById(targetId);
392 if (!target) {
393 var target = document.createElement("textarea");
394 target.style.position = "absolute";
395 target.style.left = "-9999px";
396 target.style.top = "0";
397 target.id = targetId;
398 document.body.appendChild(target);
399 }
400 target.textContent = elem.innerText;
401 }
402
403 var currentFocus = document.activeElement;
404 target.focus();
405 target.setSelectionRange(0, target.value.length);
406
407
408 var succeed;
409 try {
410 succeed = document.execCommand("copy");
411 } catch(e) {
412 succeed = false;
413 }
414
415 if (currentFocus && typeof currentFocus.focus === "function") {
416 currentFocus.focus();
417 }
418
419 if (isInput) {
420 elem.setSelectionRange(origSelectionStart, origSelectionEnd);
421 } else {
422 target.textContent = "";
423 }
424 return succeed;
425 }
426
427 $scope.enableFileUpload = function() {
428
429 if($scope.fileUploadEnabled === undefined) {
430 $http.get(BASEURL + '_api/session').then(
431 function(d) {
432 $scope.csrf_token = d.data.csrf_token;
433 $scope.fileUploadEnabled = true;
434
435 var modal = $uibModal.open({
436 templateUrl: 'scripts/hosts/partials/upload.html',
437 controller: 'hostModelModalUpload',
438 size: 'lg',
439 resolve: { }
440 });
441
442 modal.result.then(function(data) {
443 $scope.fileUploadEnabled = undefined;
444 $scope.fileToUpload = data;
445 $scope.uploadFile();
446 });
447
448 modal.result.finally(function(){
449 $scope.fileUploadEnabled = undefined;
450 });
451 }
452 );
453 } else {
454 toggleFileUpload();
455 }
456 };
457
458 function toggleFileUpload() {
459 if($scope.fileUploadEnabled === false) {
460 $scope.fileUploadEnabled = true;
461 } else {
462 $scope.fileUploadEnabled = false;
463 $scope.fileToUpload = undefined;
464 }
465 };
466
467 $scope.uploadFile = function() {
468 var fd = new FormData();
469 fd.append('csrf_token', $scope.csrf_token);
470 fd.append('file', $scope.fileToUpload);
471 $http.post(BASEURL + '_api/v2/ws/' + $scope.workspace + '/hosts/bulk_create', fd, {
472 transformRequest: angular.identity,
473 withCredentials: false,
474 headers: {'Content-Type': undefined}
475 }).then(
476 function(d) {
477 commonsFact.showMessage("Hosts Created: " + d.data.hosts_created + " Hosts with error: " + d.data.hosts_with_errors + "", true);
478 $route.reload();
479 },
480 function(d){
481 commonsFact.showMessage("Error uploading hosts");
482 toggleFileUpload();
483 }
484 );
485 };
486
487 init();
488 }]);
+0
-62
faraday/server/www/scripts/hosts/controllers/hostsModalEdit.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('hostsModalEdit', [
6 '$scope',
7 '$modalInstance',
8 '$routeParams',
9 'hostsManager',
10 'host',
11 'commonsFact',
12 function ($scope,
13 $modalInstance,
14 $routeParams,
15 hostsManager,
16 host,
17 commons) {
18
19 var ws = $routeParams.wsId;
20 $scope.hostdata = {};
21 hostsManager.getInterfaces(ws, host._id).then(function(resp){
22 $scope.interface = resp[0].value;
23 $scope.interface.hostnames = commons.arrayToObject($scope.interface.hostnames);
24 });
25
26 $scope.host = {
27 "_id": host._id,
28 "_rev": host._rev,
29 "description": host.description,
30 "default_gateway": "None",
31 "metadata": host.metadata,
32 "name": host.name,
33 "os": host.os,
34 "owner": "",
35 "owned": host.owned,
36 "parent": host.parent,
37 "type": host.type
38 };
39
40 $scope.ok = function() {
41 var date = new Date(),
42 timestamp = date.getTime()/1000.0;
43 $scope.interface.hostnames = commons.objectToArray($scope.interface.hostnames.filter(Boolean));
44
45 $scope.hostdata = $scope.host;
46 $scope.hostdata.metadata['update_time'] = timestamp;
47 $scope.hostdata.metadata['update_user'] = "UI Web";
48
49 $modalInstance.close([$scope.hostdata, $scope.interface]);
50 };
51
52 $scope.cancel = function() {
53 $modalInstance.dismiss('cancel');
54 };
55
56 $scope.newHostnames = function($event){
57 $scope.interface.hostnames.push({key:''});
58 $event.preventDefault();
59 }
60
61 }]);
+0
-60
faraday/server/www/scripts/hosts/controllers/hostsModalNew.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('hostsModalNew',
6 ['$scope', '$modalInstance', 'hostsManager',
7 function($scope, $modalInstance, hostsManager) {
8
9 $scope.hostdata = {
10 "name": "",
11 "description": "",
12 "default_gateway": "None",
13 "os": "",
14 "owned": false,
15 "owner": "",
16 };
17
18 $scope.credentialData = {
19 'name': '',
20 'username': '',
21 'password': ''
22 };
23
24 $scope.ok = function() {
25 var hostnames = [];
26 var date = new Date(),
27 timestamp = date.getTime()/1000.0;
28
29 if($scope.hostdata.parent == undefined) $scope.hostdata.parent = null;
30
31 $scope.interfaceData.hostnames.forEach(function(hname){
32 hostnames.push(hname.hostname);
33 });
34
35 $scope.hostdata.hostnames = hostnames.filter(Boolean);
36 $scope.hostdata.interfaceName = $scope.hostdata.name;
37 $scope.hostdata.metadata = {
38 "update_time": timestamp,
39 "update_user": "",
40 "update_action": 0,
41 "creator": "",
42 "create_time": timestamp,
43 "update_controller_action": "UI Web New",
44 "owner": ""
45 };
46
47 $modalInstance.close([$scope.hostdata, $scope.credentialData]);
48 };
49
50 $scope.cancel = function() {
51 $modalInstance.dismiss('cancel');
52 };
53
54 $scope.newHostnames = function($event){
55 $scope.hostdata.hostnames.push({key:''});
56 $event.preventDefault();
57 }
58
59 }]);
+0
-74
faraday/server/www/scripts/hosts/controllers/new.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('newHostCtrl', ['$scope', '$routeParams', 'workspacesFact',
6 '$uibModal', 'hostsManager', 'commonsFact', '$location',
7 function($scope, $routeParams, workspacesFact, $uibModal, hostsManager,
8 commons, $location){
9
10 init = function(){
11 $scope.workspace = $routeParams.wsId;
12 $scope.editing = true;
13 $scope.showServices = false;
14 $scope.creating = true;
15
16 $scope.host = {
17 "ip": "",
18 "hostnames": [{key: ''}],
19 "mac": "00:00:00:00:00:00",
20 "description": "",
21 "default_gateway": "None",
22 "os": "",
23 "owned": false,
24 "owner": "",
25 };
26
27 // load all workspaces
28 workspacesFact.list()
29 .then(function(wss) {
30 $scope.workspaces = wss;
31 });
32
33 $scope.newHostnames = function($event){
34 $scope.host.hostnames.push({key:''});
35 $event.preventDefault();
36 };
37
38 $scope.insert = function(hostdata) {
39 // The API expects list of strings in hostnames
40 var old_hostnames = $scope.host.hostnames;
41 $scope.host.hostnames = $scope.host.hostnames.map(function(hostname){
42 return hostname.key
43 }).filter(Boolean);
44
45 hostsManager.createHost(hostdata, $scope.workspace).then(function(host) {
46 $scope.host.hostnames = old_hostnames;
47 $location.path('/host/ws/' + $scope.workspace + '/hid/' + host.data.id);
48 }, function(message) {
49 $scope.host.hostnames = old_hostnames;
50 $uibModal.open({
51 templateUrl: 'scripts/commons/partials/modalKO.html',
52 controller: 'commonsModalKoCtrl',
53 size: 'sm',
54 resolve: {
55 msg: function() {
56 return message;
57 }
58 }
59 });
60 });
61 };
62
63 $scope.ok = function(){
64 $scope.insert($scope.host);
65 };
66
67
68 };
69
70 init();
71
72 }]);
73
+0
-24
faraday/server/www/scripts/hosts/controllers/upload.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('hostModelModalUpload',
6 ['$scope', '$modalInstance',
7 function($scope, $modalInstance) {
8 $scope.data;
9 $scope.fileToUpload = undefined;
10
11 $scope._import = function() {
12 $scope.data = $scope.fileToUpload;
13 $scope.ok();
14 };
15
16 $scope.ok = function() {
17 $modalInstance.close($scope.fileToUpload);
18 };
19
20 $scope.cancel = function() {
21 $modalInstance.dismiss('cancel');
22 };
23 }]);
+0
-298
faraday/server/www/scripts/hosts/partials/list.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion clearfix">
5 <div class="faraday-header-border-fix"></div>
6 <div class="left-main-without-pagination">
7 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
8 <div id="reports-main" class="fila clearfix">
9 <div class="button-control col-md-12 col-sm-12 col-xs-12">
10 <div class="control-wrapper control-new">
11 <button type="button" class="btn btn-success btn-new" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'New hosts'}}" ng-click="new()" ng-disabled="workspaceData.readonly === true">
12 New
13 </button>
14 </div>
15 <table>
16 <thead>
17 <tr>
18 <th class="col-s-1" style="border-left: 1px solid rgb(221, 221, 221); padding-left: 12px;">
19 <a href="#/status/ws/{{workspace}}" class="status-report" ng-class="{'navigation-active' : component == 'status'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Vulns" tooltip-placement="right">
20 Vulns
21 </a>
22 </th>
23 <th class="col-s-1">
24 <a href="#/hosts/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'hosts'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Hosts" tooltip-placement="right">
25 Hosts
26 </a>
27 <div class="flex-spacer"></div>
28 </th>
29 <th class="col-s-1">
30 <a href="#/credentials/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'credentials'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Credentials" tooltip-placement="right">
31 Credentials
32 </a>
33 <div class="flex-spacer"></div>
34 </th>
35 <th class="col-md-1" style = "border-right: 1px solid rgb(221, 221, 221); padding-right: 12px">
36 <a href="#/taskgroup" class="executive-report" ng-class="{'navigation-active' : component == 'taskgroup'}" style="color: black !important; font-weight: bold; font-size: 15px;">
37 Tasks
38 </a>
39 <div class="flex-spacer"></div>
40 </th>
41 </tr>
42 </thead>
43 </table>
44 <div class="control-wrapper control-edit">
45 <button type="button" class="btn btn-default edit" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'Edit selected hosts'}}" ng-disabled="selectedHosts().length > 1" ng-click="edit()">
46 <img src="images/icon-toolbar-edit.svg" class="edit-icon" />
47 </button>
48 </div>
49 <div class="control-wrapper">
50 <button type="button" class="btn btn-default" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'Delete selected items'}}" ng-click="delete()" ng-disabled="workspaceData.readonly === true">
51 <img src="images/icon-toolbar-delete.svg" class="delete-icon" />
52 </button>
53 </div>
54 <div class="control-wrapper search-wrapper">
55 <form role="form" ng-submit="searchFor(true, searchParams)">
56 <div class="form-group">
57 <div class="input-group">
58 <span class="input-group-addon glyphicon-btn glyphicon glyphicon-remove" ng-click="searchFor(false, '')" ng-if="search && search != 'confirmed=true'"></span>
59 <input type="text" class="form-control" placeholder="Enter keywords" ng-change="currentPage = 1" ng-model="searchParams" />
60 <span class="input-group-addon glyphicon-btn" ng-click="searchFor(true, searchParams)">
61 <img src="images/icon-toolbar-searchbar-loupe.svg" class="search-icon" />
62 </span>
63 </div>
64 </div>
65 </form>
66 </div>
67 <div class="control-wrapper download-wrapper">
68 <button ng-click="enableFileUpload()" type="button" class="btn btn-default" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'Upload CSV with hosts'}}" ng-disabled="workspaceData.readonly == true">
69 <img src="images/icon-toolbar-upload.svg"/>
70 </button>
71 </div>
72 <div class="space-wrapper"></div>
73 <div class="control-wrapper control-wrap-right">
74 <div class="btn-group">
75 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="Add columns">
76 Add columns
77 </button>
78 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="Add Columns">
79 <span class="caret"></span>
80 </button>
81 <ul class="dropdown-menu dropdown-menu-right" role="menu">
82 <li ng-repeat="(column, show) in columns">
83 <a class="ws" ng-click="toggleShow(column, show)" ng-show="!show">{{column}}</a>
84 </li>
85 </ul>
86 </div>
87 </div>
88 </div>
89 <div class="reports">
90 <table class="status-report-grid hosts-list table table-responsive">
91 <thead>
92 <tr class="ui-grid-header ">
93 <th class="ui-grid-cell-contents ui-grid-header-cell hosts-list-checkall">
94 <input type="checkbox" ng-model="selectall" ng-click="checkAll()"/>
95 </th>
96 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['id']">
97 <span ng-click="toggleSort('id')">ID</span>
98 <a ng-click="toggleShow('id')"><span class="glyphicon glyphicon-remove"></span></a>
99 </th>
100 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['ip']">
101 <span ng-click="toggleSort('ip')">IP</span>
102 <a ng-click="toggleShow('ip')"><span class="glyphicon glyphicon-remove"></span></a>
103 </th>
104 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['search_in_shodan']">
105 <span ng-click="toggleSort('search_in_shodan')">SEARCH</span>
106 <a ng-click="toggleShow('search_in_shodan')"><span class="glyphicon glyphicon-remove"></span></a>
107 </th>
108 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['os']">
109 <span ng-click="toggleSort('os')">OS</span>
110 <a ng-click="toggleShow('os')"><span class="glyphicon glyphicon-remove"></span></a>
111 </th>
112 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-if="columns['services']">
113 <span>SERVICES</span>
114 <a ng-click="toggleShow('services')"><span class="glyphicon glyphicon-remove"></span></a>
115 </th>
116 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-if="columns['hostnames']">
117 <span>HOSTNAMES</span>
118 <a ng-click="toggleShow('hostnames')"><span class="glyphicon glyphicon-remove"></span></a>
119 </th>
120 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-if="columns['mac']">
121 <span ng-click="toggleSort('mac')">MAC</span>
122 <a ng-click="toggleShow('mac')"><span class="glyphicon glyphicon-remove"></span></a>
123 </th>
124 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-if="columns['vendor']">
125 <span ng-click="toggleSort('vendor')">Vendor</a>
126 <a ng-click="toggleShow('vendor')"><span style="glyphicon glyphicon-remove" class="glyphicon glyphicon-remove"></span></a>
127 </th>
128 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['service_count']">
129 <span ng-click="toggleSort('services')">OPEN SERVICES</span>
130 <a ng-click="toggleShow('service_count')"><span class="glyphicon glyphicon-remove"></span></a>
131 </th>
132 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['vuln_count']">
133 <span ng-click="toggleSort('vulns')">VULNS</span>
134 <a ng-click="toggleShow('vuln_count')"><span class="glyphicon glyphicon-remove"></span></a>
135 </th>
136 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['credential_count']">
137 <span ng-click="toggleSort('credentials')">CREDENTIALS</span>
138 <a ng-click="toggleShow('credential_count')"><span class="glyphicon glyphicon-remove"></span></a>
139 </th>
140 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['owned']">
141 <span ng-click="toggleSort('owned')">OWNED</span>
142 <a ng-click="toggleShow('owned')"><span class="glyphicon glyphicon-remove"></span></a>
143 </th>
144 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['owner']">
145 <span ng-click="toggleSort('owner')">OWNER</span>
146 <a ng-click="toggleShow('owner')"><span class="glyphicon glyphicon-remove"></span></a>
147 </th>
148 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['description']">
149 <span ng-click="toggleSort('description')">DESCRIPTION</span>
150 <a ng-click="toggleShow('description')"><span class="glyphicon glyphicon-remove"></span></a>
151 </th>
152 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['create_time']">
153 <span ng-click="toggleSort('metadata.create_time')">CREATION TIME</span>
154 <a ng-click="toggleShow('create_time')"><span class="glyphicon glyphicon-remove"></span></a>
155 </th>
156 <th class="ui-grid-cell-contents ui-grid-header-cell" ng-show="columns['last_modified']">
157 <span ng-click="toggleSort('metadata.update_time')">LAST MODIFIED</span>
158 <a ng-click="toggleShow('last_modified')"><span class="glyphicon glyphicon-remove"></span></a>
159 </th>
160 </tr>
161 </thead>
162 <tbody>
163 <tr ng-repeat="host in hosts" class="ui-grid-row "
164 selection-model selection-model-mode="multiple-additive"
165 selection-model-on-change="selectedHosts()">
166 <td class="ui-grid-cell-contents checkbox-select">
167 <div class="">
168 <input type="checkbox" ng-model="host.selected" ng-click="host.selected = !host.selected" name="{{host._id}}"/>
169 </div>
170 </td>
171 <td class="ui-grid-cell-contents" ng-show="columns['id']">
172 <div class="">
173 <a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}">{{host.id}}</a>
174 </div>
175 </td>
176 <td class="ui-grid-cell-contents"
177 ng-show="columns['ip']">
178 <div class="">
179 <a name="{{ 'ip-' + host._id }}" ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}">{{host.ip}}</a>
180 <a ng-href="" ng-click="copyToClipboard('ip-'+host._id)" tooltip="Copy to clipboard"><i ng-style="{'font-size':'14px'}" class="fa">&#xf0c5;</i></a>
181 </div>
182 </td>
183 <td class="ui-grid-cell-contents"
184 ng-show="columns['search_in_shodan']">
185 <div class="">
186 <a href="//www.shodan.io/search?query={{host.ip}}" uib-tooltip="Search in shodan" target="_blank">
187 <img ng-src="/images/shodan.png" height="15px" width="15px" />
188 </a>
189 </div>
190 </td>
191 <td class="ui-grid-cell-contents"
192 ng-show="columns['os']">
193 <div class="">
194 <a ng-href="#/hosts/ws/{{workspace}}/search/os={{host.os}}">
195 <img ng-if="host.icon != undefined" ng-src="images/{{host.icon}}.png" uib-tooltip="{{host.os}}"/>
196 <span ng-if="host.icon == undefined" class="fa fa-laptop" uib-tooltip="{{host.os}}"></span>
197 </a>
198 </div>
199 </td>
200 <td class="ui-grid-cell-contents"
201 ng-if="columns['services']">
202 <div class="">
203 <span ng-repeat="summary in host.service_summaries">
204 {{summary}} <br>
205 </span>
206 </div>
207 </td>
208 <td class="ui-grid-cell-contents"
209 ng-if="columns['hostnames']">
210 <div class="">
211 <span ng-repeat="hostname in host.hostnames">
212 {{hostname}} <br>
213 </span>
214 </div>
215 </td>
216 <td class="ui-grid-cell-contents"
217 ng-show="columns['mac']">
218 <div class="">
219 {{host.mac}}
220 </div>
221 </td>
222 <td class="ui-grid-cell-contents" ng-show="columns['vendor']">
223 <div>{{host.mac_vendor | limitTo:20}}</div>
224 </td>
225 <td class="ui-grid-cell-contents"
226 ng-show="columns['service_count']">
227 <div class="">
228 <a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}" ng-bind="host.services || '-'"></a>
229 </div>
230 </td>
231 <td class="ui-grid-cell-contents"
232 ng-show="columns['vuln_count']">
233 <div class="">
234 <a ng-href="#/status/ws/{{workspace}}/search/target={{host.name}}" ng-bind="host.vulns"></a>
235 </div>
236 </td>
237 <td class="ui-grid-cell-contents"
238 ng-show="columns['credential_count']">
239 <a ng-href="#/credentials/ws/{{workspace}}/hid/{{host._id}}">{{host.credentials}}</a>
240 </td>
241 <td class="ui-grid-cell-contents"
242 ng-show="columns['owned']">
243 <div class="">
244 <span class="fa fa-exclamation-triangle" aria-hidden="true" ng-if="host.owned"></span>
245 <span ng-if="host.owned">owned</span>
246 <span ng-if="!host.owned">not yet</span>
247 </div>
248 </td>
249 <td class="ui-grid-cell-contents"
250 ng-show="columns['owner']">
251 <div class="">
252 <span>{{host.owner}}</span>
253 </div>
254 </td>
255 <td class="ui-grid-cell-contents"
256 ng-show="columns['description']">
257 <div class="">
258 {{host.description}}
259 </div>
260 </td>
261 <td class="ui-grid-cell-contents date-cell"
262 ng-show="columns['create_time']">
263 <div class="">
264 <span ng-style="{'display': 'inline-block'}" am-time-ago="host.metadata.create_time" am-preprocess="utc"></span><p ng-style="{'display': 'inline-block'}">&nbsp; {{host.metadata.creator ? (' by ' + host.metadata.creator) : ''}}</p>
265 </div>
266 </td>
267 <td
268 class="ui-grid-cell-contents date-cell"
269 ng-show="columns['last_modified']">
270 <div class="">
271 <span am-time-ago="host.metadata.update_time" am-preprocess="utc"></span>
272 </div>
273 </td>
274 </tr>
275 </tbody>
276 </table><!-- #hosts -->
277 <div class="showPagination">
278 <div class="form-group">
279 <ul class="pagination">
280 <li><a ng-hide="prevPageDisabled()" ng-click="prevPage()"><span aria-hidden="true">&laquo;</span><span class="sr-only">Previous</span></a></li>
281 <li><a>{{currentPage}}/{{pageCount()}}</a></li>
282 <li><a ng-hide="nextPageDisabled()" ng-click="nextPage()"><span aria-hidden="true">&raquo;</span><span class="sr-only">Next</span></a></li>
283 </ul>
284 <form name="goToPage" id="goToPageStatus">
285 <div class="col-md-2">
286 <input type="number" min="1" max="{{pageCount()}}" class="form-control" ng-model="newCurrentPage" placeholder="Go to page"/>
287 </div>
288 <button class="btn btn-default" ng-click="go()">GO</button>
289 <input type="number" min="1" class="form-control vuln_per_page" ng-model=newPageSize placeholder="Number page" />
290 </form>
291 </div>
292 </div><!-- .showPagination -->
293 <i ng-if="loading" class="fa fa-spinner fa-spin loading-spinner"></i>
294 </div><!-- .reports -->
295 </div><!-- #reports-main -->
296 </div><!-- .right-main -->
297 </section><!-- #main -->
+0
-86
faraday/server/www/scripts/hosts/partials/modalEdit.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <div class="modal-button">
7 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid">OK</button>
8 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">Edit host</h3>
11 </div>
12 <div class="modal-body">
13 <div class="form-horizontal">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
15 <div class="col-md-12">
16 <label class="sr-only" for="name">IP v4 or v6</label>
17 <input type="text" class="form-control" id="name" name="name" placeholder="IP" ng-model="host.name" required/>
18 <span class="help-block normal-size">
19 Example: 192.168.0.1
20 </span>
21 </div>
22 </div><!-- .form-group -->
23 <div class="form-group">
24 <div class="col-md-12">
25 <label class="sr-only" for="description">Description</label>
26 <textarea class="form-control" id="description" placeholder="Description" ng-model="host.description"></textarea>
27 </div>
28 </div><!-- .form-group -->
29 <div class="form-group">
30 <div class="col-md-12">
31 <label class="sr-only" for="os">Operating System</label>
32 <input type="text" class="form-control" id="os" placeholder="Operating System" ng-model="host.os"/>
33 <span class="help-block normal-size">
34 Example: Linux 3.18.6-1-ARCH
35 </span>
36 </div>
37 </div><!-- .form-group -->
38 <div class="form-group">
39 <div class="col-md-12">
40 <div class="checkbox">
41 <label>
42 <input type="checkbox" id="owned" ng-model="host.owned"/>
43 <span class="normal-size">Owned</span>
44 </label>
45 </div><!-- .checkbox -->
46 </div>
47 </div><!-- .form-group -->
48 <div class="form-group">
49 <div class="col-md-12">
50 <h5>Hostnames</h5>
51 <span class="input-group-addon button-radius background-blue" ng-click="newHostnames($event)">Add Hostname</span>
52 </div>
53 <div class="col-md-12 input-margin" ng-repeat="hostname in interface.hostnames">
54 <div class="input-group margin-bottom-sm col-md-12">
55 <label class="sr-only" for="hostsnames">Hostname</label>
56 <input type="text" class="form-control" id="hostsnames" placeholder="Hostname" ng-model="hostname.key"/>
57 <span class="input-group-addon" ng-click="interface.hostnames.splice($index, 1)" ng-hide="interface.hostnames.length == 1"><i class="fa fa-minus-circle"></i></span>
58 </div>
59 </div>
60 </div><!-- .form-group -->
61 <div class="form-group">
62 <div class="col-md-6">
63 <label class="sr-only" for="ipv4">IP v4</label>
64 <input type="text" class="form-control" id="ipv4" placeholder="IP v4" ng-model="interface.ipv4.address"/>
65 </div>
66 <div class="col-md-6">
67 <label class="sr-only" for="ipv6">IP v6</label>
68 <input type="text" class="form-control" id="ipv6" placeholder="IP v6" ng-model="interface.ipv6.address"/>
69 </div>
70 </div><!-- .form-group -->
71 <div class="form-group">
72 <div class="col-md-12">
73 <label class="sr-only" for="mac">MAC</label>
74 <input type="text" class="form-control" id="mac" placeholder="MAC" ng-model="interface.mac"/>
75 </div>
76 </div><!-- .form-group -->
77 </div>
78 </div><!-- .modal-body -->
79 <div class="modal-footer">
80 <div class="modal-button">
81 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
82 <button class="btn btn-success" ng-disabled="form.$invalid || workspace.readonly == true" ng-click="ok()">OK</button>
83 </div>
84 </div>
85 </form>
+0
-86
faraday/server/www/scripts/hosts/partials/modalNew.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <div class="modal-button">
7 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid">OK</button>
8 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">New host</h3>
11 </div>
12 <div class="modal-body">
13 <div class="form-horizontal">
14 <div class="form-group" ng-class="{'has-error': form.ip.$invalid }">
15 <div class="col-md-12">
16 <label class="sr-only" for="name">IP v4 or v6</label>
17 <input type="text" class="form-control" id="ip" name="ip" placeholder="IP" ng-model="hostdata.ip" required/>
18 <span class="help-block normal-size">
19 Example: 192.168.0.1
20 </span>
21 </div>
22 </div><!-- .form-group -->
23 <div class="form-group">
24 <div class="col-md-12">
25 <label class="sr-only" for="description">Description</label>
26 <textarea class="form-control" id="description" placeholder="Description" ng-model="hostdata.description"></textarea>
27 </div>
28 </div><!-- .form-group -->
29 <div class="form-group">
30 <div class="col-md-12">
31 <label class="sr-only" for="os">Operating System</label>
32 <input type="text" class="form-control" id="os" placeholder="Operating System" ng-model="hostdata.os"/>
33 <span class="help-block normal-size">
34 Example: Linux 3.18.6-1-ARCH
35 </span>
36 </div>
37 </div><!-- .form-group -->
38 <div class="form-group">
39 <div class="col-md-12">
40 <input type="checkbox" id="owned" ng-model="hostdata.owned"/>
41 <span class="normal-size">Owned</span>
42 </div>
43 </div><!-- .form-group -->
44 <div class="form-group">
45 <div class="col-md-12">
46 <h5><b>Hostnames</b></h5>
47 <span class="input-group-addon button-radius background-blue" ng-click="newHostnames($event)">Add Hostname</span>
48 </div>
49 <div class="col-md-12 input-margin" ng-repeat="hostname in interfaceData.hostnames">
50 <div class="input-group margin-bottom-sm col-md-12">
51 <label class="sr-only" for="hostsnames">Hostname</label>
52 <input type="text" class="form-control" id="hostsnames" placeholder="Hostname" ng-model="hostname.hostname"/>
53 <span class="input-group-addon" ng-click="interfaceData.hostnames.splice($index, 1)" ng-hide="interfaceData.hostnames.length == 1"><i class="fa fa-minus-circle"></i></span>
54 </div>
55 </div>
56 </div><!-- .form-group -->
57 <div class="form-group">
58 <div class="col-md-12">
59 <label class="sr-only" for="mac">MAC</label>
60 <input type="text" class="form-control" id="mac" placeholder="MAC" ng-model="interfaceData.mac"/>
61 </div>
62 </div><!-- .form-group -->
63 <h5>
64 <b>Credential</b>
65 </h5>
66 <div class="form-group">
67 <div class="col-md-3" ng-class="{'has-error': form.nameCredential.$invalid}">
68 <input type="text" class="form-control" id="nameCredential" name="nameCredential" placeholder="Name" ng-model="credentialData.name" ng-required="credentialData.username || credentialData.password"/>
69 </div>
70 <div class="col-md-3" ng-class="{'has-error': form.usernameCredential.$invalid}">
71 <input type="text" class="form-control" id="usernameCredential" name="usernameCredential" placeholder="Username" ng-model="credentialData.username" ng-required="credentialData.name || credentialData.password"/>
72 </div>
73 <div class="col-md-3" ng-class="{'has-error': form.passwordCredential.$invalid}">
74 <input type="text" class="form-control" id="passwordCredential" name="passwordCredential" placeholder="Password" ng-model="credentialData.password" ng-required="credentialData.name || credentialData.username"/>
75 </div>
76 </div><!-- .form-group -->
77 </div>
78 </div><!-- .modal-body -->
79 <div class="modal-footer">
80 <div class="modal-button">
81 <button class="btn btn-success" ng-disabled="form.$invalid" ng-click="ok()">OK</button>
82 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
83 </div>
84 </div>
85 </form>
+0
-98
faraday/server/www/scripts/hosts/partials/new.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion clearfix">
5 <div class="faraday-header-border-fix">
6 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
7 <div id="reports-main" class="fila clearfix">
8 <div class="reports col-md-8 col-sm-8 col-xs-8 pr" style="border-right: 1px solid #CCC">
9 <form name="form">
10 <h3>
11 Create a host
12 <span style="float:right">
13 <a class="btn btn-sm btn-default" href="#/host/ws/{{workspace}}/hid/{{host._id}}/edit" ng-if="!editing">
14 <span class="glyphicon glyphicon-pencil"></span>
15 Edit
16 </a>
17 <button type="button" class="btn btn-sm btn-default" title="Delete host" ng-click="deleteHost()" ng-if="!editing">
18 <span class="glyphicon glyphicon-trash"></span>
19 Delete
20 </button>
21 <a class="btn btn-danger" href="#/hosts/ws/{{workspace}}" ng-if="editing && creating">Cancel</a>
22 <button class="btn btn-success" ng-disabled="form.$invalid" ng-click="ok()" ng-if="editing">OK</button>
23 </span>
24 </h3>
25 <div class="form-horizontal">
26 <div class="form-group" ng-class="{'has-error': !host.ip }">
27 <div class="col-md-12">
28 <strong ng-if="!editing">IP v4 or v6</strong>
29 <h5 ng-if="editing">IP v4 or v6</h5>
30 <label class="sr-only" for="ip">IP v4 or v6</label>
31 <input type="text" class="form-control" id="ip" placeholder="IP" ng-model="host.ip" ng-if="editing" required/>
32 <p ng-if="!editing">{{host.ip}}</p>
33 <span class="help-block normal-size" ng-if="editing">
34 Example: 192.168.0.1
35 </span>
36 </div>
37 </div>
38 <div class="form-group">
39 <div class="col-md-3" style="margin-bottom: 15px">
40 <div class="checkbox">
41 <label>
42 <input type="checkbox" id="owned" ng-model="host.owned" ng-disabled="!editing"/>
43 <span class="normal-size">Owned</span>
44 </label>
45 </div><!-- .checkbox -->
46 </div>
47 <div class="col-md-12">
48 <strong ng-if="!editing">Operating System</strong>
49 <h5 ng-if="editing">Operating System</h5>
50 <label class="sr-only" for="os">Operating System</label>
51 <input type="text" class="form-control" id="os" placeholder="Operating System" ng-model="host.os" ng-if="editing"/>
52 <p ng-if="!editing">
53 <img ng-if="host.icon != undefined" ng-src="images/{{host.icon}}.png" uib-tooltip="{{host.os}}"/>
54 {{host.os}}
55 </p>
56 </div>
57 <div class="col-md-12">
58 <strong ng-if="!editing">MAC</strong>
59 <h5 ng-if="editing">MAC</h5>
60 <input type="text" class="form-control" id="ipv4" placeholder="MAC" ng-model="host.mac" ng-if="editing"/>
61 <p ng-if="!editing">{{host.mac}}</p>
62 </div>
63 <div class="col-md-12">
64 <strong ng-if="!editing">Description</strong>
65 <h5 ng-if="editing">Description</h5>
66 <label class="sr-only" for="description">Description</label>
67 <textarea class="form-control" id="description" placeholder="Description" ng-model="host.description" ng-if="editing"></textarea>
68 <p ng-if="!editing">{{host.description}}</p>
69 </div>
70 </div><!-- .form-group -->
71 </div>
72 </form>
73 </div>
74 <div class="col-md-4 col-sm-4 col-xs-4 pl">
75 <h3>
76 Hostnames
77 <span style="float:right">
78 <button class="btn btn-success background-blue" ng-click="newHostnames($event)">Add Hostname</button>
79 </span>
80 </h3>
81 <h5 ng-if="editing" style="min-height: 1.1em"></h5>
82 <div class="form-horizontal">
83 <div class="form-group">
84 <span ng-if="editing">
85 <div class="col-md-12 input-margin" ng-repeat="hostname in host.hostnames">
86 <div class="input-group margin-bottom-sm col-md-12">
87 <label class="sr-only" for="hostsnames">Hostname</label>
88 <input type="text" class="form-control" id="hostsnames" placeholder="Hostname" ng-model="hostname.key" />
89 <span class="input-group-addon" ng-click="host.hostnames.splice($index, 1)" ng-hide="host.hostnames.length == 1" ng-if="editing"><i class="fa fa-minus-circle"></i></span>
90 </div>
91 </div>
92 </span>
93 </div>
94 </div>
95 </div>
96 </div><!-- #reports-main --></div><!-- .right-main -->
97 </section><!-- #main -->
+0
-32
faraday/server/www/scripts/hosts/partials/upload.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="uploadForm" >
5 <div class="modal-header">
6 <h3 class="modal-title">Import CSV</h3>
7 </div>
8 <div class="modal-body">
9 <span class="help-block">
10 <p> <strong>CSV File Example (must contain the headers)</strong></p>
11 <p> ip,description,os,hostnames</p>
12 <p> 10.10.10.10,test_host,linux,"['localhost','test_host']"</p>
13 </span>
14 <div class="pl">
15 <span class="file-container">
16 <button type="button" class="btn btn-success btn-labeled no-border-radius">
17 <span class="btn-label"><i class="fa fa-upload"></i>
18 </span>Select file</button>
19 <input type="file" file-model="fileToUpload" ng-class="{'file-selected': fileToUpload !== undefined}">
20 <p class="file-name">{{fileToUpload.name}}</p>
21 </span>
22 </div>
23 </div><!-- .modal-body -->
24 <div class="modal-footer">
25 <div class="modal-button btn-toolbar">
26 <button class="btn btn-success" ng-disabled="uploadForm.$invalid" ng-click="_import()">OK</button>
27 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
28 </div>
29 </div>
30 </form>
31
+0
-39
faraday/server/www/scripts/hosts/providers/host.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('Host', ['BASEURL', 'ServerAPI', function(BASEURL, ServerAPI) {
6 Host = function(data){
7 this.set(data);
8 };
9
10 Host.prototype = {
11 set: function(data) {
12 var self = this;
13
14 if(data._id != undefined) {
15 if(data.metadata !== undefined) self.metadata = data.metadata;
16 }
17
18 for (var key in data) {
19 if(data[key] !== undefined) self[key] = data[key];
20 };
21 },
22 delete: function(ws) {
23 return ServerAPI.deleteHost(ws, this.id);
24 },
25
26 update: function(data, ws) {
27 var self = this;
28 return ServerAPI.updateHost(ws, data);
29 },
30
31 save: function(ws) {
32 var self = this;
33 return ServerAPI.createHost(ws, self);
34 },
35
36 }
37 return Host;
38 }]);
+0
-165
faraday/server/www/scripts/hosts/providers/hosts.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('hostsManager', ['BASEURL', '$http', '$q', 'ServerAPI', 'Host', 'commonsFact',
6 function(BASEURL, $http, $q, ServerAPI, Host, commonsFact) {
7
8 var hostsManager = {};
9
10 hostsManager._objects = {};
11
12 hostsManager._get = function(id, data) {
13 var host = this._objects[id];
14
15 if(host) {
16 host.set(data);
17 } else {
18 host = new Host(data);
19 this._objects[id] = host;
20 }
21
22 return host;
23 };
24
25 hostsManager._search = function(id) {
26 return this._objects[id];
27 };
28
29 hostsManager._load = function(id, ws, deferred) {
30 var self = this;
31 ServerAPI.getHost(ws, id).then(
32 function(response){
33 var host = self._get(response.data.id, response.data);
34 deferred.resolve(host);
35 }, function(){
36 deferred.reject();
37 });
38 };
39
40 hostsManager.getHost = function(id, ws, force_reload) {
41 var deferred = $q.defer(),
42 host = this._search(id);
43 force_reload = force_reload || false;
44
45 if((host) && (!force_reload)) {
46 deferred.resolve(host);
47 } else {
48 this._load(id, ws, deferred);
49 }
50
51 return deferred.promise;
52 };
53
54 hostsManager.getHosts = function(ws, page, page_size, filter, sort, sort_direction) {
55 var deferred = $q.defer();
56
57 var options = {page: page, page_size: page_size, sort:sort, sort_dir: sort_direction};
58 for( var property in filter ) {
59 if (filter.hasOwnProperty(property)) {
60 options[property] = filter[property];
61 }
62 };
63 ServerAPI.getHosts(ws, options)
64 .then(function(response) {
65 var result = { hosts: [], total: 0 };
66 response.data.rows.forEach(function(host_data) {
67 host = new Host(host_data.value);
68 result.hosts.push(host);
69 });
70 result.total = response.data.count;
71 deferred.resolve(result);
72 }, function(response) {
73 deferred.reject();
74 });
75
76 return deferred.promise;
77 };
78
79 hostsManager.deleteHost = function(id, ws) {
80 var deferred = $q.defer();
81 var self = this;
82 this.getHost(id, ws)
83 .then(function(host) {
84 host.delete(ws)
85 .then(function() {
86 delete self._objects[id];
87 deferred.resolve();
88 })
89 .catch(function() {
90 // host couldn't be deleted
91 deferred.reject("Error deleting host");
92 });
93 })
94 .catch(function() {
95 // host doesn't exist
96 deferred.reject("Host doesn't exist");
97 });
98 return deferred.promise;
99 };
100
101 hostsManager.createHost = function(hostData, ws) {
102 var deferred = $q.defer();
103 var self = this;
104 var host = new Host(hostData);
105 host.save(ws)
106 .then(function(saved_host) {
107 deferred.resolve(saved_host);
108 })
109 .catch(function() {
110 deferred.reject("Error: host couldn't be saved");
111 })
112
113 return deferred.promise;
114 };
115
116 hostsManager.updateHost = function(host, hostData, ws) {
117 var deferred = $q.defer(),
118 self = this;
119
120 host.update(hostData, ws)
121 .then(function(host) {
122 deferred.resolve(host);
123 })
124 .catch(function() {
125 deferred.reject("Error updating host");
126 });
127 return deferred.promise;
128 };
129
130 var get_count = function(ws, object) {
131 var deferred = $q.defer();
132 ServerAPI.getWorkspaceSummary(ws).then(
133 function(summary) {
134 deferred.resolve(summary[object])
135 }, function() {
136 deferred.reject("Unable to get vulnerability count")
137 }
138 )
139 return deferred.promise;
140 };
141
142
143 hostsManager.getAllVulnsCount = function(ws) {
144 return this.get_count(ws, 'total_vulns');
145 };
146
147 hostsManager.getAllServicesCount = function(ws) {
148 return this.get_count(ws, 'services');
149 };
150
151 hostsManager.getTools = function(hid, ws) {
152 var deferred = $q.defer();
153 ServerAPI.getTools(hid, ws).then(
154 function(result) {
155 deferred.resolve(result.data.tools)
156 }, function() {
157 deferred.reject("Unable to get tools for selected host")
158 }
159 )
160 return deferred.promise;
161 };
162
163 return hostsManager;
164 }]);
+0
-28
faraday/server/www/scripts/index/controllers/indexCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('indexCtrl',
6 ['$scope', '$uibModal', 'indexFact', 'BASEURL',
7 function($scope, $uibModal, indexFact, BASEURL) {
8 indexFact.getConf().then(function(conf) {
9 $scope.version = conf.data.ver;
10
11 var osint = conf.data.osint;
12 osint.prefix = osint.prefix || "/search?query=";
13 osint.suffix = osint.suffix || "";
14 if(!osint.use_external_icon)
15 osint.icon = "images/" + osint.icon + ".png";
16 $scope.osint = osint;
17 });
18
19 $scope.about = function() {
20 $scope.base_url = BASEURL;
21 var modal = $uibModal.open({
22 templateUrl: 'scripts/commons/partials/modalAbout.html',
23 scope: $scope
24 });
25 };
26
27 }]);
+0
-14
faraday/server/www/scripts/index/providers/index.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('indexFact', ['$http', 'BASEURL', function($http, BASEURL) {
6 var indexFact = {};
7
8 indexFact.getConf = function() {
9 return $http.get(BASEURL + '_api/config');
10 };
11
12 return indexFact;
13 }]);
+0
-208
faraday/server/www/scripts/licenses/controllers/licenses.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('licensesCtrl',
6 ['$scope', '$filter', '$q', '$uibModal', 'commonsFact', 'licensesManager',
7 function($scope, $filter, $q, $uibModal, commonsFact, licensesManager) {
8
9 $scope.expiration_month = false;
10 $scope.licenses = [];
11 $scope.loaded_licenses = false;
12 $scope.reverse;
13 $scope.search;
14 $scope.selectall_licenses;
15 $scope.sort_field;
16 $scope.store;
17
18 var init = function() {
19 $scope.store = "https://appstore.faradaysec.com/search/?q=";
20
21 // table stuff
22 $scope.selectall_licenses = false;
23 $scope.sort_field = "end";
24 $scope.reverse = true;
25
26 licensesManager.get()
27 .then(function() {
28 $scope.licenses = licensesManager.licenses;
29 $scope.loaded_licenses = true;
30
31 $scope.expiration_month = $scope.isExpirationMonth($scope.licenses);
32 }, function(message) {
33 commonsFact.errorDialog(message);
34 });
35
36 $scope.$watch(function() {
37 return licensesManager.licenses;
38 }, function(newVal, oldVal) {
39 $scope.licenses = licensesManager.licenses;
40 $scope.loaded_licenses = true;
41 $scope.expiration_month = $scope.isExpirationMonth(newVal);
42 }, true);
43 };
44
45 $scope.almostExpired = function(end) {
46 var end_date = new Date(end),
47 today = new Date();
48 return (end_date.getMonth() == today.getMonth()) && (end_date.getYear() == today.getYear());
49 };
50
51 $scope.isExpirationMonth = function(licenses) {
52 return licenses.some(function(elem, index, array) {
53 return $scope.almostExpired(elem.end);
54 });
55 };
56
57 $scope.remove = function(ids) {
58 var confirmations = [];
59
60 ids.forEach(function(id) {
61 var deferred = $q.defer();
62
63 licensesManager.delete(id, $scope.workspace)
64 .then(function(resp) {
65 deferred.resolve(resp);
66 }, function(message) {
67 deferred.reject(message);
68 });
69
70 confirmations.push(deferred);
71 });
72
73 return $q.all(confirmations);
74 };
75
76 $scope.delete = function() {
77 var selected = $scope.selectedLicenses();
78
79 if(selected.length == 0) {
80 $uibModal.open({
81 templateUrl: 'scripts/commons/partials/modalKO.html',
82 controller: 'commonsModalKoCtrl',
83 size: 'sm',
84 resolve: {
85 msg: function() {
86 return 'No licenses were selected to delete';
87 }
88 }
89 });
90 } else {
91 var message = "A license will be deleted";
92 if(selected.length > 1) {
93 message = selected.length + " licenses will be deleted";
94 }
95 message = message.concat(". This operation cannot be undone. Are you sure you want to proceed?");
96 $uibModal.open({
97 templateUrl: 'scripts/commons/partials/modalDelete.html',
98 controller: 'commonsModalDelete',
99 size: 'lg',
100 resolve: {
101 msg: function() {
102 return message;
103 }
104 }
105 }).result.then(function() {
106 $scope.remove(selected);
107 }, function() {
108 //dismised, do nothing
109 });
110 }
111 };
112
113 $scope.insert = function(data) {
114 licensesManager.create(data)
115 .catch(function(message) {
116 commonsFact.errorDialog(message);
117 });
118 };
119
120 $scope.new = function() {
121 var modal = $uibModal.open({
122 templateUrl: 'scripts/licenses/partials/modalNew.html',
123 backdrop : 'static',
124 controller: 'licensesModalNew',
125 size: 'lg',
126 resolve: {}
127 });
128
129 modal.result
130 .then(function(data) {
131 $scope.insert(data);
132 });
133 };
134
135 $scope.update = function(license, data) {
136 licensesManager.update(license, data)
137 .catch(function(message) {
138 commonsFact.errorDialog(message);
139 });
140 };
141
142 $scope.edit = function() {
143 if($scope.selectedLicenses().length == 1) {
144 var license = $scope.selectedLicenses()[0];
145 var modal = $uibModal.open({
146 templateUrl: 'scripts/licenses/partials/modalEdit.html',
147 backdrop : 'static',
148 controller: 'licensesModalEdit',
149 size: 'lg',
150 resolve: {
151 license: function() {
152 return license;
153 }
154 }
155 });
156
157 modal.result.then(function(data) {
158 $scope.update(license, data);
159 });
160 } else {
161 commonsFact.errorDialog("No licenses were selected to edit.");
162 }
163 };
164
165 $scope.selectedLicenses = function() {
166 var selected = [];
167
168 $filter('filter')($scope.licenses, $scope.search).forEach(function(license) {
169 if(license.selected === true) {
170 selected.push(license);
171 }
172 });
173
174 return selected;
175 };
176
177 $scope.checkAll = function() {
178 $scope.selectall_licenses = !$scope.selectall_licenses;
179
180 tmp_licenses = $filter('filter')($scope.licenses, $scope.search);
181 tmp_licenses.forEach(function(license) {
182 license.selected = $scope.selectall_licenses;
183 });
184 };
185
186 // toggles sort field and order
187 $scope.toggleSort = function(field) {
188 $scope.toggleSortField(field);
189 $scope.toggleReverse();
190 };
191
192 // toggles column sort field
193 $scope.toggleSortField = function(field) {
194 $scope.sort_field = field;
195 };
196
197 // toggle column sort order
198 $scope.toggleReverse = function() {
199 $scope.reverse = !$scope.reverse;
200 };
201
202 $scope.clearSearch = function() {
203 $scope.search = '';
204 };
205
206 init();
207 }]);
+0
-38
faraday/server/www/scripts/licenses/controllers/modalEdit.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('licensesModalEdit',
6 ['$scope', '$modalInstance', 'License', 'license',
7 function($scope, $modalInstance, License, license) {
8
9 $scope.data;
10 $scope.openedStart;
11 $scope.openedEnd;
12
13 var init = function() {
14 $scope.data = new License;
15 $scope.data.set(license);
16
17 $scope.data.end = new Date(license.end);
18 $scope.data.start = new Date(license.start);
19 };
20
21 $scope.ok = function() {
22 $modalInstance.close($scope.data);
23 };
24
25 $scope.open = function($event, isStart) {
26 $event.preventDefault();
27 $event.stopPropagation();
28
29 if(isStart) $scope.openedStart = true; else $scope.openedEnd = true;
30 };
31
32 $scope.cancel = function() {
33 $modalInstance.dismiss('cancel');
34 };
35
36 init();
37 }]);
+0
-51
faraday/server/www/scripts/licenses/controllers/modalNew.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('licensesModalNew',
6 ['$scope', '$modalInstance', 'License', 'licensesManager',
7 function($scope, $modalInstance, License, licensesManager) {
8
9 $scope.data;
10 $scope.other = false;
11 $scope.other_product;
12 $scope.products;
13
14 var init = function() {
15 $scope.data = new License;
16
17 $scope.products = licensesManager.products;
18
19 $scope.$watch(function() {
20 return $scope.data.product;
21 }, function(newVal, oldVal) {
22 if(newVal == "Other") {
23 $scope.other = true;
24 } else if(oldVal == "Other") {
25 $scope.other = false;
26 }
27 }, true);
28 };
29
30 $scope.open = function($event, isStart) {
31 $event.preventDefault();
32 $event.stopPropagation();
33
34 if(isStart) $scope.openedStart = true; else $scope.openedEnd = true;
35 };
36
37 $scope.ok = function() {
38 if($scope.other) {
39 $scope.data.product = $scope.other_product;
40 }
41
42 $modalInstance.close($scope.data);
43 };
44
45 $scope.cancel = function() {
46 $modalInstance.dismiss('cancel');
47 };
48
49 init();
50 }]);
+0
-87
faraday/server/www/scripts/licenses/partials/list.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion ">
5 <div class="faraday-header-border-fix">
6 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
7 <div id="reports-main" class="fila ">
8 <div class="reports col-md-12 col-sm-12 col-xs-12">
9 <div class="button-control justify-flex-start col-md-12 col-sm-12 col-xs-12">
10 <div class="control-wrapper control-new">
11 <button type="button" class="btn btn-success btn-new" title="New license" ng-click="new()">
12 New
13 </button>
14 </div>
15 <div class="control-wrapper control-edit">
16 <button type="button" class="btn btn-default edit" title="Edit selected licenses" ng-disabled="selectedLicenses().length > 1" ng-click="edit()">
17 <img src="images/icon-toolbar-edit.svg" class="edit-icon" />
18 </button>
19 </div>
20 <div class="control-wrapper">
21 <button type="button" class="btn btn-default " title="Delete selected licenses" ng-click="delete()">
22 <img src="images/icon-toolbar-delete.svg" class="delete-icon" />
23 </button>
24 </div>
25 <div class="control-wrapper search-wrapper">
26 <form role="form">
27 <div class="form-group">
28 <div class="input-group">
29 <span class="input-group-addon glyphicon-btn glyphicon glyphicon-remove" ng-if="search" ng-click="clearSearch()"></span>
30 <input type="text" class="form-control" placeholder="Enter keywords" ng-change="currentPage = 1" ng-model="search" />
31 <span class="input-group-addon glyphicon-btn">
32 <img src="images/icon-toolbar-searchbar-loupe.svg" class="search-icon" />
33 </span>
34 </div>
35 </div>
36 </form>
37 </div>
38 </div>
39 <div class="reports col-md-12 col-sm-12 cols-xs-12" ng-if="expiration_month == true">
40 <h4><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> The licenses marked in dark red are about to expire</h4>
41 </div>
42 <table class="table-v3 licenses-list table table-responsive">
43 <thead>
44 <tr class="ui-grid-header">
45 <th class="ui-grid-cell-contents ui-grid-header-cell hosts-list-checkall"><input type="checkbox" ng-model="selectall" ng-click="checkAll()"/></th>
46 <th class="ui-grid-cell-contents ui-grid-header-cell">
47 <span ng-click="toggleSort('product')">Product</span>
48 </th>
49 <th class="ui-grid-cell-contents ui-grid-header-cell">
50 <span ng-click="toggleSort('lictype')">Type</span>
51 </th>
52 <th class="ui-grid-cell-contents ui-grid-header-cell">
53 <span ng-click="toggleSort('notes')">Notes</span>
54 </th>
55 <th class="ui-grid-cell-contents ui-grid-header-cell">
56 <span ng-click="toggleSort('start')">Start date</span>
57 </th>
58 <th class="ui-grid-cell-contents ui-grid-header-cell">
59 <span ng-click="toggleSort('end')">End date</span>
60 </th>
61 <th class="ui-grid-cell-contents ui-grid-header-cell"></th>
62 </tr>
63 </thead>
64 <tbody>
65 <tr ng-repeat="license in licenses | filter:search | orderBy:sort_field:reverse"
66 selection-model selection-model-type="checkbox"
67 selection-model-mode="multiple-additive"
68 selection-model-selected-class="multi-selected"
69 selection-model-on-change="selectedLicenses()"
70 ng-class="{'almost-expired': almostExpired(license.end)}">
71 <td class="ui-grid-cell-contents checkbox-select"><input type="checkbox" name="{{license._id}}"/></td>
72 <td class="ui-grid-cell-contents">{{license.product}}</td>
73 <td class="ui-grid-cell-contents">{{license.lictype}}</td>
74 <td class="ui-grid-cell-contents">{{license.notes}}</td>
75 <td class="ui-grid-cell-contents">{{license.start | date:'MM/dd/yyyy'}}</td>
76 <td class="ui-grid-cell-contents">{{license.end|date:'MM/dd/yyyy'}}</td>
77 <td class="ui-grid-cell-contents"><i class="fa fa-history" aria-hidden="true">
78 <a ng-href="{{store}}{{license.product}}" target="_blank">renew</a>
79 </i></td>
80 </tr>
81 </tbody>
82 </table><!-- #licenses -->
83 </div><!-- .reports -->
84 </div><!-- #reports-main -->
85 </div><!-- .right-main -->
86 </section><!-- #main -->
+0
-75
faraday/server/www/scripts/licenses/partials/modalEdit.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" ng-submit="ok()" novalidate>
5 <div class="modal-header">
6 <div class="modal-button">
7 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid || form.start.$viewValue == '' || form.end.$viewValue == '' || (data.start > data.end)">OK</button>
8 <button type="button" class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">Edit {{data.product}} license</h3>
11 </div>
12 <div class="modal-body">
13 <div class="form-horizontal">
14 <div class="form-group">
15 <div class="col-md-12">
16 <label for="lictype">Type</label>
17 <input type="text" class="form-control" name="lictype" placeholder="Type" ng-model="data.lictype" />
18 </div>
19 </div><!-- .form-group -->
20 <div class="form-group">
21 <div class="col-md-12">
22 <label for="notes">Notes</label>
23 <textarea class="form-control" name="notes" placeholder="Notes" ng-model="data.notes"></textarea>
24 </div>
25 </div><!-- .form-group -->
26 <div class="form-group">
27 <div class="col-md-6 datepicker">
28 <label for="start">Start Date *</label>
29 <p class="input-group" ng-class="{'has-error': form.start.$touched && (data.start == undefined || data.start == '')}">
30 <input type="text" name="start" class="form-control" uib-datepicker-popup="MM/dd/yyyy" ng-model="data.start" is-open="openedStart" close-text="Close" placeholder="Start Date" />
31 <span class="input-group-btn">
32 <button type="button" class="btn btn-default" ng-click="open($event,true)">
33 <i class="glyphicon glyphicon-calendar"></i>
34 </button>
35 </span>
36 </p>
37 <p class="help-block normal-size" ng-class="{'has-error': form.start.$touched && !(data.start == undefined || data.start == '') && form.start.$invalid}">
38 <span class="help-block">Date format mm/dd/yyyy</span>
39 </p>
40 <p class="has-error" ng-show="form.start.$touched && (data.start == undefined || data.start == '')">
41 <span class="help-block">Start date is required</span>
42 </p>
43 </div>
44 <div class="col-md-6 datepicker">
45 <label for="end">End Date *</label>
46 <p class="input-group" ng-class="{'has-error': (form.end.$touched && (form.end.$invalid || form.end.$viewValue == '')) || (data.start > data.end && form.end.$viewValue != '')}">
47 <input type="text" name="end" class="form-control" uib-datepicker-popup="MM/dd/yyyy" ng-model="data.end" is-open="openedEnd" min-date="data.start" close-text="Close" placeholder="End Date" />
48 <span class="input-group-btn">
49 <button type="button" class="btn btn-default" ng-click="open($event)">
50 <i class="glyphicon glyphicon-calendar"></i>
51 </button>
52 </span>
53 </p>
54 <p class="help-block normal-size" ng-class="{'has-error': form.end.$touched && form.end.$invalid}">
55 <span class="help-block">Date format mm/dd/yyyy</span>
56 </p>
57 <p class="has-error" ng-show="form.end.$touched && form.end.$viewValue == ''">
58 <span class="help-block">End date is required</span>
59 </p>
60 <p class="has-error" ng-show="data.start > data.end && form.end.$viewValue != ''">
61 <span class="help-block">End date must be greater than start date</span>
62 </p>
63 </div>
64 </div><!-- .form-group -->
65 <p>All fields marked * are required</p>
66 </div><!-- .form-horizontal -->
67 </div><!-- .modal-body -->
68 <div class="modal-footer">
69 <div class="modal-button">
70 <button type="button" class="btn btn-danger" ng-click="cancel()">Cancel</button>
71 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid || form.start.$viewValue == '' || form.end.$viewValue == '' || (data.start > data.end)">OK</button>
72 </div>
73 </div>
74 </form>
+0
-92
faraday/server/www/scripts/licenses/partials/modalNew.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <div class="modal-button">
7 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid || (data.product == 'Other' && other_product == undefined) || (data.start > data.end)">OK</button>
8 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">New license</h3>
11 </div>
12 <div class="modal-body">
13 <div class="form-horizontal">
14 <div class="form-group" ng-class="{'has-error': form.product.$touched && form.product.$invalid}">
15 <div class="col-md-6">
16 <label for="product">Product *</label>
17 <select name="product" class="form-control" ng-model="data.product" ng-options="product for product in products" required>
18 <option value=""></option>
19 </select>
20 </div><!-- .col-md-6 -->
21 <div class="col-md-3" ng-show="other" ng-class="{'has-error': data.product == 'Other' && other_product == undefined}">
22 <label for="other-product">Custom product</label>
23 <input type="text" name="other-product" class="form-control" ng-model="other_product" placeholder="Custom product name" />
24 </div><!-- .col-md-3 -->
25 <div class="col-md-12">
26 <p class="has-error" ng-show="(form.product.$touched && form.product.$error.required) || (data.product == 'Other' && other_product == undefined)">
27 <span class="help-block">Product name is required</span>
28 </p>
29 </div><!-- .col-md-12 -->
30 </div><!-- .form-group -->
31 <div class="form-group">
32 <div class="col-md-12">
33 <label for="lictype">Type</label>
34 <input type="text" class="form-control" name="lictype" placeholder="Type" ng-model="data.lictype" />
35 </div>
36 </div><!-- .form-group -->
37 <div class="form-group">
38 <div class="col-md-12">
39 <label for="notes">Notes</label>
40 <textarea class="form-control" name="notes" placeholder="Notes" ng-model="data.notes"></textarea>
41 </div>
42 </div><!-- .form-group -->
43 <div class="form-group">
44 <div class="col-md-6 datepicker">
45 <label for="start">Start Date *</label>
46 <p class="input-group" ng-class="{'has-error': form.start.$touched && form.start.$invalid}">
47 <input type="text" name="start" class="form-control" uib-datepicker-popup="MM/dd/yyyy" ng-model="data.start" is-open="openedStart" close-text="Close" placeholder="Start Date" required />
48 <span class="input-group-btn">
49 <button type="button" class="btn btn-default" ng-click="open($event,true)">
50 <i class="glyphicon glyphicon-calendar"></i>
51 </button>
52 </span>
53 </p>
54 <p class="help-block normal-size" ng-class="{'has-error': form.start.$touched && !form.start.$error.required && form.start.$invalid}">
55 <span class="help-block">Date format mm/dd/yyyy</span>
56 </p>
57 <p class="has-error" ng-show="form.start.$touched && form.start.$error.required">
58 <span class="help-block">Start date is required</span>
59 </p>
60 </div>
61 <div class="col-md-6 datepicker">
62 <label for="end">End Date *</label>
63 <p class="input-group" ng-class="{'has-error': (form.end.$touched && form.end.$invalid) || (data.start > data.end)}">
64 <input type="text" name="end" class="form-control" uib-datepicker-popup="MM/dd/yyyy" ng-model="data.end" is-open="openedEnd" min-date="data.start" close-text="Close" placeholder="End Date" required />
65 <span class="input-group-btn">
66 <button type="button" class="btn btn-default" ng-click="open($event)">
67 <i class="glyphicon glyphicon-calendar"></i>
68 </button>
69 </span>
70 </p>
71 <p class="help-block normal-size" ng-class="{'has-error': form.end.$touched && !form.end.$error.required && form.end.$invalid}">
72 <span class="help-block">Date format mm/dd/yyyy</span>
73 </p>
74 <p class="has-error" ng-show="form.end.$touched && form.end.$error.required">
75 <span class="help-block">End date is required</span>
76 </p>
77 <p class="has-error" ng-show="data.start > data.end">
78 <span class="help-block">End date must be greater than start date</span>
79 </p>
80 </div>
81 </div><!-- .form-group -->
82 <p>All fields marked * are required</p>
83 </div><!-- .form-horizontal -->
84 </div><!-- .modal-body -->
85 <div class="modal-footer">
86 <div class="modal-button">
87 <button class="btn btn-success" ng-disabled="form.$invalid || (data.product == 'Other' && other_product == undefined) || (data.start > data.end)" ng-click="ok()">OK</button>
88 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
89 </div>
90 </div>
91 </form>
+0
-108
faraday/server/www/scripts/licenses/providers/license.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('License', ['APIURL', '$http', '$q',
6 function(APIURL, $http, $q) {
7 function License(data) {
8 var now = new Date(),
9 date = now.getTime() / 1000.0;
10
11 this._id = "";
12 this._rev = "";
13 this.end = "";
14 this.lictype = "";
15 this.metadata = {
16 update_time: date,
17 update_user: "",
18 update_action: 0,
19 creator: "UI Web",
20 create_time: date,
21 update_controller_action: "UI Web New",
22 owner: ""
23 };
24 this.notes = "";
25 this.product = "";
26 this.start = "";
27 this.type = "License";
28
29 if(data) {
30 if(data.product === undefined || data.product === "") {
31 throw new Error("Unable to create License without a product name");
32 }
33 this.set(data);
34 }
35 };
36
37 License.prototype = {
38 public_properties: [
39 'end', 'lictype', 'notes', 'product', 'start'
40 ],
41 set: function(data) {
42 var self = this;
43
44 // new license
45 if(data._id != undefined) {
46 self._id = data._id;
47 if(data._rev !== undefined) self._rev = data._rev;
48 if(data.metadata !== undefined) self.metadata = data.metadata;
49 }
50
51 self.public_properties.forEach(function(property) {
52 if(data[property] !== undefined) self[property] = data[property];
53 });
54 },
55 remove: function() {
56 var deferred = $q.defer(),
57 self = this;
58
59 var url = APIURL + "licenses/" + self._id + "/";
60
61 $http.delete(url)
62 .then(function(resp) {
63 deferred.resolve(resp);
64 }, function(data, status, headers, config) {
65 deferred.reject("Unable to delete License from database. " + status);
66 });
67
68 return deferred.promise;
69 },
70 update: function(data) {
71 var deferred = $q.defer(),
72 self = this;
73 var url = APIURL + "licenses/" + self._id + "/";
74
75 $http.put(url, data)
76 .then(function(res) {
77 self.set(data);
78 self._rev = res.rev;
79 deferred.resolve(self);
80 }, function(res) {
81 deferred.reject("Unable to update the License. " + res.data.reason);
82 });
83
84 return deferred.promise;
85 },
86 save: function() {
87 var deferred = $q.defer(),
88 self = this;
89
90 delete this._id;
91 delete this._rev;
92
93 $http.post(APIURL + "licenses/", self)
94 .then(function(data) {
95 self._id = data._id;
96 self._rev = data.rev;
97 deferred.resolve(self);
98 }, function(res) {
99 deferred.reject("Unable to save the License. " + res.data.reason);
100 });
101
102 return deferred.promise;
103 }
104 };
105
106 return License;
107 }]);
+0
-123
faraday/server/www/scripts/licenses/providers/licenses.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('licensesManager',
6 ['License', 'APIURL', '$http', '$q',
7 function(License, APIURL, $http, $q) {
8 var licensesManager = {};
9
10 licensesManager.licenses = [];
11
12 licensesManager.products = [
13 "Faraday",
14 "Metasploit",
15 "Nessus",
16 "Acunetix",
17 "Burp",
18 "Canvas",
19 "Maltego",
20 "Core Impact",
21 "Nexpose",
22 "Netsparker",
23 "Retina",
24 "Onapsis Security Platform",
25 "Qualys",
26 "Fortify",
27 "Checkmarx",
28 "Other"
29 ];
30
31 licensesManager.create = function(data) {
32 var deferred = $q.defer(),
33 self = this;
34
35 try {
36 var license = new License(data);
37
38 license.save()
39 .then(function(resp) {
40 licensesManager.get()
41 .then(function() {
42 deferred.resolve(self);
43 }, function(reason) {
44 deferred.reject(reason);
45 });
46 }, function(reason) {
47 deferred.reject(reason);
48 });
49 } catch(e) {
50 deferred.reject(e.name + ": " + e.message);
51 }
52
53 return deferred.promise;
54 };
55
56 licensesManager.delete = function(license) {
57 var deferred = $q.defer(),
58 self = this;
59
60 license.remove()
61 .then(function() {
62 licensesManager.get()
63 .then(function(resp) {
64 deferred.resolve(resp);
65 }, function(reason) {
66 deferred.reject(reason);
67 });
68 }, function(err) {
69 deferred.reject(err);
70 });
71
72 return deferred.promise
73 };
74
75 licensesManager.get = function() {
76 var deferred = $q.defer(),
77 self = this;
78
79 var url = APIURL + "licenses/";
80
81 $http.get(url)
82 .then(function(res) {
83 var licenses = [];
84 res.data.forEach(function(row) {
85 try {
86 var new_lic = new License(row);
87 licenses.push(new_lic);
88 } catch(e) {
89 console.log(e.stack);
90 }
91 });
92
93 angular.copy(licenses, self.licenses);
94 deferred.resolve(licenses);
95 }, function(data, status, headers, config) {
96 deferred.reject("Unable to retrieve Licenses. " + status);
97 });
98
99 return deferred.promise;
100 };
101
102 licensesManager.update = function(license, data) {
103 var deferred = $q.defer(),
104 self = this;
105
106 license.update(data)
107 .then(function() {
108 licensesManager.get()
109 .then(function(resp) {
110 deferred.resolve(resp);
111 }, function(reason) {
112 deferred.reject(reason);
113 });
114 }, function(err) {
115 deferred.reject(err);
116 });
117
118 return deferred.promise;
119 };
120
121 return licensesManager;
122 }]);
+0
-151
faraday/server/www/scripts/navigation/controllers/navigationCtrl.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('navigationCtrl', [
6 '$scope',
7 '$http',
8 '$route',
9 '$routeParams',
10 '$cookies',
11 '$location',
12 '$interval',
13 '$uibModal',
14 'configSrv',
15 'workspacesFact',
16 'Notification',
17 '$rootScope',
18 function ($scope,
19 $http,
20 $route,
21 $routeParams,
22 $cookies,
23 $location,
24 $interval,
25 $uibModal,
26 configSrv,
27 workspacesFact,
28 Notification,
29 $rootScope) {
30
31 $scope.workspace = "";
32
33 if(!$scope.component)
34 $scope.component = "";
35
36 if(!$scope.timer)
37 $scope.timer;
38
39 var componentsNeedsWS = ["dashboard","status","hosts"];
40
41 $scope.checkNews = function() {
42 $http.get('https://portal.faradaysec.com/api/v1/license_check?version=' + configSrv.faraday_version + '&key=white').then(function(response) {
43 try{
44 response.data['news'].forEach(function(element) {
45
46 var childScope = $scope.$new();
47 childScope.url = element['url'];
48
49 Notification.info({
50 message: element['description'],
51 title: 'x',
52 scope: childScope,
53 delay: 'ALWAYS',
54 templateUrl: 'scripts/navigation/partials/notification.html'});
55 }, this);
56 }
57 catch(error){
58 console.log("Can't connect to faradaysec.com");
59 }
60
61 }, function() {
62 console.log("Can't connect to faradaysec.com");
63 });
64 };
65
66 configSrv.promise.then(function() {
67 $scope.timer = $interval($scope.checkNews, 43200000);
68 $scope.checkNews();
69 });
70
71 $scope.$on('$destroy', function() {
72 $interval.cancel($scope.timer);
73 });
74
75 $rootScope.$on('$routeChangeSuccess', function() {
76 if(componentsNeedsWS.indexOf($location.path().split("/")[1]) != -1 && $routeParams.wsId !== undefined) {
77 workspacesFact.list().then(function(wss) {
78 $scope.wss = wss;
79 });
80
81 workspacesFact.exists($routeParams.wsId).then(function(response){
82 // ok! workspace was found.
83 }, function(response){
84 if(response.status === 404) {
85 $scope.modalWsNoExist();
86 }
87 });
88 }
89 $scope.updateWorkspace();
90 $scope.updateComponent();
91 });
92
93 $scope.modalWsNoExist = function() {
94 $scope.modalInstance = $uibModal.open({
95 templateUrl: 'scripts/navigation/partials/wsNo-exist.html',
96 scope: $scope,
97 backdrop: 'static',
98 keyboard: false
99 });
100 };
101
102 $scope.cancel = function() {
103 $scope.modalInstance.dismiss('cancel');
104 };
105
106 $scope.updateWorkspace = function() {
107 if($routeParams.wsId != undefined) {
108 $scope.workspace = $routeParams.wsId;
109 $cookies.put('currentUrl', $location.path());
110 }
111 };
112
113 $scope.updateComponent = function() {
114 if($location.path() == "") {
115 $scope.component = "home";
116 } else {
117 $scope.component = $location.path().split("/")[1];
118 }
119 $cookies.put('currentComponent', $scope.component);
120 };
121
122 $scope.showNavigation = function() {
123 var noNav = ["", "home", "login", "index"];
124 return noNav.indexOf($scope.component) < 0;
125 };
126
127 $scope.loadCurrentWorkspace = function() {
128 var pos = -1;
129
130 if($cookies.get('currentUrl') != undefined) {
131 pos = $cookies.get('currentUrl').indexOf('ws/');
132 }
133
134 if($routeParams.wsId != undefined) {
135 $scope.workspace = $routeParams.wsId;
136 } else if(pos >= 0) {
137 $scope.workspace = $cookies.get('currentUrl').slice(pos+3);
138 }
139 };
140
141 $scope.$on('handleChangeWSBroadcast', function () {
142 $scope.workspace = workspacesFact.workspace;
143 });
144
145 $scope.loadCurrentWorkspace();
146
147 // if(navigator.userAgent.toLowerCase().indexOf('iceweasel') > -1) {
148 // $scope.isIceweasel = "Your browser is not supported, please use Firefox or Chrome";
149 // }
150 }]);
+0
-72
faraday/server/www/scripts/navigation/partials/leftBar.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3 <aside class="left-nav" ng-if="showNavigation()">
4 <div class="head">
5 <a href="#/" class="ws-dashboard" uib-tooltip="{{version}}" tooltip-placement="bottom">
6 <img class="logo animated fadeInDown" src="images/logo-faraday-blanco.svg" alt="Faraday home | WS Dashboard"/>
7 </a>
8 </div>
9 <nav>
10 <ul>
11 <li>
12 <a href="#/dashboard/ws/{{workspace}}" class="ws-dashboard" ng-class="{'active' : component == 'dashboard'}" style="color: #ffffff !important" uib-tooltip="Dashboard" tooltip-placement="right">
13 <img src="images/ico-dashboard-menu.svg" alt="Dashboard"/>
14 </a>
15 </li>
16 <li>
17 <a href="#/status/ws/{{workspace}}" class="status-report" ng-class="{'active' : component == 'status'}" style="color: #ffffff !important" uib-tooltip="Status Report" tooltip-placement="right">
18 <img src="images/ico-status-menu.svg" alt="Status Report"/>
19 </a>
20 </li>
21 <li>
22 <a href="#/hosts/ws/{{workspace}}" class="workspaces" ng-class="{'active' : component == 'hosts'}" style="color: #ffffff !important" uib-tooltip="Hosts" tooltip-placement="right">
23 <img src="images/ico-hosts-menu.svg" alt="Hosts"/>
24 </a>
25 </li>
26 <li>
27 <a href="#/credentials/ws/{{workspace}}" class="workspaces" ng-class="{'active' : component == 'credentials'}" style="color: #ffffff !important" uib-tooltip="Credentials" tooltip-placement="right">
28 <img src="images/ico-credentials-menu.svg" alt="Credentials"/>
29 </a>
30 </li>
31 <li>
32 <a href="#/executive" class="executive-report" ng-class="{'active' : component == 'executive'}" style="color: #ffffff !important" uib-tooltip="Executive Report" tooltip-placement="right">
33 <img src="images/ico-executive-menu.svg" alt="Executive Report"/>
34 </a>
35 </li>
36 <li>
37 <a href="#/taskgroup" class="executive-report" ng-class="{'active' : component == 'taskgroup'}" style="color: #ffffff !important" uib-tooltip="Tasks" tooltip-placement="right">
38 <img src="images/ico-tasks-menu.svg" alt="Tasks"/>
39 </a>
40 </li>
41 <li>
42 <a href="#/comparison" class="executive-report" ng-class="{'active' : component == 'comparison'}" style="color: #ffffff !important" uib-tooltip="Workspaces Comparison" tooltip-placement="right">
43 <img src="images/ico-workspace-comparison-menu.svg" alt="Workspaces Comparison"/>
44 </a>
45 </li>
46 <li>
47 <a href="#/webshell" class="executive-report" ng-class="{'active' : component == 'webshell'}" style="color: #ffffff !important" uib-tooltip="Web Shell" tooltip-placement="right">
48 <img src="images/ico-web-shell-menu.svg" alt="Webshell"/>
49 </a>
50 </li>
51 <li>
52 <a href="#/vulndb" class="status-report" ng-class="{'active' : component == 'vulndb'}" style="color: #ffffff !important" uib-tooltip="Vulnerability Templates" tooltip-placement="right">
53 <img src="images/ico-vulnerability-templates-menu.svg" alt="Vulnerability Templates"/>
54 </a>
55 </li>
56 <li>
57 <a href="#/data_analysis" class="status-report" ng-class="{'active' : component == 'data_analysis'}" style="color: #ffffff !important" uib-tooltip="Data Analysis" tooltip-placement="right">
58 <img src="images/ico-data-analysis-menu.svg" alt="Data Analysis"/>
59 </a>
60 </li>
61 </ul>
62 </nav>
63 <div ng-show="isIceweasel" class="alert alert-danger alert-dismissible">
64 <button type="button" class="close" data-dismiss="alert">
65 <span aria-hidden="true">&times;</span>
66 <span class="sr-only">Close</span>
67 </button>
68 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
69 <span ng-bind="isIceweasel"></span>
70 </div>
71 </aside>
+0
-6
faraday/server/www/scripts/navigation/partials/notification.html less more
0 <div class="ui-notification">
1 <h3 ng-show="title" ng-bind="title" align="right"></h3>
2 <div class="message">
3 <a ng-href="{{url}}" target="_blank">{{message}}</a>
4 </div>
5 </div>
+0
-35
faraday/server/www/scripts/navigation/partials/topBar.html less more
0 <nav class="navbar navbar-expand-lg navbar-light bg-light" style="margin-top: 20px; margin-bottom: 0px;" ng-if="showNavigation()">
1 <div class="collapse navbar-collapse">
2 <ul class="navbar-nav mr-auto">
3 <li class="nav-item">
4 <a href="#/dashboard/ws/{{workspace}}" class="ws-dashboard" ng-class="{'navigation-active' : component == 'dashboard'}" style="color: black !important; font-weight: bold; font-size: 15px;">
5 DASHBOARD
6 </a>
7 </li>
8 <li class="nav-item">
9 <a href="#/status/ws/{{workspace}}" class="status-report" ng-class="{'navigation-active' : component == 'status' || component == 'hosts' || component == 'credentials' || component =='taskgroup' || component =='host'}" style="color: black !important; font-weight: bold; font-size: 15px;">
10 MANAGE
11 </a>
12 </li>
13 <li class="nav-item">
14 <a href="#/executive" class="executive-report" ng-class="{'navigation-active' : component == 'executive' || component == 'comparison' || component == 'data_analysis'}" style="color: black !important; font-weight: bold; font-size: 15px;">
15 INSIGHT
16 </a>
17 </li>
18 <li class="nav-item">
19 <a href="#/scheduling" class="executive-report" ng-class="{'navigation-active' : component == 'scheduling' || component == 'vulndb'}" style="color: black !important; font-weight: bold; font-size: 15px;">
20 OPERATIONS
21 </a>
22 </li>
23 <!--<li class="nav-item">
24 <a href="#/taskgroup" class="executive-report" ng-class="{'navigation-active' : component == 'taskgroup'}" style="color: black !important; font-weight: bold; font-size: 15px;">
25 TASKS
26 </a>
27 </li>
28 <li class="nav-item">
29 <a href="#/vulndb" class="status-report" ng-class="{'navigation-active' : component == 'vulndb'}" style="color: black !important; font-weight: bold; font-size: 15px;">
30 KB
31 </a>
32 </li>-->
33 </div>
34 </nav>
+0
-12
faraday/server/www/scripts/navigation/partials/wsNo-exist.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header">
5 <h3 class="modal-title"><p>This workspace does not exist.</p></h3><h4><p></This> Select one of the list or create a <a ng-click="cancel()" href="#/workspaces">new</a> one.</p></h4>
6 </div>
7 <div class="modal-body">
8 <ul class="ws-list">
9 <li ng-repeat="ws in wss"><a href="#/{{component}}/ws/{{ws}}" ng-click="cancel()"><span ng-class-even="'label label-unclassified'" ng-class-odd="'label label-high'" style="text-transform: uppercase">{{ws}}</span></a></li>
10 </ul>
11 </div><!-- .modal-body -->
+0
-84
faraday/server/www/scripts/notes/providers/notes.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('notesFact', ['BASEURL', '$http', function(BASEURL, $http) {
6 var notesFact = {};
7
8 notesFact.getNotes = function(ws, parent) {
9 var noteIds = [];
10 var notes = [];
11 var note = {};
12 var params = JSON.stringify([parent, "Note"]);
13 var url = BASEURL + ws + "/_design/mapper/_view/byparentandtype?key=" + params;
14 $.getJSON(url, function(data) {
15 $.each(data.rows, function(n, obj) {
16 noteIds.push(obj.value);
17 });
18 });
19 noteIds.forEach(function(id) {
20 url = BASEURL + ws + "/" + id;
21 $.getJSON(url, function(data) {
22 note = {
23 "id": data._id,
24 "rev": data._rev,
25 "name": data.name,
26 "text": data.text
27 };
28 notes.push(note);
29 });
30 });
31 return notes;
32 };
33
34 // updates note if existing, creates otherwise
35 notesFact.putNote = function(ws, name, parent, text) {
36 var notes = notesFact.getNotes(ws, parent);
37 var note = {};
38 var exists = false;
39 var url = BASEURL + ws + "/";
40 var id = "";
41 var rev = "";
42
43 // we need to check the name fits before updating
44 if(notes.length) {
45 notes.forEach(function(note) {
46 if(note.name === name) {
47 id = note.id;
48 rev = note.rev;
49 url += note.id;
50 exists = true;
51 }
52 });
53 }
54
55 if(!exists) {
56 // insert
57 id = parent + "." + CryptoJS.SHA1("Message").toString();
58 url += id;
59 note = {
60 "name": name,
61 "parent": parent,
62 "owned": false,
63 "text": text,
64 "type": "Note"
65 };
66 } else {
67 // update
68 note = {
69 "_id": id,
70 "_rev": rev,
71 "name": name,
72 "parent": parent,
73 "owned": false,
74 "text": text,
75 "type": "Note"
76 };
77 }
78
79 $http.put(url, note);
80 };
81
82 return notesFact;
83 }]);
+0
-94
faraday/server/www/scripts/services/controllers/serviceModalEdit.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('serviceModalEdit', [
6 '$q',
7 '$scope',
8 '$modalInstance',
9 '$routeParams',
10 'SERVICE_STATUSES',
11 'service',
12 'servicesManager',
13 'commonsFact',
14 'workspace',
15 function ($q,
16 $scope,
17 $modalInstance,
18 $routeParams,
19 SERVICE_STATUSES,
20 service,
21 servicesManager,
22 commonsFact,
23 workspace) {
24
25 init = function() {
26 // current Workspace
27 var ws = $routeParams.wsId;
28 $scope.workspace = workspace;
29
30 if(service.length == 1) {
31 $scope.data = {
32 "name": service[0].name,
33 "description": service[0].description,
34 "owned": service[0].owned,
35 "owner": service[0].owner,
36 "ports": service[0].ports,
37 "protocol": service[0].protocol,
38 "parent": service[0].parent,
39 "status": service[0].status,
40 "version": service[0].version,
41 };
42 }
43 $scope.servicesSelected = service;
44
45 $scope.statuses = SERVICE_STATUSES;
46 };
47
48 $scope.ok = function() {
49 var date = new Date(), updateAll = [];
50 var ws = $routeParams.wsId;
51 timestamp = date.getTime()/1000.0;
52
53 for (var i = 0; i < $scope.servicesSelected.length; i++) {
54 updateAll.push(servicesManager.getService($scope.servicesSelected[i]._id, ws, false).then(function(serviceObj){
55 $scope.data['_id'] = serviceObj._id;
56 return servicesManager.updateService(serviceObj, $scope.data, $routeParams.wsId);
57 }));
58 }
59
60 $q.all(updateAll).then(function(){
61 $modalInstance.close($scope.data);
62 }, function(response) {
63 if (response.status == 409) {
64 commonsFact.showMessage("Error while updating a new Vulnerability " + response.data.name + " Conflicting Vulnarability with id: " + response.data.object._id + ". " + response.data.message);
65 }if (response.status === 400) {
66 var field = Object.keys(response.data.messages)[0];
67 var error = response.data.messages[field][0];
68 commonsFact.showMessage("Your input data is wrong, " + field.toUpperCase() + ": " + error);
69 }else {
70 commonsFact.showMessage("Error from backend: " + response.status);
71 }
72
73 })
74 };
75
76 $scope.call = function(service) {
77 $scope.data = {
78 "name": service.name,
79 "description": service.description,
80 "owned": service.owned,
81 "ports": service.ports,
82 "protocol": service.protocol,
83 "status": service.status,
84 "version": service.version,
85 };
86 };
87
88 $scope.cancel = function() {
89 $modalInstance.dismiss('cancel');
90 };
91
92 init();
93 }]);
+0
-75
faraday/server/www/scripts/services/controllers/serviceModalNew.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('serviceModalNew', [
6 '$scope',
7 '$modalInstance',
8 '$routeParams',
9 'SERVICE_STATUSES',
10 'host',
11 'servicesManager',
12 'hostsManager',
13 'commonsFact',
14 function ($scope,
15 $modalInstance,
16 $routeParams,
17 SERVICE_STATUSES,
18 host,
19 servicesManager,
20 hostsManager,
21 commonsFact) {
22
23 init = function() {
24 $scope.data = {
25 "name": "",
26 "description": "",
27 "owned": false,
28 "owner": "",
29 "ports": "",
30 "protocol": "",
31 "parent": "",
32 "status": "open",
33 "version": ""
34 };
35 // current Workspace
36 var ws = $routeParams.wsId;
37 $scope.data.parent = host.id;
38 $scope.statuses = SERVICE_STATUSES;
39 };
40
41 $scope.ok = function() {
42 var date = new Date(),
43 timestamp = date.getTime()/1000.0;
44
45 $scope.data.metadata = {
46 "update_time": timestamp,
47 "update_user": "",
48 "update_action": 0,
49 "creator": "",
50 "create_time": timestamp,
51 "update_controller_action": "UI Web New",
52 "owner": ""
53 };
54 servicesManager.createService($scope.data, $routeParams.wsId).then(function() {
55 $modalInstance.close($scope.data);
56 }, function(response) {
57 if (response.status === 409) {
58 commonsFact.showMessage("Error while creating a new Service " + response.data.name + " Conflicting Vulnarability with id: " + response.data.object._id + ". " + response.data.message);
59 } if (response.status === 400) {
60 var field = Object.keys(response.data.messages)[0];
61 var error = response.data.messages[field][0];
62 commonsFact.showMessage("Your input data is wrong, " + field.toUpperCase() +": " + error);
63 }else {
64 commonsFact.showMessage("Error from backend: " + response.status);
65 }
66 });
67 };
68
69 $scope.cancel = function() {
70 $modalInstance.dismiss('cancel');
71 };
72
73 init();
74 }]);
+0
-310
faraday/server/www/scripts/services/partials/list.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion clearfix">
5 <div class="faraday-header-border-fix">
6 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
7 <div id="reports-main" class="fila clearfix">
8 <div class="col-md-8" style="padding-left: 0px !important;">
9 <span ng-hide="!showServices" class="reports">
10 <div class="button-control col-md-12 col-sm-12 col-xs-12">
11 <div class="control-wrapper control-new">
12 <button type="button" class="btn btn-success btn-new" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'New service'}}" ng-click="new()" style="padding:0px 0px" ng-disabled="workspaceData.readonly === true">
13 New service
14 </button>
15 </div>
16 <table>
17 <thead>
18 <tr>
19 <th class="col-s-1" style="border-left: 1px solid rgb(221, 221, 221); padding-left: 12px;">
20 <a href="#/status/ws/{{workspace}}" class="status-report" ng-class="{'navigation-active' : component == 'status'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Vulns" tooltip-placement="right">
21 Vulns
22 </a>
23 </th>
24 <th class="col-s-1">
25 <a href="#/hosts/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : true}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Hosts" tooltip-placement="right">
26 Hosts
27 </a>
28 <div class="flex-spacer"></div>
29 </th>
30 <th class="col-s-1">
31 <a href="#/credentials/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'credentials'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Credentials" tooltip-placement="right">
32 Credentials
33 </a>
34 <div class="flex-spacer"></div>
35 </th>
36 <th class="col-md-1" style = "border-right: 1px solid rgb(221, 221, 221); padding-right: 12px">
37 <a href="#/taskgroup" class="executive-report" ng-class="{'navigation-active' : component == 'taskgroup'}" style="color: black !important; font-weight: bold; font-size: 15px;">
38 Tasks
39 </a>
40 <div class="flex-spacer"></div>
41 </th>
42 </tr>
43 </thead>
44 </table>
45 <div class="control-wrapper control-edit">
46 <button type="button" class="btn" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'Edit selected services'}}" ng-click="edit()" ng-disabled="services.length == 0">
47 <img src="images/icon-toolbar-edit.svg" class="edit-icon" />
48 </button>
49 </div>
50 <div class="control-wrapper">
51 <button type="button" class="btn" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'Delete selected services'}}" ng-click="delete()" ng-disabled="services.length == 0 || workspaceData.readonly === true">
52 <img src="images/icon-toolbar-delete.svg" class="delete-icon" />
53 </button>
54 </div>
55 <div class="space-wrapper"></div>
56 <div class="control-wrapper search-wrapper">
57 <form role="form" ng-submit="searchFor(true, searchParams)" class="ng-pristine ng-valid">
58 <div class="form-group">
59 <div class="input-group">
60 <!-- ngIf: search && search != 'confirmed=true' -->
61 <input type="text" class="form-control ng-pristine ng-valid ng-touched" placeholder="Enter keywords" ng-change="currentPage = 1" ng-model="searchParams">
62 <span class="input-group-addon glyphicon-btn" ng-click="searchFor(true, searchParams)">
63 <img src="images/icon-toolbar-searchbar-loupe.svg" class="search-icon">
64 </span>
65 </div>
66 </div>
67 </form>
68 </div>
69 </div>
70 <div ng-if="loadedServices && services.length > 0">
71 <h3>Services for host {{hostName}}</h3>
72 </div>
73 <div ng-if="loadedServices && services.length == 0">
74 <h4>No services found for {{host.ip}}</h4>
75 </div>
76 <div ng-show="loadedServices && services.length > 0">
77 <table class="table-v3 services-list table table-responsive" style="margin-top: 15px">
78 <thead>
79 <tr class="ui-grid-header">
80 <th class="ui-grid-cell-contents ui-grid-header-cell hosts-list-checkall" >
81 <input type="checkbox" ng-model="selectall" ng-click="checkAllServices()" class="ng-pristine ng-untouched ng-valid" />
82 </th>
83 <th class="ui-grid-cell-contents ui-grid-header-cell">
84 <span ng-click="toggleSort('name')">Name</span>
85 </th>
86 <th class="ui-grid-cell-contents ui-grid-header-cell">
87 <span ng-click="toggleSort('version')">Version</span>
88 </th>
89 <th class="ui-grid-cell-contents ui-grid-header-cell">
90 <span ng-click="toggleSort('ports')">Port</span>
91 </th>
92 <th class="ui-grid-cell-contents ui-grid-header-cell">
93 <span ng-click="toggleSort('protocol')">Protocol</span>
94 </th>
95 <th class="ui-grid-cell-contents ui-grid-header-cell">
96 <span ng-click="toggleSort('status')">Status</span>
97 </th>
98 <th class="ui-grid-cell-contents ui-grid-header-cell">
99 <span ng-click="toggleSort('vulns')">Vulns</span>
100 </th>
101 <th class="ui-grid-cell-contents ui-grid-header-cell">
102 <span ng-click="toggleSort('credentials')">Credentials</span>
103 </th>
104 </tr>
105 </thead>
106 <tbody>
107 <tr ng-repeat="service in filtered = (services | filter:expression) | orderBy:sortField:reverse | startFrom:(currentPage-1)*pageSize | limitTo:pageSize"
108 selection-model selection-model-type="checkbox"
109 selection-model-mode="multiple-additive"
110 selection-model-selected-class="multi-selected">
111 <td class="ui-grid-cell-contents checkbox-select">
112 <input type="checkbox" name="{{s._id}}"/>
113 </td>
114 <td class="ui-grid-cell-contents">
115 <a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}/search/name={{service.name}}">
116 <span title="{{service.name.length > 60 ? service.name : ''}}">
117 {{service.name | limitTo: 60}}
118 <span ng-if="service.name.length > 60">...</span>
119 </span>
120 </a>
121 </td>
122 <td ng-bind="service.version || '-'" class="ui-grid-cell-contents"></td>
123 <td class="ui-grid-cell-contents">
124 <span ng-bind="service.ports"></span>
125 </td>
126 <td class="ui-grid-cell-contents">
127 <a ng-href="#/host/ws/{{workspace}}/hid/{{host._id}}/search/protocol={{service.protocol}}">
128 <span ng-bind="service.protocol"></span>
129 </a>
130 </td>
131 <td ng-bind="service.status || '-'" class="ui-grid-cell-contents"></td>
132 <td class="ui-grid-cell-contents">
133 <a ng-href="#/status/ws/{{workspace}}/search/service_id={{service.id}}">
134 <span ng-bind="service.vulns"></span>
135 </a>
136 </td>
137 <td class="ui-grid-cell-contents">
138 <a ng-href="#/credentials/ws/{{workspace}}/sid/{{service.id}}">{{service.credentials}}</a>
139 </td>
140 </tr>
141 </tbody>
142 </table><!-- #hosts -->
143 <div class="showPagination">
144 <div class="form-group">
145 <ul class="pagination">
146 <li><a ng-hide="prevPageDisabled()" ng-click="prevPage()"><span aria-hidden="true">&laquo;</span><span class="sr-only">Previous</span></a></li>
147 <li><a>{{currentPage}}/{{pageCount()}}</a></li>
148 <li><a ng-hide="nextPageDisabled()" ng-click="nextPage()"><span aria-hidden="true">&raquo;</span><span class="sr-only">Next</span></a></li>
149 </ul>
150 <form name="goToPage" id="goToPageStatus">
151 <div class="col-md-2">
152 <input type="number" min="0" max="{{pageCount()}}" class="form-control" ng-model="newCurrentPage" placeholder="Go to page"/>
153 </div>
154 <button class="btn btn-default" ng-click="go()">GO</button>
155 <input type="number" min="1" class="form-control vuln_per_page" ng-model=newPageSize placeholder="Number page" />
156 </form>
157 </div>
158 </div><!-- .showPagination -->
159 </div><!-- .reports -->
160 </span>
161 <span ng-hide="host.tools.length == 0" class="reports">
162 <h3>Tools for host {{hostName}}</h3>
163 <div>
164 <table class="table-v3 services-list table table-responsive" style="margin-top: 15px">
165 <thead>
166 <tr class="ui-grid-header">
167 <th class="ui-grid-cell-contents ui-grid-header-cell">
168 <span ng-click="toggleSort('command')">Command</span>
169 </th>
170 <th class="ui-grid-cell-contents ui-grid-header-cell">
171 <span ng-click="toggleSort('user')">User</span>
172 </th>
173 <th class="ui-grid-cell-contents ui-grid-header-cell">
174 <span>Parameters</span>
175 </th>
176 <th class="ui-grid-cell-contents ui-grid-header-cell">
177 <span ng-click="toggleSort('create_date')">Create Date</span>
178 </th>
179 </tr>
180 </thead>
181 <tbody>
182 <tr ng-repeat="tool in host.tools | startFrom:(currentToolPage-1)*toolPageSize | limitTo:toolPageSize">
183 <td class="ui-grid-cell-contents"><a href="#/status/ws/{{workspace}}/search/command_id={{tool.command_id}}">{{tool.command}}</a></td>
184 <td ng-bind="tool.user" class="ui-grid-cell-contents"></td>
185 <td class="ui-grid-cell-contents">{{tool.params.substring(tool.params.lastIndexOf('/') + 1, tool.params.length)}}</td>
186 <td ng-bind="tool.create_date | amTimeAgo" class="ui-grid-cell-contents"></td>
187 </tr>
188 </tbody>
189 </table>
190 <div class="showPagination">
191 <div class="form-group">
192 <ul class="pagination">
193 <li><a ng-hide="prevToolPageDisabled()" ng-click="prevToolPage()"><span aria-hidden="true">&laquo;</span><span class="sr-only">Previous</span></a></li>
194 <li><a>{{currentToolPage}}/{{toolPageCount()}}</a></li>
195 <li><a ng-hide="nextToolPageDisabled()" ng-click="nextToolPage()"><span aria-hidden="true">&raquo;</span><span class="sr-only">Next</span></a></li>
196 </ul>
197 <form name="goToPage" id="goToPageStatus">
198 <div class="col-md-2">
199 <input type="number" min="0" max="{{toolPageCount()}}" class="form-control" ng-model="newCurrentToolPage" placeholder="Go to page"/>
200 </div>
201 <button class="btn btn-default" ng-click="goTools()">GO</button>
202 <input type="number" min="1" class="form-control vuln_per_page" ng-model=newToolPageSize placeholder="Number page" />
203 </form>
204 </div>
205 </div>
206 </div>
207 </span>
208 </div>
209 <div class ="col-md-4">
210 <div style="border-left: 1px solid #CCC">
211 <form name="form" style="margin-left: 5px">
212 <h3>
213 Host details
214 <span style="float:right">
215 <a class="btn btn-sm btn-default" href="#/host/ws/{{workspace}}/hid/{{host.id}}/edit" ng-if="!editing">
216 <span class="glyphicon glyphicon-pencil"></span>
217 Edit
218 </a>
219 <button type="button" class="btn btn-sm btn-default" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'Delete host'}}" ng-click="deleteHost()" ng-if="!editing" ng-disabled="workspaceData.readonly === true">
220 <span class="glyphicon glyphicon-trash"></span>
221 Delete
222 </button>
223 <a class="btn btn-danger" href="#/host/ws/{{workspace}}/hid/{{host.id}}" ng-click="loadHosts()" ng-if="editing && !creating">Cancel</a>
224 <button class="btn btn-success" ng-disabled="form.$invalid || workspaceData.readonly == true" ng-click="ok()" ng-if="editing">OK</button>
225 </span>
226 </h3>
227 <div class="form-horizontal">
228 <div class="form-group" ng-class="{'has-error': !host.ip }">
229 <div class="col-md-12">
230 <strong ng-if="!editing">IP</strong>
231 <h5 ng-if="editing">IP v4 or v6</h5>
232 <label class="sr-only" for="name">IP</label>
233 <input type="text" class="form-control" id="ip" placeholder="IP" ng-model="host.ip" ng-if="editing" required/>
234 <br ng-if="!editing">
235 <span ng-if="!editing">{{host.ip}}</span>
236 <span class="help-block normal-size" ng-if="editing">
237 Example: 192.168.0.1
238 </span>
239 </div>
240 </div>
241 <div class="form-group">
242 <div class="col-md-6" style="margin-bottom: 15px">
243 <span>Owned:</span>
244 <input class="form-check-input" type="checkbox" id="owned" ng-model="host.owned" ng-disabled="!editing"></input>
245 </div>
246 <div class="col-md-12">
247 <strong ng-if="!editing">Operating System</strong>
248 <h5 ng-if="editing">Operating System</h5>
249 <label class="sr-only" for="os">Operating System</label>
250 <input type="text" class="form-control" id="os" placeholder="Operating System" ng-model="host.os" ng-if="editing"/>
251 <p ng-if="!editing">
252 <img ng-if="host.icon && host.icon != 'unknown'" ng-src="images/{{host.icon}}.png" uib-tooltip="{{host.os}}"/>
253 {{host.os}}
254 </p>
255 </div>
256 <div class="col-md-12">
257 <strong ng-if="!editing">Hostnames</strong>
258 <h5 ng-if="editing">Hostnames</h5>
259 <span class="input-group-addon button-radius background-blue" ng-click="newHostnames($event)" ng-if="editing">Add Hostname</span>
260 </div>
261 <span ng-if="editing">
262 <div class="col-md-12 input-margin" ng-repeat="hostname in host.hostnames">
263 <div class="input-group margin-bottom-sm col-md-12">
264 <label class="sr-only" for="hostsnames">Hostname</label>
265 <input type="text" class="form-control" id="hostsnames" placeholder="Hostname" ng-model="hostname.key" />
266 <span class="input-group-addon" ng-click="host.hostnames.splice($index, 1)" ng-hide="host.hostnames.length == 1" ng-if="editing"><i class="fa fa-minus-circle"></i></span>
267 </div>
268 </div>
269 </span>
270 <span ng-if="!editing">
271 <div class="col-md-12 input-margin">
272 <ul>
273 <li ng-repeat="hostname in host.hostnames">{{hostname.key}}</li>
274 </ul>
275 </div>
276 </span>
277 <div class="col-md-12">
278 <strong ng-if="!editing">MAC</strong>
279 <h5 ng-if="editing">MAC</h5>
280 <input type="text" class="form-control" id="ipv4" placeholder="MAC" ng-model="host.mac" ng-if="editing"/>
281 <p ng-if="!editing">{{host.mac}} ({{host.mac_vendor}})</p>
282 </div>
283 <div class="col-md-12">
284 <strong ng-if="!editing">Description</strong>
285 <h5 ng-if="editing">Description</h5>
286 <label class="sr-only" for="description">Description</label>
287 <textarea class="form-control" id="description" placeholder="Description" ng-model="host.description" ng-if="editing"></textarea>
288 <p ng-if="!editing">{{host.description}}</p>
289 </div>
290 <div class="col-md-12">
291 <i ng-if="!editing">
292 </br>
293 <span class="fa fa-clock-o"></span>
294 <span> Created</span>
295 <span am-time-ago="host.metadata.create_time" am-preprocess="utc"></span>
296 </i>
297 </div>
298 </div><!-- .form-group -->
299 </div>
300 <div style="float: right">
301 <a class="btn btn-danger" href="#/host/ws/{{workspace}}/hid/{{host.id}}" ng-click="loadHosts()" ng-if="editing && !creating">Cancel</a>
302 <a class="btn btn-danger" href="#/hosts/ws/{{workspace}}" ng-if="editing && creating">Cancel</a>
303 <button class="btn btn-success" ng-disabled="form.$invalid || workspaceData.readonly == true" ng-click="ok()" ng-if="editing">OK</button>
304 </div>
305 </form>
306 </div>
307 </div>
308 </div><!-- #reports-main --></div><!-- .right-main -->
309 </section><!-- #main -->
+0
-109
faraday/server/www/scripts/services/partials/modalEdit.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <div class="modal-button">
7 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid">OK</button>
8 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">Edit service</h3>
11 </div>
12 <div class="modal-body">
13 <div class="form-horizontal">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
15 <div class="col-md-12">
16 <label class="sr-only" for="name">Name</label>
17 <input type="text" class="form-control" id="name" required name="name" placeholder="Name" ng-model="data.name" />
18 </div>
19 </div><!-- .form-group -->
20 <div class="form-group">
21 <div class="col-md-12">
22 <label class="sr-only" for="description">Description</label>
23 <textarea class="form-control" id="description" placeholder="Description" ng-model="data.description"></textarea>
24 </div>
25 </div><!-- .form-group -->
26 <div class="form-group">
27 <div class="col-md-12">
28 <div class="checkbox">
29 <label>
30 <input type="checkbox" id="owned" ng-model="data.owned"/>
31 <span class="normal-size">Owned</span>
32 </label>
33 </div><!-- .checkbox -->
34 </div>
35 </div><!-- .form-group -->
36 <div class="form-group">
37 <div class="col-md-3">
38 <h5>Port</h5>
39 <div class="input-margin">
40 <label class="sr-only" for="ports">Port</label>
41 <input type="number" min="0" max="65535" class="form-control" id="ports" placeholder="Port" ng-model="data.ports"/>
42 </div>
43 </div>
44 <div class="col-md-3 protocol">
45 <h5>Protocol</h5>
46 <label class="sr-only" for="protocol">Protocol</label>
47 <input type="text" class="form-control" id="protocol" placeholder="Protocol" ng-model="data.protocol"/>
48 </div>
49 <div class="col-md-3">
50 <h5>Version</h5>
51 <label class="sr-only" for="version">Version</label>
52 <input type="text" class="form-control" id="version" placeholder="Version" ng-model="data.version"/>
53 </div>
54 <div class="col-md-3">
55 <h5>Status</h5>
56 <label class="sr-only" for="status">Status</label>
57 <select class="form-control" ng-model="data.status" ng-options="e for e in statuses" id="status">
58 </select>
59 </div>
60 </div><!-- .form-group -->
61 <div class="form-group">
62 <div class="reports col-md-12 col-sm-12 col-xs-12" ng-if="servicesSelected">
63 <h5><small>
64 Services to update
65 </small></h5>
66 <table class="status-report hosts-list table table-responsive">
67 <thead>
68 <tr>
69 <th>
70 <a href="" ng-click="toggleSort('name')">Name</a>
71 </th>
72 <th>
73 <a href="" ng-click="toggleSort('description')">Description</a>
74 </th>
75 <th>
76 <a href="" ng-click="toggleSort('ports')">Port</a>
77 </th>
78 <th>
79 <a href="" ng-click="toggleSort('protocol')">Protocol</a>
80 </th>
81 <th>
82 <a href="" ng-click="toggleSort('status')">Status</a>
83 </th>
84 <th>Copy</th>
85 </tr>
86 </thead>
87 <tbody>
88 <tr ng-repeat="service in servicesSelected | filter:query | orderBy:sortField:reverse">
89 <td ng-bind="service.name"></td>
90 <td ng-bind="service.description || '-'"></td>
91 <td ng-bind="service.ports"></td>
92 <td ng-bind="service.protocol"></td>
93 <td ng-bind="service.status"></td>
94 <td><i class="fa fa-copy copy-icon fa-lg" ng-click="call(service);"></i></td>
95 </tr>
96 </tbody>
97 </table><!-- #hosts -->
98 </div>
99 </div>
100 </div>
101 </div><!-- .modal-body -->
102 <div class="modal-footer">
103 <div class="modal-button">
104 <button class="btn btn-success" ng-disabled="form.$invalid || workspace.readonly === true" ng-click="ok()">OK</button>
105 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
106 </div>
107 </div>
108 </form>
+0
-70
faraday/server/www/scripts/services/partials/modalNew.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <div class="modal-button">
7 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid">OK</button>
8 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">New service</h3>
11 </div>
12 <div class="modal-body">
13 <div class="form-horizontal">
14 <div class="form-group">
15 <div class="col-md-12">
16 <label class="sr-only" for="service">Name</label>
17 <input type="text" class="form-control" id="service" required name="name" placeholder="Name" ng-model="data.name" />
18 </div>
19 </div><!-- .form-group -->
20 <div class="form-group">
21 <div class="col-md-12">
22 <label class="sr-only" for="description">Description</label>
23 <textarea class="form-control" id="description" placeholder="Description" ng-model="data.description"></textarea>
24 </div>
25 </div><!-- .form-group -->
26 <div class="form-group">
27 <div class="col-md-12">
28 <div class="checkbox">
29 <label>
30 <input type="checkbox" id="owned" ng-model="data.owned"/>
31 <span class="normal-size">Owned</span>
32 </label>
33 </div><!-- .checkbox -->
34 </div>
35 </div><!-- .form-group -->
36 <div class="form-group">
37 <div class="col-md-3">
38 <h5>Port</h5>
39 <div class="input-margin" ng-class="{'has-error': form.ports.$invalid }">
40 <label class="sr-only" for="ports">Port</label>
41 <input type="number" min="0" max="65535" class="form-control" id="ports" name="ports" placeholder="Port" ng-model="data.ports" required/>
42 </div>
43 </div>
44 <div class="col-md-3 protocol" ng-class="{'has-error': form.protocol.$invalid }">
45 <h5>Protocol</h5>
46 <label class="sr-only" for="protocol">Protocol</label>
47 <input type="text" class="form-control" id="protocol" name="protocol" placeholder="Protocol" ng-model="data.protocol" required/>
48 </div>
49 <div class="col-md-3">
50 <h5>Version</h5>
51 <label class="sr-only" for="version">Version</label>
52 <input type="text" class="form-control" id="version" placeholder="Version" ng-model="data.version"/>
53 </div>
54 <div class="col-md-3">
55 <h5>Status</h5>
56 <label class="sr-only" for="status">Status</label>
57 <select class="form-control" ng-model="data.status" ng-options="e for e in statuses">
58 </select>
59 </div>
60 </div><!-- .form-group -->
61 </div>
62 </div><!-- .modal-body -->
63 <div class="modal-footer">
64 <div class="modal-button">
65 <button class="btn btn-success" ng-disabled="form.$invalid" ng-click="ok()">OK</button>
66 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
67 </div>
68 </div>
69 </form>
+0
-70
faraday/server/www/scripts/services/providers/service.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('Service', ['BASEURL', 'ServerAPI', function(BASEURL, ServerAPI) {
6 Service = function(data) {
7 if(data) {
8 this.set(data);
9 }
10 };
11
12 var public_properties = [
13 'description', 'name', 'owned', 'ports', 'protocol',
14 'status', 'version'
15 ];
16
17 var saved_properties = public_properties.concat(
18 ['_id', '_rev', 'metadata', 'owner', 'parent', 'type']);
19
20 Service.prototype = {
21 public_properties: public_properties,
22 saved_properties: saved_properties,
23 set: function(data) {
24 data.type = "Service";
25 angular.extend(this, data);
26 },
27
28 delete: function(ws) {
29 return ServerAPI.deleteService(ws, this.id);
30 },
31
32 update: function(data, ws) {
33 angular.extend(this, data);
34 var self = this;
35
36 if(typeof self.ports != "object") {
37 self.ports = [self.ports];
38 }
39
40 return self._save(ws, self, true);
41 },
42 save: function(ws) {
43 var self = this;
44
45 if(typeof self.ports != "object") {
46 self.ports = [self.ports];
47 }
48
49 return self._save(ws, self, false);
50 },
51 _save: function(ws, data, isUpdate) {
52 if (typeof isUpdate === 'undefined') {isUpdate = false};
53 doc = {};
54 for (property in data) {
55 if (this.saved_properties.indexOf(property) != -1) {
56 doc[property] = data[property];
57 }
58 }
59
60 if (isUpdate) {
61 return ServerAPI.updateService(ws, doc);
62 } else {
63 return ServerAPI.createService(ws, doc);
64 }
65 }
66 }
67
68 return Service;
69 }]);
+0
-114
faraday/server/www/scripts/services/providers/services.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('servicesManager', ['BASEURL', '$http', '$q', 'Service', 'ServerAPI',
6 function(BASEURL, $http, $q, Service, ServerAPI) {
7 var servicesManager = {};
8
9 servicesManager._objects = {};
10 servicesManager._get = function(id, data) {
11 var service = this._objects[id];
12
13 if(service) {
14 service.set(data);
15 } else {
16 service = new Service(data);
17 this._objects[id] = service;
18 }
19
20 return service;
21 }
22
23 servicesManager._search = function(id) {
24 return this._objects[id];
25 }
26
27 servicesManager._load = function(id, ws) {
28 var self = this;
29 var deferred = $q.defer();
30 ServerAPI.getService(ws, id).
31 then(function(response) {
32
33 deferred.resolve(new Service(response.data));
34
35 }, function(error) {
36 deferred.reject(error);
37 });
38 return deferred.promise;
39 };
40
41 servicesManager.getService = function(id, ws, force_reload) {
42 var deferred = $q.defer();
43 var service = this._search(id);
44 force_reload = force_reload || false;
45 if((service) && (!force_reload)) {
46 deferred.resolve(service);
47 } else {
48 return this._load(id, ws);
49 }
50 return deferred.promise;
51 }
52
53 // async method - this is the one to use from now on!
54 servicesManager.getServices = function(ws) {
55 var deferred = $q.defer();
56 var self = this;
57 this._objects = {};
58
59 ServerAPI.getServices(ws)
60 .then(function(servicesArray) {
61 var services = [];
62 servicesArray.data.services.forEach(function(serviceData) {
63 var service = self._get(serviceData.value._id, serviceData.value);
64 services.push(service);
65 });
66 deferred.resolve(services);
67 }, function(){
68 deferred.reject();
69 })
70 return deferred.promise;
71 }
72
73 servicesManager.deleteServices = function(service, ws) {
74 var deferred = $q.defer();
75 var self = this;
76 var service = self._get(service.id, service);
77 service.delete(ws).then(function() {
78 delete self._objects[service.id];
79 deferred.resolve();
80 }, function(){
81 // host couldn't be deleted
82 deferred.reject("Error deleting service");
83 });
84
85 return deferred.promise;
86 }
87
88 servicesManager.createService = function(serviceData, ws) {
89 var deferred = $q.defer();
90 var self = this;
91 var service = new Service(serviceData);
92 service.save(ws).then(function(saved_service){
93 deferred.resolve(saved_service.data);
94 }, function(response){
95 deferred.reject(response);
96 })
97
98 return deferred.promise;
99 }
100
101 servicesManager.updateService = function(service, data, ws) {
102 var deferred = $q.defer();
103 var self = this;
104 service.update(data, ws).then(function() {
105 deferred.resolve();
106 }, function(response) {
107 deferred.reject(response);
108 });
109 return deferred.promise;
110 }
111
112 return servicesManager;
113 }]);
+0
-306
faraday/server/www/scripts/statusReport/controllers/modalEdit.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('modalEditCtrl', [
6 '$modalInstance',
7 '$routeParams',
8 'EASEOFRESOLUTION',
9 'STATUSES',
10 'commonsFact',
11 'BASEURL',
12 'severities',
13 'vuln',
14 'vulnModelsManager',
15 'vulnsManager',
16 'referenceFact',
17 'encodeURIComponentFilter',
18 'customFields',
19 'workspace',
20 function ($modalInstance,
21 $routeParams,
22 EASEOFRESOLUTION,
23 STATUSES,
24 commonsFact,
25 BASEURL,
26 severities,
27 vuln,
28 vulnModelsManager,
29 vulnsManager,
30 referenceFact,
31 encodeURIComponent,
32 customFields,
33 workspace) {
34
35 var vm = this;
36
37 vm.baseurl;
38 vm.saveAsModelDisabled = false;
39 vm.easeofresolution;
40 vm.new_ref;
41 vm.new_policyviolation;
42 vm.icons;
43 vm.cweList;
44 vm.cweLimit;
45 vm.cwe_filter;
46
47 vm.file_name_error;
48
49 vm.data;
50 vm.vuln;
51
52 init = function () {
53 vm.modelMessage = "Click here."
54 vm.easeofresolution = EASEOFRESOLUTION;
55 vm.severities = severities;
56 vm.statuses = STATUSES;
57 vm.new_ref = "";
58 vm.new_policyviolation = "";
59 vm.icons = {};
60 vm.baseurl = BASEURL;
61
62 vm.cweList = [];
63 vulnModelsManager.get().then(function (data) {
64 vm.cweList = data;
65 });
66 vm.cweLimit = 5;
67 vm.cwe_filter = "";
68
69 vm.file_name_error = false;
70
71 vm.customFields = customFields;
72 vm.workspace = workspace;
73
74 vm.data = {
75 _id: undefined,
76 _attachments: {},
77 confirmed: false,
78 data: "",
79 desc: "",
80 easeofresolution: undefined,
81 impact: {
82 accountability: false,
83 availability: false,
84 confidentiality: false,
85 integrity: false
86 },
87 name: "",
88 refs: {},
89 resolution: "",
90 severity: undefined,
91 method: "",
92 path: "",
93 status_code: undefined,
94 pname: "",
95 params: "",
96 query: "",
97 request: "",
98 response: "",
99 type: "Vulnerability",
100 website: "",
101 status: "opened",
102 policyviolations: [],
103 custom_fields:{},
104 external_id: ""
105 };
106
107 vm.vuln = angular.copy(vuln);
108
109 vm.populate(vm.vuln);
110
111 // TODO: EVIDENCE SHOUD BE LOADED ALREADY?
112 if (vm.vuln._attachments !== undefined) {
113 vm.data._attachments = vm.vuln._attachments;
114 vm.icons = commonsFact.loadIcons(vm.data._attachments);
115 }
116
117 angular.element('#nav-tabs-container a[data-target="#general"]').click();
118 };
119
120 vm.saveAsModel = function () {
121 vm.modelMessage = "Done."
122 vm.vulnModelsManager.create(vm.data);
123 vm.saveAsModelDisabled = true;
124 };
125
126 vm.selectedFiles = function (files, e) {
127 files.forEach(function (file) {
128 file.newfile = true;
129 if (file.name.charAt(0) != "_") {
130 if (!vm.data._attachments.hasOwnProperty(file)) vm.data._attachments[file.name] = file;
131 } else {
132 vm.file_name_error = true;
133 }
134 });
135 vm.icons = commonsFact.loadIcons(vm._attachments);
136 }
137
138 vm.removeEvidence = function (name) {
139 delete vm.data._attachments[name];
140 delete vm.icons[name];
141 };
142
143 vm.toggleImpact = function (key) {
144 vm.data.impact[key] = !vm.data.impact[key];
145 };
146
147 vm.ok = function () {
148 // add the ref in new_ref, if there's any
149 vm.newReference();
150 // convert refs to an array of strings
151 var refs = [];
152 vm.data.refs.forEach(function (ref) {
153 refs.push(ref.value);
154 });
155 vm.data.refs = refs;
156
157 // add the policy violation in new_policyviolation, if there's any
158 vm.newPolicyViolation();
159 // convert policy violations to an array of strings
160 var policyviolations = [];
161 vm.data.policyviolations.forEach(function (policyviolation) {
162 policyviolations.push(policyviolation.value);
163 });
164 vm.data.policyviolations = policyviolations;
165
166 vulnsManager.updateVuln(vm.vuln, vm.data).then(function () {
167 $modalInstance.close(vm.data);
168 }, function (data) {
169 commonsFact.showMessage("Error updating vuln " + vm.vuln.name + " (" + vm.vuln._id + "): " + (data.message || JSON.stringify(data.messages)));
170 });
171
172
173 };
174
175 vm.cancel = function () {
176 $modalInstance.dismiss('cancel');
177 };
178
179 vm.newReference = function () {
180 if (vm.new_ref != "") {
181 // we need to check if the ref already exists
182 if (vm.data.refs.filter(function (ref) {
183 return ref.value === vm.new_ref
184 }).length == 0) {
185 vm.data.refs.push({value: vm.new_ref});
186 vm.new_ref = "";
187 }
188 }
189 };
190
191 vm.openReference = function (text) {
192 window.open(referenceFact.processReference(text), '_blank');
193 };
194
195 vm.openEvidence = function (name) {
196 var currentEvidence = vm.data._attachments[name];
197 if (!currentEvidence.newfile)
198 window.open(vm.baseurl + '_api/v2/ws/' + $routeParams.wsId + '/vulns/' + vm.data._id + '/attachment/' + encodeURIComponent(name), '_blank');
199 };
200
201 vm.newPolicyViolation = function () {
202 if (vm.new_policyviolation != "") {
203 // we need to check if the policy violation already exists
204 if (vm.data.policyviolations.filter(function (policyviolation) {
205 return policyviolation.value === vm.new_policyviolation
206 }).length == 0) {
207 vm.data.policyviolations.push({value: vm.new_policyviolation});
208 vm.new_policyviolation = "";
209 }
210 }
211 };
212
213 vm.populate = function (item) {
214 for (var key in vm.data) {
215 if (key != "refs" && key != "policyviolations" && item.hasOwnProperty(key) && vm.data.hasOwnProperty(key)) {
216 vm.data[key] = item[key];
217 }
218 }
219 // convert refs to an array of objects
220 var refs = [];
221 item.refs.forEach(function (ref) {
222 refs.push({value: ref});
223 });
224 vm.data.refs = refs;
225
226 // convert policyviolations to an array of objects
227 var policyviolations = [];
228 item.policyviolations.forEach(function (policyviolation) {
229 policyviolations.push({value: policyviolation});
230 });
231 vm.data.policyviolations = policyviolations;
232
233 if(item.customfields){
234 for(var cf in item.customfields){
235 vm.data.custom_fields[cf] = item.customfields[cf];
236 }
237 }
238 };
239
240
241 vm.updateBtnSeverityColor = function (severity) {
242 var color = undefined;
243 switch (severity) {
244 case "unclassified":
245 color = '#999999';
246 break;
247 case "info":
248 color = '#2e97bd';
249 break;
250 case "low":
251 color = '#a1ce31';
252 break;
253 case "med":
254 color = '#dfbf35';
255 break;
256 case "high":
257 color = '#df3936';
258 break;
259 case "critical":
260 color = '#932ebe';
261 break;
262 }
263
264 angular.element('#btn-chg-severity').css('background-color', color);
265 angular.element('#caret-chg-severity').css('background-color', color);
266 };
267
268 vm.changeSeverity = function (severity) {
269 vm.data.severity = severity;
270 vm.updateBtnSeverityColor(severity);
271 };
272
273 vm.updateBtnStatusColor = function (status) {
274 var color = undefined;
275 switch (status) {
276 case "opened":
277 color = '#DB3130';
278 break;
279 case "closed":
280 color = '#97F72C';
281 break;
282 case "re-opened":
283 color = '#DBB72F';
284 break;
285 case "risk-accepted":
286 color = '#288DB4';
287 break;
288 default:
289 color = '#aaaaaa';
290 break;
291 }
292
293 angular.element('#btn-chg-status').css('background-color', color);
294 angular.element('#caret-chg-status').css('background-color', color);
295 };
296
297 vm.changeStatus = function (status) {
298 vm.data.status = status;
299 vm.updateBtnStatusColor(status);
300 };
301
302
303 init();
304 }])
305 ;
+0
-363
faraday/server/www/scripts/statusReport/controllers/modalNew.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('modalNewVulnCtrl', [
6 '$modalInstance',
7 '$filter',
8 '$upload',
9 'EASEOFRESOLUTION',
10 'commonsFact',
11 'severities',
12 'workspace',
13 'targetFact',
14 'vulnModelsManager',
15 'vulnsManager',
16 'customFields',
17 function ($modalInstance,
18 $filter,
19 $upload,
20 EASEOFRESOLUTION,
21 commonsFact,
22 severities,
23 workspace,
24 targetFact,
25 vulnModelsManager,
26 vulnsManager,
27 customFields) {
28
29 var vm = this;
30
31 vm.vuln_types;
32 vm.easeofresolution;
33 vm.workspace;
34 vm.new_ref;
35 vm.new_policyviolation;
36 vm.icons;
37 vm.cweList;
38 vm.cweLimit;
39 vm.cwe_filter;
40
41 vm.file_name_error;
42
43 vm.currentPage;
44 vm.newCurrentPage;
45 vm.pageSize;
46
47 vm.targets;
48 vm.target_filter;
49
50 vm.data;
51
52 // true if all the parents in data.parents are type Host
53 vm.host_parents;
54
55 vm.activeSearch;
56
57 init = function() {
58 vm.vuln_types = [
59 {name:'Vulnerability', value:'Vulnerability'},
60 {name:'Vulnerability Web', value:'VulnerabilityWeb'}
61 ];
62 vm.easeofresolution = EASEOFRESOLUTION;
63 vm.severities = severities;
64 vm.workspace = workspace;
65 vm.new_ref = "";
66 vm.new_policyviolation = "";
67 vm.icons = {};
68
69 vm.host_parents = false;
70
71 vm.customFields = customFields;
72
73 vm.cweList = [];
74 vulnModelsManager.get().then(function(data) {
75 vm.cweList = data;
76 });
77 vm.cweLimit = 5;
78 vm.cwe_filter = "";
79
80 vm.file_name_error = false;
81
82 vm.pageSize = 5;
83 vm.currentPage = 1;
84 vm.newCurrentPage = 0;
85 vm.total_rows = 0;
86
87 vm.data = {
88 _attachments: {},
89 data: "",
90 desc: "",
91 impact: {
92 accountability: false,
93 availability: false,
94 confidentiality: false,
95 integrity: false
96 },
97 method: "",
98 name: "",
99 owned: false,
100 params: "",
101 parents: [], // a tuple with (parent_id, parent_type)
102 path: "",
103 status_code: undefined,
104 pname: "",
105 policyviolations: [],
106 easeofresolution: null,
107 query: "",
108 refs: [],
109 request: "",
110 resolution: "",
111 response: "",
112 severity: undefined,
113 type: "Vulnerability",
114 website: "",
115 custom_fields:{},
116 external_id: "",
117 };
118
119 customFields.forEach(function(cf) {
120 vm.data.custom_fields[cf.field_name] = null;
121 });
122
123 vm.targets = [];
124 vm.target_filter = "";
125
126 targetFact.getTargets(workspace, vm.currentPage, vm.pageSize).then(function(targets){
127 vm.targets = targets.hosts;
128 vm.total_rows = targets.total;
129 });
130 };
131
132 vm.selectedFiles = function(files, e) {
133 files.forEach(function(file) {
134 if(file.name.charAt(0) != "_") {
135 if(!vm.data._attachments.hasOwnProperty(file)) vm.data._attachments[file.name] = file;
136 vm.file_name_error = false;
137 } else {
138 vm.file_name_error = true;
139 }
140 });
141 vm.icons = commonsFact.loadIcons(vm.data._attachments);
142 };
143
144 vm.removeEvidence = function(name) {
145 delete vm.data._attachments[name];
146 delete vm.icons[name];
147 };
148
149 vm.toggleImpact = function(key) {
150 vm.data.impact[key] = !vm.data.impact[key];
151 };
152
153 vm.ok = function() {
154 // add the ref in new_ref, if there's any
155 vm.newReference();
156 vm.newPolicyViolation();
157
158 // convert refs to an array of strings
159 var refs = [];
160 vm.data.refs.forEach(function(ref) {
161 refs.push(ref.value);
162 });
163 vm.data.refs = refs;
164
165 var policyviolations = [];
166 vm.data.policyviolations.forEach(function(violation) {
167 policyviolations.push(violation.value);
168 });
169 vm.data.policyviolations = policyviolations;
170
171 vulnsManager.createVuln(vm.workspace, vm.data).then(function(){
172 $modalInstance.close(vm.data);
173 }, function(response){
174 if (response.status == 409) {
175 commonsFact.showMessage("Error while creating a new Vulnerability " + vm.data.name + " Conflicting Vulnerability with id: " + response.data.object._id + ". " + response.data.message);
176 } else if (response.status == 400){
177 //commonsFact.showMessage("Your input data is wrong, Attachments error");
178 var field = Object.keys(response.data.messages)[0];
179 var error = response.data.messages[field][0];
180 commonsFact.showMessage("Your input data is wrong, " + field.toUpperCase() +": " + error);
181
182 }else {
183 commonsFact.showMessage("Error from backend: " + response.status);
184 }
185 });
186 };
187
188 vm.cancel = function() {
189 $modalInstance.dismiss('cancel');
190 };
191
192 vm.setTargets = function(filter, start, size) {
193 var end = start + size,
194 targets = vm.targets;
195
196 if(filter) {
197 targets = vm.targets_filtered;
198 }
199
200 vm.data.parents = targets.slice(start, end);
201
202 vm.host_parents = vm.data.parents.some(function(elem, ind, arr) {
203 return elem.type === 'Host';
204 });
205 };
206
207 vm.resetTarget = function() {
208 vm.data.parents = [];
209 vm.host_parents = false;
210 }
211
212 vm.setTarget = function(target) {
213 var index = -1;
214 var array = $.grep(vm.data.parents, function(e, i){
215 index = i;
216 return e.id === target.id && e.type === target.type
217 });
218
219 if (array.length > 0)
220 vm.data.parents.splice(index, 1);
221 else
222 vm.data.parents.push(target);
223
224 // refresh host_parents var
225 vm.host_parents = vm.data.parents.some(function(elem, ind, arr) {
226 return elem.type === 'Host';
227 });
228 }
229
230 vm.go = function() {
231 vm.currentPage = 0;
232 if((vm.newCurrentPage) <= parseInt(vm.total_rows/vm.pageSize)
233 && (vm.newCurrentPage) > 0) {
234 vm.currentPage = vm.newCurrentPage;
235 }
236
237 vm.updatePaginator(false, vm.newCurrentPage)
238 }
239
240 vm.newReference = function() {
241 if (vm.new_ref != "") {
242 // we need to check if the ref already exists
243 if (vm.data.refs.filter(function(ref) {return ref.value === vm.new_ref}).length == 0) {
244 vm.data.refs.push({value: vm.new_ref});
245 vm.new_ref = "";
246 }
247 }
248 }
249
250 vm.newPolicyViolation = function() {
251 if (vm.new_policyviolation != "") {
252 // we need to check if the policy violation already exists
253 if (vm.data.policyviolations.filter(function(policyviolation) {return policyviolation.value === vm.new_policyviolation}).length == 0) {
254 vm.data.policyviolations.push({value: vm.new_policyviolation});
255 vm.new_policyviolation = "";
256 }
257 }
258 }
259
260 vm.populate = function(item, model, label) {
261
262 for (var key in item) {
263 if(key != "refs" && key != "policyviolations" && vm.data.hasOwnProperty(key)) {
264 vm.data[key] = item[key];
265 }else if (key === 'exploitation'){
266 vm.data['severity'] = item['exploitation'];
267 }
268 }
269
270 // convert refs to an array of objects
271 var refs = [];
272 item.refs.forEach(function(ref) {
273 refs.push({value: ref});
274 });
275 vm.data.refs = refs;
276
277 var policyviolations = [];
278 if(item.hasOwnProperty('policyviolations')) item.policyviolations.forEach(function(policyviolation) {
279 policyviolations.push({value: policyviolation});
280 });
281 vm.data.policyviolations = policyviolations;
282
283 if(item.customfields){
284 for(var cf in item.customfields){
285 vm.data.custom_fields[cf] = item.customfields[cf];
286 }
287 }
288 }
289
290 vm.updateBtnSeverityColor = function (severity) {
291 var color = undefined;
292 switch (severity) {
293 case "unclassified":
294 color = '#999999';
295 break;
296 case "info":
297 color = '#2e97bd';
298 break;
299 case "low":
300 color = '#a1ce31';
301 break;
302 case "med":
303 color = '#dfbf35';
304 break;
305 case "high":
306 color = '#df3936';
307 break;
308 case "critical":
309 color = '#932ebe';
310 break;
311 default:
312 color = '#AAAAAA';
313 break;
314 }
315
316 angular.element('#btn-chg-severity').css('background-color', color);
317 angular.element('#caret-chg-severity').css('background-color', color);
318 };
319
320 vm.changeSeverity = function (severity) {
321 vm.data.severity = severity;
322 vm.updateBtnSeverityColor(severity);
323 };
324
325 vm.updatePaginator = function (isNext, toGo) {
326 if (isNext === true)
327 vm.currentPage = vm.currentPage + 1;
328 else
329 vm.currentPage = vm.currentPage - 1;
330
331 if (toGo)
332 vm.currentPage = toGo;
333
334
335 targetFact.getTargets(workspace, vm.currentPage, vm.pageSize).then(function(targets){
336 vm.targets = targets.hosts;
337 vm.targets_filtered = vm.targets
338 });
339 };
340
341 vm.isParentSelected = function (target) {
342 return $.grep(vm.data.parents, function(e){ return e.id === target.id && e.type === target.type}).length > 0;
343 };
344
345 vm.filterTargets = function () {
346 var filter = { search : vm.target_filter };
347 targetFact.getTargets(workspace, vm.currentPage, vm.pageSize, filter).then(function(targets){
348 vm.targets = targets.hosts;
349 vm.activeSearch = true;
350 });
351 };
352
353 vm.clearFilterTargets = function () {
354 vm.activeSearch = false;
355 targetFact.getTargets(workspace, vm.currentPage, vm.pageSize).then(function(targets){
356 vm.targets = targets.hosts;
357 vm.target_filter = '';
358 });
359 };
360
361 init();
362 }]);
+0
-1834
faraday/server/www/scripts/statusReport/controllers/statusReport.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module("faradayApp")
5 .controller("statusReportCtrl", [
6 "$scope",
7 "$filter",
8 "$routeParams",
9 "$location",
10 "$uibModal",
11 "$cookies",
12 "$q",
13 "$window",
14 "BASEURL",
15 "SEVERITIES",
16 "EASEOFRESOLUTION",
17 "STATUSES",
18 "hostsManager",
19 "commonsFact",
20 'parserFact',
21 "vulnsManager",
22 "workspacesFact",
23 "csvService",
24 "uiGridConstants",
25 "vulnModelsManager",
26 "referenceFact",
27 "ServerAPI",
28 '$http',
29 'uiCommonFact',
30 'FileUploader',
31 "workspaceData",
32 "$templateCache",
33 function ($scope,
34 $filter,
35 $routeParams,
36 $location,
37 $uibModal,
38 $cookies,
39 $q,
40 $window,
41 BASEURL,
42 SEVERITIES,
43 EASEOFRESOLUTION,
44 STATUSES,
45 hostsManager,
46 commonsFact,
47 parserFact,
48 vulnsManager,
49 workspacesFact,
50 csvService,
51 uiGridConstants,
52 vulnModelsManager,
53 referenceFact,
54 ServerAPI,
55 $http,
56 uiCommonFact,
57 FileUploader,
58 workspaceData,
59 $templateCache
60 ) {
61 $scope.baseurl;
62 $scope.columns;
63 $scope.columnsWidths;
64 $scope.easeofresolution;
65 $scope.interfaces;
66 $scope.reverse;
67 $scope.severities;
68 $scope.search;
69 $scope.searchParams;
70 $scope.sortField;
71 $scope.vulns;
72 $scope.workspaces;
73 $scope.currentPage;
74 $scope.gridOptions;
75 $scope.vulnModelsManager;
76
77 $scope.vulnWebSelected;
78
79 $scope.gridHeight;
80 $scope.customFields;
81
82 $scope.isShowingPreview;
83
84 $scope.cweList;
85 $scope.temTemplate;
86 $scope.new_ref;
87 $scope.new_policyviolation;
88
89 $scope.selectedAtachment;
90
91
92 var allVulns;
93
94 var searchFilter = {};
95 var paginationOptions = {
96 page: 1,
97 pageSize: 100,
98 defaultPageSizes: [10, 50, 75, 100],
99 sortColumn: null,
100 sortDirection: null
101 };
102
103 var uploader = $scope.uploader = new FileUploader({});
104
105 // FILTERS
106
107 // a sync filteronRegisterApi
108 uploader.filters.push({
109 name: 'syncFilter',
110 fn: function(item /*{File|FileLikeObject}*/, options) {
111 return this.queue.length < 10;
112 }
113 });
114
115 // an async filter
116 uploader.filters.push({
117 name: 'asyncFilter',
118 fn: function(item /*{File|FileLikeObject}*/, options, deferred) {
119 setTimeout(deferred.resolve, 1e3);
120 }
121 });
122
123
124 var init = function() {
125 $scope.baseurl = BASEURL;
126 $scope.severities = SEVERITIES;
127 $scope.easeofresolution = EASEOFRESOLUTION;
128 $scope.propertyGroupBy = $routeParams.groupbyId;
129 $scope.sortField = "date";
130 $scope.reverse = true;
131 $scope.vulns = [];
132 $scope.selected = false;
133 $scope.vulnModelsManager = vulnModelsManager;
134 $scope.loading = true;
135 $scope.gridOptions = {
136 multiSelect: true,
137 enableSelectAll: true,
138 enableColumnMenus: false,
139 enableRowSelection: true,
140 useExternalPagination: true,
141 useExternalSorting: true,
142 paginationPageSizes: paginationOptions.defaultPageSizes,
143 paginationPageSize: paginationOptions.pageSize,
144 enableHorizontalScrollbar: 0,
145 treeRowHeaderAlwaysVisible: false,
146 enableGroupHeaderSelection: true,
147 rowHeight: 47,
148 enableFullRowSelection: false
149 };
150 $scope.gridOptions.columnDefs = [];
151
152
153 var storedPageSize = parseInt($cookies.get("pageSize"));
154 if ( storedPageSize && storedPageSize > 0 ) {
155 paginationOptions.pageSize = storedPageSize;
156 $scope.gridOptions.paginationPageSize = storedPageSize;
157 }
158
159 $scope.searchParams = "";
160 if ($cookies.get("filterConfirmed") !== undefined) {
161 $scope.propertyFilterConfirmed = $cookies.get("filterConfirmed");
162 if ($scope.propertyFilterConfirmed === 'Confirmed')
163 $scope.searchParams = "confirmed:true";
164 if ($scope.propertyFilterConfirmed === 'Unconfirmed')
165 $scope.searchParams = "confirmed:false";
166 } else {
167 $scope.propertyFilterConfirmed = "All";
168 }
169
170 $scope.gridOptions.onRegisterApi = function(gridApi){
171 //set gridApi on scope
172 $scope.gridApi = gridApi;
173
174 $scope.gridApi.selection.on.rowSelectionChanged( $scope, function ( rowChanged ) {
175 $scope.selectionChange();
176 if ( typeof(rowChanged.treeLevel) !== "undefined" && rowChanged.treeLevel > -1 ) {
177 // this is a group header
178 children = $scope.gridApi.treeBase.getRowChildren( rowChanged );
179 children.forEach( function ( child ) {
180 if ( rowChanged.isSelected ) {
181 $scope.gridApi.selection.selectRow( child.entity );
182 } else {
183 $scope.gridApi.selection.unSelectRow( child.entity );
184 }
185 });
186 }
187 });
188
189 $scope.gridApi.selection.on.rowFocusChanged( $scope, function ( rowChanged ) {
190 $cookies.remove("selectedVulns");
191 });
192
193 $scope.gridApi.pagination.on.paginationChanged($scope, function (pageNumber, pageSize) {
194 // Save new page size in cookie
195 $cookies.put("pageSize", pageSize);
196
197 // Clear selection
198 $scope.gridApi.selection.clearSelectedRows();
199
200 paginationOptions.page = pageNumber;
201 paginationOptions.pageSize = pageSize;
202
203 // Load new page
204 loadVulns();
205 });
206
207 $scope.gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
208 if (sortColumns.length === 0) {
209 sortRowsBy(null, null);
210 } else {
211 sortRowsBy(sortColumns[0].name, sortColumns[0].sort.direction);
212 }
213 loadVulns();
214 });
215
216 $scope.gridApi.core.on.rowsRendered($scope, function() {
217 resizeGrid();
218 recalculateLastVisibleColSize();
219 selectRowsByCookie();
220 });
221
222 $scope.gridApi.colResizable.on.columnSizeChanged($scope, function (colDef, deltaChange) {
223 for (i = 0; i < $scope.gridApi.grid.columns.length; i++) {
224 if ($scope.gridApi.grid.columns[i].name === colDef.name) {
225 var newWidth = $scope.gridApi.grid.columns[i].width;
226 $scope.columnsWidths[colDef.name] = newWidth;
227 $cookies.put("SRcolWidth", JSON.stringify($scope.columnsWidths));
228 recalculateLastVisibleColSize();
229 break;
230 }
231 }
232 });
233 };
234
235 // load all workspaces
236 workspacesFact.list().then(function(wss) {
237 $scope.workspaces = wss;
238 });
239
240 // current workspace
241 $scope.workspace = $routeParams.wsId;
242
243 // load current workspace data
244 workspacesFact.get($scope.workspace).then(function(response) {
245 $scope.workspaceData = response;
246 });
247
248 $scope.interfaces = [];
249 // current search
250 $scope.search = $routeParams.search;
251
252 if($scope.propertyFilterConfirmed === "Confirmed") {
253 if($scope.search !== undefined) {
254 $scope.search = $scope.search.concat("&confirmed=true");
255 } else {
256 $scope.search = "confirmed=true";
257 }
258 }
259
260 if($scope.propertyFilterConfirmed === "Unconfirmed") {
261 if($scope.search !== undefined) {
262 $scope.search = $scope.search.concat("&confirmed=false");
263 } else {
264 $scope.search = "confirmed=false";
265 }
266 }
267
268
269 $scope.hash = window.location.hash;
270 if(window.location.hash.substring(1).indexOf("search") !== -1) {
271 $scope.hash = $scope.hash.slice(0, window.location.hash.indexOf("search") - 1);
272 }
273
274 if($scope.search !== "" && $scope.search !== undefined && $scope.search.indexOf("=") > -1) {
275 searchFilter = commonsFact.parseSearchURL($scope.search);
276 $scope.searchParams = commonsFact.searchFilterToExpression(searchFilter);
277 }
278
279 $scope.columns = {
280 "_id": true,
281 "date": true,
282 "name": true,
283 "severity": true,
284 "service": true,
285 "target": true,
286 "host_os": false,
287 "desc": true,
288 "resolution": false,
289 "data": false,
290 "easeofresolution": false,
291 "status": true,
292 "website": false,
293 "path": false,
294 "status_code": false,
295 "request": false,
296 "refs": false,
297 "evidence": false,
298 "hostnames": true,
299 "impact": false,
300 "method": false,
301 "params": false,
302 "pname": false,
303 "query": false,
304 "response": false,
305 "web": false,
306 "tool": false,
307 "policyviolations": false,
308 "external_id": false
309 };
310
311
312 if (typeof ($cookies.get("SRcolWidth")) !== "undefined") {
313 $scope.columnsWidths = JSON.parse($cookies.get("SRcolWidth"));
314 }
315 else {
316 $scope.columnsWidths = {
317 "name": "180",
318 "service": "110",
319 "hostnames": "130",
320 "target": "100",
321 "host_os": "300",
322 "desc": "600",
323 "resolution": "170",
324 "data": "170",
325 "easeofresolution": "140",
326 "status": "100",
327 "website": "90",
328 "path": "90",
329 "status_code": "90",
330 "request": "90",
331 "refs": "20",
332 "_attachments": "100",
333 "impact": "90",
334 "method": "90",
335 "params": "90",
336 "pname": "90",
337 "query": "100",
338 "response": "90",
339 "web": "80",
340 "tool": "100",
341 "policyviolations": "100"
342 };
343 }
344
345 // created object for columns cookie columns
346 if(typeof($cookies.get("SRcolumns")) !== "undefined"){
347 var arrayOfColumns = $cookies.get("SRcolumns").replace(/[{}"']/g, "").split(',');
348 arrayOfColumns.forEach(function(column){
349 var columnFinished = column.split(":");
350 if ($scope.columns.hasOwnProperty(columnFinished[0])) {
351 $scope.columns[columnFinished[0]] = columnFinished[1] === "true" ? true: false;
352 }
353 });
354 }
355
356 // load cookie of columns ordering if exists
357 paginationOptions.sortColumn = $cookies.get("SRsortColumn") || null;
358 paginationOptions.sortDirection = $cookies.get("SRsortDirection") || null;
359
360 defineColumns();
361
362 $scope.vulnWebSelected = false;
363
364 groupByColumn();
365
366 loadVulns();
367
368 loadCustomFields();
369
370 $cookies.remove("selectedVulns");
371 $scope.isShowingPreview = false;
372
373 $scope.cweList = [];
374
375 vulnModelsManager.get().then(function (data) {
376 $scope.cweList = data;
377 });
378
379 $scope.temTemplate = undefined;
380 $scope.new_ref = "";
381 $scope.new_policyviolation = "";
382
383 $scope.selectedAtachment = {
384 url: '',
385 name: '',
386 imgPrevFail: false
387 };
388 };
389
390
391 var selectRowsByCookie = function () {
392 var selectedVulns = $cookies.getObject("selectedVulns");
393 if (selectedVulns !== undefined) {
394 for (var i = 0; i < selectedVulns.length; i++){
395 for (var j = 0; j < $scope.gridOptions.data.length;j++){
396 if (selectedVulns[i] === $scope.gridOptions.data[j]._id){
397 $scope.gridApi.selection.selectRow($scope.gridOptions.data[j]);
398 }
399 }
400 }
401 }
402 };
403
404 var loadCustomFields = function () {
405 var deferred = $q.defer();
406 ServerAPI.getCustomFields().then(
407 function(response){
408 $scope.customFields = response.data;
409 deferred.resolve($scope.customFields);
410 }, function(){
411 deferred.reject();
412 });
413 };
414
415 var defineColumns = function() {
416
417
418 function getColumnSort(columnName){
419 if($cookies.get("SRsortColumn") === columnName){
420 direction = ($cookies.get("SRsortDirection").toLowerCase() == "asc")
421 ? uiGridConstants.AuiGridConstantsSC
422 : uiGridConstants.DESC;
423 return {ignoreSort: true, priority: 0, direction: direction};
424 }else{
425 return {};
426 }
427 }
428
429 var header = '<div ng-class="{ \'sort$scope.columnsable\': sortable }">'+
430 ' <div class="ui-grid-cell-contents" col-index="renderIndex" title="TOOLTIP">{{ col.displayName CUSTOM_FILTERS }}'+
431 ' <a href="" ng-click="grid.appScope.toggleShow(col.displayName, true)">'+
432 ' <span class="glyphicon glyphicon-remove"></span>'+
433 ' </a>'+
434 ' <span ui-grid-visible="col.sort.direction" ng-class="{ \'ui-grid-icon-up-dir\': col.sort.direction == asc, \'ui-grid-icon-down-dir\': col.sort.direction == desc, \'ui-grid-icon-blank\': !col.sort.direction }">&nbsp;</span>'+
435 ' </div>'+
436 ' <div class="ui-grid-column-menu-button" ng-if="grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false" ng-click="toggleMenu($event)" ng-class="{\'ui-grid-column-menu-button-last-col\': isLastCol}">'+
437 ' <i class="ui-grid-icon-angle-down">&nbsp;</i>'+
438 ' </div>'+
439 ' <div ui-grid-filter></div>'+
440 ' </div>';
441
442 var headerConfirm = '<div ng-class="{ \'sort$scope.columnsable\': sortable }">'+
443 ' <div class="ui-grid-cell-contents" col-index="renderIndex" title="TOOLTIP">{{ col.displayName CUSTOM_FILTERS }}'+
444 ' <a href="" ng-click="grid.appScope.toggleShow(col.displayName, true)">'+
445 ' </a>'+
446 ' <span ui-grid-visible="col.sort.direction" ng-class="{ \'ui-grid-icon-up-dir\': col.sort.direction == asc, \'ui-grid-icon-down-dir\': col.sort.direction == desc, \'ui-grid-icon-blank\': !col.sort.direction }">&nbsp;</span>'+
447 ' </div>'+
448 ' <div class="ui-grid-column-menu-button" ng-if="grid.options.enableColumnMenus && !col.isRowHeader && col.colDef.enableColumnMenu !== false" ng-click="toggleMenu($event)" ng-class="{\'ui-grid-column-menu-button-last-col\': isLastCol}">'+
449 ' <i class="ui-grid-icon-angle-down">&nbsp;</i>'+
450 ' </div>'+
451 ' <div ui-grid-filter></div>'+
452 ' </div>';
453
454
455 $scope.gridOptions.columnDefs.push({displayName : "conf", name: "confirmVuln", width: "50", enableColumnResizing: false, headerCellTemplate: headerConfirm, cellTemplate: "scripts/statusReport/partials/ui-grid/confirmbutton.html" });
456
457 $templateCache.put('ui-grid/selectionRowHeaderButtons',
458 "<div class=\"ui-grid-selection-row-header-buttons \" ng-class=\"{'ui-grid-row-selected': row.isSelected}\" ><input style=\"margin: 0; vertical-align: middle; background-position: -20px 0;\" type=\"checkbox\" ng-model=\"row.isSelected\" ng-click=\"row.isSelected=!row.isSelected;selectButtonClick(row, $event)\">&nbsp;</div>"
459 );
460
461
462 $templateCache.put('ui-grid/selectionSelectAllButtons',
463 "<div class=\"ui-grid-selection-row-header-buttons \" ng-class=\"{'ui-grid-all-selected': grid.selection.selectAll}\" ng-if=\"grid.options.enableSelectAll\"><input style=\"margin: 0; vertical-align: middle\" type=\"checkbox\" ng-model=\"grid.selection.selectAll\" ng-click=\"grid.selection.selectAll=!grid.selection.selectAll;headerButtonClick($event)\"></div>"
464 );
465
466 $scope.gridOptions.columnDefs.push({ name : 'severity',
467 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/severitycolumn.html',
468 headerCellTemplate: header,
469 displayName : "sev",
470 type: 'string',
471 visible: $scope.columns["severity"],
472 sort: getColumnSort('severity'),
473 sortingAlgorithm: compareSeverities,
474 maxWidth: 50,
475 minWidth: 50
476 });
477 $scope.gridOptions.columnDefs.push({ name : 'name',
478 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/namecolumn.html',
479 headerCellTemplate: header,
480 sort: getColumnSort('name'),
481 visible: $scope.columns["name"]
482 });
483 $scope.gridOptions.columnDefs.push({ name : 'service',
484 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/servicecolumn.html',
485 headerCellTemplate: header,
486 visible: $scope.columns["service"],
487 field: "service.summary",
488 displayName : "service",
489 sort: getColumnSort('service'),
490 });
491 $scope.gridOptions.columnDefs.push({ name : 'hostnames',
492 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/hostnamescolumn.html',
493 headerCellTemplate: header,
494 minWidth: '100',
495 maxWidth: '200',
496 enableSorting: false,
497 sort: getColumnSort('hostnames'),
498 visible: $scope.columns["hostnames"]
499 });
500 $scope.gridOptions.columnDefs.push({ name : 'target',
501 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/targetcolumn.html',
502 headerCellTemplate: header,
503 sort: getColumnSort('target'),
504 visible: $scope.columns["target"]
505 });
506 $scope.gridOptions.columnDefs.push({ name : 'host_os',
507 displayName: "host_os", // Don't touch this! It will break everything. Seriously
508 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/hostoscolumn.html',
509 headerCellTemplate: header,
510 sort: getColumnSort('host_os'),
511 visible: $scope.columns["host_os"]
512 });
513 $scope.gridOptions.columnDefs.push({ name : 'desc',
514 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/desccolumn.html',
515 headerCellTemplate: header,
516 sort: getColumnSort('desc'),
517 visible: $scope.columns["desc"],
518 minWidth: '300',
519 maxWidth: '600',
520 });
521 $scope.gridOptions.columnDefs.push({ name : 'resolution',
522 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html',
523 headerCellTemplate: header,
524 sort: getColumnSort('resolution'),
525 visible: $scope.columns["resolution"],
526 });
527 $scope.gridOptions.columnDefs.push({ name : 'data',
528 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html',
529 headerCellTemplate: header,
530 sort: getColumnSort('data'),
531 visible: $scope.columns["data"],
532 });
533 $scope.gridOptions.columnDefs.push({ name : 'easeofresolution',
534 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
535 headerCellTemplate: header,
536 minWidth: '150',
537 sort: getColumnSort('easeofresolution'),
538 visible: $scope.columns["easeofresolution"],
539 });
540 $scope.gridOptions.columnDefs.push({ name : 'website',
541 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
542 headerCellTemplate: header,
543 sort: getColumnSort('website'),
544 visible: $scope.columns["website"],
545 });
546 $scope.gridOptions.columnDefs.push({ name : 'path',
547 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
548 headerCellTemplate: header,
549 sort: getColumnSort('path'),
550 visible: $scope.columns["path"],
551 });
552 $scope.gridOptions.columnDefs.push({ name : 'status_code',
553 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
554 headerCellTemplate: header,
555 sort: getColumnSort('status_code'),
556 visible: $scope.columns["status_code"],
557 });
558 $scope.gridOptions.columnDefs.push({ name : 'request',
559 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html',
560 headerCellTemplate: header,
561 sort: getColumnSort('request'),
562 visible: $scope.columns["request"],
563 });
564 $scope.gridOptions.columnDefs.push({ name : 'refs',
565 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/refscolumn.html',
566 headerCellTemplate: header,
567 sort: getColumnSort('refs'),
568 visible: $scope.columns["refs"],
569 enableSorting: false,
570 });
571 $scope.gridOptions.columnDefs.push({ name : '_attachments',
572 displayName: "evidence",
573 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/evidencecolumn.html',
574 headerCellTemplate: header,
575 sort: getColumnSort('_attachments'),
576 visible: $scope.columns["evidence"],
577 });
578 $scope.gridOptions.columnDefs.push({ name : 'impact',
579 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/impactcolumn.html',
580 headerCellTemplate: header,
581 sort: getColumnSort('impact'),
582 enableSorting: false,
583 visible: $scope.columns["impact"],
584 });
585 $scope.gridOptions.columnDefs.push({ name : 'method',
586 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
587 headerCellTemplate: header,
588 sort: getColumnSort('method'),
589 visible: $scope.columns["method"],
590 });
591 $scope.gridOptions.columnDefs.push({ name : 'params',
592 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
593 headerCellTemplate: header,
594 sort: getColumnSort('params'),
595 visible: $scope.columns["params"],
596 });
597 $scope.gridOptions.columnDefs.push({ name : 'pname',
598 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
599 headerCellTemplate: header,
600 sort: getColumnSort('pname'),
601 visible: $scope.columns["pname"],
602 });
603 $scope.gridOptions.columnDefs.push({ name : 'query',
604 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
605 headerCellTemplate: header,
606 sort: getColumnSort('query'),
607 visible: $scope.columns["query"],
608 });
609 $scope.gridOptions.columnDefs.push({ name : 'response',
610 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html',
611 headerCellTemplate: header,
612 sort: getColumnSort('response'),
613 visible: $scope.columns["response"],
614 width: $scope.columnsWidths['response'],
615 });
616 $scope.gridOptions.columnDefs.push({ name : 'web',
617 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/webcolumn.html',
618 headerCellTemplate: header,
619 sort: getColumnSort('web'),
620 visible: $scope.columns["web"]
621 });
622 $scope.gridOptions.columnDefs.push({ name : 'metadata.creator',
623 displayName : "tool",
624 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/creatorcolumn.html',
625 headerCellTemplate: header,
626 sort: getColumnSort('tool'),
627 visible: $scope.columns["tool"]
628 });
629 $scope.gridOptions.columnDefs.push({ name : 'policyviolations',
630 // The following line breaks the remembering of the field (i.e.
631 // setting it in the SRcolumns cookie), so it is better to
632 // leave it commented (or to debug the problem, which I don't
633 // want to)
634 // displayName : "policy violations",
635 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/policyviolationscolumn.html',
636 headerCellTemplate: header,
637 sort: getColumnSort('policyviolations'),
638 visible: $scope.columns["policyviolations"],
639 enableSorting: false,
640 });
641
642 $scope.gridOptions.columnDefs.push({ name : '_id',
643 displayName : "id",
644 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/idcolumn.html',
645 headerCellTemplate: header,
646 sort: getColumnSort('_id'),
647 visible: $scope.columns["_id"],
648 maxWidth: 60,
649 });
650 $scope.gridOptions.columnDefs.push({ name : 'date',
651 displayName : "date",
652 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/datecolumn.html',
653 headerCellTemplate: header,
654 sort: getColumnSort('date'),
655 visible: $scope.columns["date"],
656 maxWidth: 100,
657 minWidth: 100,
658 });
659 $scope.gridOptions.columnDefs.push({ name : 'external_id',
660 displayName : "external_id",
661 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html',
662 headerCellTemplate: header,
663 field: "external_id",
664 sort: getColumnSort('external_id'),
665 visible: $scope.columns["external_id"],
666 maxWidth: 150,
667 minWidth: 130,
668 });
669 $scope.gridOptions.columnDefs.push({ name : 'status',
670 cellTemplate: 'scripts/statusReport/partials/ui-grid/columns/statuscolumn.html',
671 headerCellTemplate: header,
672 field: "status",
673 sort: getColumnSort('status'),
674 visible: $scope.columns["status"],
675 maxWidth: 90,
676 minWidth: 90,
677 });
678 };
679
680
681 var groupByColumn = function() {
682 for (var i = 0; i < $scope.gridOptions.columnDefs.length; i++) {
683 var column = $scope.gridOptions.columnDefs[i];
684 var colname = column.displayName !== undefined ? column.displayName : column.name;
685 if ( colname == $scope.propertyGroupBy && $scope.columns[colname] == true) {
686 column.grouping = { groupPriority: 0 };
687 paginationOptions.sortColumn = colname;
688 paginationOptions.sortDirection = 'asc';
689 }else if (colname === 'sev' && $scope.propertyGroupBy === 'severity'){
690 // Ugly ugly hack so I don't have to change the displayName of
691 // severity from "sev" to "severity"
692 column.grouping = { groupPriority: 0 };
693 paginationOptions.sortColumn = 'severity';
694 paginationOptions.sortDirection = 'asc'
695 }
696 }
697 };
698
699 var sortRowsBy = function(columnName, sortDirection) {
700 paginationOptions.sortColumn = columnName;
701 paginationOptions.sortDirection = sortDirection;
702 $cookies.put('SRsortColumn', columnName || '');
703 $cookies.put('SRsortDirection', sortDirection || '');
704 }
705
706 $scope.confirmedTooltip = function(isConfirmed) {
707 if(!$scope.workspaceData.active){
708 return 'Read-only. Workspace disabled';
709 }
710
711 if(isConfirmed === true) {
712 return "Change to false positive";
713 } else {
714 return "Confirm";
715 }
716 };
717
718 $scope.searchExploits = function(){
719
720 var promises = [];
721 var selected = $scope.getCurrentSelection();
722
723 selected.forEach(function(vuln){
724
725 vuln.refs.forEach(function(ref){
726
727 if(ref.toLowerCase().startsWith('cve')){
728
729 var response = ServerAPI.getExploits(ref);
730 promises.push(response);
731 }
732 });
733 });
734
735 return $q.all(promises).then(function(modalData){
736
737 var response = modalData.map(function(obj){
738 return obj.data;
739 });
740
741 return response.filter(function(x){
742 return !angular.equals(x["exploitdb"], []) || !angular.equals(x["metasploit"], [])
743 });
744
745 }, function(failed) {
746 commonsFact.showMessage("Something failed searching vulnerability exploits.");
747 return [];
748 });
749 }
750
751 $scope.showExploits = function(){
752
753 $scope.searchExploits().then(function(exploits){
754
755 if(exploits.length > 0){
756
757 var modal = $uibModal.open({
758 templateUrl: 'scripts/statusReport/partials/exploitsModal.html',
759 controller: 'commonsModalExploitsCtrl',
760 resolve: {
761 msg: function() {
762 return exploits;
763 }
764 }
765 });
766 }
767 });
768 }
769 var resizeGrid = function() {
770 $scope.gridHeight = getGridHeight('grid', 'left-main', 15);
771 };
772
773 var recalculateLastVisibleColSize = function () {
774 var lastFound = false;
775 for (i = $scope.gridApi.grid.columns.length - 1; i >= 0; i--) {
776 if ($scope.gridApi.grid.columns[i].visible) {
777 if (!lastFound) {
778 $scope.gridApi.grid.columns[i].width = "*";
779 lastFound = true
780 } else if ($scope.gridApi.grid.columns[i].width === "*" && $scope.columnsWidths[$scope.gridApi.grid.columns[i].name] != undefined) {
781 $scope.gridApi.grid.columns[i].width = parseInt($scope.columnsWidths[$scope.gridApi.grid.columns[i].name]);
782 }
783 }
784 }
785 };
786
787 var getGridHeight = function(gridClass, contentClass, bottomOffset) {
788 var contentOffset = angular.element(document.getElementsByClassName(contentClass)[0]).offset();
789 var contentHeight = angular.element(document.getElementsByClassName(contentClass)[0]).height();
790 var gridOffset = angular.element(document.getElementsByClassName(gridClass)).offset();
791 if (gridOffset !== undefined) {
792 var gridHeight = contentHeight - (gridOffset.top) - bottomOffset;
793 return gridHeight + 'px';
794 }
795 };
796
797 $scope.saveAsModel = function() {
798 var self = this;
799 var selected = $scope.getCurrentSelection();
800 try {
801 var vulnsToSend = [];
802 selected.forEach(function(vuln) {
803 let vulnCopy = angular.copy(vuln);
804 vulnCopy.data = '';
805 vulnCopy.exploitation = vuln.severity;
806 vulnCopy.description = vuln.desc;
807 vulnCopy.desc_summary = vuln.desc;
808 vulnCopy.references = vuln.refs;
809 vulnsToSend.push(vulnCopy);
810 });
811 if(vulnsToSend.length > 1) {
812 self.vulnModelsManager.bulkCreate(vulnsToSend).then(
813 function(response) {
814 var message = _saveAsModelMessage(response.data)
815 commonsFact.showMessage(message, true);
816 }, function(response) {
817 var message = "Error creating vulnerability templates.\n\n";
818 if(response.status === 400 && response.data.message)
819 message += response.data.message;
820 else
821 message += _saveAsModelMessage(response.data);
822 commonsFact.showMessage(message);
823 }
824 );
825 } else {
826 self.vulnModelsManager.create(vulnsToSend[0], true).then(
827 function(vuln) {
828 var message = "The following vulnerability was created as template:\n\n";
829 message += "\tId: " + vuln.id.toString() + ". " + "Name: " + vuln.name;
830 commonsFact.showMessage(message, true);
831 }, function(response) {
832 commonsFact.showMessage(response);
833 }
834 );
835 }
836 } catch(err) {
837 commonsFact.showMessage("Something failed when creating some of the templates.");
838 }
839 };
840
841 var _saveAsModelMessage = function(data) {
842 var message = "";
843 var vulnsCreated = data.vulns_created;
844 if(vulnsCreated.length > 0) {
845 message += "The following vulnerabilities were created as templates:\n";
846 vulnsCreated.forEach(function (vuln) {
847 if (vuln[0])
848 message += "\n\tId: " + vuln[0].toString() + ". "
849 message += "Name: " + vuln[1]
850 })
851 message += "\n\n"
852 }
853
854 var vulnsWithErrors = data.vulns_with_errors;
855 if(vulnsWithErrors.length > 0) {
856 message += "The following vulnerabilities couldn't be created as templates:\n";
857 vulnsWithErrors.forEach(function (vuln) {
858 if (vuln[0])
859 message += "\n\tId: " + vuln[0].toString() + ". "
860 message += "Name: " + vuln[1]
861 })
862 message += "\n\n"
863 }
864
865 var vulnsWithConflict = data.vulns_with_conflict;
866 if(vulnsWithConflict.length > 0) {
867 message += "The following vulnerabilities generated conflicts when Faraday tried " +
868 "to create them as templates, this means that their vulnerability " +
869 "templates already exist:\n";
870 vulnsWithConflict.forEach(function (vuln) {
871 if (vuln[0])
872 message += "\n\tId: " + vuln[0].toString() + ". ";
873 message += "Name: " + vuln[1];
874 })
875 message += "\n\n"
876 }
877 return message
878 };
879
880 $scope.selectAll = function() {
881 if($scope.selected === false) {
882 for(var i = 0; i <= $scope.gridOptions.paginationPageSize; i++) {
883 $scope.gridApi.selection.selectRowByVisibleIndex(i);
884 }
885 $scope.selected = true;
886 } else {
887 $scope.gridApi.selection.clearSelectedRows();
888 var allVisibleRows = $scope.gridApi.core.getVisibleRows($scope.gridApi);
889 allVisibleRows.forEach(function(row) {
890 if(row.groupHeader === true && row.isSelected === true) {
891 row.isSelected = false;
892 }
893 });
894 $scope.selected = false;
895 }
896 };
897
898 $scope.processReference = function(text) {
899 return referenceFact.processReference(text);
900 };
901
902 $scope.groupBy = function(property) {
903 var url = "/status/ws/" + $routeParams.wsId + "/groupby/" + property;
904
905 $location.path(url);
906 };
907
908 $scope.clearGroupBy = function() {
909 var url = "/status/ws/" + $routeParams.wsId;
910
911 $location.path(url);
912 };
913
914 $scope.getCurrentSelection = function() {
915 return $scope.gridApi.selection.getSelectedRows();
916 };
917
918 $scope.encodeUrl = function(text) {
919 return encodeURIComponent(encodeURIComponent(text));
920 };
921
922 $scope.csv = function() {
923 deferred = $q.defer();
924 $scope.loading = true;
925
926 var jsonOptions;
927
928 if($scope.searchParams.length > 0)
929 jsonOptions = parserFact.evaluateExpression($scope.searchParams);
930
931 vulnsManager.exportCsv($scope.workspace, jsonOptions)
932 .then(function(result){
933 var title = "";
934
935 if ($scope.workspace === null) {
936 title = 'Vulnerability Model CSV';
937 } else {
938 title = "SR-" + $scope.workspace;
939 }
940
941 var csvObj = {
942 "content": result.data,
943 "extension": "csv",
944 "title": title,
945 "type": "text/csv"
946 };
947
948 $scope.loading = false;
949
950 deferred.resolve(csvObj);
951 })
952 .catch(function(){
953 commonsFact.showMessage('An error has occurred.');
954 $scope.loading = false;
955 });
956 return deferred.promise;
957 };
958
959 $scope.filterConfirmed = function (filter) {
960 $scope.propertyFilterConfirmed = filter;
961 $cookies.put('filterConfirmed', $scope.propertyFilterConfirmed);
962 $scope.searchFor($scope.searchParams, false, false)
963 };
964
965 // deletes the vulns in the array
966 $scope.remove = function(aVulns) {
967 aVulns.forEach(function(vuln) {
968 vulnsManager.deleteVuln(vuln)
969 .then(function() {
970 loadVulns();
971 })
972 .catch(function(errorMsg) {
973 // TODO: show errors somehow
974 console.log("Error deleting vuln " + vuln._id + ": " + errorMsg);
975 });
976 });
977 };
978
979
980 // action triggered from DELETE button
981 $scope.delete = function() {
982 _delete($scope.getCurrentSelection());
983 };
984 // delete only one vuln
985 $scope.deleteVuln = function(vuln) {
986 _delete([vuln]);
987 };
988
989 var _delete = function(vulns) {
990 if(vulns.length > 0) {
991 var modal = $uibModal.open({
992 templateUrl: 'scripts/commons/partials/modalDelete.html',
993 controller: 'commonsModalDelete',
994 size: 'lg',
995 resolve: {
996 msg: function() {
997 var msg = "";
998 if(vulns.length == 1) {
999 msg = "A vulnerability will be deleted.";
1000 } else {
1001 msg = vulns.length + " vulnerabilities will be deleted.";
1002 }
1003 msg += " This action cannot be undone. Are you sure you want to proceed?";
1004 return msg;
1005 }
1006 }
1007 });
1008
1009 modal.result.then(function() {
1010 $scope.remove(vulns);
1011 });
1012 } else {
1013 commonsFact.showMessage('No vulnerabilities were selected to delete');
1014 }
1015 };
1016
1017 $scope.toggleConfirmVuln = function(vuln, confirm) {
1018 if($scope.workspaceData.active){
1019 _toggleConfirm([vuln], confirm);
1020 }
1021 };
1022
1023 var _toggleConfirm = function(vulns, confirm) {
1024 var toggleConfirm = {'confirmed': !confirm},
1025 deferred = $q.defer(),
1026 promises = [];
1027 vulns.forEach(function(vuln) {
1028 promises.push(vulnsManager.updateVuln(vuln, toggleConfirm));
1029 });
1030 $q.all(promises).then(function(res) {
1031 /*if(confirm === true) {
1032 loadVulns();
1033 }*/
1034 }, function(errorMsg){
1035 commonsFact.showMessage("Error updating vuln " + vuln.name + " (" + vuln._id + "): " + errorMsg);
1036 });
1037 };
1038
1039 // action triggered from EDIT button
1040 $scope.edit = function() {
1041 $scope.hideVulnPreview();
1042 _edit($scope.getCurrentSelection());
1043 };
1044
1045 var _edit = function(vulns) {
1046 if (vulns.length == 1) {
1047 var modal = $uibModal.open({
1048 templateUrl: 'scripts/statusReport/partials/modalEdit.html',
1049 backdrop : 'static',
1050 controller: 'modalEditCtrl as modal',
1051 size: 'lg',
1052 resolve: {
1053 severities: function() {
1054 return $scope.severities;
1055 },
1056 vuln: function() {
1057 return vulns[0];
1058 },
1059 customFields: function () {
1060 return $scope.customFields;
1061 },
1062 workspace: function () {
1063 return $scope.workspaceData;
1064 }
1065 }
1066 });
1067
1068 modal.result.then(function() {
1069 loadVulns();
1070 });
1071
1072 } else {
1073 commonsFact.showMessage('A vulnerability must be selected in order to edit');
1074 }
1075 };
1076
1077 var editProperty = function(partial, controller, message, property, opts) {
1078 if(opts == undefined) {
1079 opts = {};
1080 }
1081 var resolve = {
1082 msg: function() {
1083 return message;
1084 },
1085 options: function() {
1086 return opts.options;
1087 }
1088 };
1089 var modal = $uibModal.open({
1090 templateUrl: partial,
1091 controller: controller,
1092 size: 'lg',
1093 resolve: resolve
1094 });
1095 modal.result.then(function(data) {
1096 var selectedVulns = [];
1097 $scope.getCurrentSelection().forEach(function(vuln) {
1098 obj = {};
1099 obj[property] = data;
1100 selectedVulns.push(vuln._id);
1101 if (opts.callback != undefined){
1102 obj = opts.callback(vuln, data);
1103 }
1104
1105 vulnsManager.updateVuln(vuln, obj).then(function(vulns){
1106 loadVulns();
1107 }, function(errorMsg){
1108 // TODO: show errors somehow
1109 console.log("Error updating vuln " + vuln._id + ": " + errorMsg);
1110 });
1111 });
1112
1113 // Storage in cookies
1114 $cookies.putObject("selectedVulns", selectedVulns);
1115 });
1116 }
1117
1118 $scope.editSeverity = function() {
1119 editProperty(
1120 'scripts/commons/partials/editOptions.html',
1121 'commonsModalEditOptions',
1122 'Enter the new severity:',
1123 'severity',
1124 {options: SEVERITIES});
1125 };
1126
1127 $scope.editStatus = function() {
1128 editProperty(
1129 'scripts/commons/partials/editOptions.html',
1130 'commonsModalEditOptions',
1131 'Enter the new status:',
1132 'status',
1133 {options: STATUSES});
1134 };
1135
1136 $scope.editEaseofresolution = function() {
1137 editProperty(
1138 'scripts/commons/partials/editOptions.html',
1139 'commonsModalEditOptions',
1140 'Enter the new easeofresolution:',
1141 'easeofresolution',
1142 {options: EASEOFRESOLUTION});
1143 };
1144
1145 $scope.editPolicyviolations = function() {
1146 editProperty(
1147 'scripts/commons/partials/editArray.html',
1148 'commonsModalEditArray',
1149 'Enter the new policy violations:',
1150 'policyviolations',
1151 {callback: function (vuln, policyviolations) {
1152 var violations = vuln.policyviolations.concat([]);
1153 policyviolations.forEach(function(policyviolation) {
1154 if(vuln.policyviolations.indexOf(policyviolation) == -1){
1155 violations.push(policyviolation);
1156 }
1157 });
1158
1159 return {'policyviolations': violations};
1160 }}
1161 );
1162 };
1163
1164 $scope.editReferences = function() {
1165 editProperty(
1166 'scripts/commons/partials/editArray.html',
1167 'commonsModalEditArray',
1168 'Enter the new references:',
1169 'refs',
1170 {callback: function (vuln, refs) {
1171 var references = vuln.refs.concat([]);
1172 refs.forEach(function(ref) {
1173 if(vuln.refs.indexOf(ref) == -1){
1174 references.push(ref);
1175 }
1176 });
1177
1178 return {'refs': references};
1179 }}
1180 );
1181 };
1182
1183 $scope.editImpact = function() {
1184 editProperty(
1185 'scripts/commons/partials/editObject.html',
1186 'commonsModalEditObject',
1187 'Enter the new impact:',
1188 'impact',
1189 {
1190 options: {
1191 accountability: false,
1192 availability: false,
1193 confidentiality: false,
1194 integrity: false
1195 },
1196 callback: function (vuln, impacts) {
1197 var impact = {};
1198 for(key in vuln.impact){
1199 if(vuln.impact.hasOwnProperty(key)) {
1200 impact[key] = vuln.impact[key];
1201 if(impacts.hasOwnProperty(key)) {
1202 impact[key] = impacts[key];
1203 }
1204 }
1205 }
1206 return {'impact': impact};
1207 }
1208 }
1209 );
1210 };
1211
1212 $scope.editString = function(property, message_word) {
1213 var message;
1214 if(message_word) {
1215 message = 'Enter the new ' + message_word + ':';
1216 } else {
1217 message = 'Enter the new ' + property + ':';
1218 }
1219 editProperty(
1220 'scripts/commons/partials/editString.html',
1221 'commonsModalEditString',
1222 message,
1223 property);
1224 };
1225
1226 $scope.editText = function(property, message_word) {
1227 var message;
1228 if(message_word) {
1229 message = 'Enter the new ' + message_word + ':';
1230 } else {
1231 message = 'Enter the new ' + property + ':';
1232 }
1233 editProperty(
1234 'scripts/commons/partials/editText.html',
1235 'commonsModalEditString',
1236 message,
1237 property);
1238 };
1239
1240 $scope.editConfirm = function() {
1241 editProperty(
1242 'scripts/commons/partials/editOptions.html',
1243 'commonsModalEditOptions',
1244 'Confirm/Change to false positive:',
1245 'confirmed',
1246 {
1247 options: ['Confirm', 'Set to false positive'],
1248 callback: function(vuln, data) {
1249 var property;
1250 if(data === 'Confirm') {
1251 property = {'confirmed': true};
1252 } else {
1253 property = {'confirmed': false};
1254 }
1255 return property;
1256 }
1257 }
1258 );
1259
1260 };
1261
1262 $scope.editCWE = function() {
1263 var modal = $uibModal.open({
1264 templateUrl: 'scripts/commons/partials/editCWE.html',
1265 controller: 'commonsModalEditCWE',
1266 size: 'lg',
1267 resolve: {
1268 msg: function() {
1269 return 'Vulnerability template';
1270 }
1271 }
1272 });
1273 modal.result.then(function(data) {
1274 $scope.getCurrentSelection().forEach(function(vuln) {
1275 vulnsManager.updateVuln(vuln, data).then(function(vulns){
1276 }, function(errorMsg){
1277 // TODO: show errors somehow
1278 console.log("Error updating vuln " + vuln._id + ": " + errorMsg);
1279 });
1280 });
1281 });
1282 };
1283
1284 var loadVulns = function() {
1285 delete searchFilter.confirmed;
1286 $scope.loading = true;
1287 if ($scope.propertyFilterConfirmed === 'Confirmed')
1288 searchFilter.confirmed = true;
1289 if ($scope.propertyFilterConfirmed === 'Unconfirmed'){
1290 searchFilter.confirmed = false;
1291 }
1292
1293 if(paginationOptions.sortColumn == "metadata.creator")
1294 paginationOptions.sortColumn = "tool";
1295 // load all vulnerabilities
1296 vulnsManager.getVulns($scope.workspace,
1297 paginationOptions.page,
1298 paginationOptions.pageSize,
1299 searchFilter,
1300 paginationOptions.sortColumn,
1301 paginationOptions.sortDirection)
1302 .then(function(response) {
1303 $scope.loading = false;
1304 $scope.gridOptions.data = response.vulnerabilities;
1305 $scope.gridOptions.totalItems = response.count;
1306
1307 // Add the total amount of vulnerabilities as an option for pagination
1308 // if it is larger than our biggest page size
1309 /*if ($scope.gridOptions.totalItems > paginationOptions.defaultPageSizes[paginationOptions.defaultPageSizes.length - 1]) {
1310
1311 $scope.gridOptions.paginationPageSizes = paginationOptions.defaultPageSizes.concat([$scope.gridOptions.totalItems]);
1312
1313 // sadly, this will load the vuln list again because it fires a paginationChanged event
1314 if ($scope.gridOptions.paginationPageSize > $scope.gridOptions.totalItems)
1315 $scope.gridOptions.paginationPageSize = $scope.gridOptions.totalItems;
1316
1317 // New vuln and MAX items per page setted => reload page size.
1318 if ($scope.gridOptions.paginationPageSize === $scope.gridOptions.totalItems - 1)
1319 $scope.gridOptions.paginationPageSize = $scope.gridOptions.totalItems;
1320
1321 }*/
1322 });
1323 };
1324
1325 $scope.new = function() {
1326 $scope.hideVulnPreview();
1327 var modal = $uibModal.open({
1328 templateUrl: 'scripts/statusReport/partials/modalNew.html',
1329 backdrop : 'static',
1330 controller: 'modalNewVulnCtrl as modal',
1331 size: 'lg',
1332 resolve: {
1333 severities: function() {
1334 return $scope.severities;
1335 },
1336 workspace: function() {
1337 return $scope.workspace;
1338 },
1339 customFields: function () {
1340 return $scope.customFields;
1341 }
1342 }
1343 });
1344
1345 modal.result.then(function(data) {
1346 loadVulns();
1347 });
1348 };
1349
1350 var loadFilteredVulns = function(wsName, jsonOptions) {
1351 delete searchFilter.confirmed;
1352 $scope.loading = true;
1353
1354 vulnsManager.getFilteredVulns(wsName, jsonOptions)
1355 .then(function(response) {
1356 $scope.loading = false;
1357 $scope.gridOptions.data = response.vulnerabilities;
1358 $scope.gridOptions.totalItems = response.count;
1359
1360 // Add the total amount of vulnerabilities as an option for pagination
1361 // if it is larger than our biggest page size
1362 if ($scope.gridOptions.totalItems > paginationOptions.defaultPageSizes[paginationOptions.defaultPageSizes.length - 1]) {
1363
1364 $scope.gridOptions.paginationPageSizes = paginationOptions.defaultPageSizes.concat([$scope.gridOptions.totalItems]);
1365
1366 // sadly, this will load the vuln list again because it fires a paginationChanged event
1367 if ($scope.gridOptions.paginationPageSize > $scope.gridOptions.totalItems)
1368 $scope.gridOptions.paginationPageSize = $scope.gridOptions.totalItems;
1369
1370 // New vuln and MAX items per page setted => reload page size.
1371 if ($scope.gridOptions.paginationPageSize === $scope.gridOptions.totalItems - 1)
1372 $scope.gridOptions.paginationPageSize = $scope.gridOptions.totalItems;
1373
1374 }
1375 })
1376 .catch(function(error){
1377 $scope.loading = false;
1378 commonsFact.showMessage('Invalid filter, please check the documentation: support.faradaysec.com');
1379 });
1380 };
1381
1382 $scope.searchFor = function(params, clear, search) {
1383 // TODO: REFACTOR
1384 if (clear === true){
1385 if(window.location.hash.substring(1).indexOf('groupby') === -1) {
1386 $scope.propertyFilterConfirmed = "All";
1387 $cookies.put('filterConfirmed', $scope.propertyFilterConfirmed);
1388 $location.path("/status/ws/" + $routeParams.wsId);
1389 }else{
1390 var url = "/status/ws/" + $routeParams.wsId + "/groupby/" + $routeParams.groupbyId;
1391 $location.path(url);
1392 }
1393 $scope.searchParams = '';
1394 loadVulns();
1395 return;
1396 }
1397
1398 if (search === false) {
1399 params = params.replace(/\s?(and)?\s?confirmed:(true|false)\s?(and)?/g, '');
1400 if ($scope.propertyFilterConfirmed !== "All") {
1401 if ($scope.propertyFilterConfirmed === 'Confirmed')
1402 params += params === '' ? "confirmed:true" : " and confirmed:true";
1403 if ($scope.propertyFilterConfirmed === 'Unconfirmed')
1404 params += params === '' ? "confirmed:false" : " and confirmed:false";
1405 }
1406 }else{
1407 if (params.indexOf('confirmed:true') > -1)
1408 $scope.propertyFilterConfirmed = 'Confirmed';
1409 if (params.indexOf('confirmed:false') > -1)
1410 $scope.propertyFilterConfirmed = 'Unconfirmed'
1411 }
1412
1413 // the url without reloading the controller
1414 $scope.searchParams = params;
1415 if(window.location.hash.substring(1).indexOf('groupby') === -1) {
1416 if (params !== undefined && params !== ''){
1417 params = params.replace(/^ +| +$/g, '');
1418 var jsonOptions = parserFact.evaluateExpression(params);
1419 if (jsonOptions !== null){
1420 loadFilteredVulns($routeParams.wsId, jsonOptions);
1421 }
1422 }else{
1423 loadVulns();
1424 }
1425
1426 } else {
1427 if (params !== undefined && params !== '') {
1428 params = params.replace(/^ +| +$/g, '');
1429 var jsonOptions = parserFact.evaluateExpression(params);
1430 if (jsonOptions !== null){
1431 loadFilteredVulns($routeParams.wsId, jsonOptions);
1432 }
1433 }
1434 var url = "/status/ws/" + $routeParams.wsId + "/groupby/" + $routeParams.groupbyId;
1435 $location.path(url);
1436 }
1437 };
1438
1439 // toggles column show property
1440 $scope.toggleShow = function(column, show) {
1441 column = column.toLowerCase();
1442 $scope.columns[column] = !show;
1443 for (i = 0; i < $scope.gridOptions.columnDefs.length; i++) {
1444 if($scope.gridOptions.columnDefs[i].name === column || $scope.gridOptions.columnDefs[i].displayName === column) {
1445 $scope.gridOptions.columnDefs[i].visible = !$scope.gridOptions.columnDefs[i].visible;
1446 $scope.gridApi.grid.refresh();
1447 }
1448 }
1449 $cookies.put('SRcolumns', JSON.stringify($scope.columns));
1450 recalculateLastVisibleColSize();
1451 };
1452
1453 $scope.isValidExpression = function (expression) {
1454 return parserFact.isValid(expression);
1455 };
1456
1457 var compareSeverities = function(a, b) {
1458 if(a !== 'undefined' || b !== 'undefined') {
1459 var res = 1;
1460 if($scope.severities.indexOf(a) === $scope.severities.indexOf(b)) { return 0; }
1461 if($scope.severities.indexOf(a) > $scope.severities.indexOf(b)) {
1462 res = -1;
1463 }
1464 return res;
1465 }
1466 };
1467
1468 $scope.selectionChange = function() {
1469 $scope.vulnWebSelected = $scope.getCurrentSelection().some(function(v) {
1470 return v.type === "VulnerabilityWeb"
1471 });
1472 };
1473
1474 $scope.serviceSearch = function(srvName) {
1475 return $scope.encodeUrl(srvName);
1476 };
1477
1478 function toggleFileUpload() {
1479 if($scope.fileUploadEnabled === false) {
1480 $scope.fileUploadEnabled = true;
1481 } else {
1482 $scope.fileUploadEnabled = false;
1483 $scope.fileToUpload = undefined;
1484 }
1485 }
1486
1487 $scope.enableFileUpload = function() {
1488 if($scope.fileUploadEnabled === undefined) {
1489 $http.get($scope.baseurl + '_api/session').then(
1490 function(d) {
1491 $scope.csrf_token = d.data.csrf_token;
1492 $scope.fileUploadEnabled = true;
1493 }
1494 );
1495 } else {
1496 toggleFileUpload();
1497 }
1498 };
1499 $scope.uploadFile = function() {
1500 var fd = new FormData();
1501 fd.append('csrf_token', $scope.csrf_token);
1502 fd.append('file', $scope.fileToUpload);
1503 $http.post($scope.baseurl + '_api/v2/ws/' + $scope.workspace + '/upload_report', fd, {
1504 transformRequest: angular.identity,
1505 withCredentials: false,
1506 headers: {'Content-Type': undefined},
1507 responseType: "arraybuffer",
1508 }).then(
1509 function(d) {
1510 $location.path("/dashboard/ws/" + $routeParams.wsId);
1511 },
1512 function(d){
1513 commonsFact.showMessage("Error uploading report");
1514 }
1515 );
1516 };
1517
1518 $scope.cancelFile = function() {
1519 $scope.fileToUpload = undefined;
1520 $('#upload_report_input_file').prop("value", "")
1521 }
1522
1523 $scope.concatForTooltip = function (items, isArray, useDoubleLinebreak) {
1524 var elements = [];
1525 for (var property in items) {
1526 if (items.hasOwnProperty(property)) {
1527 if (isArray) {
1528 elements.push(items[property])
1529 }
1530 else {
1531 elements.push(property)
1532 }
1533 }
1534 }
1535
1536 return elements.join("\n" + (useDoubleLinebreak ? "\n" : ""));
1537 };
1538
1539 $scope.showVulnPreview = function () {
1540 $scope.isShowingPreview = true;
1541 angular.element('#vuln-preview').addClass('show-preview');
1542 // angular.element('.faraday-page-header').addClass('show-preview');
1543 // angular.element('#btn_bar').addClass('show-preview');
1544 };
1545
1546 $scope.hideVulnPreview = function () {
1547 $scope.lastClickedVuln = undefined;
1548 $scope.isShowingPreview = false;
1549 angular.element('#vuln-preview').removeClass('show-preview');
1550 // angular.element('.faraday-page-header').removeClass('show-preview');
1551 // angular.element('#btn_bar').removeClass('show-preview');
1552 };
1553
1554
1555 var updateSelectedVulnAtachments = function () {
1556 var url = $scope.baseurl + '_api/v2/ws/' + $routeParams.wsId + '/vulns/' + $scope.lastClickedVuln._id + '/attachments/';
1557 $http.get(url).then(
1558 function (response) {
1559 $scope.lastClickedVuln._attachments = response.data
1560 }
1561 );
1562 };
1563
1564 $scope.toggleVulnPreview = function (e, vuln) {
1565 e.stopPropagation();
1566 if ($scope.lastClickedVuln !== undefined && $scope.lastClickedVuln._id === vuln._id){
1567 $scope.hideVulnPreview();
1568 $scope.lastClickedVuln = undefined;
1569 }else{
1570 $scope.showVulnPreview();
1571 $scope.realVuln = vuln;
1572 $scope.lastClickedVuln = angular.copy(vuln);
1573 updateSelectedVulnAtachments();
1574 uiCommonFact.updateBtnSeverityColor($scope.lastClickedVuln.severity, '#btn-chg-severity-prev', '#caret-chg-severity-prev');
1575 uiCommonFact.updateBtnStatusColor($scope.lastClickedVuln.status, '#btn-chg-status-prev', '#caret-chg-status-prev');
1576 }
1577 $scope.cwe_selected = undefined;
1578 $scope.selectedAtachment = {
1579 url: '',
1580 name: '',
1581 imgPrevFail: false
1582 };
1583
1584 $scope.uploader.clearQueue();
1585 };
1586
1587
1588 $scope.changeVulnPrevByEventKey = function (event) {
1589 if ($scope.lastClickedVuln !== undefined) {
1590 var curRowindex = -1;
1591 var targetIndex = -1;
1592 for (var i = 0; i < $scope.gridApi.grid.rows.length; i++) {
1593 if ($scope.gridApi.grid.rows[i].entity._id === $scope.lastClickedVuln._id) {
1594 curRowindex = i;
1595 break;
1596 }
1597 }
1598
1599 if (event.keyCode === uiGridConstants.keymap.DOWN)
1600 targetIndex = curRowindex + 1;
1601 else if (event.keyCode === uiGridConstants.keymap.UP)
1602 targetIndex = curRowindex - 1;
1603
1604 if (targetIndex !== -1 && targetIndex < $scope.gridApi.grid.rows.length) {
1605 $scope.lastClickedVuln = $scope.gridApi.grid.rows[targetIndex].entity;
1606 }
1607 }
1608
1609 };
1610
1611 $scope.activeEditPreview = function (field) {
1612 $scope.fieldToEdit = field;
1613 };
1614
1615 $scope.processToEditPreview = function (isMandatory) {
1616 if (($scope.lastClickedVuln.hasOwnProperty($scope.fieldToEdit) &&
1617 $scope.lastClickedVuln[$scope.fieldToEdit] !== undefined &&
1618 $scope.lastClickedVuln[$scope.fieldToEdit] !== '') || isMandatory === false){
1619
1620 $scope.isUpdatingVuln = true;
1621 if ($scope.realVuln[$scope.fieldToEdit] !== $scope.lastClickedVuln[$scope.fieldToEdit] ||
1622 ($scope.realVuln['custom_fields'].hasOwnProperty($scope.fieldToEdit))){
1623 vulnsManager.updateVuln($scope.realVuln, $scope.lastClickedVuln).then(function () {
1624 $scope.isUpdatingVuln = false;
1625 $scope.fieldToEdit = undefined;
1626 }, function (data) {
1627 $scope.hideVulnPreview();
1628 commonsFact.showMessage("Error updating vuln " + $scope.realVuln.name + " (" + $scope.realVuln._id + "): " + (data.message || JSON.stringify(data.messages)));
1629 $scope.fieldToEdit = undefined;
1630 $scope.isUpdatingVuln = false;
1631 });
1632 }else{
1633 $scope.fieldToEdit = undefined;
1634 $scope.isUpdatingVuln = false;
1635 }
1636
1637 }
1638 };
1639
1640 $scope.changeSeverity = function (severity) {
1641 $scope.fieldToEdit = 'severity';
1642 $scope.lastClickedVuln.severity = severity;
1643 uiCommonFact.updateBtnSeverityColor(severity, '#btn-chg-severity-prev', '#caret-chg-severity-prev');
1644 $scope.processToEditPreview();
1645 };
1646
1647 $scope.changeEaseOfResolution = function (easeofresolution) {
1648 $scope.fieldToEdit = 'easeofresolution';
1649 $scope.lastClickedVuln.easeofresolution = easeofresolution;
1650 $scope.processToEditPreview();
1651 };
1652
1653 $scope.changeStatus = function (status) {
1654 $scope.fieldToEdit = 'status';
1655 $scope.lastClickedVuln.status = status;
1656 uiCommonFact.updateBtnStatusColor(status, '#btn-chg-status-prev', '#caret-chg-status-prev');
1657 $scope.processToEditPreview();
1658 };
1659
1660 $scope.changeConfirmed = function (confirmed) {
1661 $scope.fieldToEdit = 'confirmed';
1662 $scope.lastClickedVuln.confirmed = confirmed;
1663 $scope.processToEditPreview();
1664 };
1665
1666 $scope.toggleImpact = function (key) {
1667 $scope.fieldToEdit = 'impact';
1668 $scope.lastClickedVuln.impact[key] = !$scope.lastClickedVuln.impact[key];
1669 $scope.processToEditPreview();
1670 };
1671
1672
1673 $scope.populate = function () {
1674 $scope.temTemplate = angular.copy($scope.lastClickedVuln);
1675 uiCommonFact.populate($scope.cwe_selected, $scope.lastClickedVuln);
1676 };
1677
1678 $scope.applyTemplate = function () {
1679 $scope.fieldToEdit = 'template';
1680 $scope.isUpdatingVuln = true;
1681 vulnsManager.updateVuln($scope.realVuln, $scope.lastClickedVuln).then(function () {
1682 $scope.isUpdatingVuln = false;
1683 $scope.fieldToEdit = undefined;
1684 $scope.temTemplate = undefined;
1685 $scope.cwe_selected = undefined
1686 }, function (data) {
1687 commonsFact.showMessage("Error updating vuln " + $scope.realVuln.name + " (" + $scope.realVuln._id + "): " + (data.message || JSON.stringify(data.messages)));
1688 $scope.fieldToEdit = undefined;
1689 $scope.isUpdatingVuln = false;
1690 $scope.temTemplate = undefined;
1691 $scope.cwe_selected = undefined;
1692 $scope.hideVulnPreview();
1693 });
1694 };
1695
1696 $scope.discardTemplate = function () {
1697 uiCommonFact.populate($scope.temTemplate, $scope.lastClickedVuln);
1698 $scope.temTemplate = undefined;
1699 $scope.cwe_selected = undefined;
1700 };
1701
1702
1703 $scope.newReference = function () {
1704 $scope.fieldToEdit = 'refs';
1705 uiCommonFact.newReference($scope.new_ref, $scope.lastClickedVuln);
1706 $scope.processToEditPreview();
1707 $scope.new_ref = "";
1708 };
1709
1710
1711 $scope.removeReference = function (index) {
1712 $scope.fieldToEdit = 'refs';
1713 $scope.lastClickedVuln.refs.splice(index, 1);
1714 $scope.isUpdatingVuln = true;
1715
1716 vulnsManager.updateVuln($scope.realVuln, $scope.lastClickedVuln).then(function () {
1717 $scope.isUpdatingVuln = false;
1718 $scope.fieldToEdit = undefined;
1719 }, function (data) {
1720 $scope.hideVulnPreview();
1721 commonsFact.showMessage("Error updating vuln " + $scope.realVuln.name + " (" + $scope.realVuln._id + "): " + (data.message || JSON.stringify(data.messages)));
1722 $scope.fieldToEdit = undefined;
1723 $scope.isUpdatingVuln = false;
1724
1725 });
1726 };
1727
1728 $scope.openReference = function (text) {
1729 window.open(referenceFact.processReference(text), '_blank');
1730 };
1731
1732
1733 $scope.newPolicyviolation = function () {
1734 $scope.fieldToEdit = 'policyviolations';
1735 uiCommonFact.newPolicyViolation($scope.new_policyviolation, $scope.lastClickedVuln);
1736 $scope.processToEditPreview();
1737 $scope.new_policyviolation = "";
1738 };
1739
1740
1741 $scope.removePolicyviolation = function (index) {
1742 $scope.fieldToEdit = 'policyviolations';
1743 $scope.lastClickedVuln.policyviolations.splice(index, 1);
1744 $scope.isUpdatingVuln = true;
1745
1746 vulnsManager.updateVuln($scope.realVuln, $scope.lastClickedVuln).then(function () {
1747 $scope.isUpdatingVuln = false;
1748 $scope.fieldToEdit = undefined;
1749 }, function (data) {
1750 $scope.hideVulnPreview();
1751 commonsFact.showMessage("Error updating vuln " + $scope.realVuln.name + " (" + $scope.realVuln._id + "): " + (data.message || JSON.stringify(data.messages)));
1752 $scope.fieldToEdit = undefined;
1753 $scope.isUpdatingVuln = false;
1754
1755 });
1756 };
1757
1758
1759 uploader.onAfterAddingFile = function(fileItem) {
1760 if ($scope.lastClickedVuln._attachments.hasOwnProperty(fileItem.file.name)){
1761 fileItem.isError = true;
1762 fileItem.isReady = true;
1763 return;
1764 }
1765
1766 $http.get($scope.baseurl + '_api/session').then(
1767 function(d) {
1768 $scope.csrf_token = d.data.csrf_token;
1769 fileItem.formData.push({'csrf_token': $scope.csrf_token});
1770 fileItem.file.name = fileItem.file.name.replace(/ /g, '_');
1771 fileItem.url = $scope.baseurl + '_api/v2/ws/' + $routeParams.wsId + '/vulns/' + $scope.lastClickedVuln._id + '/attachment/';
1772 $scope.uploader.uploadAll();
1773 }
1774 );
1775
1776 };
1777
1778
1779
1780 uploader.onSuccessItem = function(fileItem, response, status, headers) {
1781 updateSelectedVulnAtachments();
1782 };
1783
1784 $scope.removeEvidence = function (name) {
1785 var url = $scope.baseurl + '_api/v2/ws/'+ $routeParams.wsId +'/vulns/'+ $scope.lastClickedVuln._id +'/attachment/' + name + '/'
1786 $http.delete(url).then(
1787 function(response) {
1788 if (response && response.status === 200){
1789 uiCommonFact.removeEvidence(name, $scope.lastClickedVuln);
1790 }
1791 }
1792 );
1793 };
1794
1795 $scope.selectItemToPrev = function (name) {
1796 $scope.selectedAtachment.name = name;
1797 $scope.selectedAtachment.url = BASEURL + '_api/v2/ws/' + $routeParams.wsId + '/vulns/' + $scope.lastClickedVuln._id + '/attachment/' + name + '/';
1798 $scope.selectedAtachment.imgPrevFail = false;
1799 var format = $scope.selectedAtachment.name.split('.').pop();
1800 var imagesFormat = ['png','jpg', 'jpeg', 'gif'];
1801 if (imagesFormat.indexOf(format) === -1){
1802 $scope.selectedAtachment.imgPrevFail = true;
1803 }
1804 };
1805
1806
1807 $scope.copyToClipboard = function (name) {
1808 var url = BASEURL + '_api/v2/ws/' + $routeParams.wsId + '/vulns/' + $scope.lastClickedVuln._id + '/attachment/' + name + '/';
1809 var copyElement = document.createElement("textarea");
1810 copyElement.style.position = 'fixed';
1811 copyElement.style.opacity = '0';
1812 copyElement.textContent = decodeURI(url);
1813 var body = document.getElementsByTagName('body')[0];
1814 body.appendChild(copyElement);
1815 copyElement.select();
1816 document.execCommand('copy');
1817 body.removeChild(copyElement);
1818 }
1819
1820
1821
1822 $scope.openEvidence = function (name) {
1823 uiCommonFact.openEvidence(name, $scope.lastClickedVuln, $routeParams.wsId);
1824 };
1825
1826 $scope.processLinesToHtml = function (rawText) {
1827 if (rawText !== undefined)
1828 return rawText.replace(/(?:\r\n|\r|\n)/g, '<br>');
1829 return '';
1830 };
1831
1832 init();
1833 }]);
+0
-38
faraday/server/www/scripts/statusReport/directives/appendSearchParam.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp').directive('appendSearchParam', ['$routeParams', '$location', function ($routeParams, $location) {
5 return {
6 restrict: 'A',
7 replace: false,
8 link: function (scope, element, attr) {
9
10 element.on('click', function (event) {
11 scope.currentParams = $routeParams.search;
12 if (scope.currentParams !== undefined) {
13 scope.newParam = attr.appendSearchParam;
14 var hash = window.location.hash;
15 var basePath = hash.slice(1, hash.indexOf("search") + 7);
16 if (scope.newParam.indexOf('%2520') !== -1){
17 scope.newParam = decodeURIComponent(scope.newParam);
18 }
19
20 scope.fullPath = basePath + scope.currentParams + '&' + scope.newParam;
21 if (paramAlreadyExists(scope.currentParams, scope.newParam)) {
22 scope.fullPath = basePath + scope.currentParams;
23 }
24
25 event.preventDefault();
26 $location.path(scope.fullPath);
27 }
28 });
29
30 var paramAlreadyExists = function (currentParam, newParam) {
31 var currentParamStr = decodeURIComponent(decodeURIComponent(currentParam));
32 var newParamStr = decodeURIComponent(decodeURIComponent(newParam));
33 return currentParamStr === newParamStr || currentParamStr.indexOf(newParamStr) !== -1;
34 }
35 }
36 };
37 }]);
+0
-15
faraday/server/www/scripts/statusReport/directives/autofocus.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('autofocus', ['$timeout', function ($timeout) {
6 return {
7 restrict: 'A',
8 link: function ($scope, $element) {
9 $timeout(function () {
10 $element[0].focus();
11 });
12 }
13 }
14 }]);
+0
-38
faraday/server/www/scripts/statusReport/directives/checkCustomType.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('checkCustomType', function () {
6 return {
7 restrict: 'A',
8 link: function (scope, elm, attrs, ctrl) {
9 elm.on('keydown', function (event) {
10 if (attrs.checkCustomType === 'int') {
11 if (event.shiftKey) {
12 event.preventDefault();
13 return false;
14 }
15 //console.log(event.which);
16 if ([8, 13, 27, 37, 38, 39, 40].indexOf(event.which) > -1) {
17 // backspace, enter, escape, arrows
18 return true;
19 } else if (event.which >= 48 && event.which <= 57) {
20 // numbers 0 to 9
21 return true;
22 } else if (event.which >= 96 && event.which <= 105) {
23 // numpad number
24 return true;
25 }
26 else {
27 event.preventDefault();
28 return false;
29 }
30 }else {
31 return true;
32 }
33
34 });
35 }
36 }
37 });
+0
-100
faraday/server/www/scripts/statusReport/directives/customField.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('customField', [function () {
6 return {
7 restrict: 'E',
8 scope: true,
9 replace: true,
10 template: '<div>\
11 <div ng-if="cf.field_type === \'str\'" ng-init="isEditable = true"> \n\
12 <div class="tab-pane-header" ng-dblclick="isEditable = true" title="Double click to edit">{{cf.field_display_name}} <span class="glyphicon glyphicon-question-sign" title="Edit using markdown code"></span></div> \n\
13 <div class="form-group"> \n\
14 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
15 <textarea class="form-control" rows="5" id="vuln-desc" name="desc" ng-show="isEditable === true" \n\
16 ng-model="modal.data.custom_fields[cf.field_name]" ng-bind-html="modal.data.custom_fields[cf.field_name] | markdown" \n\
17 style="margin: 0 2px 0 0;" ng-blur="isEditable = isEditable.length==0 || !modal.data.custom_fields[cf.field_name]" autofocus> \n\
18 </textarea> \n\
19 <div class="col-md-12" ng-cloak ng-show="modal.data.custom_fields[cf.field_name].length > 0 && isEditable === false"> \n\
20 <div class="markdown-preview" style="height: 100px;!important;" ng-bind-html="modal.data.custom_fields[cf.field_name] | markdown" ng-dblclick="isEditable = true">{{modal.data.custom_fields[cf.field_name] | markdown}}</div> \n\
21 </div> \n\
22 </div> \n\
23 </div> \n\
24 <div ng-if="cf.field_type === \'int\'"> \n\
25 <div class="tab-pane-header">{{cf.field_display_name}}</div> \n\
26 <div class="form-group"> \n\
27 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
28 <input type="text" class="form-control input-sm" id="{{cf.field_name}}" name="{{cf.field_name}}" \n\
29 placeholder="{{cf.field_display_name}}" \n\
30 ng-model="modal.data.custom_fields[cf.field_name]" check-custom-type="{{cf.field_type}}" \n\
31 uib-tooltip="Type only numbers"/> \n\
32 </div> \n\
33 </div> \n\ \
34 <div ng-if="cf.field_type === \'choice\'"> \n\
35 <div class="tab-pane-header">{{cf.field_display_name}}</div> \n\
36 <div class="btn-group col-md-6 col-sm-6 col-xs-6 btn-cf-choice" ng-if="cf.field_type === \'choice\'"> \n\
37 <button type = "button" class="dropdown-toggle btn-change-property primary-btn btn-primary-white no-overflow" data-toggle = "dropdown" id="btn-chg-choice" title="Choices">\n\
38 <span ng-if="modal.data.custom_fields[cf.field_name] !== null">{{modal.data.custom_fields[cf.field_name]}}</span>\n\
39 <span ng-if="modal.data.custom_fields[cf.field_name] === null">Select {{cf.field_display_name}}</span>\n\
40 </button>\n\
41 <button type="button" class="dropdown-toggle secondary-btn btn-change-property btn-secondary-white" data-toggle="dropdown" id="caret-choice" title="Choices">\n\
42 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span> \n\
43 </button> \n\
44 <ul class="dropdown-menu dropdown-menu-right col-md-12 dropd-cf-choice" role="menu"> \n\
45 <li ng-repeat="choice in parserOptions(cf.field_metadata)">\n\
46 <a class="ws no-overflow" ng-click="modal.data.custom_fields[cf.field_name] = choice">{{choice}}</a> \n\
47 </li>\n\
48 </ul>\n\
49 </div> \n\
50 </div> \n\
51 <div ng-if="cf.field_type === \'list\'"> \n\
52 <div class="tab-pane-header">{{cf.field_display_name}}</div> \n\
53 <div class="form-group" ng-class="modal.data.custom_fields[cf.field_name].length > 0 ? \'no-margin-bottom\' : \'\'"> \n\
54 <div class="input-group"> \n\
55 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
56 <input type="text" class="form-control input-sm" id="{{cf.field_name}}_list" name="{{cf.field_name}}" \n\
57 placeholder="{{cf.field_display_name}}" \n\
58 ng-model="valueField" \n\
59 uib-tooltip="Input type list"/> \n\
60 <span class="input-group-addon cursor" ng-click="newValueField(valueField)"><i class="fa fa-plus-circle"></i></span> \n\
61 </div> \n\
62 </div> \n\
63 <div class="reference" ng-repeat="item in modal.data.custom_fields[cf.field_name] track by $index" ng-class="{\'last-item-field\':$last}" ng-if="cf.field_type === \'list\'"> \n\
64 <div class="input-group margin-bottom-sm"> \n\
65 <label class="sr-only" for="vuln-refs-create">{{cf.field_display_name}}</label> \n\
66 <input ng-if="item.value" type="text" class="form-control input-sm" id="vuln-refs-create" placeholder="{{cf.field_display_name}}" \n\
67 ng-model="item.value" \n\
68 role="button" readonly/> \n\
69 <input ng-if="!item.value" type="text" class="form-control input-sm" id="vuln-refs-create" placeholder="{{cf.field_display_name}}" \n\
70 ng-model="item" \n\
71 role="button" readonly/> \n\
72 <span class="input-group-addon cursor" ng-click="modal.data.custom_fields[cf.field_name].splice($index, 1)"> \n\
73 <i class="fa fa-minus-circle"></i></span> \n\
74 </div> \n\
75 </div> \n\
76 </div> \n\
77 </div></div>',
78 link: function (scope, element, attrs) {
79
80 scope.newValueField = function (valueField) {
81 if (valueField !== "" && valueField !== undefined) {
82 if(scope.modal.data.custom_fields[scope.cf.field_name] == null )
83 scope.modal.data.custom_fields[scope.cf.field_name] = [];
84
85 // we need to check if the ref already exists
86 if (scope.modal.data.custom_fields[scope.cf.field_name].filter(function(field) {return field.value === valueField}).length === 0) {
87 scope.modal.data.custom_fields[scope.cf.field_name].push({value: valueField});
88 scope.valueField = "";
89 }
90 angular.element('#'+scope.cf.field_name+'_list').val("");
91 }
92 }
93
94 scope.parserOptions = function (rawOptions) {
95 return JSON.parse(rawOptions)
96 }
97 }
98 }
99 }]);
+0
-130
faraday/server/www/scripts/statusReport/directives/customFieldPrev.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('customFieldPrev', ['vulnsManager', function (vulnsManager) {
6 return {
7 restrict: 'E',
8 scope: false,
9 replace: true,
10 template: '<div> \n\
11 <div ng-if="cf.field_type === \'str\'" ng-init="isEditable = true"> \n\
12 <div class="tab-pane-header" ng-dblclick="isEditable = true" title="Double click to edit"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === cf.field_name"></i> {{cf.field_display_name}} <span class="glyphicon glyphicon-question-sign" title="Edit using markdown code"></span></div> \n\
13 <div class="form-group"> \n\
14 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
15 <textarea class="form-control" placeholder="{{cf.field_display_name}}" rows="5" id="vuln-desc" name="desc" ng-show="isEditable === true" \n\
16 ng-focus="activeEditPreview(cf.field_name)" ng-blur="processToEditPreview(false); isEditable = isEditable.length==0 || !lastClickedVuln.custom_fields[cf.field_name]" ng-model="lastClickedVuln.custom_fields[cf.field_name]" ng-bind-html="lastClickedVuln.custom_fields[cf.field_name] | markdown" \n\
17 style="margin: 0 2px 0 0;" autofocus> \n\
18 </textarea> \n\
19 <div class="col-md-12" ng-cloak ng-show="lastClickedVuln.custom_fields[cf.field_name].length > 0 && isEditable === false"> \n\
20 <div class="markdown-preview" style="height: 100px;!important;" ng-bind-html="lastClickedVuln.custom_fields[cf.field_name] | markdown" ng-dblclick="isEditable = true">{{lastClickedVuln.custom_fields[cf.field_name] | markdown}}</div> \n\
21 </div> \n\
22 </div> \n\
23 </div> \n\
24 <div ng-if="cf.field_type === \'int\'"> \n\
25 <div class="tab-pane-header"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === cf.field_name"></i> {{cf.field_display_name}}</div> \n\
26 <div class="form-group">\n\
27 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
28 <input type="text" class="form-control input-sm" id="{{cf.field_name}}" name="{{cf.field_name}}" \n\
29 placeholder="{{cf.field_display_name}}" \n\
30 ng-focus="activeEditPreview(cf.field_name)" \
31 ng-blur="processToEditPreview(false)"\
32 ng-model="lastClickedVuln.custom_fields[cf.field_name]" check-custom-type="{{cf.field_type}}" \n\
33 uib-tooltip="Type only numbers"/> \n\
34 </div> \n\
35 </div> \n\ \
36 <div ng-if="cf.field_type === \'choice\'"> \n\
37 <div class="tab-pane-header"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === cf.field_name"></i> {{cf.field_display_name}}</div> \n\
38 <div class="btn-group col-md-6 col-sm-6 col-xs-6 btn-cf-choice" ng-if="cf.field_type === \'choice\'"> \n\
39 <button type="button" class="dropdown-toggle btn-change-property primary-btn btn-primary-white no-overflow" data-toggle = "dropdown" id = "btn-chg-choice" title = "Choices">\n\
40 <span ng-if="lastClickedVuln.custom_fields[cf.field_name] !== null" > {{lastClickedVuln.custom_fields[cf.field_name]}}</span>\n\
41 <span ng-if="lastClickedVuln.custom_fields[cf.field_name] === null">Select {{cf.field_display_name}}</span> \n\
42 </button> \n\
43 <button type="button" class="dropdown-toggle secondary-btn btn-change-property btn-secondary-white" data-toggle="dropdown" id="caret-choice" title="Choices"> \n\
44 <span><i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span> \n\
45 </button> \n\
46 <ul class="dropdown-menu dropdown-menu-right col-md-12 dropd-cf-choice" role="menu"> \n\
47 <li ng-repeat="choice in parserOptions(cf.field_metadata)"> \n\
48 <a class="ws no-overflow" href="javascript:;" ng-click="onChangeChoiceCf(choice)">{{choice}}</a> \n\
49 </li> \n\
50 </ul> \n\
51 </div> \n\
52 </div> \n\
53 <div ng-if="cf.field_type === \'list\'"> \n\
54 <div class="tab-pane-header"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === cf.field_name"></i> {{cf.field_display_name}}</div> \n\
55 <div class="form-group" ng-class="lastClickedVuln.custom_fields[cf.field_name].length > 0 ? \'no-margin-bottom\' : \'\'">\n\
56 <div class="input-group"> \n\
57 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
58 <input type="text" class="form-control input-sm" id="{{cf.field_name}}" name="{{cf.field_name}}" \n\
59 placeholder="{{cf.field_display_name}}" \n\
60 ng-focus="activeEditPreview(cf.field_name)" \
61 ng-model="valueField" \n\
62 uib-tooltip="Input type list"/> \n\
63 <span class="input-group-addon cursor" ng-click="newValueField(valueField)"><i class="fa fa-plus-circle"></i></span> \n\
64 </div> \n\
65 </div> \n\
66 <div class="reference" ng-repeat="item in lastClickedVuln.custom_fields[cf.field_name] track by $index" ng-class="{\'last-item-field\':$last}" ng-if="cf.field_type === \'list\'"> \n\
67 <div class="input-group margin-bottom-sm"> \n\
68 <label class="sr-only" for="vuln-refs-create">{{cf.field_display_name}}</label> \n\
69 <input ng-if="item.value" type="text" class="form-control input-sm" id="vuln-refs-create" placeholder="{{cf.field_display_name}}" \n\
70 ng-model="item.value" \n\
71 role="button" readonly/> \n\
72 <input ng-if="!item.value" type="text" class="form-control input-sm" id="vuln-refs-create" placeholder="{{cf.field_display_name}}" \n\
73 ng-model="item" \n\
74 role="button" readonly/> \n\
75 <span class="input-group-addon cursor" ng-click="removeValueField($index)"> \n\
76 <i class="fa fa-minus-circle"></i></span> \n\
77 </div> \n\
78 </div> \n\
79 </div></div>',
80 link: function (scope, element, attrs) {
81 scope.newValueField = function (valueField) {
82 if (valueField !== "" && valueField !== undefined) {
83 if (scope.lastClickedVuln.custom_fields[scope.cf.field_name] === null)
84 scope.lastClickedVuln.custom_fields[scope.cf.field_name] = [];
85
86 // we need to check if the ref already exists
87 if (scope.lastClickedVuln.custom_fields[scope.cf.field_name].filter(function (field) {
88 return field.value === valueField
89 }).length === 0) {
90 scope.lastClickedVuln.custom_fields[scope.cf.field_name].push({value: valueField});
91 scope.valueField = "";
92 }
93 angular.element('#' + scope.cf.field_name).val("");
94
95 scope.fieldToEdit = scope.cf.field_name;
96 scope.processToEditPreview(false);
97
98 }
99 };
100
101 scope.removeValueField = function (index) {
102 scope.fieldToEdit = scope.cf.field_name;
103 scope.lastClickedVuln.custom_fields[scope.cf.field_name].splice(index, 1);
104 scope.isUpdatingVuln = true;
105
106 vulnsManager.updateVuln(scope.realVuln, scope.lastClickedVuln).then(function () {
107 scope.isUpdatingVuln = false;
108 scope.fieldToEdit = undefined;
109 }, function (data) {
110 scope.hideVulnPreview();
111 commonsFact.showMessage("Error updating vuln " + scope.realVuln.name + " (" + scope.realVuln._id + "): " + (data.message || JSON.stringify(data.messages)));
112 scope.fieldToEdit = undefined;
113 scope.isUpdatingVuln = false;
114
115 });
116 };
117
118 scope.onChangeChoiceCf = function (value) {
119 scope.fieldToEdit = scope.cf.field_name;
120 scope.activeEditPreview(scope.cf.field_name);
121 scope.lastClickedVuln.custom_fields[scope.cf.field_name] = value;
122 scope.processToEditPreview(false);
123 };
124
125 scope.parserOptions = function (rawOptions) {
126 return JSON.parse(rawOptions)
127 };
128 }}
129 }]);
+0
-52
faraday/server/www/scripts/statusReport/directives/textCollapse.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('textCollapse', ['$compile', 'commonsFact', function($compile, commons) {
6 return {
7 restrict: 'A',
8 replace: true,
9 link: function(scope, element, attrs) {
10 // start collapsed
11 scope.collapsed = false;
12
13 // create the function to toggle the collapse
14 scope.toggle = function() {
15 scope.collapsed = !scope.collapsed;
16 };
17
18 // wait for changes on the text
19 attrs.$observe('textCollapseText', function(text) {
20 // escape text
21 text = commons.htmlentities(text);
22
23 // and get the maxLength
24 var maxLength = scope.$eval(attrs.textCollapseMaxLength);
25
26 if(text.length > maxLength) {
27 // split the text in two parts, the first always showing
28 var firstPart = String(text).substring(0, maxLength);
29 var secondPart = String(text).substring(maxLength, text.length);
30
31 // create some new html elements to hold the separate info
32 var firstSpan = $compile('<span>' + firstPart + '</span>')(scope);
33 var secondSpan = $compile('<span ng-if="collapsed">' + secondPart + '</span>')(scope);
34 var moreIndicatorSpan = $compile('<span ng-if="!collapsed">...</span>')(scope);
35 var toggleButton = $compile('<span selection-model-ignore class="collapse-text-toggle" ng-click="toggle()"> <a href="" selection-model-ignore>{{collapsed ? "less" : "more"}}</a></span>')(scope);
36
37 // remove the current contents of the element
38 // and add the new ones we created
39 element.empty();
40 element.append(firstSpan);
41 element.append(secondSpan);
42 element.append(moreIndicatorSpan);
43 element.append(toggleButton);
44 } else {
45 element.empty();
46 element.append(text);
47 }
48 });
49 }
50 };
51 }]);
+0
-15
faraday/server/www/scripts/statusReport/partials/accordion-group.html less more
0 <div class="panel panel-default">
1 <div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">
2 <h4 class="panel-title">
3 <span uib-accordion-transclude="heading" class="accordion-toggle" uib-tabindex-toggle>
4 <span uib-accordion-header ng-class="{'text-muted': isDisabled}">
5 {{heading}}
6 </span>
7 <i class="pull-right glyphicon accordion-expand-button" ng-class="{'glyphicon glyphicon-minus-sign': isOpen, 'glyphicon glyphicon-plus-sign': !isOpen, 'accordion-expand-button-disabled': isDisabled}" ng-disabled="isDisabled" role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" ng-click="toggleOpen()"></i>
8 </span>
9 </h4>
10 </div>
11 <div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" uib-collapse="!isOpen">
12 <div class="panel-body" ng-transclude></div>
13 </div>
14 </div>
+0
-38
faraday/server/www/scripts/statusReport/partials/exploitsModal.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2017 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header">
5 <h3 class="modal-title">
6 <span class="glyphicon glyphicon-ok">
7 </span> Exploit(s) found for vulnerability!
8 </h3>
9 </div>
10
11 <div class="modal-body" ng-repeat="cve in objsCve">
12 <div>
13 <span> Based on the {{cve.cveid}} the following has been found:</span>
14 <h2>Metasploit</h2>
15 </div>
16
17 <div style="Padding:7px" ng-repeat="n in cve.metasploit">
18 <span><b>{{n.title | lowercase}}</b></span>
19 <h5 style="Padding:3px;background-color: #eee">{{ n.id.replace('MSF:','use ') | lowercase }}</h5>
20 <span><a ng-href="https://www.rapid7.com/db/modules/{{ n.id.replace('MSF:','') | lowercase }}">https://www.rapid7.com/db/modules/{{ n.id.replace('MSF:','') | lowercase }}</a></span>
21 </div>
22
23 <div>
24 <h2>ExploitDB</h2>
25 </div>
26
27 <div style="Padding:7px" ng-repeat="n in cve.exploitdb">
28 <b>{{n.id}} | {{n.title}}</b>
29 <h5>
30 <div><a ng-href="{{n.href}}">{{n.href}}</a></div>
31 </h5>
32 </div>
33
34 </div>
35 <div class="modal-footer">
36 <button class="btn btn-success" ng-click="ok()">OK</button>
37 </div>
+0
-427
faraday/server/www/scripts/statusReport/partials/modalEdit.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="formEdit" novalidate>
5 <!--<div class="modal-header">-->
6 <!--<div class="modal-button">-->
7 <!--<button class="btn btn-success" ng-click="modal.ok()"-->
8 <!--ng-disabled="formEdit.$invalid || modal.data.severity === undefined">OK-->
9 <!--</button>-->
10 <!--<button class="btn btn-danger" ng-click="modal.cancel()">Cancel</button>-->
11 <!--</div>-->
12 <!--<h3 class="modal-title">Vulnerability edit</h3>-->
13 <!--</div>-->
14
15
16 <div class="modal-body">
17
18 <div class="mt-3">
19 <div class="modal-data-name" ng-init="modal.isNameEditable = false">
20 <div ng-if="modal.isNameEditable == false && modal.data.name !== undefined">
21 <span class="data-name">{{modal.data.name}}</span>
22 <span class="edit-name-icon" ng-click="modal.isNameEditable = true"><i
23 class="fa fa-pencil fa-lg" aria-hidden="true"></i></span>
24 </div>
25
26 <div ng-if="modal.isNameEditable == true || modal.data.name == undefined">
27 <div class="form-group" ng-class="{'has-error': formEdit.name.$invalid }">
28 <label class="sr-only" for="inp-edit-name">Vuln name</label>
29 <input type="text" class="form-control" id="inp-edit-name"
30 ng-model="modal.data.name" name="name" placeholder="Vuln name"
31 ng-blur="modal.isNameEditable = modal.data.name == undefined "
32 autofocus required>
33 </div>
34 </div>
35
36 </div>
37
38 <div class="edit-vulns-dropdowns row" ng-init="modal.updateBtnSeverityColor(modal.data.severity);modal.updateBtnStatusColor(modal.data.status)">
39
40 <div class="btn-group col-md-3 col-sm-6 col-xs-6">
41 <button type="button" class="dropdown-toggle btn-change-property primary-btn"
42 data-toggle="dropdown"
43 id="btn-chg-severity"
44 title="{{modal.data.severity}}">
45 {{modal.data.severity | uppercase}}
46 </button>
47 <button type="button" class="dropdown-toggle secondary-btn btn-change-property"
48 data-toggle="dropdown"
49 id="caret-chg-severity"
50 title="Change severity">
51 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
52 </button>
53 <ul class="dropdown-menu dropdown-menu-right" role="menu">
54 <li>
55 <a class="ws"
56 ng-click="modal.changeSeverity('unclassified')">UNCLASSIFIED</a>
57 <a class="ws"
58 ng-click="modal.changeSeverity('info')">INFO</a>
59 <a class="ws"
60 ng-click="modal.changeSeverity('low')">LOW</a>
61 <a class="ws"
62 ng-click="modal.changeSeverity('med')">MEDIUM</a>
63 <a class="ws"
64 ng-click="modal.changeSeverity('high')">HIGH</a>
65 <a class="ws"
66 ng-click="modal.changeSeverity('critical')">CRITICAL</a>
67 </li>
68 </ul>
69 </div>
70
71
72 <div class="btn-group col-md-3 col-sm-6 col-xs-6">
73 <button type="button" class="dropdown-toggle btn-change-property primary-btn btn-primary-white"
74 data-toggle="dropdown"
75 id="btn-chg-ease_resolution"
76 title="{{modal.data.easeofresolution}}">
77 {{modal.data.easeofresolution || "Ease of Resolution"}}
78 </button>
79 <button type="button" class="dropdown-toggle secondary-btn btn-change-property btn-secondary-white"
80 data-toggle="dropdown"
81 id="caret-ease_resolution"
82 title="Change Ease of Resolution">
83 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
84 </button>
85 <ul class="dropdown-menu dropdown-menu-right" role="menu">
86 <li>
87 <a class="ws"
88 ng-click="modal.data.easeofresolution = null">Undetermined</a>
89 <a class="ws"
90 ng-click="modal.data.easeofresolution = 'trivial'">Trivial</a>
91 <a class="ws"
92 ng-click="modal.data.easeofresolution = 'simple'">Simple</a>
93 <a class="ws"
94 ng-click="modal.data.easeofresolution = 'moderate'">Moderate</a>
95 <a class="ws"
96 ng-click="modal.data.easeofresolution = 'difficult'">Difficult</a>
97 <a class="ws"
98 ng-click="modal.data.easeofresolution = 'infeasible'">Infeasible</a>
99 </li>
100 </ul>
101 </div>
102
103
104 <div class="btn-group col-md-3 col-sm-6 col-xs-6">
105 <button type="button" class="dropdown-toggle btn-change-property primary-btn text-capitalize"
106 data-toggle="dropdown"
107 id="btn-chg-status"
108 title="{{modal.data.status}}">
109 {{modal.data.status || "Status"}}
110 </button>
111 <button type="button" class="dropdown-toggle secondary-btn btn-change-property"
112 data-toggle="dropdown"
113 id="caret-chg-status"
114 title="Change Status">
115 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
116 </button>
117 <ul class="dropdown-menu dropdown-menu-right" role="menu">
118 <li>
119 <a class="ws"
120 ng-click="modal.changeStatus('opened')">Opened</a>
121 <a class="ws"
122 ng-click="modal.changeStatus('closed')">Closed</a>
123 <a class="ws"
124 ng-click="modal.changeStatus('re-opened')">Re-opened</a>
125 <a class="ws"
126 ng-click="modal.changeStatus('risk-accepted')">Risk-accepted</a>
127 </li>
128 </ul>
129 </div>
130
131 <div class="col-md-3 col-sm-6 col-xs-6">
132 <label class="chbox-container">
133 <div class="tab-pane-header"><h4>Confirmed</h4></div>
134 <input type="checkbox" ng-checked="modal.data.confirmed === true" ng-model="modal.data.confirmed">
135 <span class="checkmark"></span>
136 </label>
137 </div>
138
139 </div>
140
141
142 <!-- Nav tabs -->
143 <ul class="nav nav-tabs" id="nav-tabs-container">
144 <li class="nav-item active" ng-class="{'has-error': formEdit.desc.$invalid}">
145 <a class="nav-link active" data-toggle="tab" data-target="#general"
146 href="javascript:;">General</a>
147 </li>
148 <li class="nav-item">
149 <a class="nav-link" data-toggle="tab" data-target="#technical_details" href="javascript:;">Technical
150 Details</a>
151 </li>
152 <li class="nav-item">
153 <a class="nav-link" data-toggle="tab" data-target="#tab-evidence" href="javascript:;">Evidence</a>
154 </li>
155 <li class="nav-item">
156 <a class="nav-link" data-toggle="tab" data-target="#tab-custom-fields" href="javascript:;">Custom Fields</a>
157 </li>
158 </ul>
159
160 <!-- Tab panes -->
161 <div class="tab-content">
162 <div id="general" class="container tab-pane-container tab-pane active"><br>
163
164 <div class="col-md-12">
165 <div class="tab-pane-header">Search vulnerability database templates
166 <a
167 href="https://github.com/infobyte/faraday/wiki/vulnerabilities-database"
168 target="_blank"><span class="glyphicon glyphicon-question-sign"
169 title="Read more about vulnerability templates in the official Faraday Documentation"></span></a>
170 </div>
171 <div class="form-group">
172 <input type="text" ng-model="modal.cwe_selected" class="form-control input-sm"
173 placeholder="Search for vulnerability templates"
174 uib-typeahead="cwe as cwe.name for cwe in modal.cweList | filter:{name: $viewValue} | limitTo:10"
175 typeahead-on-select="modal.populate($item, $model, $label)">
176 </div>
177 </div>
178
179 <div class="col-md-12 custom-divider"></div>
180
181 <div class="col-md-12">
182 <div class="tab-pane-header">Description</div>
183 <div class="form-group" ng-class="{'has-error': formEdit.desc.$invalid }">
184 <label class="sr-only" for="vuln-data">Vuln description</label>
185 <textarea class="form-control" id="vuln-desc" name="desc"
186 ng-model="modal.data.desc" placeholder="Description"
187 style="margin: 0 2px 0 0; height: 239px; width: 810px;" required></textarea>
188 </div><!-- .form-group -->
189 </div>
190
191 <div class="col-md-12 margin-top-22px">
192 <div class="tab-pane-header">External ID</div>
193 <div class="form-group">
194 <label class="sr-only control-label" for="vuln-external_id">External ID</label>
195 <input type="text" class="form-control" id="vuln-external_id" placeholder="External ID" name="external_id" ng-model="modal.data.external_id"/>
196 </div>
197 </div>
198
199
200 <div class="form-group margin-top-22px">
201 <div class="col-md-12">
202 <div class="tab-pane-header">References</div>
203 <div class="input-group margin-bottom-sm">
204 <label class="sr-only" for="vuln-refs">References</label>
205 <input type="text" class="form-control" id="vuln-refs" placeholder="Reference"
206 ng-model="modal.new_ref"/>
207 <span class="input-group-addon cursor" ng-click="modal.newReference()"><i
208 class="fa fa-plus-circle"></i></span>
209 </div>
210 </div>
211 <div class="col-md-12 reference" ng-repeat="reference in modal.data.refs">
212 <div class="input-group margin-bottom-sm">
213 <label class="sr-only" for="vuln-refs-create">References</label>
214 <input type="text" class="form-control" id="vuln-refs-create" placeholder="Reference"
215 ng-model="reference.value" ng-click="modal.openReference(reference.value)"
216 role="button"
217 readonly/>
218 <span class="input-group-addon cursor" ng-click="modal.data.refs.splice($index, 1)"><i
219 class="fa fa-minus-circle"></i></span>
220 </div>
221 </div>
222 </div><!-- .form-group -->
223
224
225
226
227 <div class="col-md-12 margin-top-22px">
228 <div class="tab-pane-header">Resolution</div>
229 <div class="form-group">
230 <label class="sr-only" for="vuln-data">Vuln resolution</label>
231 <textarea class="form-control" id="vuln-resolution" rows="4"
232 ng-model="modal.data.resolution" placeholder="Resolution"></textarea>
233 </div><!-- .form-group -->
234 </div>
235
236
237 <div class="form-group margin-top-22px">
238 <div class="col-md-12">
239 <div class="tab-pane-header">Policy Violations</div>
240 <div class="input-group margin-bottom-sm">
241 <label class="sr-only" for="vuln-policyviolations">Policy Violations</label>
242 <input type="text" class="form-control" id="vuln-policyviolations"
243 placeholder="Policy Violations" ng-model="modal.new_policyviolation"/>
244 <span class="input-group-addon cursor" ng-click="modal.newPolicyViolation()"><i
245 class="fa fa-plus-circle"></i></span>
246 </div>
247 </div>
248 <div class="col-md-12 reference" ng-repeat="policyviolation in modal.data.policyviolations">
249 <div class="input-group margin-bottom-sm">
250 <label class="sr-only" for="vuln-policyviolations-value">Policy Violation</label>
251 <input type="text" class="form-control" id="vuln-policyviolations-value"
252 placeholder="Policy Violation" ng-model="policyviolation.value" readonly/>
253 <span class="input-group-addon cursor"
254 ng-click="modal.data.policyviolations.splice($index, 1)"><i
255 class="fa fa-minus-circle"></i></span>
256 </div>
257 </div>
258 </div><!-- .form-group -->
259
260 <div class="col-md-12 margin-bottom-15px margin-top-22px">
261 <div class="tab-pane-header">Impact</div>
262 <h4><span ng-repeat="(key, value) in modal.data.impact" class="normal-size"
263 style="cursor: pointer;">
264 <span ng-class="{'label-impact label-default-impact': !value, 'label-impact label-success-impact': value}"
265 ng-click="modal.toggleImpact(key)">{{key}}</span>
266 </span></h4><!-- .normal-size -->
267 </div>
268
269 </div>
270 <div id="technical_details" class="container tab-pane-container tab-pane fade"><br>
271 <div class="col-md-12">
272 <div class="tab-pane-header">Data</div>
273 <div class="form-group">
274 <label class="sr-only" for="vuln-data">Vuln data</label>
275 <textarea class="form-control" id="vuln-data" rows="5"
276 ng-model="modal.data.data" placeholder="Data"></textarea>
277 </div><!-- .form-group -->
278 </div>
279
280 <div class="col-md-6 col-sm-12 col-xs-12" ng-show="modal.data.type === 'VulnerabilityWeb'">
281 <div class="tab-pane-header">Request</div>
282 <div class="form-group">
283 <label class="sr-only" for="vuln-request">Vuln request</label>
284 <textarea class="form-control" id="vuln-request" rows="8"
285 ng-model="modal.data.request" placeholder="Request"></textarea>
286 </div><!-- .form-group -->
287 </div>
288
289 <div class="col-md-6 col-sm-12 col-xs-12" ng-show="modal.data.type === 'VulnerabilityWeb'">
290 <div class="tab-pane-header">Response</div>
291 <div class="form-group">
292 <label class="sr-only" for="vuln-response">Vuln response</label>
293 <textarea class="form-control" id="vuln-response" rows="8"
294 ng-model="modal.data.response" placeholder="Response"></textarea>
295 </div><!-- .form-group -->
296 </div>
297
298 <div class="margin-top-22px" ng-show="modal.data.type === 'VulnerabilityWeb'">
299 <div class="col-md-4">
300 <div class="tab-pane-header">Method</div>
301 <div class="form-group">
302 <label class="sr-only control-label" for="vuln-method">Method</label>
303 <input type="text" class="form-control" id="vuln-method" placeholder="Method"
304 ng-model="modal.data.method"/>
305 </div><!-- .form-group -->
306 </div>
307
308 <div class="col-md-3">
309 <div class="tab-pane-header">Param Name</div>
310 <div class="form-group">
311 <label class="sr-only control-label" for="vuln-pname">Param Name</label>
312 <input type="text" class="form-control" id="vuln-pname" placeholder="Param name"
313 ng-model="modal.data.pname"/>
314 </div><!-- .form-group -->
315 </div>
316
317 <div class="col-md-5">
318 <div class="tab-pane-header">Params</div>
319 <div class="form-group">
320 <label class="sr-only control-label" for="vuln-params">Params</label>
321 <input type="text" class="form-control" id="vuln-params" placeholder="Params"
322 ng-model="modal.data.params"/>
323 </div><!-- .form-group -->
324 </div>
325
326 <div class="col-md-3">
327 <div class="tab-pane-header">Path</div>
328 <div class="form-group">
329 <label class="sr-only control-label" for="vuln-path">Path</label>
330 <input type="text" class="form-control" id="vuln-path" placeholder="Path"
331 ng-model="modal.data.path"/>
332 </div><!-- .form-group -->
333 </div>
334
335 <div class="col-md-2">
336 <div class="tab-pane-header">Status code</div>
337 <div class="form-group">
338 <label class="sr-only control-label" for="vuln-path">Status code</label>
339 <input type="text" class="form-control" id="vuln-status-code" placeholder="Status code"
340 ng-model="modal.data.status_code"/>
341 </div><!-- .form-group -->
342 </div>
343
344 <div class="col-md-3">
345 <div class="tab-pane-header">Query</div>
346 <div class="form-group">
347 <label class="sr-only control-label" for="vuln-query">Query</label>
348 <input type="text" class="form-control" id="vuln-query" placeholder="Query"
349 ng-model="modal.data.query"/>
350 </div><!-- .form-group -->
351 </div>
352
353 <div class="col-md-4">
354 <div class="tab-pane-header">Website</div>
355 <div class="form-group">
356 <label class="sr-only control-label" for="vuln-website">Website</label>
357 <input type="text" class="form-control" id="vuln-website" placeholder="Website"
358 ng-model="modal.data.website"/>
359 </div><!-- .form-group -->
360 </div>
361 </div>
362 </div>
363 <div id="tab-evidence" class="container tab-pane fade"><br>
364 <div class="col-md-12 margin-bottom-15px">
365 <div class="tab-pane-header">Evidence</div>
366 <div class="alert alert-danger normal-size" role="alert" ng-if="modal.file_name_error">
367 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
368 <span class="sr-only">Error:</span>
369 Cannot upload evidence starting with underscore, please choose a different name for the
370 file.
371 </div>
372 <div class="form-group normal-size">
373 <input type="file" id="evidence" ng-file-select ng-multiple="true" resetOnClick="false"
374 ng-file-change="modal.selectedFiles($files, $event)"/>
375 <p class="help-block">Multiple files are allowed.</p>
376 </div><!-- .form-group -->
377 <div id="evidenceFiles" class="normal-size" ng-if="modal.data._attachments">
378 <ul>
379 <li ng-repeat="(name, file) in modal.data._attachments">
380 <div class="btn-group">
381 <button type="button" class="btn btn-default"
382 ng-click="modal.openEvidence(name)">
383 <span class="fa {{icons[name]}}"
384 title="Evidence {{name | decodeURIComponent}}"></span> {{name |
385 decodeURIComponent}}
386 </button><!-- ng-repeat -->
387 <button type="button" class="btn btn-danger"
388 ng-click="modal.removeEvidence(name)">
389 <span class="glyphicon glyphicon-trash"></span>
390 </button>
391 </div>
392 </li>
393 </ul>
394 </div><!-- #evidenceFiles -->
395 </div>
396
397 </div>
398
399 <div id="tab-custom-fields" class="container tab-pane-container tab-pane fade"><br>
400 <div ng-if="modal.customFields.length === 0" class="no-info-overlay" style="margin-bottom: 15px;">
401 <p class="no-info-text">
402 No custom fields were found. To create one refer to our
403 <a href="https://github.com/infobyte/faraday/wiki/Custom-Fields" target="_blank">wiki page</a>.
404 </p>
405 </div>
406 <div class="col-md-12 margin-bottom-15px">
407 <div class="col-md-12" ng-repeat="cf in modal.customFields | orderBy : 'field_order'">
408 <custom-field field="{{cf}}"></custom-field>
409 </div>
410
411 </div>
412 </div>
413 </div>
414
415
416 <div class="modal-footer">
417 <div class="modal-button">
418 <button class="btn btn-success" ng-click="modal.ok()" ng-disabled="formEdit.$invalid || modal.workspace.readonly == true">OK</button>
419 <button class="btn btn-danger" ng-click="modal.cancel()">Cancel</button>
420 </div>
421 </div>
422
423
424 <!--</div>-->
425 </div>
426 </form>
+0
-524
faraday/server/www/scripts/statusReport/partials/modalNew.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <!--<div class="modal-button btn-toolbar">-->
7 <!--<button class="btn btn-success" ng-click="modal.ok()" ng-disabled="form.$invalid || modal.data.severity === undefined || (modal.data.type === 'VulnerabilityWeb' && modal.host_parents) || modal.data.parents.length == 0">OK</button>-->
8 <!--<button class="btn btn-danger" ng-click="modal.cancel()">Cancel</button>-->
9 <!--</div>-->
10 <h3 class="modal-title">Vulnerability creation</h3>
11 </div>
12 <div class="modal-body">
13 <div class="mt-3">
14
15 <div class="edit-vulns-dropdowns row" ng-init="modal.changeSeverity('unclassified')">
16
17 <div class="btn-group col-md-3 col-sm-6 col-xs-6">
18 <button type="button" class="dropdown-toggle btn-change-property primary-btn"
19 data-toggle="dropdown"
20 id="btn-chg-severity"
21 title="{{modal.data.severity}}">
22 {{modal.data.severity || "Add Severity" | uppercase }}
23 </button>
24 <button type="button" class="dropdown-toggle secondary-btn btn-change-property"
25 data-toggle="dropdown"
26 id="caret-chg-severity"
27 title="Change severity">
28 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
29 </button>
30 <ul class="dropdown-menu dropdown-menu-right" role="menu">
31 <li>
32 <a class="ws"
33 ng-click="modal.changeSeverity('unclassified')">UNCLASSIFIED</a>
34 <a class="ws"
35 ng-click="modal.changeSeverity('info')">INFO</a>
36 <a class="ws"
37 ng-click="modal.changeSeverity('low')">LOW</a>
38 <a class="ws"
39 ng-click="modal.changeSeverity('med')">MEDIUM</a>
40 <a class="ws"
41 ng-click="modal.changeSeverity('high')">HIGH</a>
42 <a class="ws"
43 ng-click="modal.changeSeverity('critical')">CRITICAL</a>
44 </li>
45 </ul>
46 </div>
47
48
49 <div class="btn-group col-md-3 col-sm-6 col-xs-6">
50 <button type="button" class="dropdown-toggle btn-change-property primary-btn btn-primary-white"
51 data-toggle="dropdown"
52 id="btn-chg-ease_resolution"
53 title="{{modal.data.easeofresolution}}">
54 {{modal.data.easeofresolution || "Ease of Resolution"}}
55 </button>
56 <button type="button" class="dropdown-toggle secondary-btn btn-change-property btn-secondary-white"
57 data-toggle="dropdown"
58 id="caret-ease_resolution"
59 title="Change Ease of Resolution">
60 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
61 </button>
62 <ul class="dropdown-menu dropdown-menu-right" role="menu">
63 <li>
64 <a class="ws"
65 ng-click="modal.data.easeofresolution = null">Undetermined</a>
66 <a class="ws"
67 ng-click="modal.data.easeofresolution = 'trivial'">Trivial</a>
68 <a class="ws"
69 ng-click="modal.data.easeofresolution = 'simple'">Simple</a>
70 <a class="ws"
71 ng-click="modal.data.easeofresolution = 'moderate'">Moderate</a>
72 <a class="ws"
73 ng-click="modal.data.easeofresolution = 'difficult'">Difficult</a>
74 <a class="ws"
75 ng-click="modal.data.easeofresolution = 'infeasible'">Infeasible</a>
76 </li>
77 </ul>
78 </div>
79
80 <div class="customs-radio-inline">
81 <label class="radio-container"
82 ng-click="modal.data.type = 'Vulnerability'"
83 title="Change type to Vulnerability">
84 <h5>Vulnerability</h5>
85 <input type="radio" checked="checked" name="radio" ng-checked="modal.data.type === 'Vulnerability'">
86 <span class="checkmark background-blue"></span>
87 </label>
88 <label class="radio-container"
89 ng-click="modal.data.type = 'VulnerabilityWeb'"
90 title="Change type to Web Vulnerability">
91 <h5>Web Vulnerability</h5>
92 <input type="radio" name="radio" ng-checked="modal.data.type === 'VulnerabilityWeb'">
93 <span class="checkmark background-blue"></span>
94 </label>
95 </div>
96
97 </div>
98
99 <!-- Nav tabs -->
100 <ul class="nav nav-tabs" id="nav-tabs-container">
101 <li class="nav-item active" ng-class="{'has-error': modal.data.type == 'Vulnerability' && modal.data.parents.length == 0}">
102 <a class="nav-link" data-toggle="tab" data-target="#hosts" href="javascript:;">Hosts</a>
103 </li>
104 <li class="nav-item" ng-class="{'has-error': form.name.$invalid || form.desc.$invalid}">
105 <a class="nav-link active" data-toggle="tab" data-target="#general"
106 href="javascript:;">General</a>
107 </li>
108 <li class="nav-item">
109 <a class="nav-link" data-toggle="tab" data-target="#technical_details" href="javascript:;">Technical
110 Details</a>
111 </li>
112 <li class="nav-item">
113 <a class="nav-link" data-toggle="tab" data-target="#tab-evidence" href="javascript:;">Evidence</a>
114 </li>
115 <li class="nav-item">
116 <a class="nav-link" data-toggle="tab" data-target="#tab-custom-fields" href="javascript:;">Custom Fields</a>
117 </li>
118 </ul>
119
120
121 <div class="tab-content">
122 <div id="hosts" class="container tab-pane-container tab-pane active"><br>
123 <div class="col-md-12 margin-bottom-15px">
124 <div class="form-horizontal">
125 <div class="tab-pane-header">Target</div>
126 <div class="form-group">
127 <form name="formSearch" role="form">
128 <div class="col-md-8">
129 <div class="form-group input-accordion">
130 <input type="text" ng-model="modal.target_filter" class="form-control input-sm"
131 placeholder="Search targets" ng-change="modal.currentPage = 1" >
132 <span class="btn btn-danger" id="btn_clear_search"
133 ng-if="modal.target_filter != '' && modal.activeSearch == true"
134 ng-click="modal.clearFilterTargets()"> <i class="fa fa-times"></i></span>
135 </div>
136 </div>
137
138 <div class="col-md-2">
139 <div class="form-group">
140 <button type="submit" class="btn btn-success btn-xs background-blue" title="Search targets"
141 ng-click="modal.filterTargets()"
142 style="height: 30px!important; float: left;"
143 ng-disabled="modal.target_filter == ''">
144 Search
145 </button>
146 </div>
147 </div>
148 </form>
149 <div class="col-md-2">
150 <div class="btn-group btn-small-margin">
151 <button type="button" class="btn btn-default btn-xs" title="Select page"
152 ng-click="modal.setTargets(true, modal.currentPage*modal.pageSize, modal.pageSize)"
153 style="height: 30px!important;">
154 Select page
155 </button>
156 <button type="button" class="btn btn-default btn-xs dropdown-toggle"
157 style="height: 30px!important;"
158 data-toggle="dropdown"
159 title="Select options">
160 <span class="caret"></span>
161 </button>
162 <ul class="dropdown-menu dropdown-menu-right" role="menu">
163 <li ng-show="modal.target_filter && modal.targets_filtered.length > 0">
164 <a class="ws"
165 ng-click="modal.setTargets(true, 0, modal.targets_filtered.length)">Select
166 all hosts in search</a>
167 </li>
168 <li>
169 <a class="ws"
170 ng-click="modal.setTargets(false, 0, modal.targets.length)">Select
171 all
172 hosts</a>
173 </li>
174 <li>
175 <a class="ws" ng-click="modal.setTargets(false, 0, 0)">Clear
176 selection</a>
177 </li>
178 </ul>
179 </div><!-- .btn-group -->
180 </div>
181 </div>
182 <div class="form-group">
183 <div class="col-md-12">
184 <uib-accordion close-others="true">
185 <uib-accordion-group is-open="isopen"
186 ng-repeat="host in modal.targets_filtered = modal.targets "
187 template-url="scripts/statusReport/partials/accordion-group.html"
188 is-disabled="host.services.length < 1">
189
190 <uib-accordion-heading>
191 <a ng-click="modal.setTarget(host)"
192 ng-class="{'multi-selected': modal.isParentSelected(host)}">{{host.name}}
193 ({{host.hostnames[0]}})</a>
194 </uib-accordion-heading>
195 <div class="panel-body" ng-repeat="service in host.services">
196 <a ng-model="service" ng-click="modal.setTarget(service)"
197 ng-class="{'multi-selected': modal.data.parents.indexOf(service) >= 0}">{{service.name}}
198 {{service.ports}}</a>
199 </div>
200 </uib-accordion-group>
201 </uib-accordion>
202
203 <div class="showPagination"
204 ng-if="modal.total_rows > modal.targets_filtered.length">
205 <div class="form-group">
206 <ul class="pagination">
207 <li><a ng-hide="modal.currentPage <= 1"
208 ng-click="modal.updatePaginator()"><span
209 aria-hidden="true">&laquo;</span><span
210 class="sr-only">Previous</span></a></li>
211 <li><a>{{modal.currentPage}}/{{ ((modal.total_rows / modal.pageSize) | integer) + 1}}</a></li>
212 <li>
213 <a ng-hide="modal.currentPage > ((modal.total_rows / modal.pageSize) | integer)"
214 ng-click="modal.updatePaginator(true)"><span
215 aria-hidden="true">&raquo;</span><span
216 class="sr-only">Next</span></a></li>
217 </ul>
218 <ng-form name="goToPage">
219 <div class="col-md-2">
220 <input type="number" class="form-control" ng-maxlength="((modal.total_rows / modal.pageSize) | integer)"
221 ng-model="modal.newCurrentPage"
222 placeholder="Go to page"/>
223 </div>
224 <button class="btn btn-danger background-blue" ng-click="modal.go()">GO</button>
225 </ng-form>
226 </div>
227 </div>
228 </div>
229 </div>
230 <div class="alert alert-danger target_not_selected" role="alert"
231 ng-hide="modal.data.parents.length > 0">
232 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
233 <span class="sr-only">Error:</span>
234 There is no target selected
235 </div>
236 <div class="alert alert-danger target_not_selected" role="alert"
237 ng-show="modal.data.type === 'VulnerabilityWeb' && modal.host_parents">
238 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
239 <span class="sr-only">Error:</span>
240 Trying to create a Web Vulnerability with one or more Host parents. Please deselect the
241 Host targets or
242 <a href="" ng-click="modal.resetTarget()">click here to deselect all targets</a>
243 </div>
244 </div>
245
246 </div>
247 </div>
248
249 <div id="general" class="container tab-pane-container tab-pane"><br>
250 <div class="col-md-12">
251 <div class="tab-pane-header">Search vulnerability database templates
252 <a
253 href="https://github.com/infobyte/faraday/wiki/vulnerabilities-database"
254 target="_blank"><span class="glyphicon glyphicon-question-sign"
255 title="Read more about vulnerability templates in the official Faraday Documentation"></span></a>
256 </div>
257 <div class="form-group">
258 <input type="text" ng-model="modal.cwe_selected" class="form-control input-sm"
259 placeholder="Search for vulnerability templates"
260 uib-typeahead="cwe as cwe.name for cwe in modal.cweList | filter:{name: $viewValue} | limitTo:10"
261 typeahead-on-select="modal.populate($item, $model, $label)">
262 </div>
263 </div>
264
265 <div class="col-md-12 custom-divider"></div>
266
267 <div class="col-md-12">
268 <div class="tab-pane-header">Name</div>
269 <div class="form-group" ng-class="{'has-error': form.name.$invalid }">
270 <label class="sr-only" for="vuln-name">Vuln name</label>
271 <input type="text" class="form-control input-sm" id="vuln-name" name="name"
272 placeholder="Name"
273 ng-model="modal.data.name" required/>
274 </div><!-- .form-group -->
275 </div>
276
277
278 <div class="col-md-12">
279 <div class="tab-pane-header">Description</div>
280 <div class="form-group" ng-class="{'has-error': form.desc.$invalid }">
281 <label class="sr-only" for="vuln-data">Vuln description</label>
282 <textarea class="form-control" id="vuln-desc" name="desc"
283 ng-model="modal.data.desc" required placeholder="Description"
284 style="margin: 0 2px 0 0; height: 239px; width: 810px;"></textarea>
285 </div><!-- .form-group -->
286 </div>
287
288 <div class="col-md-12 margin-top-22px">
289 <div class="tab-pane-header">External ID</div>
290 <div class="form-group">
291 <label class="sr-only control-label" for="vuln-external_id">External ID</label>
292 <input type="text" class="form-control" id="vuln-external_id" placeholder="External ID" name="external_id" ng-model="modal.data.external_id"/>
293 </div>
294 </div>
295
296
297 <div class="form-group margin-top-22px">
298 <div class="col-md-12">
299 <div class="tab-pane-header">References</div>
300 <div class="input-group margin-bottom-sm">
301 <label class="sr-only" for="vuln-refs">References</label>
302 <input type="text" class="form-control" id="vuln-refs" placeholder="Reference"
303 ng-model="modal.new_ref"/>
304 <span class="input-group-addon cursor" ng-click="modal.newReference()"><i
305 class="fa fa-plus-circle"></i></span>
306 </div>
307 </div>
308 <div class="col-md-12 reference" ng-repeat="reference in modal.data.refs">
309 <div class="input-group margin-bottom-sm">
310 <label class="sr-only" for="vuln-refs-create">References</label>
311 <input type="text" class="form-control" id="vuln-refs-create" placeholder="Reference"
312 ng-model="reference.value" ng-click="modal.openReference(reference.value)"
313 role="button"
314 readonly/>
315 <span class="input-group-addon cursor" ng-click="modal.data.refs.splice($index, 1)"><i
316 class="fa fa-minus-circle"></i></span>
317 </div>
318 </div>
319 </div><!-- .form-group -->
320
321
322 <div class="col-md-12 margin-top-22px">
323 <div class="tab-pane-header">Resolution</div>
324 <div class="form-group">
325 <label class="sr-only" for="vuln-data">Vuln resolution</label>
326 <textarea class="form-control" id="vuln-resolution" rows="4"
327 ng-model="modal.data.resolution" placeholder="Resolution"></textarea>
328 </div><!-- .form-group -->
329 </div>
330
331
332 <div class="form-group margin-top-22px">
333 <div class="col-md-12">
334 <div class="tab-pane-header">Policy Violations</div>
335 <div class="input-group margin-bottom-sm">
336 <label class="sr-only" for="vuln-policyviolations">Policy Violations</label>
337 <input type="text" class="form-control" id="vuln-policyviolations"
338 placeholder="Policy Violations" ng-model="modal.new_policyviolation"/>
339 <span class="input-group-addon cursor" ng-click="modal.newPolicyViolation()"><i
340 class="fa fa-plus-circle"></i></span>
341 </div>
342 </div>
343 <div class="col-md-12 reference" ng-repeat="policyviolation in modal.data.policyviolations">
344 <div class="input-group margin-bottom-sm">
345 <label class="sr-only" for="vuln-policyviolations-value">Policy Violation</label>
346 <input type="text" class="form-control" id="vuln-policyviolations-value"
347 placeholder="Policy Violation" ng-model="policyviolation.value" readonly/>
348 <span class="input-group-addon cursor"
349 ng-click="modal.data.policyviolations.splice($index, 1)"><i
350 class="fa fa-minus-circle"></i></span>
351 </div>
352 </div>
353 </div><!-- .form-group -->
354
355
356 <div class="col-md-12 margin-bottom-15px margin-top-22px">
357 <div class="tab-pane-header">Impact</div>
358 <h4><span ng-repeat="(key, value) in modal.data.impact" class="normal-size"
359 style="cursor: pointer;">
360 <span ng-class="{'label-impact label-default-impact': !value, 'label-impact label-success-impact': value}"
361 ng-click="modal.toggleImpact(key)">{{key}}</span>
362 </span></h4><!-- .normal-size -->
363 </div>
364
365 </div>
366
367 <div id="technical_details" class="container tab-pane-container tab-pane"><br>
368 <div class="col-md-12">
369 <div class="tab-pane-header">Data</div>
370 <div class="form-group">
371 <label class="sr-only" for="vuln-data">Vuln data</label>
372 <textarea class="form-control" id="vuln-data" rows="5"
373 ng-model="modal.data.data" placeholder="Data"></textarea>
374 </div><!-- .form-group -->
375 </div>
376
377 <div class="col-md-6 col-sm-12 col-xs-12" ng-show="modal.data.type === 'VulnerabilityWeb'">
378 <div class="tab-pane-header">Request</div>
379 <div class="form-group">
380 <label class="sr-only" for="vuln-request">Vuln request</label>
381 <textarea class="form-control" id="vuln-request" rows="8"
382 ng-model="modal.data.request" placeholder="Request"></textarea>
383 </div><!-- .form-group -->
384 </div>
385
386 <div class="col-md-6 col-sm-12 col-xs-12" ng-show="modal.data.type === 'VulnerabilityWeb'">
387 <div class="tab-pane-header">Response</div>
388 <div class="form-group">
389 <label class="sr-only" for="vuln-response">Vuln response</label>
390 <textarea class="form-control" id="vuln-response" rows="8"
391 ng-model="modal.data.response" placeholder="Response"></textarea>
392 </div><!-- .form-group -->
393 </div>
394
395 <div class="margin-top-22px" ng-show="modal.data.type === 'VulnerabilityWeb'">
396 <div class="col-md-4">
397 <div class="tab-pane-header">Method</div>
398 <div class="form-group">
399 <label class="sr-only control-label" for="vuln-method">Method</label>
400 <input type="text" class="form-control" id="vuln-method" placeholder="Method"
401 ng-model="modal.data.method"/>
402 </div><!-- .form-group -->
403 </div>
404
405 <div class="col-md-3">
406 <div class="tab-pane-header">Param Name</div>
407 <div class="form-group">
408 <label class="sr-only control-label" for="vuln-pname">Param Name</label>
409 <input type="text" class="form-control" id="vuln-pname" placeholder="Param name"
410 ng-model="modal.data.pname"/>
411 </div><!-- .form-group -->
412 </div>
413
414 <div class="col-md-5">
415 <div class="tab-pane-header">Params</div>
416 <div class="form-group">
417 <label class="sr-only control-label" for="vuln-params">Params</label>
418 <input type="text" class="form-control" id="vuln-params" placeholder="Params"
419 ng-model="modal.data.params"/>
420 </div><!-- .form-group -->
421 </div>
422
423 <div class="col-md-3">
424 <div class="tab-pane-header">Path</div>
425 <div class="form-group">
426 <label class="sr-only control-label" for="vuln-path">Path</label>
427 <input type="text" class="form-control" id="vuln-path" placeholder="Path"
428 ng-model="modal.data.path"/>
429 </div><!-- .form-group -->
430 </div>
431
432 <div class="col-md-2">
433 <div class="tab-pane-header">Status code</div>
434 <div class="form-group">
435 <label class="sr-only control-label" for="vuln-path">Status code</label>
436 <input type="text" class="form-control" id="vuln-status-code" placeholder="Status code"
437 ng-model="modal.data.status_code"/>
438 </div><!-- .form-group -->
439 </div>
440
441 <div class="col-md-3">
442 <div class="tab-pane-header">Query</div>
443 <div class="form-group">
444 <label class="sr-only control-label" for="vuln-query">Query</label>
445 <input type="text" class="form-control" id="vuln-query" placeholder="Query"
446 ng-model="modal.data.query"/>
447 </div><!-- .form-group -->
448 </div>
449
450 <div class="col-md-4">
451 <div class="tab-pane-header">Website</div>
452 <div class="form-group">
453 <label class="sr-only control-label" for="vuln-website">Website</label>
454 <input type="text" class="form-control" id="vuln-website" placeholder="Website"
455 ng-model="modal.data.website"/>
456 </div><!-- .form-group -->
457 </div>
458 </div>
459 </div>
460
461 <div id="tab-evidence" class="container tab-pane fade"><br>
462 <div class="col-md-12 margin-bottom-15px">
463 <div class="tab-pane-header">Evidence</div>
464 <div class="alert alert-danger normal-size" role="alert" ng-if="modal.file_name_error">
465 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
466 <span class="sr-only">Error:</span>
467 Cannot upload evidence starting with underscore, please choose a different name for the
468 file.
469 </div>
470 <div class="form-group normal-size">
471 <input type="file" id="evidence" ng-file-select ng-multiple="true" resetOnClick="false"
472 ng-file-change="modal.selectedFiles($files, $event)"/>
473 <p class="help-block">Multiple files are allowed.</p>
474 </div><!-- .form-group -->
475 <div id="evidenceFiles" class="normal-size" ng-if="modal.data._attachments">
476 <ul>
477 <li ng-repeat="(name, file) in modal.data._attachments">
478 <div class="btn-group">
479 <button type="button" class="btn btn-default"
480 ng-click="modal.openEvidence(name)">
481 <span class="fa {{icons[name]}}"
482 title="Evidence {{name | decodeURIComponent}}"></span> {{name |
483 decodeURIComponent}}
484 </button><!-- ng-repeat -->
485 <button type="button" class="btn btn-danger"
486 ng-click="modal.removeEvidence(name)">
487 <span class="glyphicon glyphicon-trash"></span>
488 </button>
489 </div>
490 </li>
491 </ul>
492 </div><!-- #evidenceFiles -->
493 </div>
494
495 </div>
496
497 <div id="tab-custom-fields" class="container tab-pane-container tab-pane fade"><br>
498 <div ng-if="modal.customFields.length === 0" class="no-info-overlay" style="margin-bottom: 15px;">
499 <p class="no-info-text">
500 No custom fields were found. To create one refer to our
501 <a href="https://github.com/infobyte/faraday/wiki/Custom-Fields" target="_blank">wiki page</a>.
502 </p>
503 </div>
504 <div class="col-md-12 margin-bottom-15px">
505 <div class="col-md-12" ng-repeat="cf in modal.customFields | orderBy : 'field_order'">
506 <custom-field field="{{cf}}"></custom-field>
507 </div>
508 </div>
509 </div>
510 </div>
511
512 <div class="modal-footer">
513 <div class="modal-button btn-toolbar">
514 <button class="btn btn-success" ng-click="modal.ok()"
515 ng-disabled="form.$invalid || modal.data.severity === undefined || (modal.data.type === 'VulnerabilityWeb' && modal.host_parents) || modal.data.parents.length == 0">
516 OK
517 </button>
518 <button class="btn btn-danger" ng-click="modal.cancel()">Cancel</button>
519 </div>
520 </div>
521 </div>
522 </div>
523 </form>
+0
-622
faraday/server/www/scripts/statusReport/partials/statusReport.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="status-report seccion clearfix">
5 <div class="faraday-header-border-fix"></div>
6 <div class="left-main">
7 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
8 <div id="reports-main" class="fila clearfix">
9 <div class="button-control col-md-12 col-sm-12 col-xs-12" id="btn_bar">
10 <div class="control-wrapper control-new">
11 <button type="button" class="btn btn-success btn-new" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'New Vulns'}}" ng-click="new()" ng-disabled="workspaceData.readonly == true">
12 New
13 </button>
14 </div>
15 <table>
16 <thead>
17 <tr>
18 <th class="col-md-2" style="border-left: 1px solid rgb(221, 221, 221); padding-left: 12px;">
19 <a href="#/status/ws/{{workspace}}" class="status-report" ng-class="{'navigation-active' : component == 'status'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Vulns" tooltip-placement="right">
20 Vulns
21 </a>
22 </th>
23 <th class="col-md-2">
24 <a href="#/hosts/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'hosts'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Hosts" tooltip-placement="right">
25 Hosts
26 </a>
27 <div class="flex-spacer"></div>
28 </th>
29 <th class="col-md-2">
30 <a href="#/credentials/ws/{{workspace}}" class="workspaces" ng-class="{'navigation-active' : component == 'credentials'}" style="color: black !important; font-weight: bold; font-size: 15px;" uib-tooltip="Credentials" tooltip-placement="right">
31 Credentials
32 </a>
33 <div class="flex-spacer"></div>
34 </th>
35 <th class="col-md-2" style = "border-right: 1px solid rgb(221, 221, 221); padding-right: 12px">
36 <a href="#/taskgroup" class="executive-report" ng-class="{'navigation-active' : component == 'taskgroup'}" style="color: black !important; font-weight: bold; font-size: 15px;">
37 Tasks
38 </a>
39 <div class="flex-spacer"></div>
40 </th>
41 </tr>
42 </thead>
43 </table>
44 <div class="control-wrapper control-edit">
45 <button type="button" class="btn btn-default edit" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'Edit selected vulns'}}" ng-click="edit()" ng-disabled="getCurrentSelection().length != 1">
46 <img src="images/icon-toolbar-edit.svg" class="edit-icon" />
47 </button>
48 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="SingleActions" ng-show="getCurrentSelection().length === 1" ng-disabled="workspaceData.readonly == true">
49 <span class="caret"></span>
50 </button>
51 <ul class="dropdown-menu dropdown-menu-right" role="menu">
52 <li><a class="ws" ng-click="saveAsModel()">Create template</a></li>
53 <li><a class="ws" ng-click="showExploits()">Search exploits</a></li>
54 </ul>
55 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="Actions" ng-hide="getCurrentSelection().length < 2" ng-disabled="workspaceData.readonly == true">
56 <span class="caret"></span>
57 </button>
58 <ul class="dropdown-menu dropdown-menu-right" role="menu" ng-show="getCurrentSelection().length >= 2">
59 <li><a class="ws" ng-click="editString('name')">Edit name</a></li>
60 <li><a class="ws" ng-click="editText('desc', 'description')">Edit description</a></li>
61 <li><a class="ws" ng-click="editText('data')">Edit data</a></li>
62 <li><a class="ws" ng-click="editText('resolution')">Edit resolution</a></li>
63 <li><a class="ws" ng-click="editSeverity()">Edit severity</a></li>
64 <li><a class="ws" ng-click="editEaseofresolution()">Edit ease of resolution</a></li>
65 <li><a class="ws" ng-click="editReferences()">Add references</a></li>
66 <li><a class="ws" ng-click="editImpact()">Edit impact</a></li>
67 <li><a class="ws" ng-click="editStatus()">Edit status</a></li>
68 <li><a class="ws" ng-click="editPolicyviolations()">Edit policy violations</a></li>
69 <li><a class="ws" ng-click="editConfirm()">Confirm/Change to false positive</a></li>
70 <li ng-show="vulnWebSelected" role="separator" class="divider"></li>
71 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editString('method')">Edit method</a></li>
72 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editString('pname', 'param name')">Edit param name</a></li>
73 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editString('params', 'parameters')">Edit parameters</a></li>
74 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editString('path')">Edit path</a></li>
75 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editString('query')">Edit query</a></li>
76 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editString('website')">Edit website</a></li>
77 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editText('request')">Edit request</a></li>
78 <li ng-show="vulnWebSelected"><a class="ws" ng-click="editText('response')">Edit response</a></li>
79 <li role="separator" class="divider"></li>
80 <li><a class="ws" ng-click="editCWE()">From vulnerability template</a></li>
81 <li><a class="ws" ng-click="saveAsModel()">Create vulnerability templates</a></li>
82 <li role="separator" class="divider"></li>
83 <li><a class="ws" ng-click="showExploits()">Search exploits</a></li>
84 </ul>
85 </div>
86 <div class="control-wrapper">
87 <button type="button" class="btn btn-default" title="{{workspaceData.readonly == true? 'Read-only. Workspace disabled': 'Delete selected items'}}" ng-click="delete()" ng-disabled="workspaceData.readonly == true">
88 <img src="images/icon-toolbar-delete.svg" class="delete-icon" />
89 </button>
90 </div>
91 <div class="control-wrapper search-wrapper">
92 <form role="form" ng-submit="searchFor(searchParams, false, true)" title="The search expression can't contain parentheses that are not closed, double quotes that are not closed, or double spaces.">
93 <div class="form-group" ng-class="{'has-error':!isValidExpression(searchParams)}">
94 <div class="input-group">
95 <span class="input-group-addon glyphicon-btn glyphicon glyphicon-remove" ng-click="searchFor(null, true, false)" ng-if="searchParams !== '' || (search && search != 'confirmed=true')"></span>
96 <input type="text" class="form-control" placeholder="Enter keywords" ng-change="currentPage = 1" ng-model="searchParams" />
97 <span class="input-group-addon glyphicon-btn" ng-click="searchFor(searchParams, false, true)" ng-disabled="!isValidExpression(searchParams)">
98 <img src="images/icon-toolbar-searchbar-loupe.svg" class="search-icon" />
99 </span>
100 </div>
101 </div>
102 </form>
103 </div>
104 <div class="control-wrapper download-wrapper">
105 <button file-exporter="csv()" type="button" class="btn btn-default" title="Download CSV for current workspace">
106 <img src="images/icon-toolbar-download.svg" class="download-icon" />
107 </button>
108 </div>
109 <div class="control-wrapper download-wrapper" ng-hide="fileUploadEnabled === true">
110 <button ng-click="enableFileUpload()" type="button" class="btn btn-default" title="{{workspaceData.readonly == true ? 'Read-only. Workspace disabled': 'Upload a report'}}" ng-disabled="workspaceData.readonly == true">
111 <img src="images/icon-toolbar-upload.svg"/>
112 </button>
113 </div>
114 <div class="pl" ng-show="fileUploadEnabled === true">
115 <span class="file-container">
116 <button ng-if="fileToUpload === undefined" type="button" class="btn btn-success btn-labeled no-border-radius background-blue">
117 <span class="btn-label"><i class="fa fa-upload"></i>
118 </span>Select file</button>
119 <input type="file" id="upload_report_input_file" file-model="fileToUpload" ng-class="{'file-selected': fileToUpload !== undefined}">
120 </span>
121 <span ng-if="fileToUpload !== undefined">
122 <button type="button" class="btn btn-success btn-labeled no-border-radius background-blue" title="Upload selected file" ng-click="uploadFile()">
123 <span class="btn-label"><i class="fa fa-upload"></i>
124 </span>Upload file</button>
125 <span class="file-name">{{fileToUpload.name}}</span>
126 <span class='remove-uploaded-file'
127 ng-click="cancelFile()">
128 <i class="fa fa-remove"></i>
129 </span>
130 </span>
131 </div>
132 <div class="space-wrapper"></div>
133 <div class="control-wrapper control-wrap-right">
134 <div class="btn-group">
135 <button type="button" ng-if="propertyGroupBy" class="btn btn-danger" title="Clear" ng-click="clearGroupBy()">
136 <i class="fa fa-times"></i>
137 </button>
138 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="{{propertyGroupBy || 'Group By'}}">
139 {{ (propertyGroupBy | uppercase) || "Group By"}}
140 </button>
141 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="Group By">
142 <span class="caret"></span>
143 </button>
144 <ul class="dropdown-menu dropdown-menu-right" role="menu">
145 <li ng-repeat="(column, show) in columns">
146 <a class="ws" ng-show="show && (column !== 'evidence' && column !== 'impact' && column !== 'web' && column !== 'easeofresolution' && column !== 'date')" ng-click="groupBy(column)">{{column}}</a>
147 </li>
148 </ul>
149 </div>
150 <div class="btn-group">
151 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="{{propertyFilterConfirmed}}">
152 {{ (propertyFilterConfirmed) }}
153 </button>
154 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="Filter confirmed vulns">
155 <span class="caret"></span>
156 </button>
157 <ul class="dropdown-menu dropdown-menu-right" role="menu">
158 <li>
159 <a class="ws" ng-if="propertyFilterConfirmed !== 'All'" ng-click="filterConfirmed('All')">All</a>
160 <a class="ws" ng-if="propertyFilterConfirmed !== 'Confirmed'" ng-click="filterConfirmed('Confirmed')">Confirmed</a>
161 <a class="ws" ng-if="propertyFilterConfirmed !== 'Unconfirmed'" ng-click="filterConfirmed('Unconfirmed')">Unconfirmed</a>
162 </li>
163 </ul>
164 </div>
165 <div class="btn-group">
166 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="Add columns">
167 Add columns
168 </button>
169 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="Add Columns">
170 <span class="caret"></span>
171 </button>
172 <ul class="dropdown-menu dropdown-menu-right" role="menu">
173 <li ng-repeat="(column, show) in columns">
174 <a class="ws" ng-click="toggleShow(column, show)" ng-show="!show">{{column}}</a>
175 </li>
176 </ul>
177 </div>
178 </div>
179 </div>
180 <div class="reports col-md-12 col-sm-12 col-xs-12">
181 <i ng-if="loading" class="fa fa-spinner fa-spin loading-spinner"></i>
182 <div ui-grid="gridOptions" ui-grid-grouping ui-grid-selection ui-grid-pagination ui-grid-pinning ui-grid-resize-columns class="grid status-report-grid" ng-style="{'height' : gridHeight }"></div>
183
184 <div id="counter">
185 <span>Total</span>
186 <span class="counterNum">{{gridOptions.totalItems}}</span>
187 <div ng-if="search">
188 <span>Viewing</span>
189 <span class="counterNum">{{gridOptions.data.length}}</span>
190 </div>
191 <p style="margin:0px" ng-if="!search"></p>
192 <span>Selected</span>
193 <span class="counterNum">{{getCurrentSelection().length}}</span>
194 </div>
195 </div>
196 <!-- .reports -->
197 </div>
198 <!-- #reports-main -->
199
200 <div id="vuln-preview">
201 <div class="preview-header">
202 <button type="button" class="close" ng-click="hideVulnPreview()" data-dismiss="alert"><span area-hidden="true">&times;</span><span class="sr-only">Close</span></button>
203 </div>
204 <div class="mt-3 height-100 ">
205 <div class="margin-left-0 edit-vulns-dropdowns row" ng-init="updateBtnSeverityColor(lastClickedVuln.severity);updateBtnStatusColor(lastClickedVuln.status)">
206
207 <div class="margin-left-0 btn-group col-md-2 col-sm-4 col-xs-4">
208 <button type="button" class="dropdown-toggle btn-change-property primary-btn"
209 data-toggle="dropdown"
210 id="btn-chg-severity-prev"
211 title="{{lastClickedVuln.severity}}">
212 <i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === 'severity'"></i>{{lastClickedVuln.severity | uppercase}}
213 </button>
214 <button type="button" class="dropdown-toggle secondary-btn btn-change-property"
215 data-toggle="dropdown"
216 id="caret-chg-severity-prev"
217 title="Change severity-prev">
218 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
219 </button>
220 <ul class="dropdown-menu dropdown-menu-right" role="menu">
221 <li>
222 <a class="ws text-unclassified"
223 ng-click="changeSeverity('unclassified')">UNCLASSIFIED</a>
224 <a class="ws text-info"
225 ng-click="changeSeverity('info')">INFO</a>
226 <a class="ws text-low"
227 ng-click="changeSeverity('low')">LOW</a>
228 <a class="ws text-med"
229 ng-click="changeSeverity('med')">MEDIUM</a>
230 <a class="ws text-high"
231 ng-click="changeSeverity('high')">HIGH</a>
232 <a class="ws text-critical"
233 ng-click="changeSeverity('critical')">CRITICAL</a>
234 </li>
235 </ul>
236 </div>
237
238
239 <div class="btn-group col-md-2 col-sm-4 col-xs-4">
240 <button type="button" class="dropdown-toggle btn-change-property primary-btn btn-primary-white"
241 data-toggle="dropdown"
242 id="btn-chg-ease_resolution"
243 title="{{lastClickedVuln.easeofresolution}}">
244 <i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === 'easeofresolution'"></i>{{lastClickedVuln.easeofresolution || "Fix Effort"}}
245 </button>
246 <button type="button" class="dropdown-toggle secondary-btn btn-change-property btn-secondary-white"
247 data-toggle="dropdown"
248 id="caret-ease_resolution"
249 title="Change Ease of Resolution">
250 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
251 </button>
252 <ul class="dropdown-menu dropdown-menu-right" role="menu">
253 <li>
254 <a class="ws"
255 ng-click="changeEaseOfResolution(null)">Undetermined</a>
256 <a class="ws"
257 ng-click="changeEaseOfResolution('trivial')">Trivial</a>
258 <a class="ws"
259 ng-click="changeEaseOfResolution('simple')">Simple</a>
260 <a class="ws"
261 ng-click="changeEaseOfResolution('moderate')">Moderate</a>
262 <a class="ws"
263 ng-click="changeEaseOfResolution('difficult')">Difficult</a>
264 <a class="ws"
265 ng-click="changeEaseOfResolution('infeasible')">Infeasible</a>
266 </li>
267 </ul>
268 </div>
269
270
271 <div class="btn-group col-md-2 col-sm-4 col-xs-4">
272 <button type="button" class="dropdown-toggle btn-change-property primary-btn text-capitalize"
273 data-toggle="dropdown"
274 id="btn-chg-status-prev"
275 title="{{lastClickedVuln.status}}">
276 <i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === 'status'"></i>{{lastClickedVuln.status || "Status"}}
277 </button>
278 <button type="button" class="dropdown-toggle secondary-btn btn-change-property"
279 data-toggle="dropdown"
280 id="caret-chg-status-prev"
281 title="Change Status">
282 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span>
283 </button>
284 <ul class="dropdown-menu dropdown-menu-right" role="menu">
285 <li>
286 <a class="ws"
287 ng-click="changeStatus('opened')">Opened</a>
288 <a class="ws"
289 ng-click="changeStatus('closed')">Closed</a>
290 <a class="ws"
291 ng-click="changeStatus('re-opened')">Re-opened</a>
292 <a class="ws"
293 ng-click="changeStatus('risk-accepted')">Risk-accepted</a>
294 </li>
295 </ul>
296 </div>
297
298 <div class="col-md-2 col-sm-4 col-xs-4">
299 <label class="chbox-container">
300 <div class="tab-pane-header"><h4>Confirmed</h4></div>
301 <input type="checkbox" ng-checked="lastClickedVuln.confirmed === true" ng-model="lastClickedVuln.confirmed" ng-change="changeConfirmed(lastClickedVuln.confirmed)">
302 <span class="checkmark"></span>
303 </label>
304 </div>
305
306 </div>
307
308 <div class="margin-left-0 row">
309 <div ng-if="fieldToEdit !== 'name'">
310 <div class="margin-left-0 col-md-12">
311 <div class="tab-pane-header" ng-dblclick="activeEditPreview('name')" title="Double click to edit">
312 {{lastClickedVuln.name}} <span>({{lastClickedVuln.target}})</span>
313 </div>
314 </div>
315 </div>
316 <div class="form-group col-md-12" ng-if="fieldToEdit === 'name'" style="margin-bottom: 24px">
317 <label for="inp-edit-name"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true"></i> Vulnerability name</label>
318 <input type="text" class="form-control" id="inp-edit-name"
319 ng-model="lastClickedVuln.name" name="name" placeholder="Vulnerability name"
320 ng-blur="processToEditPreview()"
321 autofocus required>
322 </div>
323 </div>
324
325 <!-- Nav tabs -->
326 <ul class="nav nav-tabs" id="nav-tabs-container">
327 <li class="nav-item active" ng-class="{'has-error': formEdit.desc.$invalid}">
328 <a class="nav-link active" data-toggle="tab" data-target="#general_prev"
329 href="javascript:;">General</a>
330 </li>
331 <li class="nav-item">
332 <a class="nav-link" data-toggle="tab" data-target="#technical_details_prev" href="javascript:;">Technical
333 Details</a>
334 </li>
335 <li class="nav-item">
336 <a class="nav-link" data-toggle="tab" data-target="#tab-evidence_prev" href="javascript:;">Evidence</a>
337 </li>
338 <li class="nav-item">
339 <a class="nav-link" data-toggle="tab" data-target="#hosts_prev" href="javascript:;">Host</a>
340 </li>
341 <li class="nav-item">
342 <a class="nav-link" data-toggle="tab" data-target="#tab-custom-fields_prev" href="javascript:;">Custom Fields</a>
343 </li>
344 </ul>
345
346 <!-- Tab panes -->
347 <div class="tab-content height-100 ">
348 <div id="general_prev" class="container tab-pane-container tab-pane active"><br>
349
350 <div class="row margin-left-0">
351 <div class="height-100 padding-left-0 col-md-7">
352 <div class="height-100 padding-left-0 col-md-12">
353 <div ng-if="fieldToEdit !== 'desc'" class="height-100">
354 <div class="height-100 padding-left-0 col-md-12 margin-bottom-24">
355 <div ng-if="lastClickedVuln.desc === '' || lastClickedVuln.desc === undefined" style="margin-bottom: 15px;color: #aaa;">
356 <p>
357 No Description was found.
358 </p>
359 </div>
360
361 <div class="tab-pane-header" ng-dblclick="activeEditPreview('desc')" title="Double click to edit">
362 <i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === 'desc'"></i>
363 Description
364 </div>
365
366 <div>
367 <div class="tab-pane-header pretty-text" id="desc-prev" ng-dblclick="activeEditPreview('desc')" title="Double click to edit">
368 <span class="line-breaks">{{lastClickedVuln.desc}}</span>
369 </div>
370 </div>
371
372 </div>
373 </div>
374 <div class="form-group" ng-if="fieldToEdit === 'desc'">
375 <label for="inp-edit-desc"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true"></i> Description</label>
376 <textarea type="text" class="form-control" id="inp-edit-desc" rows="18"
377 ng-model="lastClickedVuln.desc" name="desc" placeholder="Description"
378 ng-blur="processToEditPreview()"
379 autofocus>
380 </textarea>
381 </div>
382 </div>
383 </div>
384
385 <div class="col-md-5">
386 <div class="row">
387 <div ng-if="fieldToEdit !== 'resolution'">
388 <div class="col-md-12 margin-bottom-24">
389 <div class="tab-pane-header" ng-dblclick="activeEditPreview('resolution')" title="Double click to edit">
390 <i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === 'resolution'"></i>
391 Resolution
392 </div>
393 <div ng-if="lastClickedVuln.resolution === '' || lastClickedVuln.resolution === undefined" style="margin-bottom: 15px;color: #aaa;">
394 <p>
395 No Resolution was found.
396 </p>
397 </div>
398 <div class="tab-pane-header pretty-text" id="resolution-prev" ng-dblclick="activeEditPreview('resolution')" title="Double click to edit">
399 <span class="line-breaks">{{lastClickedVuln.resolution}}</span>
400 </div>
401
402 </div>
403 </div>
404 <div class="form-group" ng-if="fieldToEdit === 'resolution'">
405 <label for="inp-edit-desc"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true"></i> Resolution</label>
406 <textarea type="text" class="form-control" id="inp-edit-res" rows="18"
407 ng-model="lastClickedVuln.resolution" name="desc" placeholder="Resolution"
408 ng-blur="processToEditPreview(false)"
409 autofocus>
410 </textarea>
411 </div>
412 </div>
413 </div>
414 </div>
415
416 <div class="row margin-top-30px small-size">
417 <div class="tab-pane-header col-md-2">
418 Owner
419 <div class="text-gray">{{lastClickedVuln.metadata['owner']}}</div>
420 </div>
421 <div class="tab-pane-header col-md-3">
422 Created
423 <div class="text-gray"><span am-time-ago="lastClickedVuln.metadata['create_time']"></span></div>
424 </div>
425 <div class="tab-pane-header col-md-4 ">
426 Updated
427 <div class="text-gray"><span am-time-ago="lastClickedVuln.metadata['update_time']"></span></div>
428 </div>
429 </div>
430
431 </div>
432
433 <div id="technical_details_prev" class="container tab-pane-container tab-pane fade"><br>
434 <div class="padding-left-0 col-md-12">
435 <div class="padding-left-0 col-md-12">
436 <div class="tab-pane-header" ng-dblclick="activeEditPreview('data')" title="Double click to edit">
437 <i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === 'data'"></i> Data
438 </div>
439 <div ng-if="fieldToEdit !== 'data'">
440 <div class="padding-left-0 col-md-12 margin-bottom-24">
441 <div ng-if="lastClickedVuln.data === '' || lastClickedVuln.data === undefined" style="margin-bottom: 15px;color: #aaa;">
442 <p>
443 No Data was found.
444 </p>
445 </div>
446 <div class="tab-pane-header pretty-text" id="data-prev" ng-dblclick="activeEditPreview('data')" title="Double click to edit">
447 <span class="line-breaks">{{lastClickedVuln.data}} </span>
448 </div>
449
450 </div>
451 </div>
452 <div class="form-group" ng-if="fieldToEdit === 'data'">
453 <textarea type="text" class="form-control" id="inp-edit-data" rows="18"
454 ng-model="lastClickedVuln.data" name="desc" placeholder="Data"
455 ng-blur="processToEditPreview(false)"
456 autofocus>
457 </textarea>
458 </div>
459 </div>
460
461 <div class="padding-left-0 row" style="margin-left: 0; margin-right: 0">
462 <div class="padding-left-0 col-md-6 col-sm-12 col-xs-12" ng-show="lastClickedVuln.type === 'VulnerabilityWeb'">
463 <div class="tab-pane-header" ng-dblclick="activeEditPreview('request')" title="Double click to edit"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === 'request'"></i> Request
464 </div>
465 <div ng-if="fieldToEdit !== 'request'" >
466 <div class="col-md-12 margin-bottom-24">
467 <div class="tab-pane-header pretty-text text-code" id="request-prev">
468 <div ng-if="lastClickedVuln.request === '' || lastClickedVuln.request === undefined"
469 style="margin-bottom: 15px;color: #aaa;">
470 <p>
471 No Request was found.
472 </p>
473 </div>
474 <span class="line-breaks" ng-dblclick="activeEditPreview('request')" title="Double click to edit"> {{lastClickedVuln.request}} </span>
475 </div>
476 </div>
477 </div>
478 <div class="form-group" ng-if="fieldToEdit === 'request'">
479 <textarea type="text" class="form-control" id="inp-edit-request" rows="18"
480 ng-model="lastClickedVuln.request" name="desc" placeholder="Request"
481 ng-blur="processToEditPreview(false)"
482 autofocus>
483 </textarea>
484 </div>
485
486 </div>
487 <div class="col-md-6 col-sm-12 col-xs-12" ng-show="lastClickedVuln.type === 'VulnerabilityWeb'">
488 <div class="tab-pane-header" ng-dblclick="activeEditPreview('response')" title="Double click to edit"><i class="fa fa-spinner fa-spin" ng-show="isUpdatingVuln === true && fieldToEdit === 'response'"></i> Response
489 </div>
490 <div ng-if="fieldToEdit !== 'response'">
491 <div class="col-md-12 margin-bottom-24">
492 <div class="tab-pane-header pretty-text text-code" id="response-prev" >
493 <div ng-if="lastClickedVuln.response === '' || lastClickedVuln.response === undefined" style="margin-bottom: 15px;color: #aaa;">
494 <p>
495 No Response was found.
496 </p>
497 </div>
498 <span class="line-breaks" ng-dblclick="activeEditPreview('response')" title="Double click to edit"> {{lastClickedVuln.response}} </span>
499
500 </div>
501
502 </div>
503 </div>
504 <div class="form-group" ng-if="fieldToEdit === 'response'">
505 <textarea type="text" class="form-control" id="inp-edit-response" rows="18"
506 ng-model="lastClickedVuln.response" name="desc" placeholder="Response"
507 ng-blur="processToEditPreview(false)"
508 autofocus>
509 </textarea>
510 </div>
511 </div>
512 </div>
513 </div>
514 </div>
515
516 <div id="tab-evidence_prev" class="container tab-pane-container tab-pane fade"><br>
517 <div class="padding-left-0 col-md-12 margin-bottom-15px">
518
519 <div class="col-md-4">
520
521 <div class="tab-pane-header padding-left-0 col-md-8">Attachments</div>
522 <div class="padding-left-0 form-group col-md-4">
523 <div class="upload-plus">
524 <div class="icon-evidence">
525 <button type="button" class="btn btn-success col-md-12">
526 <i class="fa fa-plus"></i> New
527 </button>
528
529 </div>
530 <input type="file" class="input-evidence" nv-file-select="" uploader="uploader" multiple/>
531 </div>
532 </div>
533
534
535
536 <table class="table">
537 <thead>
538 <tr>
539 <th width="50%">Name</th>
540 <th>Actions</th>
541 </tr>
542 </thead>
543 <tbody>
544 <tr ng-repeat="(name, file) in lastClickedVuln._attachments">
545 <td>
546 <strong><a href="javascript:;" ng-click="selectItemToPrev(name)">{{ name }}</a></strong>
547 <div ng-show="uploader.isHTML5" ng-thumb="{ file: file, height: 100 }"></div>
548 </td>
549 <td nowrap>
550 <button type="button" class="btn btn-danger btn-xs" ng-click="removeEvidence(name)">
551 <span class="glyphicon glyphicon-trash"></span> Remove
552 </button>
553 <button type="button" class="btn btn-info btn-xs" ng-click="copyToClipboard(name)">
554 <span class="fa fa-copy"></span> Copy link
555 </button>
556 </td>
557 </tr>
558 </tbody>
559 </table>
560 </div>
561
562
563 <div class="col-md-8 attachment-prev">
564 <div ng-if="selectedAtachment.url === ''" class="no-info-overlay" style="margin-bottom: 15px;top: -8px;">
565 <p class="no-info-text">
566 No attachment selected
567 </p>
568 </div>
569
570 <div class="tab-pane-header">{{selectedAtachment.name}}</div>
571 <img ng-if="selectedAtachment.url !== '' && selectedAtachment.imgPrevFail === false" src="{{selectedAtachment.url}}" id="attachment-img">
572 <div class="no-info-overlay" ng-if="selectedAtachment.imgPrevFail === true" style="margin-bottom: 15px;top: -8px;">
573 <p class="no-info-text">
574 No available preview to this attachment
575 </p>
576 </div>
577 </div>
578
579
580
581 </div>
582
583 </div>
584
585 <div id="hosts_prev" class="container tab-pane-container tab-pane fade"><br>
586 <div class="padding-left-0 col-md-12">
587 <div class="padding-left-0 col-md-3">
588 <div class="tab-pane-header">Host</div>
589 <div class="tab-pane-header"><i class="fa fa-desktop"></i>&nbsp;&nbsp;{{lastClickedVuln.target}}:{{lastClickedVuln.service.ports}}</div>
590 </div>
591
592 <div class="padding-left-0 col-md-3">
593 <div class="tab-pane-header">Hostnames</div>
594 <div class="tab-pane-header" ng-repeat="hostname in lastClickedVuln.hostnames"><i class="fa fa-desktop"></i>&nbsp;&nbsp;{{hostname}}</div>
595 </div>
596 </div>
597 </div>
598
599 <div id="tab-custom-fields_prev" class="container tab-pane-container tab-pane fade"><br>
600 <div ng-if="customFields.length === 0" class="no-info-overlay" style="margin-bottom: 15px;">
601 <p class="no-info-text">
602 No custom fields were found. To create one refer to our
603 <a href="https://github.com/infobyte/faraday/wiki/Custom-Fields" target="_blank">wiki page</a>.
604 </p>
605 </div>
606 <div class="padding-left-0 col-md-5 margin-bottom-15px">
607 <div class="padding-left-0 col-md-12" ng-repeat="cf in customFields | orderBy : 'field_order'">
608 <custom-field-prev field="{{cf}}"></custom-field-prev>
609 </div>
610 </div>
611 </div>
612 </div>
613
614
615
616 </div>
617 </div>
618 </div>
619 <!-- .right-main -->
620 </section>
621 <!-- #main -->
+0
-4
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/creatorcolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents white-space" uib-tooltip="{{COL_FIELD}}"><a href='{{grid.appScope.hash}}/search/tool={{grid.appScope.encodeUrl(row.entity.metadata.creator)}}' append-search-param="creator={{grid.appScope.encodeUrl(row.entity.metadata.creator)}}">{{COL_FIELD CUSTOM_FILTERS}}</a></div>
2 </div>
3 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD.split("(")[0] !== " " ? COL_FIELD : "EMPTY" + COL_FIELD}}</div>
+0
-5
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/datecolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents date-cell white-space"><span uib-tooltip="{{row.entity.metadata.create_time | amTimeAgo}}">{{row.entity.metadata.create_time | amTimeAgo}}</span>
2 </div>
3 </div>
4 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{row.entity.metadata.create_time | amUtc | amDateFormat:'MM/DD/YYYY'}}</div>
+0
-1
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/defaultcolumn.html less more
0 <div ng-if="row.entity._id != undefined"><div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents white-space" uib-tooltip="{{COL_FIELD}}"><a href='{{grid.appScope.hash}}/search/{{col.name}}={{grid.appScope.encodeUrl(row.entity[col.name])}}' append-search-param="{{col.name}}={{grid.appScope.encodeUrl(row.entity[col.name])}}">{{COL_FIELD CUSTOM_FILTERS}}</a></div></div><div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD.split("(")[0] !== " " ? COL_FIELD : "EMPTY" + COL_FIELD}}</div>
+0
-1
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/desccolumn.html less more
0 <div><div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents white-space" >{{COL_FIELD CUSTOM_FILTERS | removeLinebreaks}}</div></div>
+0
-4
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/evidencecolumn.html less more
0 <div class="ui-grid-cell-contents center" uib-tooltip="{{grid.appScope.concatForTooltip(COL_FIELD,false) | decodeURIComponent}}">
1 <span ng-repeat="(key, value) in COL_FIELD" class='pos-middle crop-text'><a href='{{grid.appScope.baseurl}}_api/v2/ws/{{grid.appScope.workspace}}/vulns/{{row.entity._id}}/attachment/{{key | encodeURIComponent}}/' target='_blank'>{{key | decodeURIComponent}}</a>&nbsp;</span>
2 </div>
3 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined">{{COL_FIELD CUSTOM_FILTERS}}</div>
+0
-1
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/externalidcolumn.html less more
0 <div><div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents white-space" >{{COL_FIELD CUSTOM_FILTERS | removeLinebreaks}}</div></div>
+0
-6
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/hostnamescolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div class="ui-grid-cell-contents center" uib-tooltip="{{grid.appScope.concatForTooltip(COL_FIELD, true) | decodeURIComponent}}">
2 <span ng-repeat="hostname in COL_FIELD"><a href="{{grid.appScope.hash}}/search/hostnames={{hostname}}" append-search-param="hostnames={{hostname}}">{{hostname}}</a>&nbsp;</span>
3 </div>
4 </div>
5 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD.split('(')[0] !== ' ' ? COL_FIELD : 'EMPTY' + COL_FIELD}}</div>
+0
-1
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/hostoscolumn.html less more
0 <div ng-if='row.entity._id != undefined' class='ui-grid-cell-contents row-tooltip'><a ng-href="{{grid.appScope.hash}}/search/host_os={{row.entity.host_os}}" append-search-param="host_os={{row.entity.host_os}}">{{COL_FIELD CUSTOM_FILTERS}}</a></div><div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD CUSTOM_FILTERS}}</div>
+0
-4
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/idcolumn.html less more
0 <div class="grid_id" ng-if="row.entity._id != undefined">
1 <span ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents white-space ng-scope"><span>{{COL_FIELD CUSTOM_FILTERS}}</span></pan>
2 </div>
3
+0
-6
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/impactcolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div class="ui-grid-cell-contents center" uib-tooltip="{{grid.appScope.concatForTooltip(COL_FIELD, false) | decodeURIComponent}}">
2 <span ng-repeat="(key, value) in COL_FIELD" class='pos-middle crop-text' ng-if='value === true'>{{key}}&nbsp;</span>
3 </div>
4 </div>
5 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD.split('(')[0] !== ' ' ? COL_FIELD : 'EMPTY' + COL_FIELD}}</div>
+0
-5
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/namecolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div ng-keyup="grid.appScope.changeVulnPrevByEventKey($event)" ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents white-space"><a href="javascript:;" ng-click="grid.appScope.toggleVulnPreview($event, row.entity)" style="color:#555555; font-weight:bold;">{{COL_FIELD CUSTOM_FILTERS}}</a> &nbsp; &nbsp; <span style="color: #337ab7" ng-if="row.entity._id === grid.appScope.lastClickedVuln._id"><i class="fa fa-check"></i></span>
2 </div>
3 </div>
4 <div ng-keyup="grid.appScope.changeVulnPrevByEventKey($event)" ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD CUSTOM_FILTERS}}</div>
+0
-6
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/policyviolationscolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div class="ui-grid-cell-contents center" uib-tooltip="{{grid.appScope.concatForTooltip(COL_FIELD, true, false) | decodeURIComponent}}">
2 <span ng-repeat="policyviolation in COL_FIELD" class='pos-middle crop-text'><a href='{{grid.appScope.processReference(policyviolation)}}' target="_blank">{{policyviolation}}&nbsp;</a></span>
3 </div>
4 </div>
5 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD.split('(')[0] !== ' ' ? COL_FIELD : 'EMPTY' + COL_FIELD}}</div>
+0
-6
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/refscolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div class="ui-grid-cell-contents center" uib-tooltip="{{grid.appScope.concatForTooltip(COL_FIELD, true, true) | decodeURIComponent}}">
2 <span ng-repeat="ref in COL_FIELD" class='pos-middle crop-text'><a href='{{grid.appScope.processReference(ref)}}' target="_blank">{{ref}}</a>&nbsp;</span>
3 </div>
4 </div>
5 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD.split('(')[0] !== ' ' ? COL_FIELD : 'EMPTY' + COL_FIELD}}</div>
+0
-1
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/resolutioncolumn.html less more
0 <div><div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents white-space" uib-tooltip="{{COL_FIELD}}">{{COL_FIELD.split("(")[0] !== " " ? COL_FIELD : "EMPTY" + COL_FIELD | removeLinebreaks}}</div></div>
+0
-6
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/servicecolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div class='ui-grid-cell-contents'>
2 <a href="{{grid.appScope.hash}}/search/service={{row.entity.service.name}}" append-search-param="service={{row.entity.service.name}}">{{COL_FIELD}}</a>
3 </div>
4 </div>
5 <div ng-if='row.groupHeader && col.grouping.groupPriority !== undefined' class='ui-grid-cell-contents white-space'>{{COL_FIELD}}</div>
+0
-11
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/severitycolumn.html less more
0 <div ng-if="row.entity._id != undefined">
1 <div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents ui-grid-text-center">
2 <a ng-href="{{grid.appScope.hash}}/search/severity={{COL_FIELD}}" append-search-param="severity={{COL_FIELD}}">
3 <span class="label vuln fondo-{{COL_FIELD}}">{{COL_FIELD | uppercase | limitTo:4}}
4 </span>
5 </a>
6 </div>
7 </div>
8 <div class="ui-grid-cell-contents ui-grid-text-center" ng-if="row.groupHeader && col.grouping.groupPriority !== undefined">
9 <span class="label vuln fondo-{{COL_FIELD}}">{{COL_FIELD | uppercase}}</span>
10 </div>
+0
-12
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/statuscolumn.html less more
0 <div ng-if="row.entity._id != undefined" class="status-wrapper">
1 <div ng-if="!col.grouping || col.grouping.groupPriority === undefined || col.grouping.groupPriority === null || ( row.groupHeader && col.grouping.groupPriority === row.treeLevel )" class="ui-grid-cell-contents status {{COL_FIELD}}">
2 <a href="#/status/ws/{{grid.appScope.workspace}}/search/status={{COL_FIELD}}" append-search-param="status={{COL_FIELD}}">
3 <span >{{COL_FIELD | uppercase}}</span>
4 </a>
5 </div>
6 </div>
7 <div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="status-wrapper">
8 <a href="#/status/ws/{{grid.appScope.workspace}}/search/status={{COL_FIELD}}" append-search-param="status={{COL_FIELD}}">
9 <span >{{COL_FIELD | uppercase}}</span>
10 </a>
11 </div>
+0
-1
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/targetcolumn.html less more
0 <div ng-if='row.entity._id != undefined' class='ui-grid-cell-contents row-tooltip'><a ng-href="{{grid.appScope.hash}}/search/target={{row.entity.target}}" append-search-param="target={{row.entity.target}}">{{COL_FIELD CUSTOM_FILTERS}}</a></div><div ng-if="row.groupHeader && col.grouping.groupPriority !== undefined" class="ui-grid-cell-contents white-space">{{COL_FIELD CUSTOM_FILTERS}}</div>
+0
-1
faraday/server/www/scripts/statusReport/partials/ui-grid/columns/webcolumn.html less more
0 <div ng-if='row.entity._id != undefined' class="ui-grid-cell-contents center"><span class="glyphicon glyphicon-ok" ng-show="row.entity.type === 'VulnerabilityWeb'"></span><span class="glyphicon glyphicon-remove" ng-show="row.entity.type !== 'VulnerabilityWeb'"></span></div>
+0
-5
faraday/server/www/scripts/statusReport/partials/ui-grid/confirmbutton.html less more
0 <div ng-if="row.entity._id != undefined" class="ui-grid-cell-contents row-tooltip confirm-toggle" style="margin-left: -7px;">
1 <span ng-click="grid.appScope.toggleConfirmVuln(row.entity, row.entity.confirmed); $event.stopPropagation();" class="cursor" uib-tooltip="{{grid.appScope.confirmedTooltip(row.entity.confirmed)}}" tooltip-placement="right" ng-class="{ disabled:row.entity.confirmed === false }">
2 <img ng-src="{{ (row.entity.confirmed) ? 'images/icon-list-confirmed.png' : 'images/icon-list-notconfirmed.png'}}" class="confirm-icon" ng-style="{ 'opacity': (row.entity.confirmed === true) ? '1' : '0.7' }" />
3 </span>
4 </div>
+0
-1
faraday/server/www/scripts/statusReport/partials/ui-grid/headercell.html less more
0 <div></div>
+0
-1118
faraday/server/www/scripts/statusReport/providers/logical.js less more
0 /*
1 * Generated by PEG.js 0.10.0.
2 *
3 * http://pegjs.org/
4 */
5
6 "use strict";
7
8 function peg$subclass(child, parent) {
9 function ctor() { this.constructor = child; }
10 ctor.prototype = parent.prototype;
11 child.prototype = new ctor();
12 }
13
14 function peg$SyntaxError(message, expected, found, location) {
15 this.message = message;
16 this.expected = expected;
17 this.found = found;
18 this.location = location;
19 this.name = "SyntaxError";
20
21 if (typeof Error.captureStackTrace === "function") {
22 Error.captureStackTrace(this, peg$SyntaxError);
23 }
24 }
25
26 peg$subclass(peg$SyntaxError, Error);
27
28 peg$SyntaxError.buildMessage = function(expected, found) {
29 var DESCRIBE_EXPECTATION_FNS = {
30 literal: function(expectation) {
31 return "\"" + literalEscape(expectation.text) + "\"";
32 },
33
34 "class": function(expectation) {
35 var escapedParts = "",
36 i;
37
38 for (i = 0; i < expectation.parts.length; i++) {
39 escapedParts += expectation.parts[i] instanceof Array
40 ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1])
41 : classEscape(expectation.parts[i]);
42 }
43
44 return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
45 },
46
47 any: function(expectation) {
48 return "any character";
49 },
50
51 end: function(expectation) {
52 return "end of input";
53 },
54
55 other: function(expectation) {
56 return expectation.description;
57 }
58 };
59
60 function hex(ch) {
61 return ch.charCodeAt(0).toString(16).toUpperCase();
62 }
63
64 function literalEscape(s) {
65 return s
66 .replace(/\\/g, '\\\\')
67 .replace(/"/g, '\\"')
68 .replace(/\0/g, '\\0')
69 .replace(/\t/g, '\\t')
70 .replace(/\n/g, '\\n')
71 .replace(/\r/g, '\\r')
72 .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
73 .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
74 }
75
76 function classEscape(s) {
77 return s
78 .replace(/\\/g, '\\\\')
79 .replace(/\]/g, '\\]')
80 .replace(/\^/g, '\\^')
81 .replace(/-/g, '\\-')
82 .replace(/\0/g, '\\0')
83 .replace(/\t/g, '\\t')
84 .replace(/\n/g, '\\n')
85 .replace(/\r/g, '\\r')
86 .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
87 .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); });
88 }
89
90 function describeExpectation(expectation) {
91 return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
92 }
93
94 function describeExpected(expected) {
95 var descriptions = new Array(expected.length),
96 i, j;
97
98 for (i = 0; i < expected.length; i++) {
99 descriptions[i] = describeExpectation(expected[i]);
100 }
101
102 descriptions.sort();
103
104 if (descriptions.length > 0) {
105 for (i = 1, j = 1; i < descriptions.length; i++) {
106 if (descriptions[i - 1] !== descriptions[i]) {
107 descriptions[j] = descriptions[i];
108 j++;
109 }
110 }
111 descriptions.length = j;
112 }
113
114 switch (descriptions.length) {
115 case 1:
116 return descriptions[0];
117
118 case 2:
119 return descriptions[0] + " or " + descriptions[1];
120
121 default:
122 return descriptions.slice(0, -1).join(", ")
123 + ", or "
124 + descriptions[descriptions.length - 1];
125 }
126 }
127
128 function describeFound(found) {
129 return found ? "\"" + literalEscape(found) + "\"" : "end of input";
130 }
131
132 return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
133 };
134
135 function peg$parse(input, options) {
136 options = options !== void 0 ? options : {};
137
138 var peg$FAILED = {},
139
140 peg$startRuleFunctions = { start: peg$parsestart },
141 peg$startRuleFunction = peg$parsestart,
142
143 peg$c0 = function(token) { return {name:'name', op:'ilike', val: '%'+ token + '%'}},
144 peg$c1 = ":",
145 peg$c2 = peg$literalExpectation(":", false),
146 peg$c3 = ".",
147 peg$c4 = peg$literalExpectation(".", false),
148 peg$c5 = "'",
149 peg$c6 = peg$literalExpectation("'", false),
150 peg$c7 = "-",
151 peg$c8 = peg$literalExpectation("-", false),
152 peg$c9 = "/",
153 peg$c10 = peg$literalExpectation("/", false),
154 peg$c11 = function(exp, optional) {
155 return {
156 name: 'name',
157 op: 'ilike' ,
158 val: processValue(name, null, exp += optional.join(""))
159 }
160 },
161 peg$c12 = "or",
162 peg$c13 = peg$literalExpectation("or", false),
163 peg$c14 = function(left, right) { return {"or": [left, right]} },
164 peg$c15 = "and",
165 peg$c16 = peg$literalExpectation("and", false),
166 peg$c17 = function(left, right) { return {"and": [left, right]} },
167 peg$c18 = "not",
168 peg$c19 = peg$literalExpectation("not", false),
169 peg$c20 = function(operand) { return processLogicalNot(operand) },
170 peg$c21 = "(",
171 peg$c22 = peg$literalExpectation("(", false),
172 peg$c23 = ")",
173 peg$c24 = peg$literalExpectation(")", false),
174 peg$c25 = function(logical_or) { return logical_or; },
175 peg$c26 = function(name, value) {
176 return {
177 name: processName(name),
178 op: processOperator(name, null) ,
179 val: processValue(name, null, value)
180 }
181 },
182 peg$c27 = "\"",
183 peg$c28 = peg$literalExpectation("\"", false),
184 peg$c29 = function(name, mandatory, optional) {
185 return {
186 name: processName(name),
187 op: processOperator(name, null) ,
188 val: processValue(name, null, mandatory += optional.join(""))
189 }
190 },
191 peg$c30 = /^[a-zA-Z0-9_.-\/]/,
192 peg$c31 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"], "_", [".", "/"]], false, false),
193 peg$c32 = function(token) { return token.join(""); },
194 peg$c33 = /^[ \t]/,
195 peg$c34 = peg$classExpectation([" ", "\t"], false, false),
196
197 peg$currPos = 0,
198 peg$savedPos = 0,
199 peg$posDetailsCache = [{ line: 1, column: 1 }],
200 peg$maxFailPos = 0,
201 peg$maxFailExpected = [],
202 peg$silentFails = 0,
203
204 peg$result;
205
206 if ("startRule" in options) {
207 if (!(options.startRule in peg$startRuleFunctions)) {
208 throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
209 }
210
211 peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
212 }
213
214 function text() {
215 return input.substring(peg$savedPos, peg$currPos);
216 }
217
218 function location() {
219 return peg$computeLocation(peg$savedPos, peg$currPos);
220 }
221
222 function expected(description, location) {
223 location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
224
225 throw peg$buildStructuredError(
226 [peg$otherExpectation(description)],
227 input.substring(peg$savedPos, peg$currPos),
228 location
229 );
230 }
231
232 function error(message, location) {
233 location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)
234
235 throw peg$buildSimpleError(message, location);
236 }
237
238 function peg$literalExpectation(text, ignoreCase) {
239 return { type: "literal", text: text, ignoreCase: ignoreCase };
240 }
241
242 function peg$classExpectation(parts, inverted, ignoreCase) {
243 return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
244 }
245
246 function peg$anyExpectation() {
247 return { type: "any" };
248 }
249
250 function peg$endExpectation() {
251 return { type: "end" };
252 }
253
254 function peg$otherExpectation(description) {
255 return { type: "other", description: description };
256 }
257
258 function peg$computePosDetails(pos) {
259 var details = peg$posDetailsCache[pos], p;
260
261 if (details) {
262 return details;
263 } else {
264 p = pos - 1;
265 while (!peg$posDetailsCache[p]) {
266 p--;
267 }
268
269 details = peg$posDetailsCache[p];
270 details = {
271 line: details.line,
272 column: details.column
273 };
274
275 while (p < pos) {
276 if (input.charCodeAt(p) === 10) {
277 details.line++;
278 details.column = 1;
279 } else {
280 details.column++;
281 }
282
283 p++;
284 }
285
286 peg$posDetailsCache[pos] = details;
287 return details;
288 }
289 }
290
291 function peg$computeLocation(startPos, endPos) {
292 var startPosDetails = peg$computePosDetails(startPos),
293 endPosDetails = peg$computePosDetails(endPos);
294
295 return {
296 start: {
297 offset: startPos,
298 line: startPosDetails.line,
299 column: startPosDetails.column
300 },
301 end: {
302 offset: endPos,
303 line: endPosDetails.line,
304 column: endPosDetails.column
305 }
306 };
307 }
308
309 function peg$fail(expected) {
310 if (peg$currPos < peg$maxFailPos) { return; }
311
312 if (peg$currPos > peg$maxFailPos) {
313 peg$maxFailPos = peg$currPos;
314 peg$maxFailExpected = [];
315 }
316
317 peg$maxFailExpected.push(expected);
318 }
319
320 function peg$buildSimpleError(message, location) {
321 return new peg$SyntaxError(message, null, null, location);
322 }
323
324 function peg$buildStructuredError(expected, found, location) {
325 return new peg$SyntaxError(
326 peg$SyntaxError.buildMessage(expected, found),
327 expected,
328 found,
329 location
330 );
331 }
332
333 function peg$parsestart() {
334 var s0, s1;
335
336 s0 = peg$parselogical_or();
337 if (s0 === peg$FAILED) {
338 s0 = peg$parsefree_exp();
339 if (s0 === peg$FAILED) {
340 s0 = peg$currPos;
341 s1 = peg$parsetoken();
342 if (s1 !== peg$FAILED) {
343 peg$savedPos = s0;
344 s1 = peg$c0(s1);
345 }
346 s0 = s1;
347 }
348 }
349
350 return s0;
351 }
352
353 function peg$parsefree_exp() {
354 var s0, s1, s2, s3;
355
356 s0 = peg$currPos;
357 s1 = peg$parsetoken();
358 if (s1 !== peg$FAILED) {
359 s2 = [];
360 if (input.charCodeAt(peg$currPos) === 58) {
361 s3 = peg$c1;
362 peg$currPos++;
363 } else {
364 s3 = peg$FAILED;
365 if (peg$silentFails === 0) { peg$fail(peg$c2); }
366 }
367 if (s3 === peg$FAILED) {
368 if (input.charCodeAt(peg$currPos) === 46) {
369 s3 = peg$c3;
370 peg$currPos++;
371 } else {
372 s3 = peg$FAILED;
373 if (peg$silentFails === 0) { peg$fail(peg$c4); }
374 }
375 if (s3 === peg$FAILED) {
376 s3 = peg$parsews();
377 if (s3 === peg$FAILED) {
378 if (input.charCodeAt(peg$currPos) === 39) {
379 s3 = peg$c5;
380 peg$currPos++;
381 } else {
382 s3 = peg$FAILED;
383 if (peg$silentFails === 0) { peg$fail(peg$c6); }
384 }
385 if (s3 === peg$FAILED) {
386 if (input.charCodeAt(peg$currPos) === 45) {
387 s3 = peg$c7;
388 peg$currPos++;
389 } else {
390 s3 = peg$FAILED;
391 if (peg$silentFails === 0) { peg$fail(peg$c8); }
392 }
393 if (s3 === peg$FAILED) {
394 if (input.charCodeAt(peg$currPos) === 47) {
395 s3 = peg$c9;
396 peg$currPos++;
397 } else {
398 s3 = peg$FAILED;
399 if (peg$silentFails === 0) { peg$fail(peg$c10); }
400 }
401 if (s3 === peg$FAILED) {
402 s3 = peg$parsetoken();
403 }
404 }
405 }
406 }
407 }
408 }
409 while (s3 !== peg$FAILED) {
410 s2.push(s3);
411 if (input.charCodeAt(peg$currPos) === 58) {
412 s3 = peg$c1;
413 peg$currPos++;
414 } else {
415 s3 = peg$FAILED;
416 if (peg$silentFails === 0) { peg$fail(peg$c2); }
417 }
418 if (s3 === peg$FAILED) {
419 if (input.charCodeAt(peg$currPos) === 46) {
420 s3 = peg$c3;
421 peg$currPos++;
422 } else {
423 s3 = peg$FAILED;
424 if (peg$silentFails === 0) { peg$fail(peg$c4); }
425 }
426 if (s3 === peg$FAILED) {
427 s3 = peg$parsews();
428 if (s3 === peg$FAILED) {
429 if (input.charCodeAt(peg$currPos) === 39) {
430 s3 = peg$c5;
431 peg$currPos++;
432 } else {
433 s3 = peg$FAILED;
434 if (peg$silentFails === 0) { peg$fail(peg$c6); }
435 }
436 if (s3 === peg$FAILED) {
437 if (input.charCodeAt(peg$currPos) === 45) {
438 s3 = peg$c7;
439 peg$currPos++;
440 } else {
441 s3 = peg$FAILED;
442 if (peg$silentFails === 0) { peg$fail(peg$c8); }
443 }
444 if (s3 === peg$FAILED) {
445 if (input.charCodeAt(peg$currPos) === 47) {
446 s3 = peg$c9;
447 peg$currPos++;
448 } else {
449 s3 = peg$FAILED;
450 if (peg$silentFails === 0) { peg$fail(peg$c10); }
451 }
452 if (s3 === peg$FAILED) {
453 s3 = peg$parsetoken();
454 }
455 }
456 }
457 }
458 }
459 }
460 }
461 if (s2 !== peg$FAILED) {
462 peg$savedPos = s0;
463 s1 = peg$c11(s1, s2);
464 s0 = s1;
465 } else {
466 peg$currPos = s0;
467 s0 = peg$FAILED;
468 }
469 } else {
470 peg$currPos = s0;
471 s0 = peg$FAILED;
472 }
473
474 return s0;
475 }
476
477 function peg$parselogical_or() {
478 var s0, s1, s2, s3, s4, s5;
479
480 s0 = peg$currPos;
481 s1 = peg$parselogical_and();
482 if (s1 !== peg$FAILED) {
483 s2 = [];
484 s3 = peg$parsews();
485 if (s3 !== peg$FAILED) {
486 while (s3 !== peg$FAILED) {
487 s2.push(s3);
488 s3 = peg$parsews();
489 }
490 } else {
491 s2 = peg$FAILED;
492 }
493 if (s2 !== peg$FAILED) {
494 if (input.substr(peg$currPos, 2) === peg$c12) {
495 s3 = peg$c12;
496 peg$currPos += 2;
497 } else {
498 s3 = peg$FAILED;
499 if (peg$silentFails === 0) { peg$fail(peg$c13); }
500 }
501 if (s3 !== peg$FAILED) {
502 s4 = [];
503 s5 = peg$parsews();
504 if (s5 !== peg$FAILED) {
505 while (s5 !== peg$FAILED) {
506 s4.push(s5);
507 s5 = peg$parsews();
508 }
509 } else {
510 s4 = peg$FAILED;
511 }
512 if (s4 !== peg$FAILED) {
513 s5 = peg$parselogical_or();
514 if (s5 !== peg$FAILED) {
515 peg$savedPos = s0;
516 s1 = peg$c14(s1, s5);
517 s0 = s1;
518 } else {
519 peg$currPos = s0;
520 s0 = peg$FAILED;
521 }
522 } else {
523 peg$currPos = s0;
524 s0 = peg$FAILED;
525 }
526 } else {
527 peg$currPos = s0;
528 s0 = peg$FAILED;
529 }
530 } else {
531 peg$currPos = s0;
532 s0 = peg$FAILED;
533 }
534 } else {
535 peg$currPos = s0;
536 s0 = peg$FAILED;
537 }
538 if (s0 === peg$FAILED) {
539 s0 = peg$parselogical_and();
540 }
541
542 return s0;
543 }
544
545 function peg$parselogical_and() {
546 var s0, s1, s2, s3, s4, s5;
547
548 s0 = peg$currPos;
549 s1 = peg$parselogical_not();
550 if (s1 !== peg$FAILED) {
551 s2 = [];
552 s3 = peg$parsews();
553 if (s3 !== peg$FAILED) {
554 while (s3 !== peg$FAILED) {
555 s2.push(s3);
556 s3 = peg$parsews();
557 }
558 } else {
559 s2 = peg$FAILED;
560 }
561 if (s2 !== peg$FAILED) {
562 if (input.substr(peg$currPos, 3) === peg$c15) {
563 s3 = peg$c15;
564 peg$currPos += 3;
565 } else {
566 s3 = peg$FAILED;
567 if (peg$silentFails === 0) { peg$fail(peg$c16); }
568 }
569 if (s3 !== peg$FAILED) {
570 s4 = [];
571 s5 = peg$parsews();
572 if (s5 !== peg$FAILED) {
573 while (s5 !== peg$FAILED) {
574 s4.push(s5);
575 s5 = peg$parsews();
576 }
577 } else {
578 s4 = peg$FAILED;
579 }
580 if (s4 !== peg$FAILED) {
581 s5 = peg$parselogical_and();
582 if (s5 !== peg$FAILED) {
583 peg$savedPos = s0;
584 s1 = peg$c17(s1, s5);
585 s0 = s1;
586 } else {
587 peg$currPos = s0;
588 s0 = peg$FAILED;
589 }
590 } else {
591 peg$currPos = s0;
592 s0 = peg$FAILED;
593 }
594 } else {
595 peg$currPos = s0;
596 s0 = peg$FAILED;
597 }
598 } else {
599 peg$currPos = s0;
600 s0 = peg$FAILED;
601 }
602 } else {
603 peg$currPos = s0;
604 s0 = peg$FAILED;
605 }
606 if (s0 === peg$FAILED) {
607 s0 = peg$parselogical_not();
608 }
609
610 return s0;
611 }
612
613 function peg$parselogical_not() {
614 var s0, s1, s2, s3;
615
616 s0 = peg$currPos;
617 if (input.substr(peg$currPos, 3) === peg$c18) {
618 s1 = peg$c18;
619 peg$currPos += 3;
620 } else {
621 s1 = peg$FAILED;
622 if (peg$silentFails === 0) { peg$fail(peg$c19); }
623 }
624 if (s1 !== peg$FAILED) {
625 s2 = [];
626 s3 = peg$parsews();
627 while (s3 !== peg$FAILED) {
628 s2.push(s3);
629 s3 = peg$parsews();
630 }
631 if (s2 !== peg$FAILED) {
632 s3 = peg$parselogical_not();
633 if (s3 !== peg$FAILED) {
634 peg$savedPos = s0;
635 s1 = peg$c20(s3);
636 s0 = s1;
637 } else {
638 peg$currPos = s0;
639 s0 = peg$FAILED;
640 }
641 } else {
642 peg$currPos = s0;
643 s0 = peg$FAILED;
644 }
645 } else {
646 peg$currPos = s0;
647 s0 = peg$FAILED;
648 }
649 if (s0 === peg$FAILED) {
650 s0 = peg$parseprimary();
651 }
652
653 return s0;
654 }
655
656 function peg$parseprimary() {
657 var s0, s1, s2, s3;
658
659 s0 = peg$parseterm();
660 if (s0 === peg$FAILED) {
661 s0 = peg$currPos;
662 if (input.charCodeAt(peg$currPos) === 40) {
663 s1 = peg$c21;
664 peg$currPos++;
665 } else {
666 s1 = peg$FAILED;
667 if (peg$silentFails === 0) { peg$fail(peg$c22); }
668 }
669 if (s1 !== peg$FAILED) {
670 s2 = peg$parselogical_or();
671 if (s2 !== peg$FAILED) {
672 if (input.charCodeAt(peg$currPos) === 41) {
673 s3 = peg$c23;
674 peg$currPos++;
675 } else {
676 s3 = peg$FAILED;
677 if (peg$silentFails === 0) { peg$fail(peg$c24); }
678 }
679 if (s3 !== peg$FAILED) {
680 peg$savedPos = s0;
681 s1 = peg$c25(s2);
682 s0 = s1;
683 } else {
684 peg$currPos = s0;
685 s0 = peg$FAILED;
686 }
687 } else {
688 peg$currPos = s0;
689 s0 = peg$FAILED;
690 }
691 } else {
692 peg$currPos = s0;
693 s0 = peg$FAILED;
694 }
695 }
696
697 return s0;
698 }
699
700 function peg$parseterm() {
701 var s0, s1, s2, s3;
702
703 s0 = peg$parseexpression();
704 if (s0 === peg$FAILED) {
705 s0 = peg$currPos;
706 s1 = peg$parsetoken();
707 if (s1 !== peg$FAILED) {
708 if (input.charCodeAt(peg$currPos) === 58) {
709 s2 = peg$c1;
710 peg$currPos++;
711 } else {
712 s2 = peg$FAILED;
713 if (peg$silentFails === 0) { peg$fail(peg$c2); }
714 }
715 if (s2 !== peg$FAILED) {
716 s3 = peg$parsetoken();
717 if (s3 !== peg$FAILED) {
718 peg$savedPos = s0;
719 s1 = peg$c26(s1, s3);
720 s0 = s1;
721 } else {
722 peg$currPos = s0;
723 s0 = peg$FAILED;
724 }
725 } else {
726 peg$currPos = s0;
727 s0 = peg$FAILED;
728 }
729 } else {
730 peg$currPos = s0;
731 s0 = peg$FAILED;
732 }
733 }
734
735 return s0;
736 }
737
738 function peg$parseexpression() {
739 var s0, s1, s2, s3, s4, s5, s6;
740
741 s0 = peg$currPos;
742 s1 = peg$parsetoken();
743 if (s1 !== peg$FAILED) {
744 if (input.charCodeAt(peg$currPos) === 58) {
745 s2 = peg$c1;
746 peg$currPos++;
747 } else {
748 s2 = peg$FAILED;
749 if (peg$silentFails === 0) { peg$fail(peg$c2); }
750 }
751 if (s2 !== peg$FAILED) {
752 if (input.charCodeAt(peg$currPos) === 34) {
753 s3 = peg$c27;
754 peg$currPos++;
755 } else {
756 s3 = peg$FAILED;
757 if (peg$silentFails === 0) { peg$fail(peg$c28); }
758 }
759 if (s3 !== peg$FAILED) {
760 s4 = peg$parsetoken();
761 if (s4 !== peg$FAILED) {
762 s5 = [];
763 if (input.charCodeAt(peg$currPos) === 58) {
764 s6 = peg$c1;
765 peg$currPos++;
766 } else {
767 s6 = peg$FAILED;
768 if (peg$silentFails === 0) { peg$fail(peg$c2); }
769 }
770 if (s6 === peg$FAILED) {
771 if (input.charCodeAt(peg$currPos) === 46) {
772 s6 = peg$c3;
773 peg$currPos++;
774 } else {
775 s6 = peg$FAILED;
776 if (peg$silentFails === 0) { peg$fail(peg$c4); }
777 }
778 if (s6 === peg$FAILED) {
779 s6 = peg$parsews();
780 if (s6 === peg$FAILED) {
781 if (input.charCodeAt(peg$currPos) === 39) {
782 s6 = peg$c5;
783 peg$currPos++;
784 } else {
785 s6 = peg$FAILED;
786 if (peg$silentFails === 0) { peg$fail(peg$c6); }
787 }
788 if (s6 === peg$FAILED) {
789 if (input.charCodeAt(peg$currPos) === 45) {
790 s6 = peg$c7;
791 peg$currPos++;
792 } else {
793 s6 = peg$FAILED;
794 if (peg$silentFails === 0) { peg$fail(peg$c8); }
795 }
796 if (s6 === peg$FAILED) {
797 if (input.charCodeAt(peg$currPos) === 47) {
798 s6 = peg$c9;
799 peg$currPos++;
800 } else {
801 s6 = peg$FAILED;
802 if (peg$silentFails === 0) { peg$fail(peg$c10); }
803 }
804 if (s6 === peg$FAILED) {
805 s6 = peg$parsetoken();
806 }
807 }
808 }
809 }
810 }
811 }
812 while (s6 !== peg$FAILED) {
813 s5.push(s6);
814 if (input.charCodeAt(peg$currPos) === 58) {
815 s6 = peg$c1;
816 peg$currPos++;
817 } else {
818 s6 = peg$FAILED;
819 if (peg$silentFails === 0) { peg$fail(peg$c2); }
820 }
821 if (s6 === peg$FAILED) {
822 if (input.charCodeAt(peg$currPos) === 46) {
823 s6 = peg$c3;
824 peg$currPos++;
825 } else {
826 s6 = peg$FAILED;
827 if (peg$silentFails === 0) { peg$fail(peg$c4); }
828 }
829 if (s6 === peg$FAILED) {
830 s6 = peg$parsews();
831 if (s6 === peg$FAILED) {
832 if (input.charCodeAt(peg$currPos) === 39) {
833 s6 = peg$c5;
834 peg$currPos++;
835 } else {
836 s6 = peg$FAILED;
837 if (peg$silentFails === 0) { peg$fail(peg$c6); }
838 }
839 if (s6 === peg$FAILED) {
840 if (input.charCodeAt(peg$currPos) === 45) {
841 s6 = peg$c7;
842 peg$currPos++;
843 } else {
844 s6 = peg$FAILED;
845 if (peg$silentFails === 0) { peg$fail(peg$c8); }
846 }
847 if (s6 === peg$FAILED) {
848 if (input.charCodeAt(peg$currPos) === 47) {
849 s6 = peg$c9;
850 peg$currPos++;
851 } else {
852 s6 = peg$FAILED;
853 if (peg$silentFails === 0) { peg$fail(peg$c10); }
854 }
855 if (s6 === peg$FAILED) {
856 s6 = peg$parsetoken();
857 }
858 }
859 }
860 }
861 }
862 }
863 }
864 if (s5 !== peg$FAILED) {
865 if (input.charCodeAt(peg$currPos) === 34) {
866 s6 = peg$c27;
867 peg$currPos++;
868 } else {
869 s6 = peg$FAILED;
870 if (peg$silentFails === 0) { peg$fail(peg$c28); }
871 }
872 if (s6 !== peg$FAILED) {
873 peg$savedPos = s0;
874 s1 = peg$c29(s1, s4, s5);
875 s0 = s1;
876 } else {
877 peg$currPos = s0;
878 s0 = peg$FAILED;
879 }
880 } else {
881 peg$currPos = s0;
882 s0 = peg$FAILED;
883 }
884 } else {
885 peg$currPos = s0;
886 s0 = peg$FAILED;
887 }
888 } else {
889 peg$currPos = s0;
890 s0 = peg$FAILED;
891 }
892 } else {
893 peg$currPos = s0;
894 s0 = peg$FAILED;
895 }
896 } else {
897 peg$currPos = s0;
898 s0 = peg$FAILED;
899 }
900
901 return s0;
902 }
903
904 function peg$parsetoken() {
905 var s0, s1, s2;
906
907 s0 = peg$currPos;
908 s1 = [];
909 if (peg$c30.test(input.charAt(peg$currPos))) {
910 s2 = input.charAt(peg$currPos);
911 peg$currPos++;
912 } else {
913 s2 = peg$FAILED;
914 if (peg$silentFails === 0) { peg$fail(peg$c31); }
915 }
916 if (s2 !== peg$FAILED) {
917 while (s2 !== peg$FAILED) {
918 s1.push(s2);
919 if (peg$c30.test(input.charAt(peg$currPos))) {
920 s2 = input.charAt(peg$currPos);
921 peg$currPos++;
922 } else {
923 s2 = peg$FAILED;
924 if (peg$silentFails === 0) { peg$fail(peg$c31); }
925 }
926 }
927 } else {
928 s1 = peg$FAILED;
929 }
930 if (s1 !== peg$FAILED) {
931 peg$savedPos = s0;
932 s1 = peg$c32(s1);
933 }
934 s0 = s1;
935
936 return s0;
937 }
938
939 function peg$parsews() {
940 var s0;
941
942 if (peg$c33.test(input.charAt(peg$currPos))) {
943 s0 = input.charAt(peg$currPos);
944 peg$currPos++;
945 } else {
946 s0 = peg$FAILED;
947 if (peg$silentFails === 0) { peg$fail(peg$c34); }
948 }
949
950 return s0;
951 }
952
953
954 function processName(name) {
955 var processedName = "";
956 switch (name) {
957 case 'accountability':
958 case 'availability':
959 case 'confidentiality':
960 case 'integrity':
961 processedName = 'impact_' + name;
962 break;
963 case 'service':
964 processedName = 'service__name';
965 break;
966 case 'easeofresolution':
967 case 'ease_of_resolution':
968 processedName = 'ease_of_resolution';
969 break;
970 case 'web':
971 case 'type':
972 processedName = 'type';
973 break;
974 case 'creator':
975 processedName = 'creator_command_tool';
976 break;
977 case 'policy_violations':
978 case 'policyviolations':
979 processedName = 'policy_violations__name';
980 break;
981 case 'host_os':
982 processedName = 'host__os';
983 break;
984 case 'refs':
985 case 'ref':
986 processedName = 'references__name';
987 break;
988 case 'evidence':
989 processedName = 'evidence__filename';
990 break;
991 case 'params':
992 case 'parameters':
993 processedName = 'parameters';
994 break;
995 case 'pname':
996 case 'parameter_name':
997 processedName = 'parameter_name';
998 break;
999 case 'query':
1000 case 'query_string':
1001 processedName = 'query_string';
1002 break;
1003 case 'tags':
1004 case 'tag':
1005 processedName = 'tags__name';
1006 break;
1007 case 'port':
1008 case 'service_port':
1009 processedName = 'service__port';
1010 break;
1011 case 'protocol':
1012 case 'service_protocol':
1013 processedName = 'service__protocol';
1014 break;
1015 case 'hostname':
1016 processedName = 'hostnames';
1017 break;
1018 default:
1019 processedName = name;
1020 break;
1021 }
1022 return processedName;
1023 }
1024
1025
1026 function processOperator(name, operator) {
1027 var processedOperator = "";
1028 name = processName(name);
1029 switch (name) {
1030 case 'confirmed':
1031 case 'impact_accountability':
1032 case 'impact_availability':
1033 case 'impact_confidentiality':
1034 case 'impact_integrity':
1035 case 'ease_of_resolution':
1036 case 'type':
1037 case 'id':
1038 processedOperator = operator !== 'not' ? '==' : '!=';
1039 break;
1040 case 'severity':
1041 case 'target':
1042 case 'hostnames':
1043 case 'policy_violations__name':
1044 case 'references__name':
1045 case 'status':
1046 case 'status_code':
1047 processedOperator = operator !== 'not' ? 'eq' : '!=';
1048 break;
1049 case 'service__name':
1050 case 'service__port':
1051 case 'service__protocol':
1052 case 'host__os':
1053 processedOperator = operator !== 'not' ? 'has' : '!=';
1054 break;
1055 case 'evidence__filename':
1056 case 'tags__name':
1057 processedOperator = operator !== 'not' ? 'any' : '!=';
1058 break;
1059 default:
1060 processedOperator = operator !== 'not' ? 'ilike' : '!=';
1061 break;
1062 }
1063
1064 return processedOperator;
1065 }
1066
1067
1068 function processValue(name, operator, value) {
1069 name = processName(name);
1070 operator = processOperator(name, operator);
1071 var val = value;
1072
1073 if (val === 'info') val = 'informational';
1074 if (val === 'med') val = 'medium';
1075
1076 if (operator === 'ilike' && name !== 'creator_command_tool') {
1077 val = '%' + value + '%';
1078 }
1079 return val;
1080 }
1081
1082 function processLogicalNot(operand){
1083 try{
1084 operand.val = operand.val.replace(/%/g,'');
1085 return {
1086 name: operand.name,
1087 op: processOperator(operand.name, 'not') ,
1088 val: processValue(operand.name, 'not', operand.val)
1089 }
1090 }catch(e){
1091 throw '"NOT" expression only can contain one operand'
1092 return null;
1093 }
1094
1095
1096 }
1097
1098
1099
1100 peg$result = peg$startRuleFunction();
1101
1102 if (peg$result !== peg$FAILED && peg$currPos === input.length) {
1103 return peg$result;
1104 } else {
1105 if (peg$result !== peg$FAILED && peg$currPos < input.length) {
1106 peg$fail(peg$endExpectation());
1107 }
1108
1109 throw peg$buildStructuredError(
1110 peg$maxFailExpected,
1111 peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
1112 peg$maxFailPos < input.length
1113 ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
1114 : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
1115 );
1116 }
1117 }
+0
-206
faraday/server/www/scripts/statusReport/providers/logical.pegjs less more
0 {
1 function processName(name) {
2 var processedName = "";
3 switch (name) {
4 case 'accountability':
5 case 'availability':
6 case 'confidentiality':
7 case 'integrity':
8 processedName = 'impact_' + name;
9 break;
10 case 'service':
11 processedName = 'service__name';
12 break;
13 case 'easeofresolution':
14 case 'ease_of_resolution':
15 processedName = 'ease_of_resolution';
16 break;
17 case 'web':
18 case 'type':
19 processedName = 'type';
20 break;
21 case 'creator':
22 processedName = 'creator_command_tool';
23 break;
24 case 'policy_violations':
25 case 'policyviolations':
26 processedName = 'policy_violations__name';
27 break;
28 case 'host_os':
29 processedName = 'host__os';
30 break;
31 case 'refs':
32 case 'ref':
33 processedName = 'references__name';
34 break;
35 case 'evidence':
36 processedName = 'evidence__filename';
37 break;
38 case 'params':
39 case 'parameters':
40 processedName = 'parameters';
41 break;
42 case 'pname':
43 case 'parameter_name':
44 processedName = 'parameter_name';
45 break;
46 case 'query':
47 case 'query_string':
48 processedName = 'query_string';
49 break;
50 case 'tags':
51 case 'tag':
52 processedName = 'tags__name';
53 break;
54 case 'port':
55 case 'service_port':
56 processedName = 'service__port';
57 break;
58 case 'protocol':
59 case 'service_protocol':
60 processedName = 'service__protocol';
61 break;
62 case 'hostname':
63 processedName = 'hostnames';
64 break;
65 default:
66 processedName = name;
67 break;
68 }
69 return processedName;
70 }
71
72
73 function processOperator(name, operator) {
74 var processedOperator = "";
75 name = processName(name);
76 switch (name) {
77 case 'confirmed':
78 case 'impact_accountability':
79 case 'impact_availability':
80 case 'impact_confidentiality':
81 case 'impact_integrity':
82 case 'ease_of_resolution':
83 case 'type':
84 case 'id':
85 processedOperator = operator !== 'not' ? '==' : '!=';
86 break;
87 case 'severity':
88 case 'target':
89 case 'hostnames':
90 case 'policy_violations__name':
91 case 'references__name':
92 case 'status':
93 case 'status_code':
94 processedOperator = operator !== 'not' ? 'eq' : '!=';
95 break;
96 case 'service__name':
97 case 'service__port':
98 case 'service__protocol':
99 case 'host__os':
100 processedOperator = operator !== 'not' ? 'has' : '!=';
101 break;
102 case 'evidence__filename':
103 case 'tags__name':
104 processedOperator = operator !== 'not' ? 'any' : '!=';
105 break;
106 default:
107 processedOperator = operator !== 'not' ? 'ilike' : '!=';
108 break;
109 }
110
111 return processedOperator;
112 }
113
114
115 function processValue(name, operator, value) {
116 name = processName(name);
117 operator = processOperator(name, operator);
118 var val = value;
119
120 if (val === 'info') val = 'informational';
121 if (val === 'med') val = 'medium';
122
123 if (operator === 'ilike' && name !== 'creator_command_tool') {
124 val = '%' + value + '%';
125 }
126 return val;
127 }
128
129 function processLogicalNot(operand){
130 try{
131 operand.val = operand.val.replace(/%/g,'');
132 return {
133 name: operand.name,
134 op: processOperator(operand.name, 'not') ,
135 val: processValue(operand.name, 'not', operand.val)
136 }
137 }catch(e){
138 throw '"NOT" expression only can contain one operand'
139 return null;
140 }
141
142
143 }
144
145 }
146
147
148
149 start
150 = logical_or /
151 free_exp /
152 token:token { return {name:'name', op:'ilike', val: '%'+ token + '%'}}
153
154 free_exp
155 = exp : token optional: (":" / "." / ws / "'" / "-" / "/" / token)*
156 {
157 return {
158 name: 'name',
159 op: 'ilike' ,
160 val: processValue(name, null, exp += optional.join(""))
161 }
162 }
163
164 logical_or
165 = left:logical_and ws+ "or" ws+ right:logical_or { return {"or": [left, right]} }
166 / logical_and
167
168 logical_and
169 = left:logical_not ws+ "and" ws+ right:logical_and { return {"and": [left, right]} }
170 / logical_not
171
172 logical_not
173 = "not" ws* operand:logical_not { return processLogicalNot(operand) }
174 / primary
175
176 primary
177 = term
178 / "(" logical_or:logical_or ")" { return logical_or; }
179
180 term
181 = expression
182 / name:token ":" value:token
183 {
184 return {
185 name: processName(name),
186 op: processOperator(name, null) ,
187 val: processValue(name, null, value)
188 }
189 }
190
191 expression
192 = name: token ':' '"' mandatory: token optional: (":" / "." / ws / "'" / "-" / "/" / token)* '"'
193 {
194 return {
195 name: processName(name),
196 op: processOperator(name, null) ,
197 val: processValue(name, null, mandatory += optional.join(""))
198 }
199 }
200
201 token
202 = token:[a-zA-Z0-9_.-/]+ { return token.join(""); }
203
204 ws
205 = [ \t]
+0
-60
faraday/server/www/scripts/statusReport/providers/parser.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('parserFact', ['commonsFact', function (commonsFact) {
6 var parserFact = {};
7
8 parserFact.evaluateExpression = function (expression) {
9 var outputJson = {
10 "filters": []
11 };
12
13 try {
14 var filter = peg$parse(expression);
15 outputJson["filters"].push(filter);
16 return escape(JSON.stringify(outputJson));
17 } catch (e) {
18 commonsFact.showMessage(e.message || e);
19 return null;
20 }
21 };
22
23 var testParenthesisPairs = function (string) {
24 var length = string.length,
25 i = 0,
26 count = 0,
27 openChar = arguments[1] || "(",
28 closeChar = arguments[2] || ")";
29
30 while (i < length) {
31 char = string.charAt(i);
32
33 if (char === openChar) {
34 count += 1;
35 } else if (char === closeChar) {
36 count -= 1;
37 }
38
39 if (count < 0) {
40 return false;
41 }
42
43 i += 1;
44 }
45
46 return count === 0;
47 };
48
49
50 parserFact.isValid = function (expression) {
51 var reQuotes = /^(?:[^"\\]|\\.|"(?:\\.|[^"\\])*")*$/; // checks if the expressions contains unclosed quotes
52 var reDoubleSpaces = /\s\s/; // checks if the expressions contains double spaces
53 return testParenthesisPairs(expression) && expression.match(reQuotes) !== null && expression.match(reDoubleSpaces) === null;
54 };
55
56
57 return parserFact;
58
59 }]);
+0
-42
faraday/server/www/scripts/statusReport/providers/reference.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('referenceFact', [
6 function () {
7 var referenceFact = {};
8
9 referenceFact.processReference = function (text) {
10 var url = 'http://google.com/',
11 url_pattern = new RegExp('^(http|https):\\/\\/?');
12
13 var cve_pattern = new RegExp(/^CVE-\d{4}-\d{4,7}$/),
14 cwe_pattern = new RegExp(/^CWE(-|:)\d{1,7}$/),
15 edb_pattern = new RegExp(/^EDB-ID:\s?\d{1,}$/),
16 osvdb_pattern = new RegExp(/^OSVDB:\s?\d{1,}$/);
17
18 var cve = text.search(cve_pattern),
19 cwe = text.search(cwe_pattern),
20 edb = text.search(edb_pattern),
21 osvdb = text.search(osvdb_pattern);
22
23 if (url_pattern.test(text)) {
24 url = text;
25 } else if (cve > -1) {
26 url = "https://cve.mitre.org/cgi-bin/cvename.cgi?name=" + text.substring(cve + 4);
27 } else if (cwe > -1) {
28 url = "https://cwe.mitre.org/data/definitions/" + text.substring(cwe + 4) + ".html";
29 } else if (osvdb > -1) {
30 url = "http://osvdb.org/show/osvdb/" + text.substring(osvdb + 6);
31 } else if (edb > -1) {
32 url = "https://www.exploit-db.com/exploits/" + text.substring(edb + 7);
33 } else {
34 url += 'search?q=' + text;
35 }
36
37 return url;
38 }
39
40 return referenceFact;
41 }]);
+0
-41
faraday/server/www/scripts/statusReport/providers/target.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('targetFact', ['BASEURL', '$q', 'hostsManager', 'servicesManager',
6 function(BASEURL, $q, hostsManager, servicesManager) {
7 var targetFact = {};
8
9 targetFact.getTargets = function(workspace, page, page_size, filter, sort, sort_direction) {
10 var deferred = $q.defer();
11 var res = {hosts: [], total: 0};
12 var hosts_dict = {};
13 hostsManager.getHosts(workspace, page, page_size, filter, sort, sort_direction).then(function(resp) {
14 resp.hosts.forEach(function(host) {
15 host.hostnames = host.hostnames || [];
16 host.services = [];
17 hosts_dict[host._id] = host;
18 res.hosts.push(host);
19 });
20
21 res.total = resp.total;
22
23 servicesManager.getServices(workspace).then(function(services) {
24 services.forEach(function(service) {
25 host_id = service.host_id
26 if (hosts_dict.hasOwnProperty(host_id)) {
27 hosts_dict[host_id].services.push(service);
28 }
29 });
30 }, function(err) {deferred.reject(err)});
31
32 deferred.resolve(res);
33
34 }, function(err) {deferred.reject(err)});
35
36 return deferred.promise;
37 };
38
39 return targetFact;
40 }]);
+0
-124
faraday/server/www/scripts/statusReport/providers/ui-common.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('uiCommonFact', ['BASEURL', function (BASEURL) {
6
7 var uiCommonFact = {};
8
9 uiCommonFact.updateBtnSeverityColor = function (severity, btnSelector, caretSelector) {
10 var color = undefined;
11 switch (severity) {
12 case "unclassified":
13 color = '#999999';
14 break;
15 case "info":
16 color = '#2e97bd';
17 break;
18 case "low":
19 color = '#a1ce31';
20 break;
21 case "med":
22 color = '#dfbf35';
23 break;
24 case "high":
25 color = '#df3936';
26 break;
27 case "critical":
28 color = '#932ebe';
29 break;
30 }
31
32 angular.element(btnSelector).css('background-color', color);
33 angular.element(caretSelector).css('background-color', color);
34 };
35
36
37 uiCommonFact.updateBtnStatusColor = function (status, btnSelector, caretSelector) {
38 var color = undefined;
39 switch (status) {
40 case "opened":
41 color = '#DB3130';
42 break;
43 case "closed":
44 color = '#97F72C';
45 break;
46 case "re-opened":
47 color = '#DBB72F';
48 break;
49 case "risk-accepted":
50 color = '#288DB4';
51 break;
52 default:
53 color = '#aaaaaa';
54 break;
55 }
56
57 angular.element(btnSelector).css('background-color', color);
58 angular.element(caretSelector).css('background-color', color);
59 };
60
61
62 uiCommonFact.populate = function (template, vuln) {
63 for (var key in vuln) {
64 if (key !== "refs" && key !== "policyviolations" && template.hasOwnProperty(key) && vuln.hasOwnProperty(key)) {
65 vuln[key] = template[key];
66 }
67 }
68 // convert refs to an array of objects
69 var refs = [];
70 template.refs.forEach(function (ref) {
71 refs.push(ref);
72 });
73 vuln.refs = refs;
74
75 // convert policyviolations to an array of objects
76 var policyviolations = [];
77 template.policyviolations.forEach(function (policyviolation) {
78 policyviolations.push(policyviolation);
79 });
80 vuln.policyviolations = policyviolations;
81 };
82
83
84 uiCommonFact.newReference = function (newRef, vuln) {
85 if (newRef !== "") {
86 // we need to check if the ref already exists
87 if (vuln.refs.filter(function (ref) {
88 return ref === newRef
89 }).length === 0) {
90 vuln.refs.push(newRef);
91 newRef = "";
92 }
93 }
94 };
95
96
97 uiCommonFact.newPolicyViolation = function (newPolicyViolation, vuln) {
98 if (newPolicyViolation !== "") {
99 // we need to check if the policy violation already exists
100 if (vuln.policyviolations.filter(function (policyviolation) {
101 return policyviolation.value === newPolicyViolation
102 }).length === 0) {
103 vuln.policyviolations.push(newPolicyViolation);
104 newPolicyViolation = "";
105 }
106 }
107 };
108
109
110 uiCommonFact.removeEvidence = function (name, vuln) {
111 delete vuln._attachments[name];
112 };
113
114 uiCommonFact.openEvidence = function (name, vuln, ws) {
115 var currentEvidence = vuln._attachments[name];
116 if (!currentEvidence.newfile)
117 window.open(BASEURL + '_api/v2/ws/' + ws + '/vulns/' + vuln._id + '/attachment/' + encodeURIComponent(name), '_blank');
118 };
119
120
121 return uiCommonFact;
122
123 }]);
+0
-300
faraday/server/www/scripts/statusReport/styles/status.css less more
0 .status-report-grid .ui-grid-header{
1 border-top: solid #E5E5E5 5px;
2 border-bottom: 1px solid #d8d8d8;
3 background: none;
4 color: #E9E9E9;
5 padding: 0px;
6 height: 45px;
7 }
8
9 .status-report-grid .ui-grid-header .ui-grid-cell-contents {
10 color: #7c7c7c;
11 padding: 9px 3px 9px 5px !important;
12 text-align: left;
13 }
14
15 .status-report-grid .ui-grid-cell-contents {
16 text-align: left;
17 font-size: 11px;
18 }
19
20 .status-report-grid .ui-grid-cell-contents.confirm-toggle{
21 text-align: center;
22 }
23
24 .status-report-grid .ui-grid-header-cell{
25 border-right: solid #E9E9E9 1px;
26 text-align: center;
27 }
28
29 .status-report-grid .ui-grid-header-cell i, .status-report-grid .grid_id{
30 padding: 11px 9px 9px 5px !important
31 }
32
33 .status-report-grid .ui-grid-row {
34 height: 45px;
35 }
36
37 .status-report-grid .date-cell {
38 opacity: 0.5;
39 }
40
41 .status-report-grid .grid_id .ui-grid-cell-contents{
42 position: relative;
43 top: 3px;
44 }
45
46 .status-report-grid .ui-grid-row-selected .ui-grid-cell{
47 background-color: #8DA2B7 !important;
48 color: #FFFFFF;
49 }
50
51 .status-report-grid .ui-grid-row-selected a{
52 color: #FFFFFF;
53 }
54
55 .status-report-grid .no-background{
56 background: none;
57 }
58
59 .control-edit {
60 width:44px;
61 }
62
63 .status-report-grid .ui-grid-row:last-child .ui-grid-cell{
64 border:none;
65 }
66
67 .checkbox-select{
68 text-align: center !important;
69 }
70
71 .hosts-list .ui-grid-header .ui-grid-cell-contents{
72 padding: 8px 3px 11px 5px !important
73 }
74
75 .hosts-list .ui-grid-header .ui-grid-cell-contents span{
76 color: #7c7c7c;
77 }
78
79 .hosts-list .ui-grid-header .hosts-list-checkall{
80 position: relative;
81 text-align: center;
82 }
83
84 .status-report-grid .ui-grid-pager-panel {
85 background-color: #f1f1f1;
86 }
87
88
89 .status-report-grid .status.opened {
90 background-color: #F6E6E9 !important;
91 text-align: center;
92 }
93
94 .status-report-grid .status-wrapper {
95 height: 100%;
96 }
97
98 .status-report-grid .status.opened span {
99 color: #DB3130;
100 font-size: 11px;
101 }
102
103 .status-report-grid .status.risk-accepted {
104 background-color: #288DB4 !important;
105 text-align: center;
106 }
107
108 .status-report-grid .status.re-opened span {
109 color: #DBB72F;
110 font-size: 11px;
111 }
112
113 .status-report-grid .status.re-opened {
114 background-color: #F5F2E5 !important;
115 text-align: center;
116 }
117
118 .status-report-grid .status.risk-accepted span {
119 color: #DBEBF1;
120 font-size: 11px;
121 }
122
123 .status-report-grid .status.closed {
124 background-color: #E5F5D6 !important;
125 text-align: center;
126 }
127
128 .status-report-grid .status.closed span {
129 color: #97F72C;
130 font-size: 11px;
131 }
132
133 .control-edit .edit-icon, .download-wrapper .download-icon, .control-wrapper .delete-icon, .search-wrapper .search-icon {
134 height: 20px;
135 color: #000;
136 position: relative;
137 bottom: 2px;
138 }
139
140 .search-wrapper .search-icon {
141 bottom: 0px;
142 }
143
144 .status-report-grid .confirm-icon {
145 width: 50%;
146 }
147
148 .status-report-grid .ui-grid-header-cell{
149 text-align: center;
150 }
151
152 .download-wrapper {
153 bottom: 5px;
154 }
155
156 .status-report-grid .ui-grid-header-cell .glyphicon-remove{
157 color: #ccc;
158 font-size: 8px;
159 font-weight: lighter;
160 top: 0px;
161 left: 4px;
162 }
163
164 .search-wrapper .form-group{
165 margin: 0px;
166 }
167
168 .status-report-grid .ui-grid-contents-wrapper{
169 clear: both;
170 }
171
172 .status-report-grid .ui-grid-cell {
173 border: none ;
174 }
175
176 .button-control {
177 display:flex;
178 flex-direction: row;
179 padding-right: 20px;
180 padding-left: 0px;
181 padding-bottom: 17px;
182 justify-content: space-between;
183 align-items: center;
184 }
185
186 #reports-main {
187 padding: 0px 0 0 24px;
188 }
189
190 #reports-main .reports{
191 padding: 0px;
192 }
193
194 .search-wrapper {
195 width: 385px;
196 padding: 0px;
197 margin-right: 16px;
198 margin-left: 16px;
199 }
200
201 .search-wrapper input{
202 height: 40px !important;
203 font-size: 14px;
204 box-shadow: none;
205 }
206
207 .search-wrapper .input-group input, .search-wrapper .input-group span {
208 border: none;
209 border-radius: 0px;
210 background-color: #FFFFFF
211 }
212
213 .control-wrapper {
214 font-size: 14px;
215 }
216
217 .control-wrapper button:focus {outline:0;}
218
219 .filter-wrapper .confirm-button{
220 position: relative;
221 bottom: 1px;
222 }
223
224 .space-wrapper{
225 flex:1;
226 }
227
228 .control-wrapper button{
229 border-radius: 0px;
230 }
231
232 .control-wrapper > button{
233 border: none;
234 background: none;
235 width: 47px;
236 height: 33px;
237 }
238
239 .control-edit {
240 padding-right: 0px;
241 position: relative;
242 }
243
244 .control-edit .dropdown-menu-right{
245 left: 0px !important;
246 width: 245px;
247 }
248
249 .control-edit .edit {
250 width: 30px;
251 }
252
253 .control-edit .dropdown-toggle {
254 padding-right: 0px;
255 padding-left: 0px;
256 width: 10px;
257 }
258
259 button.btn-new {
260 width:95px;
261 height:33px;
262 background-color: #00a8e1;
263 }
264
265 button.btn-new:focus {
266 background-color: #00a8e1 !important;
267 }
268
269 button.btn-new:hover {
270 background-color: #0097ca !important;
271 }
272
273 .control-wrap-right {
274 justify-self: flex-end;
275 }
276
277 .control-wrap-right button{
278 font-size: 12px;
279 }
280
281 .control-new{
282 margin-right: 16px;
283 }
284
285
286 .status-report-grid .ui-grid-row-selected .ui-grid-cell .status {
287 color: white !important;
288 background-color:transparent !important;
289 }
290
291
292 .status-report-grid .ui-grid-row-selected .ui-grid-cell .status span {
293 color: white !important;
294 background-color:transparent !important;
295 }
296
297 .status-report-grid .ui-grid-pager-panel {
298 bottom: -18px;
299 }
+0
-104
faraday/server/www/scripts/vulndb/controllers/modalEdit.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('vulndDbModalEdit',
6 ['$scope', '$modalInstance', 'VulnModel', 'model', 'EXPLOITATIONS', 'EASEOFRESOLUTION', 'customFields',
7 function($scope, $modalInstance, VulnModel, model, EXPLOITATIONS, EASEOFRESOLUTION, customFields) {
8
9 $scope.data;
10 $scope.openedStart;
11 $scope.openedEnd;
12 var EXCLUDED_TOKENS = [""];
13
14 var init = function() {
15 $scope.exploitations = EXPLOITATIONS;
16 $scope.easeofresolution = EASEOFRESOLUTION;
17 $scope.data = new VulnModel;
18 $scope.data.set(model);
19 $scope.impact = {
20 accountability: false,
21 availability: false,
22 confidentiality: false,
23 integrity: false
24 }
25 for (var [key, value] of Object.entries(angular.copy($scope.data.impact))) {
26 $scope.impact[key] = value
27 }
28 $scope.policyviolations = clearList(angular.copy($scope.data.policyviolations), EXCLUDED_TOKENS);
29 $scope.references = clearList(angular.copy($scope.data.refs), EXCLUDED_TOKENS);
30 $scope.new_policyviolation = "";
31 $scope.new_reference = "";
32 $scope.customFields = customFields;
33
34 for (var key in $scope.data.customfields) {
35 $scope.customFields.forEach(function(cf){
36 if(cf.field_name == key)
37 cf.value = $scope.data.customfields[key];
38 })
39 }
40 };
41
42 $scope.ok = function() {
43 $scope.data.impact = angular.copy($scope.impact);
44 $scope.data.policyviolations = angular.copy($scope.policyviolations);
45 $scope.data.refs = angular.copy($scope.references);
46 $scope.data.references = $scope.data.refs.join(',');
47 for (const fieldName in $scope.data.customfields) {
48 $scope.customFields.forEach(function(cf){
49 if(cf.field_name === fieldName){
50 cf.value = $scope.data.customfields[fieldName];
51 }
52 })
53 }
54
55 $modalInstance.close($scope.data);
56 };
57
58 $scope.open = function($event, isStart) {
59 $event.preventDefault();
60 $event.stopPropagation();
61
62 if(isStart) $scope.openedStart = true; else $scope.openedEnd = true;
63 };
64
65 $scope.cancel = function() {
66 $modalInstance.dismiss('cancel');
67 };
68
69 $scope.toggleImpact = function(key) {
70 $scope.impact[key] = !$scope.impact[key];
71 };
72
73 $scope.newPolicyViolation = function() {
74 if ($scope.new_policyviolation !== "") {
75 // we need to check if the policy violation already exists
76 if ($scope.policyviolations.filter(function(policyviolation) {return policyviolation === $scope.new_policyviolation}).length === 0) {
77 $scope.policyviolations.push($scope.new_policyviolation);
78 $scope.new_policyviolation = "";
79 }
80 }
81 };
82
83 $scope.newReference = function() {
84 if ($scope.new_reference !== "") {
85 // we need to check if the reference already exists
86 if ($scope.references.filter(function(reference) {return reference === $scope.new_reference}).length === 0) {
87 $scope.references.push($scope.new_reference);
88 $scope.new_reference = "";
89 }
90 }
91 };
92
93 var clearList = function (list, excludedTokens) {
94 for (var i = 0; i< list.length ; i++){
95 if (excludedTokens.indexOf(list[i]) > -1){
96 list.splice(i, 1);
97 }
98 }
99 return list;
100 };
101
102 init();
103 }]);
+0
-94
faraday/server/www/scripts/vulndb/controllers/modalNew.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('vulnModelModalNew',
6 ['$scope', '$modalInstance', 'VulnModel', 'vulnModelsManager', 'EXPLOITATIONS', 'EASEOFRESOLUTION', 'customFields',
7 function($scope, $modalInstance, VulnModel, vulnModelsManager, EXPLOITATIONS, EASEOFRESOLUTION, customFields) {
8
9 $scope.data;
10 $scope.exploitations;
11 $scope.models;
12
13 var init = function() {
14 $scope.exploitations = EXPLOITATIONS;
15 $scope.easeofresolution = EASEOFRESOLUTION;
16 $scope.data = new VulnModel;
17 $scope.models = vulnModelsManager.models;
18 $scope.data.customfields = {};
19 // $scope.exploitations = ['a'];
20 $scope.customFields = customFields;
21
22 $scope.$watch(function() {
23 return $scope.data.model;
24 }, function(newVal, oldVal) {
25 if(newVal == "Other") {
26 $scope.other = true;
27 } else if(oldVal == "Other") {
28 $scope.other = false;
29 }
30 }, true);
31
32 customFields.forEach(function(cf) {
33 $scope.data.customfields[cf.field_name] = null;
34 });
35 };
36
37 $scope.open = function($event, isStart) {
38 $event.preventDefault();
39 $event.stopPropagation();
40
41 if(isStart) $scope.openedStart = true; else $scope.openedEnd = true;
42 };
43
44 $scope.ok = function() {
45 if($scope.other) {
46 $scope.data.model = $scope.other_model;
47 }
48
49 for (const fieldName in $scope.data.customfields) {
50 $scope.customFields.forEach(function(cf){
51 if(cf.field_name === fieldName){
52 cf.value = $scope.data.customfields[fieldName];
53 }
54 })
55 }
56
57 if ($scope.data.easeofresolution === ""){
58 $scope.data.easeofresolution = null;
59 }
60
61 $modalInstance.close($scope.data);
62 };
63
64 $scope.cancel = function() {
65 $modalInstance.dismiss('cancel');
66 };
67
68 $scope.toggleImpact = function(key) {
69 $scope.data.impact[key] = !$scope.data.impact[key];
70 };
71
72 $scope.newPolicyViolation = function() {
73 if ($scope.new_policyviolation !== "") {
74 // we need to check if the policy violation already exists
75 if ($scope.data.policyviolations.filter(function(policyviolation) {return policyviolation === $scope.new_policyviolation}).length === 0) {
76 $scope.data.policyviolations.push($scope.new_policyviolation);
77 $scope.new_policyviolation = "";
78 }
79 }
80 };
81
82 $scope.newReference = function() {
83 if ($scope.new_reference !== "") {
84 // we need to check if the reference already exists
85 if ($scope.data.references.filter(function(reference) {return reference === $scope.new_reference}).length === 0) {
86 $scope.data.references.push($scope.new_reference);
87 $scope.new_reference = "";
88 }
89 }
90 };
91
92 init();
93 }]);
+0
-24
faraday/server/www/scripts/vulndb/controllers/modalUpload.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('vulnModelModalUpload',
6 ['$scope', '$modalInstance',
7 function($scope, $modalInstance) {
8 $scope.data;
9
10 $scope._import = function() {
11 var csv = document.getElementById('file').files[0];
12 $scope.data = csv;
13 $scope.ok();
14 };
15
16 $scope.ok = function() {
17 $modalInstance.close($scope.data);
18 };
19
20 $scope.cancel = function() {
21 $modalInstance.dismiss('cancel');
22 };
23 }]);
+0
-439
faraday/server/www/scripts/vulndb/controllers/vulnModels.js less more
0 angular.module('faradayApp')
1 .controller('vulnModelsCtrl', [
2 '$scope',
3 '$filter',
4 '$http',
5 '$q',
6 '$uibModal',
7 'ServerAPI',
8 'csvService',
9 'commonsFact',
10 'vulnModelsManager',
11 'APIURL',
12 '$route',
13 'BASEURL',
14 function ($scope,
15 $filter,
16 $http,
17 $q,
18 $uibModal,
19 ServerAPI,
20 csvService,
21 commonsFact,
22 vulnModelsManager,
23 APIURL,
24 $route,
25 BASEURL) {
26
27 $scope.models = [];
28 $scope.loaded_models = false;
29 $scope.totalModels = 0;
30 $scope.disabledClick = false;
31 $scope.reverse;
32 $scope.search = '';
33 $scope.currentPage;
34 $scope.pageSize = 20;
35 $scope.loading = false;
36 $scope.customFields;
37
38 var init = function() {
39 // table stuff
40 $scope.selectall_models = false;
41 $scope.sort_field = "name";
42 $scope.reverse = true;
43 $scope.currentPage = 1;
44 $scope.loading = true;
45 vulnModelsManager.get()
46 .then(function() {
47 $scope.loading = false;
48 $scope.totalModels = vulnModelsManager.totalNumberOfModels;
49 $scope.models = vulnModelsManager.models;
50 $scope.loaded_models = true;
51 });
52
53 $scope.$watch(function() {
54 return vulnModelsManager.models;
55 }, function(newVal, oldVal) {
56 $scope.models = vulnModelsManager.models;
57 $scope.loaded_models = true;
58 }, true);
59 $scope.$watch(function() {
60 return $scope.pageCount();
61 }, function(newVal, oldVal, scope) {
62 if ($scope.currentPage > $scope.pageCount()) {
63 $scope.currentPage = $scope.pageCount();
64 }
65 });;
66
67 loadCustomFields();
68 };
69
70 var loadCustomFields = function () {
71 var deferred = $q.defer();
72 ServerAPI.getCustomFields().then(
73 function(response){
74 $scope.customFields = response.data;
75 deferred.resolve($scope.customFields);
76 }, function(){
77 deferred.reject();
78 });
79 };
80
81 $scope.pageCount = function() {
82 // if the guy searched for something with exactly 0 results, there's just '1' page;
83 // the one she's seeing with zero results
84 var searchPages = $scope.pagesOnSearch();
85
86 if (searchPages === undefined) {
87 return (Math.ceil(vulnModelsManager.totalNumberOfModels / this.pageSize) || 1);
88 } else {
89 // if searchpages is zero, pretend like its one
90 return (searchPages || 1);
91 }
92 };
93
94 $scope.prevPageDisabled = function() {
95 return $scope.currentPage <= 1;
96 };
97
98 $scope.nextPageDisabled = function() {
99 return $scope.currentPage >= $scope.pageCount();
100 };
101
102 $scope.nextPage = function() {
103 if ($scope.currentPagepage <= 0 || $scope.currentPage > $scope.pageCount) { return; }
104 $scope.currentPage += 1;
105 };
106
107 $scope.prevPage = function() {
108 if ($scope.currentPagepage <= 0 || $scope.currentPage > $scope.pageCount) { return; }
109 $scope.currentPage -= 1;
110 };
111
112
113 $scope.go = function() {
114 var page = $scope.newCurrentPage;
115 if (page <= 0 || page > $scope.pageCount || ! page) { return; }
116 $scope.currentPage = page;
117 };
118
119
120 $scope.remove = function(ids) {
121 var confirmations = [];
122
123 ids.forEach(function(id) {
124 var deferred = $q.defer();
125
126 var promise = vulnModelsManager.delete(id)
127 .then(function(resp) {
128 deferred.resolve(resp);
129 }, function(message) {
130 deferred.reject(message);
131 });
132
133 confirmations.push(promise);
134 });
135
136 return $q.all(confirmations);
137 };
138
139 $scope.importCSV = function() {
140 var modal = $uibModal.open({
141 templateUrl: 'scripts/vulndb/partials/upload.html',
142 controller: 'vulnModelModalUpload',
143 size: 'lg',
144 resolve: { }
145 });
146
147 var loadCSV = function(data) {
148
149 $http.get(BASEURL + '_api/session').then(
150 function(d) {
151 $scope.csrf_token = d.data.csrf_token;
152
153 var fd = new FormData();
154 fd.append('csrf_token', $scope.csrf_token);
155 fd.append('file', data);
156
157 $scope.loading = true;
158
159 $http.post(APIURL + 'vulnerability_template/bulk_create/', fd, {
160 transformRequest: angular.identity,
161 withCredentials: false,
162 headers: {'Content-Type': undefined}
163 }).then(
164 function(d) {
165 $scope.loading = false;
166 var message = "Vulnerability templates created:\n";
167 d.data.vulns_created.forEach(function(vuln) {
168 message += "\t" + vuln[1] + "\n";
169 });
170
171 message += "\n\n";
172 message += loadCSVErrorMessage(d.data);
173
174 commonsFact.showMessage(message, true);
175 $route.reload();
176 },
177 function(d){
178 $scope.loading = false;
179 var message = "Error uploading vulnerability templates.\n\n";
180 if(d.status === 400 && d.data.message)
181 message += d.data.message;
182 else
183 message += loadCSVErrorMessage(d.data)
184 commonsFact.showMessage(message);
185 }
186 );
187 }
188 );
189 };
190
191 var loadCSVErrorMessage = function(data) {
192 var message = "";
193 if(data.vulns_with_conflict.length > 0) {
194 message += "Vulnerability templates that were " +
195 "not created due to conflict error:\n";
196 data.vulns_with_conflict.forEach(function(vuln) {
197 message += "\t" + vuln[1] + "\n";
198 });
199 }
200 message += "\n\n";
201
202 if(data.vulns_with_errors.length > 0) {
203 message += "Vulnerability templates that were " +
204 "not create due to an error:\n";
205 data.vulns_with_errors.forEach(function(vuln) {
206 message += "\t" + vuln[1] + "\n";
207 });
208 }
209
210 return message;
211 };
212
213 modal.result.then(function(data) {
214 document.body.style.cursor='wait';
215 $scope.disabledClick = true;
216 var reader = new FileReader();
217 reader.readAsText(data);
218 reader.onload = function(e) {
219 loadCSV(data);
220 };
221 });
222 };
223
224 $scope.delete = function() {
225 var selected = $scope.selectedModels();
226
227 if(selected.length == 0) {
228 $uibModal.open({
229 templateUrl: 'scripts/commons/partials/modalKO.html',
230 controller: 'commonsModalKoCtrl',
231 size: 'sm',
232 resolve: {
233 msg: function() {
234 return 'No models were selected to delete';
235 }
236 }
237 });
238 } else {
239 var message = "A vulnerability model will be deleted";
240 if(selected.length > 1) {
241 message = selected.length + " vulnerability models will be deleted";
242
243 }
244 message = message.concat(". This operation cannot be undone. Are you sure you want to proceed?");
245 $uibModal.open({
246 templateUrl: 'scripts/commons/partials/modalDelete.html',
247 controller: 'commonsModalDelete',
248 size: 'lg',
249 resolve: {
250 msg: function() {
251 return message;
252 }
253 }
254 }).result.then(function() {
255 $scope.remove(selected).then(function(){
256
257 vulnModelsManager.get().then(function() {
258 $scope.totalModels = vulnModelsManager.totalNumberOfModels;
259 $scope.models = vulnModelsManager.models;
260 });
261 });
262 }, function() {
263 //dismised, do nothing
264 });
265 }
266 };
267
268 $scope.insert = function(data) {
269 $scope.loading = false;
270
271 return vulnModelsManager.create(data)
272 .then(function(data) {
273 $scope.loading = false;
274 })
275 .catch(function(message) {
276 $scope.loading = false;
277 commonsFact.errorDialog(message);
278 });
279 };
280
281 $scope.new = function() {
282 var modal = $uibModal.open({
283 templateUrl: 'scripts/vulndb/partials/modalNew.html',
284 backdrop : 'static',
285 controller: 'vulnModelModalNew',
286 size: 'lg',
287 resolve: {
288 customFields: function () {
289 return $scope.customFields;
290 }
291 }
292 });
293
294 modal.result
295 .then(function(data) {
296 $scope.insert(data).then(function() {
297
298 vulnModelsManager.get().then(function() {
299 $scope.totalModels = vulnModelsManager.totalNumberOfModels;
300 $scope.models = vulnModelsManager.models;
301 });
302 });
303 });
304 };
305
306 $scope.update = function(model, data) {
307 return vulnModelsManager.update(model, data)
308 .catch(function(message) {
309 commonsFact.errorDialog(message);
310 });
311 };
312
313 $scope.edit = function() {
314 if($scope.selectedModels().length == 1) {
315 var model = $scope.selectedModels()[0];
316 var modal = $uibModal.open({
317 templateUrl: 'scripts/vulndb/partials/modalEdit.html',
318 backdrop : 'static',
319 controller: 'vulndDbModalEdit',
320 size: 'lg',
321 resolve: {
322 model: function() {
323 return model;
324 },customFields: function () {
325 return $scope.customFields;
326 }
327 }
328 });
329
330 modal.result.then(function(data) {
331 $scope.update(model, data).then(function() {
332
333 vulnModelsManager.get().then(function() {
334 $scope.totalModels = vulnModelsManager.totalNumberOfModels;
335 $scope.models = vulnModelsManager.models;
336 });
337
338 });
339 });
340 } else {
341 commonsFact.errorDialog("No Vulnerability Models were selected to edit.");
342 }
343 };
344
345 $scope.selectedModels = function() {
346 var selected = [];
347
348 $filter('filter')($scope.models, $scope.search).forEach(function(model) {
349 if(model.selected === true) {
350 selected.push(model);
351 }
352 });
353
354 return selected;
355 };
356
357 $scope.pagesOnSearch = function() {
358 var number = $scope.howManyInSearch();
359 if (number === undefined) { return undefined; }
360 return Math.ceil(number / 20);
361 };
362
363 $scope.howManyInSearch = function() {
364 if (! $scope.search) { return undefined; } // if nothing is searched, there's nothing there
365 var filteredModels = $filter('filter')($scope.models, $scope.search);
366 return filteredModels.length;
367 };
368
369 $scope.checkAll = function() {
370 $scope.selectall_models = !$scope.selectall_models;
371
372 tmp_models = $filter('filter')($scope.models, $scope.search);
373 tmp_models = $filter('orderBy')(tmp_models, $scope.sort_field, $scope.reverse);
374 tmp_models = tmp_models.slice(this.currentPage * this.pageSize-20, this.currentPage * this.pageSize);
375 tmp_models.forEach(function(model) {
376 model.selected = $scope.selectall_models;
377 });
378 };
379
380 // changes the URL according to search params
381 $scope.searchFor = function(search, params) {
382 // TODO: It would be nice to find a way for changing
383 // the url without reloading the controller
384 if(search && params != "" && params != undefined) {
385 var filter = commonsFact.parseSearchExpression(params);
386 var URLParams = commonsFact.searchFilterToURLParams(filter);
387 url += "/search/" + URLParams;
388 }
389
390 $location.path(url);
391 };
392
393
394 // toggles sort field and order
395 $scope.toggleSort = function(field) {
396 $scope.toggleSortField(field);
397 $scope.toggleReverse();
398 };
399
400 // toggles column sort field
401 $scope.toggleSortField = function(field) {
402 $scope.sort_field = field;
403 };
404
405 // toggle column sort order
406 $scope.toggleReverse = function() {
407 $scope.reverse = !$scope.reverse;
408 };
409
410 $scope.clearSearch = function() {
411 $scope.search = '';
412 };
413
414 var equalAsSets = function(a, b) {
415 if(a.length != b.length) return false;
416
417 a.forEach(function(elem) {
418 if(b.indexOf(elem) == -1) return false
419 });
420
421 b.forEach(function(elem) {
422 if(a.indexOf(elem) == -1) return false
423 });
424
425 return true;
426 };
427
428 init();
429 }]);
430
431 //We already have a limitTo filter built-in to angular,
432 //let's make a startFrom filter
433 angular.module('faradayApp').filter('startFrom', function() {
434 return function(input, start) {
435 start = +start; //parse to int
436 return input.slice(start);
437 };
438 });
+0
-100
faraday/server/www/scripts/vulndb/directives/customField.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2018 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .directive('customFieldsVulnDb', [function () {
6 return {
7 restrict: 'E',
8 scope: true,
9 replace: true,
10 template: '<div>\
11 <div ng-if="cf.field_type === \'str\'" ng-init="isEditable = true"> \n\
12 <div class="tab-pane-header" ng-dblclick="isEditable = true" title="Double click to edit">{{cf.field_display_name}} <span class="glyphicon glyphicon-question-sign" title="Edit using markdown code"></span></div> \n\
13 <div class="form-group"> \n\
14 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
15 <textarea class="form-control" rows="5" id="vuln-desc" name="desc" ng-show="isEditable === true" \n\
16 ng-model="data.customfields[cf.field_name]" ng-bind-html="data.customfields[cf.field_name] | markdown" \n\
17 style="margin: 0 2px 0 0;" ng-blur="isEditable = isEditable.length==0 || !data.customfields[cf.field_name]" autofocus> \n\
18 </textarea> \n\
19 <div class="col-md-12" ng-cloak ng-show="data.customfields[cf.field_name].length > 0 && isEditable === false"> \n\
20 <div class="markdown-preview" style="height: 100px;!important;" ng-bind-html="data.customfields[cf.field_name] | markdown" ng-dblclick="isEditable = true">{{data.customfields[cf.field_name] | markdown}}</div> \n\
21 </div> \n\
22 </div> \n\
23 </div> \n\
24 <div ng-if="cf.field_type === \'int\'"> \n\
25 <div class="tab-pane-header">{{cf.field_display_name}}</div> \n\
26 <div class="form-group"> \n\
27 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
28 <input type="text" class="form-control input-sm" id="{{cf.field_name}}" name="{{cf.field_name}}" \n\
29 placeholder="{{cf.field_display_name}}" \n\
30 ng-model="data.customfields[cf.field_name]" check-custom-type="{{cf.field_type}}" \n\
31 uib-tooltip="Type only numbers"/> \n\
32 </div> \n\
33 </div> \n\ \
34 <div ng-if="cf.field_type === \'choice\'"> \n\
35 <div class="tab-pane-header">{{cf.field_display_name}}</div> \n\
36 <div class="btn-group col-md-6 col-sm-6 col-xs-6 btn-cf-choice" ng-if="cf.field_type === \'choice\'"> \n\
37 <button type = "button" class="dropdown-toggle btn-change-property primary-btn btn-primary-white no-overflow" data-toggle = "dropdown" id="btn-chg-choice" title="Choices">\n\
38 <span ng-if="data.customfields[cf.field_name] !== null">{{data.customfields[cf.field_name]}}</span>\n\
39 <span ng-if="data.customfields[cf.field_name] === null">Select {{cf.field_display_name}}</span>\n\
40 </button>\n\
41 <button type="button" class="dropdown-toggle secondary-btn btn-change-property btn-secondary-white" data-toggle="dropdown" id="caret-choice" title="Choices">\n\
42 <span> <i class="fa fa-angle-down fa-lg" aria-hidden="true"></i> </span> \n\
43 </button> \n\
44 <ul class="dropdown-menu dropdown-menu-right col-md-12 dropd-cf-choice" role="menu"> \n\
45 <li ng-repeat="choice in parserOptions(cf.field_metadata)">\n\
46 <a class="ws no-overflow" ng-click="data.customfields[cf.field_name] = choice">{{choice}}</a> \n\
47 </li>\n\
48 </ul>\n\
49 </div> \n\
50 </div> \n\
51 <div ng-if="cf.field_type === \'list\'"> \n\
52 <div class="tab-pane-header">{{cf.field_display_name}}</div> \n\
53 <div class="form-group" ng-class="data.customfields[cf.field_name].length > 0 ? \'no-margin-bottom\' : \'\'"> \n\
54 <div class="input-group"> \n\
55 <label class="sr-only" for="{{cf.field_name}}">{{cf.field_display_name}}</label> \n\
56 <input type="text" class="form-control input-sm" id="{{cf.field_name}}_list" name="{{cf.field_name}}" \n\
57 placeholder="{{cf.field_display_name}}" \n\
58 ng-model="valueField" \n\
59 uib-tooltip="Input type list"/> \n\
60 <span class="input-group-addon cursor" ng-click="newValueField(valueField)"><i class="fa fa-plus-circle"></i></span> \n\
61 </div> \n\
62 </div> \n\
63 <div class="reference" ng-repeat="item in data.customfields[cf.field_name] track by $index" ng-class="{\'last-item-field\':$last}" ng-if="cf.field_type === \'list\'"> \n\
64 <div class="input-group margin-bottom-sm"> \n\
65 <label class="sr-only" for="vuln-refs-create">{{cf.field_display_name}}</label> \n\
66 <input ng-if="item.value" type="text" class="form-control input-sm" id="vuln-refs-create" placeholder="{{cf.field_display_name}}" \n\
67 ng-model="item.value" \n\
68 role="button" readonly/> \n\
69 <input ng-if="!item.value" type="text" class="form-control input-sm" id="vuln-refs-create" placeholder="{{cf.field_display_name}}" \n\
70 ng-model="item" \n\
71 role="button" readonly/> \n\
72 <span class="input-group-addon cursor" ng-click="data.customfields[cf.field_name].splice($index, 1)"> \n\
73 <i class="fa fa-minus-circle"></i></span> \n\
74 </div> \n\
75 </div> \n\
76 </div> \n\
77 </div></div>',
78 link: function (scope, element, attrs) {
79
80 scope.newValueField = function (valueField) {
81 if (valueField !== "" && valueField !== undefined) {
82 if(scope.data.customfields[scope.cf.field_name] == null )
83 scope.data.customfields[scope.cf.field_name] = [];
84
85 // we need to check if the ref already exists
86 if (scope.data.customfields[scope.cf.field_name].filter(function(field) {return field.value === valueField}).length === 0) {
87 scope.data.customfields[scope.cf.field_name].push({value: valueField});
88 scope.valueField = "";
89 }
90 angular.element('#'+scope.cf.field_name+'_list').val("");
91 }
92 }
93
94 scope.parserOptions = function (rawOptions) {
95 return JSON.parse(rawOptions)
96 }
97 }
98 }
99 }]);
+0
-161
faraday/server/www/scripts/vulndb/partials/modalEdit.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" ng-submit="ok()" novalidate>
5 <div class="modal-header">
6 <div class="modal-button btn-toolbar">
7 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid">OK</button>
8 <button type="button" class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">Edit {{model.name}} Vulnerability Template</h3>
11 </div>
12 <div class="modal-body">
13 <div class="mt-3">
14 <!-- Nav tabs -->
15 <ul class="nav nav-tabs" id="nav-tabs-container">
16 <li class="nav-item active" ng-class="{'has-error': formEdit.desc.$invalid}">
17 <a class="nav-link active" data-toggle="tab" data-target="#general"
18 href="javascript:;">General</a>
19 </li>
20 <li class="nav-item">
21 <a class="nav-link" data-toggle="tab" data-target="#details" href="javascript:;">Details</a>
22 </li>
23 <li class="nav-item">
24 <a class="nav-link" data-toggle="tab" data-target="#custom_fields" href="javascript:;">Custom FIelds</a>
25 </li>
26 </ul>
27
28 <!-- Tab panes -->
29 <div class="tab-content height-100 ">
30 <div id="general" class="container tab-pane-container tab-pane active visible-overflow"><br>
31 <div class="col-md-12 margin-bottom-15px">
32 <div class="form-horizontal">
33 <div class="form-group">
34 <div class="col-md-6">
35 <label for="model">Name *</label>
36 <input type="text" name="name" class="form-control" placeholder="Name" ng-model="data.name" required>
37 </div><!-- .col-md-6 -->
38 <div class="col-md-12">
39 <p class="has-error" ng-show="(form.product.$touched && form.product.$error.required)">
40 <span class="help-block">Vulnerability Template name is required</span>
41 </p>
42 </div><!-- .col-md-12 -->
43 </div><!-- .form-group -->
44 <div class="form-group">
45 <div class="col-md-12">
46 <label for="description">Description</label>
47 <textarea class="form-control" name="description" placeholder="Description" ng-model="data.description"></textarea>
48 </div>
49 </div><!-- .form-group -->
50 <div class="form-group">
51 <div class="col-md-6">
52 <label>Impact</label>
53 <h4><span ng-repeat="(key, value) in impact" class="normal-size" style="cursor: pointer;">
54 <span ng-class="{'label-impact label-default-impact': !value, 'label-impact label-success-impact': value}" ng-click="toggleImpact(key)">{{key}}</span>
55 </span></h4><!-- .normal-size -->
56 </div>
57 <div class="col-md-2"></div>
58 <div class="col-md-4">
59 <label>Ease of Resolution</label>
60 <select class="form-control" ng-model="data.easeofresolution" ng-options="e for e in easeofresolution" style="padding:0px 12px;">
61 <option value=""></option>
62 </select>
63 </div>
64 </div><!-- .form-group -->
65 <div class="form-group">
66 <div class="col-md-12">
67 <label for="Explotation">Severity</label>
68 <button type="button" class="btn btn-default dropdown-toggle" name="exploitation" data-toggle="dropdown" title="Choose exploitation" ng-class="{'button-error': data.exploitation === undefined}">
69 {{data.exploitation || 'Choose Severity'}} <span class="caret"></span>
70 </button>
71 <ul id="nav" class="dropdown-menu dropdown-menu-left" role="menu">
72 <li ng-repeat="s in exploitations"><a href="" class="ws color-{{s}}" ng-click="data.exploitation=s">{{s}}</a></li>
73 </ul><!-- WS navigation -->
74 </div>
75 </div><!-- .form-group -->
76 <p>All fields marked * are required</p>
77 </div>
78 </div>
79 </div>
80 <div id="details" class="container tab-pane-container tab-pane"><br>
81 <div class="col-md-12 margin-bottom-15px">
82 <div class="form-horizontal">
83 <div class="form-group">
84 <div class="col-md-12">
85 <label for="external_id">External ID</label>
86 <input type="text" class="form-control" name="external_id" id="external_id" placeholder="External ID" ng-model="data.external_id">
87 </div>
88 </div><!-- .form-group -->
89 <div class="form-group">
90 <div class="col-md-12">
91 <label for="data">Data</label>
92 <textarea class="form-control" id="data" placeholder="Data" ng-model="data.data"></textarea>
93 </div>
94 </div><!-- .form-group -->
95 <div class="form-group">
96 <div class="col-md-12">
97 <label for="resolution">Resolution</label>
98 <textarea class="form-control" name="resolution" placeholder="Resolution" ng-model="data.resolution"></textarea>
99 </div>
100 </div><!-- .form-group -->
101 <div class="form-group">
102 <div class="col-md-12">
103 <label for="references">References</label>
104 <div class="input-group margin-bottom-sm">
105 <label class="sr-only" for="references">References</label>
106 <input type="text" class="form-control" id="references" placeholder="References" ng-model="new_reference"/>
107 <span class="input-group-addon cursor" ng-click="newReference()"><i class="fa fa-plus-circle"></i></span>
108 </div>
109 </div>
110 <div class="col-md-12 reference" ng-repeat="reference in references">
111 <div class="input-group margin-bottom-sm">
112 <label class="sr-only" for="ireferences">References</label>
113 <input type="text" class="form-control" id="ireferences" placeholder="References" ng-model="reference" readonly/>
114 <span class="input-group-addon cursor" ng-click="references.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
115 </div>
116 </div>
117 </div><!-- .form-group -->
118 <div class="form-group">
119 <div class="col-md-12">
120 <label for="vuln-policyviolations">Policy Violations</label>
121 <div class="input-group margin-bottom-sm">
122 <label class="sr-only" for="vuln-policyviolations">Policy Violations</label>
123 <input type="text" class="form-control" id="vuln-policyviolations" placeholder="Policy Violations" ng-model="new_policyviolation"/>
124 <span class="input-group-addon cursor" ng-click="newPolicyViolation()"><i class="fa fa-plus-circle"></i></span>
125 </div>
126 </div>
127 <div class="col-md-12 reference" ng-repeat="policyviolation in policyviolations">
128 <div class="input-group margin-bottom-sm">
129 <label class="sr-only" for="vuln-policyviolations">Policy Violation</label>
130 <input type="text" class="form-control" id="vuln-policyviolations" placeholder="Policy Violation" ng-model="policyviolation" readonly/>
131 <span class="input-group-addon cursor" ng-click="policyviolations.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
132 </div>
133 </div>
134 </div>
135 </div>
136 </div>
137 </div>
138 <div id="custom_fields" class="container tab-pane-container tab-pane fade"><br>
139 <div ng-if="customFields.length === 0" class="no-info-overlay" style="margin-bottom: 15px;">
140 <p class="no-info-text">
141 No custom fields were found. To create one refer to our
142 <a href="https://github.com/infobyte/faraday/wiki/Custom-Fields" target="_blank">wiki page</a>.
143 </p>
144 </div>
145 <div class="col-md-12 margin-bottom-15px">
146 <div class="col-md-12" ng-repeat="cf in customFields | orderBy : 'field_order'">
147 <custom-fields-vuln-db field="{{cf}}"></custom-fields-vuln-db>
148 </div>
149 </div>
150 </div>
151 </div>
152 </div><!-- .form-horizontal -->
153 </div><!-- .modal-body -->
154 <div class="modal-footer">
155 <div class="modal-button btn-toolbar">
156 <button class="btn btn-success" ng-disabled="form.$invalid || (data.name == '')" ng-click="ok()">OK</button>
157 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
158 </div>
159 </div><!-- .modal-body -->
160 </form>
+0
-166
faraday/server/www/scripts/vulndb/partials/modalNew.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <div class="modal-button btn-toolbar">
7 <button class="btn btn-success" ng-click="ok()" ng-disabled="form.$invalid || (data.name == '') || (data.exploitation === '')">OK</button>
8 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">New Vulnerability Template</h3>
11 </div>
12 <div class="modal-body">
13 <div class="mt-3">
14
15 <!-- Nav tabs -->
16 <ul class="nav nav-tabs" id="nav-tabs-container">
17 <li class="nav-item active" ng-class="{'has-error': formEdit.desc.$invalid}">
18 <a class="nav-link active" data-toggle="tab" data-target="#general"
19 href="javascript:;">General</a>
20 </li>
21 <li class="nav-item">
22 <a class="nav-link" data-toggle="tab" data-target="#details" href="javascript:;">Details</a>
23 </li>
24 <li class="nav-item">
25 <a class="nav-link" data-toggle="tab" data-target="#custom_fields" href="javascript:;">Custom FIelds</a>
26 </li>
27 </ul>
28 <!-- Tab panes -->
29 <div class="tab-content height-100 ">
30 <div id="general" class="container tab-pane-container tab-pane active visible-overflow"><br>
31 <div class="col-md-12 margin-bottom-15px">
32 <div class="form-horizontal">
33 <div class="form-group">
34 <div class="col-md-6">
35 <label for="model">Name *</label>
36 <input type="text" name="name" class="form-control" placeholder="Name" ng-model="data.name" required>
37 </div>
38 <div class="col-md-12">
39 <p class="has-error" ng-show="(form.name.$touched && form.name.$error.required)">
40 <span class="help-block">Vulnerability Template name is required</span>
41 </p>
42 </div>
43 </div>
44 <div class="form-group">
45 <div class="col-md-12">
46 <label for="description">Description</label>
47 <textarea class="form-control" name="description" placeholder="Description" ng-model="data.description"></textarea>
48 </div>
49 </div>
50 <div class="form-group">
51 <div class="col-md-8">
52 <label>Impact</label>
53 <h4><span ng-repeat="(key, value) in data.impact" class="normal-size" style="cursor: pointer;">
54 <span ng-class="{'label-impact label-default-impact': !value, 'label-impact label-success-impact': value}" ng-click="toggleImpact(key)">{{key}}</span>
55 </span></h4>
56 </div>
57 <div class="col-md-4">
58 <label>Ease of Resolution</label>
59 <select class="form-control" ng-model="data.easeofresolution" ng-options="e for e in easeofresolution" style="padding:0px 12px;">
60 <option value=""></option>
61 </select>
62 </div>
63 </div>
64 <div class="form-group">
65 <div class="col-md-12">
66 <label for="Explotation">Severity *</label>
67 <button type="button" class="btn btn-default dropdown-toggle" name="exploitation" data-toggle="dropdown"
68 title="Choose exploitation" ng-class="{'button-error': modal.data.exploitation === undefined}">
69 {{data.exploitation || 'Choose Severity'}} <span class="caret"></span>
70 </button>
71 <ul id="nav" class="dropdown-menu dropdown-menu-left" role="menu">
72 <li ng-repeat="s in exploitations"><a href="" class="ws color-{{s}}" ng-click="data.exploitation=s">{{s}}</a></li>
73 </ul><!-- WS navigation -->
74 </div><!-- .col-md-12 -->
75 <div class="col-md-12">
76 <p class="has-error" ng-show="(form.exploitation.$touched && form.exploitation.$error.required)">
77 <span class="help-block">Vulnerability Template Severity is required</span>
78 </p>
79 </div><!-- .col-md-12 -->
80 </div>
81 <p>All fields marked * are required</p>
82 </div>
83 </div>
84 </div>
85 <div id="details" class="container tab-pane-container tab-pane visible-overflow"><br>
86 <div class="col-md-12 margin-bottom-15px">
87 <div class="form-horizontal">
88 <div class="form-group">
89 <div class="col-md-12">
90 <label for="external_id">External ID</label>
91 <input type="text" class="form-control" name="external_id" id="external_id" placeholder="External ID" ng-model="data.external_id">
92 </div>
93 </div>
94 <div class="form-group">
95 <div class="col-md-12">
96 <label for="data">Data</label>
97 <textarea class="form-control" id="data" placeholder="Data" ng-model="data.data"></textarea>
98 </div>
99 </div>
100 <div class="form-group">
101 <div class="col-md-12">
102 <label for="resolution">Resolution</label>
103 <textarea class="form-control" name="resolution" placeholder="Resolution" ng-model="data.resolution"></textarea>
104 </div>
105 </div>
106 <div class="form-group">
107 <div class="col-md-12">
108 <label for="references">References</label>
109 <div class="input-group margin-bottom-sm">
110 <label class="sr-only" for="references">References</label>
111 <input type="text" class="form-control" id="references" placeholder="References" ng-model="new_reference"/>
112 <span class="input-group-addon cursor" ng-click="newReference()"><i class="fa fa-plus-circle"></i></span>
113 </div>
114 </div>
115 <div class="col-md-12 reference" ng-repeat="reference in data.references">
116 <div class="input-group margin-bottom-sm">
117 <label class="sr-only" for="ireferences">References</label>
118 <input type="text" class="form-control" id="ireferences" placeholder="References" ng-model="reference" readonly/>
119 <span class="input-group-addon cursor" ng-click="data.references.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
120 </div>
121 </div>
122 </div>
123 <div class="form-group">
124 <div class="col-md-12">
125 <label for="vuln-policyviolations">Policy Violations</label>
126 <div class="input-group margin-bottom-sm">
127 <label class="sr-only" for="vuln-policyviolations">Policy Violations</label>
128 <input type="text" class="form-control" id="vuln-policyviolations" placeholder="Policy Violations" ng-model="new_policyviolation"/>
129 <span class="input-group-addon cursor" ng-click="newPolicyViolation()"><i class="fa fa-plus-circle"></i></span>
130 </div>
131 </div>
132 <div class="col-md-12 reference" ng-repeat="policyviolation in data.policyviolations">
133 <div class="input-group margin-bottom-sm">
134 <label class="sr-only" for="vuln-policyviolations">Policy Violation</label>
135 <input type="text" class="form-control" id="vuln-policyviolations" placeholder="Policy Violation" ng-model="policyviolation" readonly/>
136 <span class="input-group-addon cursor" ng-click="data.policyviolations.splice($index, 1)"><i class="fa fa-minus-circle"></i></span>
137 </div>
138 </div>
139 </div>
140 </div>
141 </div>
142 </div>
143 <div id="custom_fields" class="container tab-pane-container tab-pane fade"><br>
144 <div ng-if="customFields.length === 0" class="no-info-overlay" style="margin-bottom: 15px;">
145 <p class="no-info-text">
146 No custom fields were found. To create one refer to our
147 <a href="https://github.com/infobyte/faraday/wiki/Custom-Fields" target="_blank">wiki page</a>.
148 </p>
149 </div>
150 <div class="col-md-12 margin-bottom-15px">
151 <div class="col-md-12" ng-repeat="cf in customFields | orderBy : 'field_order'">
152 <custom-fields-vuln-db field="{{cf}}"></custom-fields-vuln-db>
153 </div>
154 </div>
155 </div>
156 </div>
157 </div><!-- .form-horizontal -->
158 </div><!-- .modal-body -->
159 <div class="modal-footer">
160 <div class="modal-button btn-toolbar">
161 <button class="btn btn-success" ng-disabled="form.$invalid || (data.name == '') || (data.exploitation === '')" ng-click="ok()">OK</button>
162 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
163 </div>
164 </div>
165 </form>
+0
-27
faraday/server/www/scripts/vulndb/partials/upload.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="uploadForm" >
5 <div class="modal-header">
6 <h3 class="modal-title">Import CSV</h3>
7 </div>
8 <div class="modal-body">
9 <!-- <input type="file" id="file" name="file"/> -->
10 <!-- <button ng-click="_import()">Upload</button> -->
11 <span class="help-block">
12 <p> Please note the required header: name, exploitation (severity)</p>
13 <p> Available headers: cwe, description, desc, exploitation, name,
14 refs, resolution, impact, easeofresolution, policyviolations, </p>
15 data, external_id, creator, create_at, customfields</p>
16 <p> Please check our portal page to download the templates </p>
17 </span>
18 <input type="file" id="file" name="file" accept=".csv" ng-model="filename" valid-file required/>
19 </div><!-- .modal-body -->
20 <div class="modal-footer">
21 <div class="modal-button btn-toolbar">
22 <button class="btn btn-success" ng-disabled="uploadForm.$invalid" ng-click="_import()">OK</button>
23 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
24 </div>
25 </div>
26 </form>
+0
-134
faraday/server/www/scripts/vulndb/partials/vulndb.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <section id="main" class="seccion clearfix">
5 <div class="faraday-header-border-fix"></div>
6 <div class="left-main">
7 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
8 <div id="reports-main" class="fila clearfix">
9 <div class="reports col-md-12 col-sm-12 col-xs-12">
10 <div class="button-control justify-flex-start col-md-12 col-sm-12 col-xs-12">
11 <div class="control-wrapper control-new">
12 <button id="import" type="button" class="btn btn-success btn-new" title="New vuln template" ng-click="disabledClick || new()">
13 New
14 </button>
15 </div>
16 <table>
17 <thead>
18 <tr>
19 <th class="col-md-2">
20 <a href="#/scheduling" class="workspaces" ng-class="{'navigation-active' : component == 'scheduling'}" style="color: black !important; font-weight: bold; font-size: 15px;">
21 Scheduling
22 </a>
23 <div class="flex-spacer"></div>
24 </th>
25 <th class="col-md-2" style = "border-right: 1px solid rgb(221, 221, 221); padding-right: 12px">
26 <a href="#/vulndb" class="workspaces" ng-class="{'navigation-active' : component == 'vulndb'}" style="color: black !important; font-weight: bold; font-size: 15px;">
27 KB
28 </a>
29 <div class="flex-spacer"></div>
30 </th>
31 </tr>
32 </thead>
33 </table>
34 <div class="control-wrapper control-edit">
35 <button type="button" class="btn btn-default edit" title="Edit selected vulns" ng-click="disabledClick || edit()">
36 <img src="images/icon-toolbar-edit.svg" class="edit-icon" />
37 </button>
38 </div>
39 <div class="control-wrapper">
40 <button id="delete" type="button" class="btn btn-default" title="Delete selected items" ng-click="disabledClick || delete()">
41 <img src="images/icon-toolbar-delete.svg" class="delete-icon" />
42 </button>
43 </div>
44 <div class="control-wrapper search-wrapper">
45 <form role="form">
46 <div class="form-group">
47 <div class="input-group">
48 <span class="input-group-addon glyphicon-btn glyphicon glyphicon-remove" ng-if="search && search != 'confirmed=true'" ng-click="clearSearch()"></span>
49 <input type="text" class="form-control" placeholder="Enter keywords" ng-model="search" />
50 <span class="input-group-addon glyphicon-btn">
51 <img src="images/icon-toolbar-searchbar-loupe.svg" class="search-icon" />
52 </span>
53 </div>
54 </div>
55 </form>
56 </div>
57 <div class="space-wrapper"></div>
58 <div class="control-wrapper control-wrap-right">
59 <span class="ui-grid-cell-contents" ng-show="loading"> Importing templates...</span>
60 <button id="import" type="button" class="btn btn-success btn-new" title="Import from CSV" ng-click="disabledClick || importCSV()">
61 Import
62 </button>
63 </div>
64 </div>
65 <table rz-table class="table-v3 licenses-list table table-responsive">
66 <thead>
67 <tr class="ui-grid-header">
68 <th class="ui-grid-cell-contents checkbox-select ui-grid-header-cell">
69 <input type="checkbox" ng-model="selectall" ng-click="disabledClick || checkAll()"/>
70 </th>
71 <th class="ui-grid-cell-contents ui-grid-header-cell">
72 <span ng-click="toggleSort('name')">Template Name</span>
73 </th>
74 <th class="ui-grid-cell-contents ui-grid-header-cell">
75 <span ng-click="toggleSort('description')">Description</span>
76 </th>
77 <th class="ui-grid-cell-contents ui-grid-header-cell">
78 <span ng-click="toggleSort('references')">References</span>
79 </th>
80 <th class="ui-grid-cell-contents ui-grid-header-cell">
81 <span ng-click="toggleSort('resolution')">Resolution</span>
82 </th>
83 <th class="ui-grid-cell-contents ui-grid-header-cell">
84 <span ng-click="toggleSort('exploitation')">Severity</span>
85 </th>
86 <th class="ui-grid-cell-contents ui-grid-header-cell">
87 <span ng-click="toggleSort('policyviolations')">Policy Violations</span>
88 </th>
89 <th class="ui-grid-cell-contents ui-grid-header-cell">
90 <span ng-click="toggleSort('creator')">Creator</span>
91 </th>
92 <th class="ui-grid-cell-contents ui-grid-header-cell">
93 <span ng-click="toggleSort('create_at')">Create Date</span>
94 </th>
95 </tr>
96 </thead>
97 <tbody>
98 <tr ng-repeat="model in models | filter:search | orderBy:sort_field: reverse | startFrom:(currentPage*pageSize)-20 | limitTo:pageSize"
99 selection-model selection-model-type="checkbox"
100 selection-model-mode="multiple-additive"
101 selection-model-selected-class="multi-selected"
102 selection-model-on-change="selectedModels()">
103 <td class="checkbox-select"><input type="checkbox" name="{{model._id}}"/></td>
104 <td class="ui-grid-cell-contents" style="max-width: 20vw;">{{model.name}}</td>
105 <td class="ui-grid-cell-contents" style="max-width: 20vw;">{{model.description}}</td>
106 <td><div ng-repeat="ref in model.refs|limitTo:4" class="ui-grid-cell-contents no-padding" style="max-width: 15vw;">{{ref}}</div></td>
107 <td class="ui-grid-cell-contents no-padding" style="max-width: 10vw;">{{model.resolution}}</td>
108 <td>{{model.exploitation}}</td>
109 <td><div ng-repeat="policy in model.policyviolations|limitTo:4" class="ui-grid-cell-contents no-padding" style="max-width: 10vw;">{{policy}}</div></td>
110 <td style="max-width: 10vw;">{{model.creator}}</td>
111 <td><p ng-bind="model.create_at | date:'MM/dd/yyyy'"></p></td>
112 </tr>
113 </tbody>
114 </table>
115 <i ng-if="loading" class="fa fa-spinner fa-spin loading-spinner"></i>
116 <div class="showPagination">
117 <div class="form-group">
118 <ul class="pagination">
119 <li><a ng-hide="prevPageDisabled()" ng-click="disabledClick || prevPage()"><span aria-hidden="true">&laquo;</span><span class="sr-only">Previous</span></a></li>
120 <li><a>{{currentPage}}/{{pageCount()}}</a></li>
121 <li><a ng-hide="nextPageDisabled()" ng-click="disabledClick || nextPage()"><span aria-hidden="true">&raquo;</span><span class="sr-only">Next</span></a></li>
122 </ul>
123 <form name="goToPage" id="goToPageStatus">
124 <div class="col-md-2">
125 <input type="number" min="1" max="{{pageCount()}}" class="form-control" ng-model="newCurrentPage" placeholder="Go to page"/>
126 </div>
127 <button class="btn btn-default" ng-click="disabledClick || go()">GO</button>
128 </form>
129 </div>
130 </div><!-- .showPagination -->
131 </div><!-- #reports-main -->
132 </div><!-- .right-main -->
133 </section><!-- #main -->
+0
-132
faraday/server/www/scripts/vulndb/providers/vulnModel.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp').
5 factory('VulnModel', ['BASEURL', 'configSrv', 'ServerAPI', '$http', '$q',
6 function(BASEURL, configSrv, ServerAPI, $http, $q) {
7 function VulnModel(data) {
8 this._id = "";
9 this.id = "";
10 this._rev = "";
11 this.cwe = "";
12 this.description = "";
13 this.desc = "";
14 this.data = "";
15 this.exploitation = "";
16 this.name = "";
17 this.references = [];
18 this.refs = [];
19 this.data = "";
20 this.resolution = "";
21 this.impact = {
22 accountability: false,
23 availability: false,
24 confidentiality: false,
25 integrity: false
26 };
27 this.policyviolations = [];
28 this.customfields = [];
29 this.easeofresolution = "";
30 this.external_id = "";
31 this.creator = "";
32 this.create_at = "";
33 if (data) {
34 if(data.name === undefined || data.name === "") {
35 throw new Error("Unable to create a Vulnerability Model whithout a name");
36 }
37 this.set(data);
38 }
39 };
40
41 VulnModel.prototype = {
42
43 public_properties: ['exploitation', 'references', 'name', 'resolution', 'cwe', 'description',
44 'desc', 'data', 'id', 'refs', 'impact', 'easeofresolution', 'policyviolations', 'customfields',
45 'external_id', 'creator', 'create_at'],
46
47 set: function(data) {
48 var self = this;
49
50 if(data._id != undefined) {
51 self._id = data._id;
52 self.id = data._id;
53 if(data._rev !== undefined) {
54 self._rev = data._rev;
55 };
56 }
57
58 self.public_properties.forEach(function(property) {
59 if(data[property] !== undefined) {
60 self[property] = data[property];
61 };
62 });
63 },
64
65 remove: function() {
66 var deferred = $q.defer();
67 var self = this;
68
69 ServerAPI.deleteVulnerabilityTemplate(self._id)
70 .then(function(resp) {
71 deferred.resolve(resp);
72 }, function(data, status, headers, config) {
73 deferred.reject("Unable to delete Vuln Model from DB. " + status)
74 });
75
76 return deferred.promise;
77 },
78
79 update: function(data) {
80 var deferred = $q.defer();
81 var self = this;
82
83 ServerAPI.updateVulnerabilityTemplate(data)
84 .then(function(res) {
85 self.set(res.data);
86 deferred.resolve(self);
87 }, function(res) {
88 deferred.reject("Unable to update the Vuln Model. " + JSON.stringify(res.data));
89 });
90 return deferred.promise;
91 },
92
93 save : function() {
94 var self = this;
95 var deferred = $q.defer();
96
97 delete this._id;
98 delete this._rev;
99
100 ServerAPI.createVulnerabilityTemplate(self)
101 .then(function(data) {
102 self._id = data.id;
103 self._rev = data.rev;
104 deferred.resolve(self);
105 }, function(res) {
106 try {
107 var msg = '';
108 for(var item in res.data.messages) {
109 if(res.data.messages.hasOwnProperty(item)) {
110 msg += item.charAt(0).toUpperCase() + item.slice(1) + ": ";
111 msg += res.data.messages[item][0];
112 }
113 }
114 var message;
115 if (res.status == 409) {
116 message = "Vulnerability template \"" + res.data.object.name +
117 "\" already exists with vulnerability template ID: " + res.data.object.id;
118 } else {
119 message = "Unable to save the Vuln Model. " + msg;
120 }
121 deferred.reject(message);
122 } catch(err) {
123 deferred.reject(err);
124 }
125 });
126 return deferred.promise;
127 }
128 };
129
130 return VulnModel;
131 }]);
+0
-134
faraday/server/www/scripts/vulndb/providers/vulnModels.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 //
4 angular.module('faradayApp').
5 factory('vulnModelsManager',
6 ['VulnModel', 'BASEURL', '$http', '$q', 'ServerAPI',
7 function(VulnModel, BASEURL, $http, $q, ServerAPI) {
8 var vulnModelsManager = {};
9 vulnModelsManager.models = [];
10 vulnModelsManager.totalNumberOfModels = 0;
11
12 vulnModelsManager.create = function(data) {
13 var deferred = $q.defer();
14 var self = this;
15 try {
16 var vulnModel = new VulnModel(data);
17 vulnModel.save()
18 .then(function(resp) {
19 self.updateState(self.totalNumberOfModels + 1);
20 deferred.resolve(resp);
21 }, function(reason) {
22 deferred.reject(reason);
23 });
24 } catch(e) {
25 deferred.reject(e.name + ": " + e.message);
26 }
27
28 return deferred.promise;
29 };
30
31
32 vulnModelsManager.bulkCreate = function(vulns){
33 var deferred = $q.defer();
34 var self = this;
35 $http.get(BASEURL + '_api/session')
36 .then(function(d) {
37 var dataToSend = {}
38 dataToSend.csrf_token = d.data.csrf_token;
39 dataToSend.vulns = vulns;
40 ServerAPI.bulkCreateVulnerabilityTemplate(dataToSend)
41 .then(function (response) {
42 var vulnsCreated = response.data.vulns_created;
43 self.updateState(self.totalNumberOfModels + vulnsCreated.length);
44 deferred.resolve(response);
45 }, function (response) {
46 deferred.reject(response)
47 })
48 })
49 return deferred.promise;
50 }
51
52 vulnModelsManager.delete = function(vulnModel) {
53 var deferred = $q.defer();
54 var self = this;
55
56 vulnModel.remove().
57 then(function(resp) {
58 self.updateState(self.totalNumberOfModels - 1);
59 deferred.resolve(resp);
60 }, function(err) {
61 deferred.reject(err);
62 });
63 return deferred.promise;
64 };
65
66 vulnModelsManager.get = function() {
67 var deferred = $q.defer();
68 var self = this;
69
70 ServerAPI.getVulnerabilityTemplates()
71 .then(function(res) {
72 var data = res.data;
73 self.updateState(data.total_rows);
74 var vulnModels = [];
75
76 if (data.hasOwnProperty("rows")) {
77 data.rows.forEach(function(row) {
78 try {
79 vulnModels.push(new VulnModel(row.doc));
80 } catch(e) {
81 console.log(e.stack);
82 }
83 });
84 }
85
86 angular.copy(vulnModels, self.models);
87 deferred.resolve(vulnModels);
88 }, function(data, status, headers, config) {
89 deferred.reject("Unable to retrieve vuln models. " + status);
90 });
91
92 return deferred.promise;
93 };
94
95 vulnModelsManager.getSize = function() {
96 var deferred = $q.defer();
97 var self = this;
98
99 ServerAPI.getVulnerabilityTemplates()
100 .then(function(res) {
101 var data = res.data;
102 self.updateState(data.total_rows);
103 deferred.resolve();
104 }, function(data, status) {
105 deferred.reject("Unable to retrieve documents " + status);
106 });
107 return deferred.promise;
108 };
109
110 vulnModelsManager.updateState = function(numberOfModels) {
111 this.totalNumberOfModels = numberOfModels;
112 };
113
114 vulnModelsManager.update = function(vulnModel, data) {
115 var deferred = $q.defer();
116 var self = this;
117
118 if (data._rev === undefined) {
119 data._rev = vulnModel._rev;
120 }
121
122 vulnModel.update(data).
123 then(function(resp) {
124 deferred.resolve(resp);
125 }, function(err) {
126 deferred.reject(err);
127 });
128
129 return deferred.promise;
130 };
131
132 return vulnModelsManager;
133 }]);
+0
-224
faraday/server/www/scripts/vulns/providers/vuln.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('Vuln', ['BASEURL', '$q', 'ServerAPI', 'attachmentsFact',
6 function(BASEURL, $q, ServerAPI, attachmentsFact) {
7 Vuln = function(ws, data) {
8 var now = new Date(),
9 date = now.getTime() / 1000.0;
10
11 this._id = "";
12 this._rev = "";
13 this._attachments = {};
14 this.confirmed = true;
15 this.data = "";
16 this.desc = "";
17 this.hostnames = "";
18 this.impact = {
19 accountability: false,
20 availability: false,
21 confidentiality: false,
22 integrity: false
23 };
24 this.metadata = {
25 update_time: date,
26 update_user: "",
27 update_action: 0,
28 creator: "UI Web",
29 create_time: date,
30 update_controller_action: "UI Web New",
31 owner: ""
32 };
33 this.name = "";
34 this.obj_id = "";
35 this.owner = "";
36 this.owned = "";
37 this.parent = "";
38 this.parent_type = "";
39 this.refs = "";
40 this.resolution = "";
41 this.service = "";
42 this.severity = "";
43 this.target = "";
44 this.host_os = "";
45 this.type = "Vulnerability";
46 this.ws = "";
47 this.status = "opened";
48 this.policyviolations = "";
49 this.custom_fields = {};
50
51 if(data) {
52 if(data.name === undefined || data.name === "") {
53 throw new Error("Unable to create Vuln without a name");
54 }
55 this.set(ws, data);
56 }
57 };
58
59 var public_properties = [
60 '_attachments', 'confirmed', 'data', 'desc', 'easeofresolution',
61 'impact', 'name', 'owned', 'policyviolations', 'refs', 'resolution',
62 'severity', 'status', 'custom_fields', 'external_id'
63 ];
64
65 var saved_properties = public_properties.concat(
66 ['_id', '_rev', 'metadata', 'obj_id', 'owner', 'parent', 'type']);
67
68 Vuln.prototype = {
69 public_properties: public_properties,
70 saved_properties: saved_properties,
71 set: function(ws, data) {
72 var self = this;
73
74 if(data._id !== undefined || data.id !== undefined) self._id = data._id | data.id;
75 if(data.metadata !== undefined) self.metadata = data.metadata;
76 if(data.target !== undefined || data.target_host_ip !== undefined) self.target = data.target || data.target_host_ip;
77 if(data.host_os !== undefined || data.target_host_os !== undefined) self.host_os = data.host_os || data.target_host_os;
78 if(data.hostnames !== undefined) self.hostnames = data.hostnames;
79 if(data.service !== undefined) self.service = data.service;
80 if(data.owner !== undefined) self.owner = data.owner;
81 self.ws = ws;
82 if(data.parent !== undefined) self.parent = data.parent;
83 if(data.parent_type !== undefined) self.parent_type = data.parent_type;
84 if(data.custom_fields !== undefined) self.custom_fields = data.custom_fields;
85
86 self.public_properties.forEach(function(property) {
87 if(data[property] !== undefined) self[property] = data[property];
88 });
89 },
90 remove: function() {
91 var self = this;
92 return ServerAPI.deleteVuln(self.ws, self._id, self._rev);
93
94 },
95 _update: function(vuln, data) {
96 var deferred = $q.defer(),
97 self = this;
98
99 var now = new Date(),
100 date = now.getTime();
101
102 vuln.metadata.update_time = date;
103
104 vuln.public_properties.forEach(function(prop) {
105 if(data.hasOwnProperty(prop)) {
106 if(prop != "_attachments") vuln[prop] = data[prop];
107 }
108 });
109
110 if(data._attachments !== undefined) {
111 var files = {},
112 stubs = {};
113 vuln._attachments = {};
114
115 // the list of evidence may have mixed objects, some of them already in CouchDB, some of them new
116 // new attachments are of File type and need to be processed by attachmentsFact.loadAttachments
117 // old attachments are of type Object and they represent a Stub, nothing should be done to them
118 for(var name in data._attachments) {
119 if(data._attachments.hasOwnProperty(name)) {
120 if(data._attachments[name] instanceof File) {
121 files[name] = data._attachments[name];
122 } else {
123 stubs[name] = data._attachments[name];
124 }
125 }
126 }
127 angular.extend(vuln._attachments, stubs);
128 attachmentsFact.loadAttachments(files).then(function(atts) {
129 angular.extend(vuln._attachments, atts);
130 self._save(vuln, true)
131 .then(function(response) {
132 self.set(self.ws, vuln);
133 deferred.resolve();
134 }, function(response) {
135 deferred.reject(response.data);
136 });
137 });
138 } else {
139 self._save(vuln, true)
140 .then(function(response) {
141 self.set(self.ws, vuln);
142 self._rev = response.rev;
143 deferred.resolve();
144 }, function(response) {
145 deferred.reject(response.data.message);
146 });
147 }
148
149 return deferred.promise;
150 },
151
152 update: function(data) {
153 var self = this,
154 vuln = new Vuln(self.ws, self);
155 return self._update(vuln, data);
156 },
157
158 populate: function() {
159 var deferred = $q.defer(),
160 self = this,
161 vuln = {};
162
163 vuln.metadata = self.metadata;
164 vuln.obj_id = self.obj_id;
165 vuln.owner = self.owner;
166 vuln.parent = self.parent;
167 vuln.parent_type = self.parent_type;
168 vuln.type = self.type;
169 vuln.ws = self.ws;
170
171 self.public_properties.forEach(function(prop) {
172 if(prop !== "_attachments") vuln[prop] = self[prop];
173 });
174
175 if(self._attachments !== undefined) {
176 attachmentsFact.loadAttachments(self._attachments).then(function(atts) {
177 vuln._attachments = atts;
178 deferred.resolve(vuln);
179 }, function() {
180 deferred.reject("Unable to load attachments");
181 });
182 } else {
183 deferred.resolve(vuln);
184 }
185
186 return deferred.promise;
187 },
188 save: function() {
189 var deferred = $q.defer(),
190 loadAtt,
191 self = this;
192
193 self.populate().then(function(resp) {
194 self._save(resp, false)
195 .then(function(data) {
196 deferred.resolve(self);
197 }, function(data) {
198 deferred.reject(data);
199 });
200 }, function(data) {
201 deferred.reject(data);
202 });
203
204 return deferred.promise;
205 },
206 _save: function(data, update) {
207 var doc = {};
208 if (typeof update === "undefined") {var update = false};
209 for (var property in data) {
210 if (this.saved_properties.indexOf(property) != -1) {
211 doc[property] = data[property];
212 }
213 }
214 if (update) {
215 return ServerAPI.updateVuln(this.ws, data);
216 }
217 else {
218 return ServerAPI.createVuln(this.ws, data);
219 }
220 }
221 }
222 return Vuln;
223 }]);
+0
-146
faraday/server/www/scripts/vulns/providers/vulns.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('vulnsManager',
6 ['Vuln', 'WebVuln', '$q', 'ServerAPI', 'commonsFact', 'workspacesFact',
7 function(Vuln, WebVuln, $q, ServerAPI, commonsFact, workspacesFact) {
8 var vulnsManager = {};
9 var vulnsCounter = -1;
10 var totalVulns = 0;
11
12 vulnsManager.createVuln = function(ws, data) {
13 var parents = data.parents,
14 promises = [];
15
16 parents.forEach(function(parent) {
17 // we iterate parents when creating multiple vulns from new vuln modal.
18 data.parent = parent.id;
19 data.parent_type = parent.type
20
21 if(data.type == "Vulnerability") {
22 var vuln = new Vuln(ws, data);
23 } else {
24 var vuln = new WebVuln(ws, data);
25 }
26
27 promises.push(vuln.save());
28 });
29
30 return $q.all(promises);
31 };
32
33 vulnsManager.deleteVuln = function(vuln) {
34 return vuln.remove();
35 };
36
37 vulnsManager.exportCsv = function(ws, jsonOptions){
38 let deferred = $q.defer();
39 ServerAPI.exportCsv(ws, jsonOptions)
40 .then(function(response) {
41 deferred.resolve(response);
42 }, function(response) {
43 deferred.reject("Unable to export csv.");
44 });
45 return deferred.promise;
46 }
47
48 vulnsManager.getVulns = function(ws, page, page_size, filter, sort, sort_direction) {
49 var deferred = $q.defer();
50 var options = {page: page, page_size: page_size, sort:sort, sort_dir: sort_direction}
51 for( var property in filter ) {
52 if (filter.hasOwnProperty(property)) {
53 options[property] = filter[property];
54 }
55 };
56 ServerAPI.getVulns(ws, options)
57 .then(function(response) {
58 var result = {
59 vulnerabilities: [],
60 count: 0
61 };
62
63 for(var i = 0; i < response.data.vulnerabilities.length; i++) {
64 var vulnData = response.data.vulnerabilities[i].value;
65 try {
66 if(vulnData.type == "Vulnerability") {
67 var vuln = new Vuln(ws, vulnData);
68 } else {
69 var vuln = new WebVuln(ws, vulnData);
70 }
71 result.vulnerabilities.push(vuln);
72 } catch(e) {
73 console.log(e.stack);
74 }
75 }
76 vulnsCounter = response.data.count;
77 result.count = response.data.count;
78 deferred.resolve(result);
79 }, function(response) {
80 deferred.reject("Unable to retrieve vulnerabilities from server");
81 });
82 return deferred.promise;
83 };
84
85 vulnsManager.getFilteredVulns = function(wsName, jsonOptions) {
86 var deferred = $q.defer();
87 ServerAPI.getFilteredVulns(wsName, jsonOptions)
88 .then(function(response) {
89 var result = {
90 vulnerabilities: [],
91 count: 0
92 };
93
94 for(var i = 0; i < response.data.vulnerabilities.length; i++) {
95 var vulnData = response.data.vulnerabilities[i].value;
96 try {
97 if(vulnData.type === "Vulnerability") {
98 var vuln = new Vuln(wsName, vulnData);
99 } else if(vulnData.type === "VulnerabilityWeb") {
100 var vuln = new WebVuln(wsName, vulnData);
101 } else {
102 throw Exception("Unknown vulnerability type");
103 }
104 result.vulnerabilities.push(vuln);
105 } catch(e) {
106 console.log(e.stack);
107 }
108 }
109 vulnsCounter = response.data.count;
110 result.count = response.data.count;
111 deferred.resolve(result);
112 }, function(response) {
113 deferred.reject("Unable to retrieve vulnerabilities from server");
114 });
115 return deferred.promise;
116 };
117
118 vulnsManager.loadVulnsCounter = function(ws){
119 // Ugly hack to populate the vulnsCounter global variable
120 workspacesFact.get(ws).then(function(data){
121 // Commenting this line worked. I'm not sure why
122 // vulnsCounter = data.stats.total_vulns;
123 totalVulns = data.stats.total_vulns;
124 })
125 };
126
127 vulnsManager.getVulnsNum = function(ws) {
128 if( vulnsCounter > -1) {
129 return vulnsCounter;
130 }else{
131 return totalVulns;
132 }
133 };
134
135 vulnsManager.getTotalVulns = function(ws) {
136 return totalVulns;
137 };
138
139 vulnsManager.updateVuln = function(vuln, data) {
140 return vuln.update(data);
141 };
142
143 return vulnsManager;
144
145 }]);
+0
-60
faraday/server/www/scripts/vulns/providers/web.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('WebVuln', ['Vuln', 'BASEURL', function(Vuln, BASEURL) {
6 WebVuln = function(ws, data) {
7 Vuln.call(this, data);
8 if(data) {
9 if(data.name === undefined || data.name === "") {
10 throw new Error("Unable to create Vuln without a name");
11 }
12 this.set(ws, data);
13 }
14 };
15
16 var public_properties = [
17 'method', 'params', 'path', 'pname', 'query',
18 'request', 'response', 'website', 'status_code'
19 ];
20
21 WebVuln.prototype = Object.create(Vuln.prototype);
22
23 WebVuln.prototype.public_properties = Vuln.prototype.public_properties.concat(public_properties);
24
25 WebVuln.prototype.saved_properties = Vuln.prototype.saved_properties.concat(public_properties);
26
27 WebVuln.prototype.set = function(ws, data) {
28 var self = this;
29
30 Vuln.prototype.set.call(self, ws, data);
31
32 self.type = "VulnerabilityWeb";
33
34 public_properties.forEach(function(property) {
35 if(data[property] !== undefined) self[property] = data[property];
36 });
37 };
38
39 WebVuln.prototype.update = function(data) {
40 var self = this,
41 vuln = new WebVuln(self.ws, self);
42 return Vuln.prototype._update.call(self, vuln, data);
43 };
44
45 WebVuln.prototype.populate = function() {
46 var self = this,
47 vuln = Vuln.prototype.populate.call(self);
48
49 public_properties.forEach(function(property) {
50 vuln[property] = self[property];
51 });
52
53 return vuln;
54 };
55
56 WebVuln.prototype.constructor = WebVuln;
57
58 return WebVuln;
59 }]);
+0
-398
faraday/server/www/scripts/workspaces/controllers/workspaces.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('workspacesCtrl', ['$uibModal', '$scope', '$q', 'workspacesFact', 'dashboardSrv', '$location', '$cookies',
6 function ($uibModal, $scope, $q, workspacesFact, dashboardSrv, $location, $cookies) {
7 $scope.hash;
8 $scope.objects;
9 $scope.workspaces;
10 $scope.wss;
11 $scope.search;
12
13 $scope.init = function () {
14 $scope.objects = [];
15 $scope.workspaces = [];
16 $scope.wss = [];
17 $scope.archived = false;
18 // $scope.newworkspace = {};
19
20 var hash_tmp = window.location.hash.split("/")[1];
21 switch (hash_tmp) {
22 case "status":
23 $scope.hash = "status";
24 break;
25 case "dashboard":
26 $scope.hash = "dashboard";
27 break;
28 case "hosts":
29 $scope.hash = "hosts";
30 break;
31 default:
32 $scope.hash = "";
33 }
34
35 workspacesFact.getWorkspaces().then(function (wss) {
36
37 $scope.wss = []; // Store workspace names
38 wss.forEach(function (ws) {
39 $scope.wss.push(ws.name);
40 $scope.onSuccessGet(ws);
41 $scope.objects[ws.name] = {
42 "total_vulns": "-",
43 "hosts": "-",
44 "services": "-"
45 };
46 for (var stat in ws.stats) {
47 if (ws.stats.hasOwnProperty(stat)) {
48 if ($scope.objects[ws.name].hasOwnProperty(stat))
49 $scope.objects[ws.name][stat] = ws.stats[stat];
50 }
51 }
52 ;
53 });
54 });
55 };
56
57 $scope.onSuccessGet = function (workspace) {
58 workspace.selected = false;
59 workspace.scope = workspace.scope.map(function (scope) {
60 return {key: scope}
61 });
62 if (workspace.scope.length == 0) workspace.scope.push({key: ''});
63 $scope.workspaces.push(workspace);
64 };
65
66 $scope.onSuccessInsert = function (workspace) {
67 $scope.wss.push(workspace.name);
68 workspace.scope = workspace.scope.map(function (scope) {
69 return {key: scope}
70 });
71 if (workspace.scope.length == 0) workspace.scope.push({key: ''});
72
73 $scope.objects[workspace.name] = workspace.stats;
74
75 // Ulgy hack to keep the workspaces sorted alphabetically
76 for (var i = 0; i < $scope.workspaces.length; i++) {
77 if ($scope.workspaces[i].name > workspace.name) break;
78 }
79 $scope.workspaces.splice(i, 0, workspace);
80 };
81
82 $scope.onFailInsert = function (error) {
83 var modal = $uibModal.open({
84 templateUrl: 'scripts/commons/partials/modalKO.html',
85 controller: 'commonsModalKoCtrl',
86 resolve: {
87 msg: function () {
88 if (error.status == 409) {
89 return "A workspace with that name already exists"
90 }
91 return error.data.message;
92 }
93 }
94 });
95 };
96
97 $scope.onSuccessEdit = function (workspace) {
98 for (var i = 0; i < $scope.workspaces.length; i++) {
99 if ($scope.workspaces[i]._id == workspace._id) {
100 $scope.workspaces[i].name = workspace.name;
101 $scope.workspaces[i]._rev = workspace._rev;
102 $scope.workspaces[i].description = workspace.description;
103 if ($scope.workspaces[i].duration === undefined)
104 $scope.workspaces[i].duration = {};
105 $scope.workspaces[i].duration.start_date = workspace.duration.start_date;
106 $scope.workspaces[i].duration.end_date = workspace.duration.end_date;
107 $scope.workspaces[i].scope = workspace.scope;
108 break;
109 }
110 }
111 ;
112 };
113
114 $scope.onSuccessDelete = function (workspace_name) {
115 remove = function (arr, item) {
116 for (var i = arr.length; i--;) {
117 if (arr[i] === item) {
118 arr.splice(i, 1);
119 }
120 }
121 return arr;
122 };
123
124 $scope.wss = remove($scope.wss, workspace_name);
125 for (var i = 0; i < $scope.workspaces.length; i++) {
126 if ($scope.workspaces[i].name == workspace_name) {
127 $scope.workspaces.splice(i, 1);
128 break;
129 }
130 }
131 ;
132 };
133
134 $scope.insert = function (workspace) {
135 delete workspace.selected;
136 workspacesFact.put(workspace).then(function (resp) {
137 workspace.active = resp.data.active;
138 workspace.stats = resp.data.stats;
139 $scope.onSuccessInsert(workspace)
140 },
141 $scope.onFailInsert);
142 };
143
144 $scope.update = function (ws, wsName, finally_) {
145 if (typeof(ws.duration.start_date) == "number") {
146 start_date = ws.duration.start_date;
147 } else if (ws.duration.start_date) {
148 start_date = ws.duration.start_date.getTime();
149 } else {
150 start_date = "";
151 }
152 if (typeof(ws.duration.end_date) == "number") {
153 end_date = ws.duration.end_date;
154 } else if (ws.duration.end_date) {
155 end_date = ws.duration.end_date.getTime();
156 } else {
157 end_date = "";
158 }
159 duration = {'start_date': start_date, 'end_date': end_date};
160 workspace = {
161 "_id": ws._id,
162 "_rev": ws._rev,
163 "children": ws.children,
164 "customer": ws.customer,
165 "description": ws.description,
166 "duration": duration,
167 "name": ws.name,
168 "scope": ws.scope,
169 "type": ws.type
170 };
171 workspacesFact.update(workspace, wsName).then(function (workspace) {
172 if (finally_) finally_(workspace);
173 $scope.onSuccessEdit(workspace);
174 }, function (error) {
175 if (finally_) finally_(workspace);
176 var modal = $uibModal.open({
177 templateUrl: 'scripts/commons/partials/modalKO.html',
178 controller: 'commonsModalKoCtrl',
179 resolve: {
180 msg: function () {
181 if (error.status == 409) {
182 return "A workspace with that name already exists"
183 }
184 return error;
185 }
186 }
187 });
188 });
189 };
190
191 $scope.remove = function (workspace_name) {
192 workspacesFact.delete(workspace_name).then(function (resp) {
193 $scope.onSuccessDelete(resp);
194 });
195 };
196
197 // Modals methods
198 $scope.new = function () {
199 $scope.modal = $uibModal.open({
200 templateUrl: 'scripts/workspaces/partials/modalNew.html',
201 backdrop: 'static',
202 controller: 'workspacesModalNew',
203 size: 'lg'
204 });
205
206 $scope.modal.result.then(function (workspace) {
207 // The API expects list of strings in scope
208 api_scope = workspace.scope.map(function (scope) {
209 return scope.key
210 }).filter(Boolean);
211
212 workspace = $scope.create(workspace.name, workspace.description, workspace.start_date, workspace.end_date, api_scope);
213 $scope.insert(workspace);
214 });
215
216 };
217
218 $scope.edit = function () {
219 var workspace;
220
221 $scope.workspaces.forEach(function (w) {
222 if (w.selected) {
223 workspace = w;
224 }
225 });
226
227 if (workspace) {
228 var oldName = workspace.name;
229 var modal = $uibModal.open({
230 templateUrl: 'scripts/workspaces/partials/modalEdit.html',
231 backdrop: 'static',
232 controller: 'workspacesModalEdit',
233 size: 'lg',
234 resolve: {
235 ws: function () {
236 return workspace;
237 }
238 }
239 });
240
241 modal.result.then(function (workspace) {
242 // The API expects list of strings in scope
243 var old_scope = workspace.scope;
244 workspace.scope = workspace.scope.map(function (scope) {
245 return scope.key
246 }).filter(Boolean);
247
248 $scope.update(workspace, oldName, function (workspace) {
249 workspace.scope = old_scope;
250 });
251 });
252 } else {
253 var modal = $uibModal.open({
254 templateUrl: 'scripts/commons/partials/modalKO.html',
255 controller: 'commonsModalKoCtrl',
256 resolve: {
257 msg: function () {
258 return 'No workspaces were selected to edit';
259 }
260 }
261 });
262 }
263
264 };
265
266 $scope.delete = function () {
267 var selected = false;
268
269 $scope.workspaces.forEach(function (w) {
270 if (w.selected) {
271 selected = true;
272 return;
273 }
274 });
275
276 if (selected) {
277 $scope.modal = $uibModal.open({
278 templateUrl: 'scripts/commons/partials/modalDelete.html',
279 controller: 'commonsModalDelete',
280 size: 'lg',
281 resolve: {
282 msg: function () {
283 var msg = "A workspace will be deleted. This action cannot be undone. Are you sure you want to proceed?";
284 return msg;
285 }
286 }
287 });
288
289 $scope.modal.result.then(function () {
290 $scope.workspaces.forEach(function (w) {
291 if (w.selected == true)
292 $scope.remove(w.name);
293 });
294 });
295 } else {
296 var modal = $uibModal.open({
297 templateUrl: 'scripts/commons/partials/modalKO.html',
298 controller: 'commonsModalKoCtrl',
299 resolve: {
300 msg: function () {
301 return 'No workspaces were selected to delete';
302 }
303 }
304 });
305 }
306 };
307 // This is in the modal context only
308 $scope.okDelete = function () {
309 $scope.modal.close();
310 };
311 // end of modal context
312
313 $scope.create = function (wname, wdesc, start_date, end_date, scope) {
314 if (end_date) end_date = end_date.getTime(); else end_date = "";
315 if (start_date) start_date = start_date.getTime(); else start_date = "";
316 var workspace = {
317 "_id": wname,
318 "customer": "",
319 "name": wname,
320 "type": "Workspace",
321 "children": [],
322 "duration": {"start_date": start_date, "end_date": end_date},
323 "scope": scope,
324 "description": wdesc
325 };
326 return (workspace);
327
328 };
329
330 $scope.redirect = function (path) {
331 $location.path("/" + ($location.path().split('/')[1] || 'dashboard') + "/ws/" + path);
332 };
333 $scope.dashboardRedirect = function (path) {
334 $location.path("/dashboard/ws/" + path);
335 };
336
337 $scope.clearSearch = function () {
338 $scope.search = '';
339 };
340
341 $scope.activeToggle = function (ws) {
342 if (ws.active) {
343 workspacesFact.deactivate(ws.name).then(function (resp) {
344 if (resp.data) {
345 ws.active = false;
346
347 let pos = -1;
348 if ($cookies.get('currentUrl') !== undefined)
349 pos = $cookies.get('currentUrl').indexOf('ws/');
350
351 if (pos >= 0) {
352 let savedWs = $cookies.get('currentUrl').slice(pos + 3);
353 if (ws.name === savedWs){
354 $cookies.remove('currentUrl');
355 workspacesFact.changeWorkspace(null);
356 }
357
358 }
359 }
360 });
361 } else {
362 workspacesFact.activate(ws.name).then(function (resp) {
363 if (resp.data) {
364 ws.active = true
365 }
366 });
367 }
368 };
369 // toggles sort field and order
370 $scope.toggleSort = function(field) {
371 $scope.toggleSortField(field);
372 $scope.toggleReverse();
373 };
374
375 // toggles column sort field
376 $scope.toggleSortField = function(field) {
377 $scope.sortField = field;
378 };
379
380 // toggle column sort order
381 $scope.toggleReverse = function() {
382 $scope.reverse = !$scope.reverse;
383 }
384
385
386 $scope.clearSearch = function() {
387 $scope.search = '';
388 };
389
390 $scope.readonlyToggle = function (ws) {
391 workspacesFact.readOnlyToogle(ws.name).then(function (resp) {
392 ws.readonly = resp.data;
393 });
394 };
395
396 $scope.init();
397 }]);
+0
-53
faraday/server/www/scripts/workspaces/controllers/workspacesModalEdit.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('workspacesModalEdit', ['$modalInstance', '$scope', 'ws',
6 function($modalInstance, $scope, ws) {
7 $scope.minDate;
8 $scope.dateOptions;
9 $scope.workspace;
10
11 init = function () {
12 $scope.minDate = new Date();
13 $scope.dateOptions = {
14 formatYear: 'yy',
15 startingDay: 1
16 };
17
18 $scope.workspace = angular.copy(ws);
19 };
20
21 //DATE PICKER
22 $scope.today = function() {
23 $scope.dt = new Date();
24 };
25 $scope.today();
26
27 $scope.newScope = function($event){
28 $scope.workspace.scope.push({key:''});
29 $event.preventDefault();
30 }
31
32 $scope.clear = function () {
33 $scope.dt = null;
34 };
35
36 $scope.open = function($event, isStart) {
37 $event.preventDefault();
38 $event.stopPropagation();
39
40 if(isStart) $scope.openedStart = true; else $scope.openedEnd = true;
41 };
42
43 $scope.okEdit = function() {
44 $modalInstance.close($scope.workspace);
45 };
46
47 $scope.cancel = function() {
48 $modalInstance.dismiss('cancel');
49 };
50
51 init();
52 }]);
+0
-52
faraday/server/www/scripts/workspaces/controllers/workspacesModalNew.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .controller('workspacesModalNew', ['$modalInstance', '$scope',
6 function($modalInstance, $scope) {
7
8 $scope.minDate;
9 $scope.dateOptions;
10 $scope.workspace;
11
12 init = function () {
13 $scope.workspace = {
14 "description": "",
15 "name": "",
16 "scope": [{key: ''}]
17 };
18 };
19
20 //DATE PICKER
21 $scope.today = function() {
22 $scope.dt = new Date();
23 };
24 $scope.today();
25
26 $scope.clear = function () {
27 $scope.dt = null;
28 };
29
30 $scope.open = function($event, isStart) {
31 $event.preventDefault();
32 $event.stopPropagation();
33
34 if(isStart) $scope.openedStart = true; else $scope.openedEnd = true;
35 };
36
37 $scope.newScope = function($event){
38 $scope.workspace.scope.push({key:''});
39 $event.preventDefault();
40 }
41
42 $scope.okNew = function(){
43 $modalInstance.close($scope.workspace);
44 };
45
46 $scope.cancel = function() {
47 $modalInstance.dismiss('cancel');
48 };
49
50 init();
51 }]);
+0
-104
faraday/server/www/scripts/workspaces/partials/list.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form novalidate>
5 <div class="faraday-header-border-fix"></div>
6 <section id="main" class="seccion clearfix">
7 <div class="left-main-without-pagination">
8 <div ng-controller="headerCtrl" ng-include="'scripts/commons/partials/header.html'"></div>
9 <div id="reports-main" class="fila clearfix">
10 <div class="reports col-md-12 col-sm-12 col-xs-12">
11 <div class="button-control justify-flex-start col-md-12 col-sm-12 col-xs-12">
12 <div class="control-wrapper control-new">
13 <button id="merge" type="button" class="btn btn-success btn-new" title="New Workspace" ng-click="new()">
14 New
15 </button>
16 </div>
17 <div class="control-wrapper control-edit">
18 <button type="button" class="btn btn-default edit" title="Edit selected Workspaces" ng-click="edit()">
19 <img src="images/icon-toolbar-edit.svg" class="edit-icon" />
20 </button>
21 </div>
22 <div class="control-wrapper">
23 <button id="delete" type="button" class="btn btn-default" title="Delete selected Workspaces" ng-click="delete()">
24 <img src="images/icon-toolbar-delete.svg" class="delete-icon" />
25 </button>
26 </div>
27 <div class="control-wrapper search-wrapper">
28 <form role="form">
29 <div class="form-group">
30 <div class="input-group">
31 <span class="input-group-addon glyphicon-btn glyphicon glyphicon-remove" ng-if="search && search != 'confirmed=true'" ng-click="clearSearch()"></span>
32 <input type="text" class="form-control" placeholder="Enter keywords" ng-model="search" />
33 <span class="input-group-addon glyphicon-btn">
34 <img src="images/icon-toolbar-searchbar-loupe.svg" class="search-icon" />
35 </span>
36 </div>
37 </div>
38 </form>
39 </div>
40 <div class="control-wrapper">
41 <div class="checkbox">
42 <label>
43 <input type="checkbox" id="archived" ng-model="archived"/>
44 <span class="normal-size">Show archived</span>
45 </label>
46 </div>
47 </div>
48 </div>
49 <table class="table-v3 table table-responsive">
50 <thead>
51 <tr class="ui-grid-header">
52 <th class="ui-grid-cell-contents ui-grid-header-cell">
53 <a href="" ng-click="toggleSort('name')">Name</a>
54 </th>
55 <th class="ui-grid-cell-contents ui-grid-header-cell">Start Date</th>
56 <th class="ui-grid-cell-contents ui-grid-header-cell">End Date</th>
57 <th class="ui-grid-cell-contents ui-grid-header-cell">Vulns</th>
58 <th class="ui-grid-cell-contents ui-grid-header-cell">Hosts</th>
59 <th class="ui-grid-cell-contents ui-grid-header-cell">Services</th>
60 <th class="ui-grid-cell-contents ui-grid-header-cell">Active Agents</th>
61 <th class="ui-grid-cell-contents ui-grid-header-cell">Last Modified</th>
62 <th class="ui-grid-cell-contents ui-grid-header-cell">Active</th>
63 <th class="ui-grid-cell-contents ui-grid-header-cell">Read only</th>
64 </tr>
65 </thead>
66 <tbody>
67 <tr ng-repeat="ws in workspaces | filter:query | filter:search | filter:{active:archived == false? true : undefined} | orderBy:sortField:reverse"
68 selection-model selection-model-selected-class="multi-selected">
69 <td class="ui-grid-cell-contents">
70 <span class="onhover upsize" ng-click="dashboardRedirect(ws.name)">
71 <b>{{ws.name}}</b>
72 </span>
73 </td>
74 <td class="ui-grid-cell-contents" ng-if="ws.duration.start_date" ng-bind="ws.duration.start_date | amTimeAgo"></td>
75 <td class="ui-grid-cell-contents" ng-if="!ws.duration.start_date">-</td>
76 <td class="ui-grid-cell-contents" ng-if="ws.duration.end_date" ng-bind="ws.duration.end_date | amTimeAgo"></td>
77 <td class="ui-grid-cell-contents" ng-if="!ws.duration.end_date">-</td>
78 <td class="ui-grid-cell-contents"><a href="#/status/ws/{{ws.name}}">{{objects[ws.name]['total_vulns']}}</a></td>
79 <td class="ui-grid-cell-contents"><a href="#/hosts/ws/{{ws.name}}">{{objects[ws.name]['hosts']}}</a></td>
80 <td class="ui-grid-cell-contents" ng-bind="objects[ws.name]['services']"></td>
81 <td class="ui-grid-cell-contents" ng-bind="ws.active_agents_count"></td>
82 <td class="ui-grid-cell-contents" ng-bind="ws.update_date | amTimeAgo"></td>
83 <td class="ui-grid-cell-contents active-toggle">
84 <div class="toogle-img-container">
85 <span ng-click="activeToggle(ws)" class="active-toggle-container" ng-class="{ disabled:ws.active === false }" uib-tooltip="{{(ws.active === true) ? 'Disable workspace' : 'Enable workspace'}}" tooltip-placement="right">
86 <img ng-src="{{ (ws.active) ? 'images/ok-active.svg' : 'images/active.svg'}}" class="confirm-icon" ng-style="{ 'opacity': (ws.active === true) ? '1' : '0.7' }" />
87 </span>
88 </div>
89 </td>
90 <td class="ui-grid-cell-contents active-toggle">
91 <div class="toogle-img-container">
92 <span ng-click="readonlyToggle(ws)" class="active-toggle-container" ng-class="{ disabled:ws.readonly === false }" uib-tooltip="{{(ws.readonly === false) ? 'Workspace with all permissions' : 'Workspace read only'}}" tooltip-placement="right">
93 <img ng-src="{{ (ws.readonly == true) ? 'images/padlock_closed.svg' : 'images/padlock_open.svg'}}" class="confirm-icon" ng-style="{ 'opacity': (ws.readonly === true) ? '1' : '0.7' }" />
94 </span>
95 </div>
96 </td>
97 </tr>
98 </tbody>
99 </table><!-- #hosts -->
100 </div><!-- .reports -->
101 </div><!-- #reports-main --></div><!-- .right-main -->
102 </section><!-- #main -->
103 </form>
+0
-14
faraday/server/www/scripts/workspaces/partials/modalDelete.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header">
5 <h3 class="modal-title">Workspace Delete</h3>
6 </div>
7 <div class="modal-body">
8 <h5>You are about to remove {{workspacesCtrl.selectedItems.length}} Workspaces. Proceed?</h5>
9 </div><!-- .modal-body -->
10 <div class="modal-footer">
11 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
12 <button class="btn btn-success" ng-click="okDelete()">OK</button>
13 </div>
+0
-78
faraday/server/www/scripts/workspaces/partials/modalEdit.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form novalidate>
5 <div class="modal-header">
6 <div class="modal-button btn-toolbar">
7 <button class="btn btn-success" ng-click="okEdit()" ng-disabled="form.$invalid || date.$invalid">OK</button>
8 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">Edit Workspace: {{workspace.name}}</h3>
11 </div>
12 <div class="modal-body">
13 <div class="form-horizontal">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid && form.name.$dirty}">
15 <div class="col-md-12">
16 <ng-form name="form" novalidate>
17 <label class="sr-only" for="wsp-name">Workspace Name</label>
18 <input type="text" class="form-control"
19 ng-pattern=/^[a-z0-9][a-z0-9\_\$\(\)\+\-\/]*$/ id="vuln-name" name="name" placeholder="Workspace Name"
20 ng-model="workspace.name" required/>
21 <div ng-if="form.$invalid && form.name.$dirty">
22 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="">
23 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
24 <span class="sr-only">Error:</span>
25 <button type="button" class="close" data-dismiss="alert"><span area-hidden="true">&times;</span><span class="sr-only">Close</span></button>
26 Workspace name can not contain white spaces or start with uppercase.
27 </div>
28 </div>
29 </ng-form>
30 </div>
31 </div><!-- .form-group -->
32 <div class="form-group">
33 <div class="col-md-12">
34 <label class="sr-only" for="vuln-desc">Workspace Description</label>
35 <textarea class="form-control" id="vuln-desc"
36 placeholder="Description" value={{workspace.description}}
37 ng-model="workspace.description"></textarea>
38 </div>
39 </div><!-- .form-group -->
40 <div class="form-group">
41 <div class="col-md-6 datepicker">
42 <h5>Start Date</h5>
43 <label class="sr-only" for="work-start">Start Date</label>
44 <p class="input-group">
45 <input type="text" class="form-control" uib-datepicker-popup="MM/dd/yyyy" ng-model="workspace.duration.start_date" is-open="openedStart" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" close-text="Close" placeholder="Start Date"/>
46 <span class="input-group-btn">
47 <button type="button" class="btn btn-default" ng-click="open($event,true)"><i class="glyphicon glyphicon-calendar"></i></button>
48 </span>
49 </p>
50 </div>
51 <div class="col-md-6 datepicker">
52 <h5>End Date</h5>
53 <label class="sr-only" for="work-end">End Date</label>
54 <p class="input-group">
55 <input type="text" class="form-control" uib-datepicker-popup="MM/dd/yyyy" ng-model="workspace.duration.end_date" is-open="openedEnd" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" close-text="Close" placeholder="End Date"/>
56 <span class="input-group-btn">
57 <button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
58 </span>
59 </p>
60 </div>
61
62 </div>
63 <div class="form-group">
64 <div class="col-md-12">
65 <h5>Scope</h5>
66 <span class="input-group-addon button-radius" ng-click="newScope($event)">Add scope target</span>
67 </div>
68 <div class="col-md-12 input-margin" ng-repeat="scope in workspace.scope">
69 <div class="input-group margin-bottom-sm col-md-12">
70 <input type="text" class="form-control" placeholder="Scope target" ng-model="scope.key"/>
71 <span class="input-group-addon" ng-click="workspace.scope.splice($index, 1)" ng-hide="workspace.scope.length == 1"><i class="fa fa-minus-circle"></i></span>
72 </div>
73 </div>
74 </div><!-- .form-group -->
75 </div><!-- .form-horizontal -->
76 </div><!-- .modal-body -->
77 </form>
+0
-86
faraday/server/www/scripts/workspaces/partials/modalNew.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <form name="form" novalidate>
5 <div class="modal-header">
6 <div class="modal-button btn-toolbar">
7 <button class="btn btn-success" ng-disabled="form.$invalid || date.$invalid || workspace.end_date< workspace.start_date" ng-click="okNew()">Save</button>
8 <button class="btn btn-danger" ng-click="cancel()">Cancel</button>
9 </div>
10 <h3 class="modal-title">New Workspace</h3>
11 </div>
12 <div class="modal-body">
13 <div class="form-horizontal">
14 <div class="form-group" ng-class="{'has-error': form.name.$invalid && form.name.$dirty}">
15 <div class="col-md-12">
16 <ng-form name="form" novalidate>
17 <label class="sr-only" for="wsp-name">Workspace Name</label>
18 <input type="text" class="form-control"
19 ng-pattern=/^[a-z0-9][a-z0-9\_\$\(\)\+\-\/]*$/ id="vuln-name" name="name" placeholder="Workspace Name"
20 ng-model="workspace.name" required/>
21 <div ng-if="form.$invalid && form.name.$dirty">
22 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="">
23 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
24 <span class="sr-only">Error:</span>
25 <button type="button" class="close" data-dismiss="alert"><span area-hidden="true">&times;</span><span class="sr-only">Close</span></button>
26 Workspace name can not contain white spaces or start with uppercase.
27 </div>
28 </div>
29 </ng-form>
30 </div>
31 </div><!-- .form-group -->
32 <div class="form-group">
33 <div class="col-md-12">
34 <label class="sr-only" for="vuln-desc">Workspace Description</label>
35 <textarea class="form-control" id="vuln-desc"
36 placeholder="Description" ng-model="workspace.description"
37 >
38 </textarea>
39 </div>
40 </div><!-- .form-group -->
41 <div class="form-group">
42 <ng-form name="date" novalidate>
43 <div class="col-md-6 datepicker">
44 <label class="sr-only" for="work-start">Start Date</label>
45 <p class="input-group">
46 <input type="text" class="form-control" uib-datepicker-popup="MM/dd/yyyy" ng-model="workspace.start_date" is-open="openedStart" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" close-text="Close" placeholder="Start Date" />
47 <span class="input-group-btn">
48 <button type="button" class="btn btn-default" ng-click="open($event,true)"><i class="glyphicon glyphicon-calendar"></i></button>
49 </span>
50 </p>
51 </div>
52 <div class="col-md-6 datepicker">
53 <label class="sr-only" for="work-end">End Date</label>
54 <p class="input-group">
55 <input type="text" class="form-control" uib-datepicker-popup="MM/dd/yyyy" ng-model="workspace.end_date" is-open="openedEnd" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" close-text="Close" placeholder="End Date" />
56 <span class="input-group-btn">
57 <button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
58 </span>
59 </p>
60 </div>
61 <div ng-if="date.$invalid || workspace.end_date< workspace.start_date" class="col-md-12">
62 <div class="alert alert-danger target_not_selected" role="alert" ng-hide="">
63 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
64 <span class="sr-only">Error:</span>
65 <button type="button" class="close" data-dismiss="alert"><span area-hidden="true">&times;</span><span class="sr-only">Close</span></button>
66 Invalid Date
67 </div>
68 </div>
69 </ng-form>
70 </div><!-- .form-group -->
71 <div class="form-group">
72 <div class="col-md-12">
73 <h5>Scope</h5>
74 <span class="input-group-addon button-radius" ng-click="newScope($event)">Add scope target</span>
75 </div>
76 <div class="col-md-12 input-margin" ng-repeat="scope in workspace.scope">
77 <div class="input-group margin-bottom-sm col-md-12">
78 <input type="text" class="form-control" placeholder="Scope target" ng-model="scope.key"/>
79 <span class="input-group-addon" ng-click="workspace.scope.splice($index, 1)" ng-hide="workspace.scope.length == 1"><i class="fa fa-minus-circle"></i></span>
80 </div>
81 </div>
82 </div><!-- .form-group -->
83 </div><!-- .form-horizontal -->
84 </div><!-- .modal-body -->
85 </form>
+0
-13
faraday/server/www/scripts/workspaces/partials/modalOK.html less more
0 <!-- Faraday Penetration Test IDE -->
1 <!-- Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) -->
2 <!-- See the file 'doc/LICENSE' for the license information -->
3
4 <div class="modal-header">
5 <h3 class="modal-title">Oops!</h3>
6 </div>
7 <div class="modal-body">
8 <h5>{{ msg }}</h5>
9 </div><!-- .modal-body -->
10 <div class="modal-footer">
11 <button class="btn btn-success" ng-click="ok()">OK</button>
12 </div>
+0
-156
faraday/server/www/scripts/workspaces/providers/workspaces.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 angular.module('faradayApp')
5 .factory('workspacesFact', ['BASEURL', 'ServerAPI', '$http', '$q', '$rootScope', function(BASEURL, ServerAPI, $http, $q, $rootScope) {
6 var workspacesFact = {};
7 workspacesFact.workspace = '';
8
9 workspacesFact.list = function() {
10 var deferred = $q.defer();
11 ServerAPI.getWorkspacesNames().
12 then(function(response) {
13 var names = [];
14 response.data.forEach(function(workspace){
15 names.push(workspace.name);
16 });
17 deferred.resolve(names);
18 }, errorHandler);
19 return deferred.promise;
20 };
21
22 workspacesFact.getWorkspaces = function() {
23 var deferred = $q.defer();
24 ServerAPI.getWorkspaces().
25 then(function(response)
26 { deferred.resolve(response.data) }, errorHandler);
27 return deferred.promise;
28 };
29
30 returnStatus = function(data) {
31 return $q.when(data.status);
32 };
33
34 workspacesFact.get = function(workspace_name) {
35 var deferred = $q.defer();
36 ServerAPI.getWorkspace(workspace_name).
37 then(function(ws) {
38 deferred.resolve(ws.data);
39 }, function() {
40 deferred.reject();
41 });
42 return deferred.promise;
43 };
44
45 workspacesFact.getDuration = function(workspace_name) {
46 var deferred = $q.defer();
47 ServerAPI.getWorkspace(workspace_name).then(function(workspace) {
48 deferred.resolve({
49 "start": workspace.data.duration.start_date,
50 "end": workspace.data.duration.end_date
51 });
52 });
53 return deferred.promise;
54 };
55
56 workspacesFact.exists = function(workspace_name) {
57 var deferred = $q.defer();
58 ServerAPI.getWorkspace(workspace_name).then(
59 function(response) {
60 deferred.resolve(response);
61 }, function(response) {
62 deferred.reject(response);
63 });
64 return deferred.promise;
65 };
66
67 errorHandler = function(response) {
68 if(typeof(response) == "object")
69 return $q.reject(response.data.reason.replace("file", "workspace"));
70 else if(typeof(response) == "string")
71 return $q.reject(response);
72 else
73 return $q.reject("Something bad happened");
74 };
75
76 workspacesFact.put = function(workspace) {
77 return ServerAPI.createWorkspace(workspace.name, workspace);
78 };
79
80 indexOfDocument = function(list, name) {
81 var ret = -1;
82 list.forEach(function(item, index) {
83 if(item._id == name) {
84 ret = index;
85 }
86 });
87 return ret;
88 };
89
90 workspacesFact.update = function(workspace, wsName) {
91 var deferred = $q.defer();
92 ServerAPI.updateWorkspace(workspace, wsName).then(function(data){
93 workspace._rev = data.rev;
94 deferred.resolve(workspace);
95 }, function(err){
96 deferred.reject(err);
97 });
98 return deferred.promise;
99 };
100
101 workspacesFact.delete = function(workspace_name) {
102 var deferred = $q.defer();
103 ServerAPI.deleteWorkspace(workspace_name).then(function(data) {
104 deferred.resolve(workspace_name);
105 }, function() {
106 deferred.reject();
107 });
108 return deferred.promise;
109 };
110
111 workspacesFact.activate = function(wsName) {
112 var deferred = $q.defer();
113 ServerAPI.activateWorkspace(wsName).then(function(data){
114 deferred.resolve(data);
115 }, function(err){
116 deferred.reject(err);
117 });
118 return deferred.promise;
119 };
120
121 workspacesFact.deactivate = function(wsName) {
122 var deferred = $q.defer();
123 ServerAPI.deactivateWorkspace(wsName).then(function(data){
124 deferred.resolve(data);
125 }, function(err){
126 deferred.reject(err);
127 });
128 return deferred.promise;
129 };
130
131 workspacesFact.readOnlyToogle = function(wsName) {
132 var deferred = $q.defer();
133 ServerAPI.readOnlyToogle(wsName).then(function(data){
134 deferred.resolve(data);
135 }, function(err){
136 deferred.reject(err);
137 });
138 return deferred.promise;
139 };
140
141 workspacesFact.changeWorkspace = function (workspace) {
142 this.workspace = workspace;
143 this.broadcastItem();
144 };
145
146 workspacesFact.getWorkspace = function () {
147 return workspacesFact.workspace;
148 };
149
150 workspacesFact.broadcastItem = function () {
151 $rootScope.$broadcast('handleChangeWSBroadcast');
152 };
153
154 return workspacesFact;
155 }]);
+0
-59
faraday/server/www/sequences.css less more
0 /* Faraday Penetration Test IDE */
1 /* Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) */
2 /* See the file 'doc/LICENSE' for the license information */
3
4 body {
5 font-family: 'Open Sans', sans-serif;
6 font-size: 12px;
7 font-weight: 400;
8 background-color: #fff;
9 width: 960px;
10 height: 700px;
11 margin-top: 10px;
12 }
13
14 #main {
15 float: left;
16 width: 750px;
17 }
18
19 #sidebar {
20 float: right;
21 width: 100px;
22 }
23
24 #sequence {
25 width: 600px;
26 height: 70px;
27 }
28
29 #legend {
30 padding: 10px 0 0 3px;
31 }
32
33 #sequence text, #legend text {
34 font-weight: 600;
35 fill: #fff;
36 }
37
38 #chart {
39 position: relative;
40 }
41
42 #chart path {
43 stroke: #fff;
44 }
45
46 #explanation {
47 position: absolute;
48 top: 260px;
49 left: 305px;
50 width: 140px;
51 text-align: center;
52 color: #666;
53 z-index: -1;
54 }
55
56 #percentage {
57 font-size: 2.5em;
58 }
+0
-104
faraday/server/www/styles/angular-hotkeys.css less more
0 .cfp-hotkeys-container {
1 display: table !important;
2 position: fixed;
3 width: 100%;
4 height: 100%;
5 top: 0;
6 left: 0;
7 color: #333;
8 font-size: 1em;
9 background-color: rgba(255,255,255,0.9);
10 }
11
12 .cfp-hotkeys-container.fade {
13 z-index: -1024;
14 visibility: hidden;
15 opacity: 0;
16 -webkit-transition: opacity 0.15s linear;
17 -moz-transition: opacity 0.15s linear;
18 -o-transition: opacity 0.15s linear;
19 transition: opacity 0.15s linear;
20 }
21
22 .cfp-hotkeys-container.fade.in {
23 z-index: 10002;
24 visibility: visible;
25 opacity: 1;
26 }
27
28 .cfp-hotkeys-title {
29 font-weight: bold;
30 text-align: center;
31 font-size: 1.2em;
32 }
33
34 .cfp-hotkeys {
35 width: 100%;
36 height: 100%;
37 display: table-cell;
38 vertical-align: middle;
39 }
40
41 .cfp-hotkeys table {
42 margin: auto;
43 color: #333;
44 }
45
46 .cfp-content {
47 display: table-cell;
48 vertical-align: middle;
49 }
50
51 .cfp-hotkeys-keys {
52 padding: 5px;
53 text-align: right;
54 }
55
56 .cfp-hotkeys-key {
57 display: inline-block;
58 color: #fff;
59 background-color: #333;
60 border: 1px solid #333;
61 border-radius: 5px;
62 text-align: center;
63 margin-right: 5px;
64 box-shadow: inset 0 1px 0 #666, 0 1px 0 #bbb;
65 padding: 5px 9px;
66 font-size: 1em;
67 }
68
69 .cfp-hotkeys-text {
70 padding-left: 10px;
71 font-size: 1em;
72 }
73
74 .cfp-hotkeys-close {
75 position: fixed;
76 top: 20px;
77 right: 20px;
78 font-size: 2em;
79 font-weight: bold;
80 padding: 5px 10px;
81 border: 1px solid #ddd;
82 border-radius: 5px;
83 min-height: 45px;
84 min-width: 45px;
85 text-align: center;
86 }
87
88 .cfp-hotkeys-close:hover {
89 background-color: #fff;
90 cursor: pointer;
91 }
92
93 @media all and (max-width: 500px) {
94 .cfp-hotkeys {
95 font-size: 0.8em;
96 }
97 }
98
99 @media all and (min-width: 750px) {
100 .cfp-hotkeys {
101 font-size: 1.2em;
102 }
103 }
+0
-1672
faraday/server/www/styles/font-awesome.css less more
0 /*!
1 * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
2 * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
3 */
4 /* FONT PATH
5 * -------------------------- */
6 @font-face {
7 font-family: 'FontAwesome';
8 src: url('../fonts/font-awesome/fontawesome-webfont.eot?v=4.2.0');
9 src: url('../fonts/font-awesome/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'), url('../fonts/font-awesome/fontawesome-webfont.woff?v=4.2.0') format('woff'), url('../fonts/font-awesome/fontawesome-webfont.ttf?v=4.2.0') format('truetype'), url('../fonts/font-awesome/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');
10 font-weight: normal;
11 font-style: normal;
12 }
13 .fa {
14 display: inline-block;
15 font: normal normal normal 14px/1 FontAwesome;
16 font-size: inherit;
17 text-rendering: auto;
18 -webkit-font-smoothing: antialiased;
19 -moz-osx-font-smoothing: grayscale;
20 }
21 /* makes the font 33% larger relative to the icon container */
22 .fa-lg {
23 font-size: 1.33333333em;
24 line-height: 0.75em;
25 vertical-align: -15%;
26 }
27 .fa-2x {
28 font-size: 2em;
29 }
30 .fa-3x {
31 font-size: 3em;
32 }
33 .fa-4x {
34 font-size: 4em;
35 }
36 .fa-5x {
37 font-size: 5em;
38 }
39 .fa-fw {
40 width: 1.28571429em;
41 text-align: center;
42 }
43 .fa-ul {
44 padding-left: 0;
45 margin-left: 2.14285714em;
46 list-style-type: none;
47 }
48 .fa-ul > li {
49 position: relative;
50 }
51 .fa-li {
52 position: absolute;
53 left: -2.14285714em;
54 width: 2.14285714em;
55 top: 0.14285714em;
56 text-align: center;
57 }
58 .fa-li.fa-lg {
59 left: -1.85714286em;
60 }
61 .fa-border {
62 padding: .2em .25em .15em;
63 border: solid 0.08em #eeeeee;
64 border-radius: .1em;
65 }
66 .pull-right {
67 float: right;
68 }
69 .pull-left {
70 float: left;
71 }
72 .fa.pull-left {
73 margin-right: .3em;
74 }
75 .fa.pull-right {
76 margin-left: .3em;
77 }
78 .fa-spin {
79 -webkit-animation: fa-spin 2s infinite linear;
80 animation: fa-spin 2s infinite linear;
81 }
82 @-webkit-keyframes fa-spin {
83 0% {
84 -webkit-transform: rotate(0deg);
85 transform: rotate(0deg);
86 }
87 100% {
88 -webkit-transform: rotate(359deg);
89 transform: rotate(359deg);
90 }
91 }
92 @keyframes fa-spin {
93 0% {
94 -webkit-transform: rotate(0deg);
95 transform: rotate(0deg);
96 }
97 100% {
98 -webkit-transform: rotate(359deg);
99 transform: rotate(359deg);
100 }
101 }
102 .fa-rotate-90 {
103 filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
104 -webkit-transform: rotate(90deg);
105 -ms-transform: rotate(90deg);
106 transform: rotate(90deg);
107 }
108 .fa-rotate-180 {
109 filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
110 -webkit-transform: rotate(180deg);
111 -ms-transform: rotate(180deg);
112 transform: rotate(180deg);
113 }
114 .fa-rotate-270 {
115 filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
116 -webkit-transform: rotate(270deg);
117 -ms-transform: rotate(270deg);
118 transform: rotate(270deg);
119 }
120 .fa-flip-horizontal {
121 filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);
122 -webkit-transform: scale(-1, 1);
123 -ms-transform: scale(-1, 1);
124 transform: scale(-1, 1);
125 }
126 .fa-flip-vertical {
127 filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);
128 -webkit-transform: scale(1, -1);
129 -ms-transform: scale(1, -1);
130 transform: scale(1, -1);
131 }
132 :root .fa-rotate-90,
133 :root .fa-rotate-180,
134 :root .fa-rotate-270,
135 :root .fa-flip-horizontal,
136 :root .fa-flip-vertical {
137 filter: none;
138 }
139 .fa-stack {
140 position: relative;
141 display: inline-block;
142 width: 2em;
143 height: 2em;
144 line-height: 2em;
145 vertical-align: middle;
146 }
147 .fa-stack-1x,
148 .fa-stack-2x {
149 position: absolute;
150 left: 0;
151 width: 100%;
152 text-align: center;
153 }
154 .fa-stack-1x {
155 line-height: inherit;
156 }
157 .fa-stack-2x {
158 font-size: 2em;
159 }
160 .fa-inverse {
161 color: #ffffff;
162 }
163 /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
164 readers do not read off random characters that represent icons */
165 .fa-glass:before {
166 content: "\f000";
167 }
168 .fa-music:before {
169 content: "\f001";
170 }
171 .fa-search:before {
172 content: "\f002";
173 }
174 .fa-envelope-o:before {
175 content: "\f003";
176 }
177 .fa-heart:before {
178 content: "\f004";
179 }
180 .fa-star:before {
181 content: "\f005";
182 }
183 .fa-star-o:before {
184 content: "\f006";
185 }
186 .fa-user:before {
187 content: "\f007";
188 }
189 .fa-film:before {
190 content: "\f008";
191 }
192 .fa-th-large:before {
193 content: "\f009";
194 }
195 .fa-th:before {
196 content: "\f00a";
197 }
198 .fa-th-list:before {
199 content: "\f00b";
200 }
201 .fa-check:before {
202 content: "\f00c";
203 }
204 .fa-remove:before,
205 .fa-close:before,
206 .fa-times:before {
207 content: "\f00d";
208 }
209 .fa-search-plus:before {
210 content: "\f00e";
211 }
212 .fa-search-minus:before {
213 content: "\f010";
214 }
215 .fa-power-off:before {
216 content: "\f011";
217 }
218 .fa-signal:before {
219 content: "\f012";
220 }
221 .fa-gear:before,
222 .fa-cog:before {
223 content: "\f013";
224 }
225 .fa-trash-o:before {
226 content: "\f014";
227 }
228 .fa-home:before {
229 content: "\f015";
230 }
231 .fa-file-o:before {
232 content: "\f016";
233 }
234 .fa-clock-o:before {
235 content: "\f017";
236 }
237 .fa-road:before {
238 content: "\f018";
239 }
240 .fa-download:before {
241 content: "\f019";
242 }
243 .fa-arrow-circle-o-down:before {
244 content: "\f01a";
245 }
246 .fa-arrow-circle-o-up:before {
247 content: "\f01b";
248 }
249 .fa-inbox:before {
250 content: "\f01c";
251 }
252 .fa-play-circle-o:before {
253 content: "\f01d";
254 }
255 .fa-rotate-right:before,
256 .fa-repeat:before {
257 content: "\f01e";
258 }
259 .fa-refresh:before {
260 content: "\f021";
261 }
262 .fa-list-alt:before {
263 content: "\f022";
264 }
265 .fa-lock:before {
266 content: "\f023";
267 }
268 .fa-flag:before {
269 content: "\f024";
270 }
271 .fa-headphones:before {
272 content: "\f025";
273 }
274 .fa-volume-off:before {
275 content: "\f026";
276 }
277 .fa-volume-down:before {
278 content: "\f027";
279 }
280 .fa-volume-up:before {
281 content: "\f028";
282 }
283 .fa-qrcode:before {
284 content: "\f029";
285 }
286 .fa-barcode:before {
287 content: "\f02a";
288 }
289 .fa-tag:before {
290 content: "\f02b";
291 }
292 .fa-tags:before {
293 content: "\f02c";
294 }
295 .fa-book:before {
296 content: "\f02d";
297 }
298 .fa-bookmark:before {
299 content: "\f02e";
300 }
301 .fa-print:before {
302 content: "\f02f";
303 }
304 .fa-camera:before {
305 content: "\f030";
306 }
307 .fa-font:before {
308 content: "\f031";
309 }
310 .fa-bold:before {
311 content: "\f032";
312 }
313 .fa-italic:before {
314 content: "\f033";
315 }
316 .fa-text-height:before {
317 content: "\f034";
318 }
319 .fa-text-width:before {
320 content: "\f035";
321 }
322 .fa-align-left:before {
323 content: "\f036";
324 }
325 .fa-align-center:before {
326 content: "\f037";
327 }
328 .fa-align-right:before {
329 content: "\f038";
330 }
331 .fa-align-justify:before {
332 content: "\f039";
333 }
334 .fa-list:before {
335 content: "\f03a";
336 }
337 .fa-dedent:before,
338 .fa-outdent:before {
339 content: "\f03b";
340 }
341 .fa-indent:before {
342 content: "\f03c";
343 }
344 .fa-video-camera:before {
345 content: "\f03d";
346 }
347 .fa-photo:before,
348 .fa-image:before,
349 .fa-picture-o:before {
350 content: "\f03e";
351 }
352 .fa-pencil:before {
353 content: "\f040";
354 }
355 .fa-map-marker:before {
356 content: "\f041";
357 }
358 .fa-adjust:before {
359 content: "\f042";
360 }
361 .fa-tint:before {
362 content: "\f043";
363 }
364 .fa-edit:before,
365 .fa-pencil-square-o:before {
366 content: "\f044";
367 }
368 .fa-share-square-o:before {
369 content: "\f045";
370 }
371 .fa-check-square-o:before {
372 content: "\f046";
373 }
374 .fa-arrows:before {
375 content: "\f047";
376 }
377 .fa-step-backward:before {
378 content: "\f048";
379 }
380 .fa-fast-backward:before {
381 content: "\f049";
382 }
383 .fa-backward:before {
384 content: "\f04a";
385 }
386 .fa-play:before {
387 content: "\f04b";
388 }
389 .fa-pause:before {
390 content: "\f04c";
391 }
392 .fa-stop:before {
393 content: "\f04d";
394 }
395 .fa-forward:before {
396 content: "\f04e";
397 }
398 .fa-fast-forward:before {
399 content: "\f050";
400 }
401 .fa-step-forward:before {
402 content: "\f051";
403 }
404 .fa-eject:before {
405 content: "\f052";
406 }
407 .fa-chevron-left:before {
408 content: "\f053";
409 }
410 .fa-chevron-right:before {
411 content: "\f054";
412 }
413 .fa-plus-circle:before {
414 content: "\f055";
415 }
416 .fa-minus-circle:before {
417 content: "\f056";
418 }
419 .fa-times-circle:before {
420 content: "\f057";
421 }
422 .fa-check-circle:before {
423 content: "\f058";
424 }
425 .fa-question-circle:before {
426 content: "\f059";
427 }
428 .fa-info-circle:before {
429 content: "\f05a";
430 }
431 .fa-crosshairs:before {
432 content: "\f05b";
433 }
434 .fa-times-circle-o:before {
435 content: "\f05c";
436 }
437 .fa-check-circle-o:before {
438 content: "\f05d";
439 }
440 .fa-ban:before {
441 content: "\f05e";
442 }
443 .fa-arrow-left:before {
444 content: "\f060";
445 }
446 .fa-arrow-right:before {
447 content: "\f061";
448 }
449 .fa-arrow-up:before {
450 content: "\f062";
451 }
452 .fa-arrow-down:before {
453 content: "\f063";
454 }
455 .fa-mail-forward:before,
456 .fa-share:before {
457 content: "\f064";
458 }
459 .fa-expand:before {
460 content: "\f065";
461 }
462 .fa-compress:before {
463 content: "\f066";
464 }
465 .fa-plus:before {
466 content: "\f067";
467 }
468 .fa-minus:before {
469 content: "\f068";
470 }
471 .fa-asterisk:before {
472 content: "\f069";
473 }
474 .fa-exclamation-circle:before {
475 content: "\f06a";
476 }
477 .fa-gift:before {
478 content: "\f06b";
479 }
480 .fa-leaf:before {
481 content: "\f06c";
482 }
483 .fa-fire:before {
484 content: "\f06d";
485 }
486 .fa-eye:before {
487 content: "\f06e";
488 }
489 .fa-eye-slash:before {
490 content: "\f070";
491 }
492 .fa-warning:before,
493 .fa-exclamation-triangle:before {
494 content: "\f071";
495 }
496 .fa-plane:before {
497 content: "\f072";
498 }
499 .fa-calendar:before {
500 content: "\f073";
501 }
502 .fa-random:before {
503 content: "\f074";
504 }
505 .fa-comment:before {
506 content: "\f075";
507 }
508 .fa-magnet:before {
509 content: "\f076";
510 }
511 .fa-chevron-up:before {
512 content: "\f077";
513 }
514 .fa-chevron-down:before {
515 content: "\f078";
516 }
517 .fa-retweet:before {
518 content: "\f079";
519 }
520 .fa-shopping-cart:before {
521 content: "\f07a";
522 }
523 .fa-folder:before {
524 content: "\f07b";
525 }
526 .fa-folder-open:before {
527 content: "\f07c";
528 }
529 .fa-arrows-v:before {
530 content: "\f07d";
531 }
532 .fa-arrows-h:before {
533 content: "\f07e";
534 }
535 .fa-bar-chart-o:before,
536 .fa-bar-chart:before {
537 content: "\f080";
538 }
539 .fa-twitter-square:before {
540 content: "\f081";
541 }
542 .fa-facebook-square:before {
543 content: "\f082";
544 }
545 .fa-camera-retro:before {
546 content: "\f083";
547 }
548 .fa-key:before {
549 content: "\f084";
550 }
551 .fa-gears:before,
552 .fa-cogs:before {
553 content: "\f085";
554 }
555 .fa-comments:before {
556 content: "\f086";
557 }
558 .fa-thumbs-o-up:before {
559 content: "\f087";
560 }
561 .fa-thumbs-o-down:before {
562 content: "\f088";
563 }
564 .fa-star-half:before {
565 content: "\f089";
566 }
567 .fa-heart-o:before {
568 content: "\f08a";
569 }
570 .fa-sign-out:before {
571 content: "\f08b";
572 }
573 .fa-linkedin-square:before {
574 content: "\f08c";
575 }
576 .fa-thumb-tack:before {
577 content: "\f08d";
578 }
579 .fa-external-link:before {
580 content: "\f08e";
581 }
582 .fa-sign-in:before {
583 content: "\f090";
584 }
585 .fa-trophy:before {
586 content: "\f091";
587 }
588 .fa-github-square:before {
589 content: "\f092";
590 }
591 .fa-upload:before {
592 content: "\f093";
593 }
594 .fa-lemon-o:before {
595 content: "\f094";
596 }
597 .fa-phone:before {
598 content: "\f095";
599 }
600 .fa-square-o:before {
601 content: "\f096";
602 }
603 .fa-bookmark-o:before {
604 content: "\f097";
605 }
606 .fa-phone-square:before {
607 content: "\f098";
608 }
609 .fa-twitter:before {
610 content: "\f099";
611 }
612 .fa-facebook:before {
613 content: "\f09a";
614 }
615 .fa-github:before {
616 content: "\f09b";
617 }
618 .fa-unlock:before {
619 content: "\f09c";
620 }
621 .fa-credit-card:before {
622 content: "\f09d";
623 }
624 .fa-rss:before {
625 content: "\f09e";
626 }
627 .fa-hdd-o:before {
628 content: "\f0a0";
629 }
630 .fa-bullhorn:before {
631 content: "\f0a1";
632 }
633 .fa-bell:before {
634 content: "\f0f3";
635 }
636 .fa-certificate:before {
637 content: "\f0a3";
638 }
639 .fa-hand-o-right:before {
640 content: "\f0a4";
641 }
642 .fa-hand-o-left:before {
643 content: "\f0a5";
644 }
645 .fa-hand-o-up:before {
646 content: "\f0a6";
647 }
648 .fa-hand-o-down:before {
649 content: "\f0a7";
650 }
651 .fa-arrow-circle-left:before {
652 content: "\f0a8";
653 }
654 .fa-arrow-circle-right:before {
655 content: "\f0a9";
656 }
657 .fa-arrow-circle-up:before {
658 content: "\f0aa";
659 }
660 .fa-arrow-circle-down:before {
661 content: "\f0ab";
662 }
663 .fa-globe:before {
664 content: "\f0ac";
665 }
666 .fa-wrench:before {
667 content: "\f0ad";
668 }
669 .fa-tasks:before {
670 content: "\f0ae";
671 }
672 .fa-filter:before {
673 content: "\f0b0";
674 }
675 .fa-briefcase:before {
676 content: "\f0b1";
677 }
678 .fa-arrows-alt:before {
679 content: "\f0b2";
680 }
681 .fa-group:before,
682 .fa-users:before {
683 content: "\f0c0";
684 }
685 .fa-chain:before,
686 .fa-link:before {
687 content: "\f0c1";
688 }
689 .fa-cloud:before {
690 content: "\f0c2";
691 }
692 .fa-flask:before {
693 content: "\f0c3";
694 }
695 .fa-cut:before,
696 .fa-scissors:before {
697 content: "\f0c4";
698 }
699 .fa-copy:before,
700 .fa-files-o:before {
701 content: "\f0c5";
702 }
703 .fa-paperclip:before {
704 content: "\f0c6";
705 }
706 .fa-save:before,
707 .fa-floppy-o:before {
708 content: "\f0c7";
709 }
710 .fa-square:before {
711 content: "\f0c8";
712 }
713 .fa-navicon:before,
714 .fa-reorder:before,
715 .fa-bars:before {
716 content: "\f0c9";
717 }
718 .fa-list-ul:before {
719 content: "\f0ca";
720 }
721 .fa-list-ol:before {
722 content: "\f0cb";
723 }
724 .fa-strikethrough:before {
725 content: "\f0cc";
726 }
727 .fa-underline:before {
728 content: "\f0cd";
729 }
730 .fa-table:before {
731 content: "\f0ce";
732 }
733 .fa-magic:before {
734 content: "\f0d0";
735 }
736 .fa-truck:before {
737 content: "\f0d1";
738 }
739 .fa-pinterest:before {
740 content: "\f0d2";
741 }
742 .fa-pinterest-square:before {
743 content: "\f0d3";
744 }
745 .fa-google-plus-square:before {
746 content: "\f0d4";
747 }
748 .fa-google-plus:before {
749 content: "\f0d5";
750 }
751 .fa-money:before {
752 content: "\f0d6";
753 }
754 .fa-caret-down:before {
755 content: "\f0d7";
756 }
757 .fa-caret-up:before {
758 content: "\f0d8";
759 }
760 .fa-caret-left:before {
761 content: "\f0d9";
762 }
763 .fa-caret-right:before {
764 content: "\f0da";
765 }
766 .fa-columns:before {
767 content: "\f0db";
768 }
769 .fa-unsorted:before,
770 .fa-sort:before {
771 content: "\f0dc";
772 }
773 .fa-sort-down:before,
774 .fa-sort-desc:before {
775 content: "\f0dd";
776 }
777 .fa-sort-up:before,
778 .fa-sort-asc:before {
779 content: "\f0de";
780 }
781 .fa-envelope:before {
782 content: "\f0e0";
783 }
784 .fa-linkedin:before {
785 content: "\f0e1";
786 }
787 .fa-rotate-left:before,
788 .fa-undo:before {
789 content: "\f0e2";
790 }
791 .fa-legal:before,
792 .fa-gavel:before {
793 content: "\f0e3";
794 }
795 .fa-dashboard:before,
796 .fa-tachometer:before {
797 content: "\f0e4";
798 }
799 .fa-comment-o:before {
800 content: "\f0e5";
801 }
802 .fa-comments-o:before {
803 content: "\f0e6";
804 }
805 .fa-flash:before,
806 .fa-bolt:before {
807 content: "\f0e7";
808 }
809 .fa-sitemap:before {
810 content: "\f0e8";
811 }
812 .fa-umbrella:before {
813 content: "\f0e9";
814 }
815 .fa-paste:before,
816 .fa-clipboard:before {
817 content: "\f0ea";
818 }
819 .fa-lightbulb-o:before {
820 content: "\f0eb";
821 }
822 .fa-exchange:before {
823 content: "\f0ec";
824 }
825 .fa-cloud-download:before {
826 content: "\f0ed";
827 }
828 .fa-cloud-upload:before {
829 content: "\f0ee";
830 }
831 .fa-user-md:before {
832 content: "\f0f0";
833 }
834 .fa-stethoscope:before {
835 content: "\f0f1";
836 }
837 .fa-suitcase:before {
838 content: "\f0f2";
839 }
840 .fa-bell-o:before {
841 content: "\f0a2";
842 }
843 .fa-coffee:before {
844 content: "\f0f4";
845 }
846 .fa-cutlery:before {
847 content: "\f0f5";
848 }
849 .fa-file-text-o:before {
850 content: "\f0f6";
851 }
852 .fa-building-o:before {
853 content: "\f0f7";
854 }
855 .fa-hospital-o:before {
856 content: "\f0f8";
857 }
858 .fa-ambulance:before {
859 content: "\f0f9";
860 }
861 .fa-medkit:before {
862 content: "\f0fa";
863 }
864 .fa-fighter-jet:before {
865 content: "\f0fb";
866 }
867 .fa-beer:before {
868 content: "\f0fc";
869 }
870 .fa-h-square:before {
871 content: "\f0fd";
872 }
873 .fa-plus-square:before {
874 content: "\f0fe";
875 }
876 .fa-angle-double-left:before {
877 content: "\f100";
878 }
879 .fa-angle-double-right:before {
880 content: "\f101";
881 }
882 .fa-angle-double-up:before {
883 content: "\f102";
884 }
885 .fa-angle-double-down:before {
886 content: "\f103";
887 }
888 .fa-angle-left:before {
889 content: "\f104";
890 }
891 .fa-angle-right:before {
892 content: "\f105";
893 }
894 .fa-angle-up:before {
895 content: "\f106";
896 }
897 .fa-angle-down:before {
898 content: "\f107";
899 }
900 .fa-desktop:before {
901 content: "\f108";
902 }
903 .fa-laptop:before {
904 content: "\f109";
905 }
906 .fa-tablet:before {
907 content: "\f10a";
908 }
909 .fa-mobile-phone:before,
910 .fa-mobile:before {
911 content: "\f10b";
912 }
913 .fa-circle-o:before {
914 content: "\f10c";
915 }
916 .fa-quote-left:before {
917 content: "\f10d";
918 }
919 .fa-quote-right:before {
920 content: "\f10e";
921 }
922 .fa-spinner:before {
923 content: "\f110";
924 }
925 .fa-circle:before {
926 content: "\f111";
927 }
928 .fa-mail-reply:before,
929 .fa-reply:before {
930 content: "\f112";
931 }
932 .fa-github-alt:before {
933 content: "\f113";
934 }
935 .fa-folder-o:before {
936 content: "\f114";
937 }
938 .fa-folder-open-o:before {
939 content: "\f115";
940 }
941 .fa-smile-o:before {
942 content: "\f118";
943 }
944 .fa-frown-o:before {
945 content: "\f119";
946 }
947 .fa-meh-o:before {
948 content: "\f11a";
949 }
950 .fa-gamepad:before {
951 content: "\f11b";
952 }
953 .fa-keyboard-o:before {
954 content: "\f11c";
955 }
956 .fa-flag-o:before {
957 content: "\f11d";
958 }
959 .fa-flag-checkered:before {
960 content: "\f11e";
961 }
962 .fa-terminal:before {
963 content: "\f120";
964 }
965 .fa-code:before {
966 content: "\f121";
967 }
968 .fa-mail-reply-all:before,
969 .fa-reply-all:before {
970 content: "\f122";
971 }
972 .fa-star-half-empty:before,
973 .fa-star-half-full:before,
974 .fa-star-half-o:before {
975 content: "\f123";
976 }
977 .fa-location-arrow:before {
978 content: "\f124";
979 }
980 .fa-crop:before {
981 content: "\f125";
982 }
983 .fa-code-fork:before {
984 content: "\f126";
985 }
986 .fa-unlink:before,
987 .fa-chain-broken:before {
988 content: "\f127";
989 }
990 .fa-question:before {
991 content: "\f128";
992 }
993 .fa-info:before {
994 content: "\f129";
995 }
996 .fa-exclamation:before {
997 content: "\f12a";
998 }
999 .fa-superscript:before {
1000 content: "\f12b";
1001 }
1002 .fa-subscript:before {
1003 content: "\f12c";
1004 }
1005 .fa-eraser:before {
1006 content: "\f12d";
1007 }
1008 .fa-puzzle-piece:before {
1009 content: "\f12e";
1010 }
1011 .fa-microphone:before {
1012 content: "\f130";
1013 }
1014 .fa-microphone-slash:before {
1015 content: "\f131";
1016 }
1017 .fa-shield:before {
1018 content: "\f132";
1019 }
1020 .fa-calendar-o:before {
1021 content: "\f133";
1022 }
1023 .fa-fire-extinguisher:before {
1024 content: "\f134";
1025 }
1026 .fa-rocket:before {
1027 content: "\f135";
1028 }
1029 .fa-maxcdn:before {
1030 content: "\f136";
1031 }
1032 .fa-chevron-circle-left:before {
1033 content: "\f137";
1034 }
1035 .fa-chevron-circle-right:before {
1036 content: "\f138";
1037 }
1038 .fa-chevron-circle-up:before {
1039 content: "\f139";
1040 }
1041 .fa-chevron-circle-down:before {
1042 content: "\f13a";
1043 }
1044 .fa-html5:before {
1045 content: "\f13b";
1046 }
1047 .fa-css3:before {
1048 content: "\f13c";
1049 }
1050 .fa-anchor:before {
1051 content: "\f13d";
1052 }
1053 .fa-unlock-alt:before {
1054 content: "\f13e";
1055 }
1056 .fa-bullseye:before {
1057 content: "\f140";
1058 }
1059 .fa-ellipsis-h:before {
1060 content: "\f141";
1061 }
1062 .fa-ellipsis-v:before {
1063 content: "\f142";
1064 }
1065 .fa-rss-square:before {
1066 content: "\f143";
1067 }
1068 .fa-play-circle:before {
1069 content: "\f144";
1070 }
1071 .fa-ticket:before {
1072 content: "\f145";
1073 }
1074 .fa-minus-square:before {
1075 content: "\f146";
1076 }
1077 .fa-minus-square-o:before {
1078 content: "\f147";
1079 }
1080 .fa-level-up:before {
1081 content: "\f148";
1082 }
1083 .fa-level-down:before {
1084 content: "\f149";
1085 }
1086 .fa-check-square:before {
1087 content: "\f14a";
1088 }
1089 .fa-pencil-square:before {
1090 content: "\f14b";
1091 }
1092 .fa-external-link-square:before {
1093 content: "\f14c";
1094 }
1095 .fa-share-square:before {
1096 content: "\f14d";
1097 }
1098 .fa-compass:before {
1099 content: "\f14e";
1100 }
1101 .fa-toggle-down:before,
1102 .fa-caret-square-o-down:before {
1103 content: "\f150";
1104 }
1105 .fa-toggle-up:before,
1106 .fa-caret-square-o-up:before {
1107 content: "\f151";
1108 }
1109 .fa-toggle-right:before,
1110 .fa-caret-square-o-right:before {
1111 content: "\f152";
1112 }
1113 .fa-euro:before,
1114 .fa-eur:before {
1115 content: "\f153";
1116 }
1117 .fa-gbp:before {
1118 content: "\f154";
1119 }
1120 .fa-dollar:before,
1121 .fa-usd:before {
1122 content: "\f155";
1123 }
1124 .fa-rupee:before,
1125 .fa-inr:before {
1126 content: "\f156";
1127 }
1128 .fa-cny:before,
1129 .fa-rmb:before,
1130 .fa-yen:before,
1131 .fa-jpy:before {
1132 content: "\f157";
1133 }
1134 .fa-ruble:before,
1135 .fa-rouble:before,
1136 .fa-rub:before {
1137 content: "\f158";
1138 }
1139 .fa-won:before,
1140 .fa-krw:before {
1141 content: "\f159";
1142 }
1143 .fa-bitcoin:before,
1144 .fa-btc:before {
1145 content: "\f15a";
1146 }
1147 .fa-file:before {
1148 content: "\f15b";
1149 }
1150 .fa-file-text:before {
1151 content: "\f15c";
1152 }
1153 .fa-sort-alpha-asc:before {
1154 content: "\f15d";
1155 }
1156 .fa-sort-alpha-desc:before {
1157 content: "\f15e";
1158 }
1159 .fa-sort-amount-asc:before {
1160 content: "\f160";
1161 }
1162 .fa-sort-amount-desc:before {
1163 content: "\f161";
1164 }
1165 .fa-sort-numeric-asc:before {
1166 content: "\f162";
1167 }
1168 .fa-sort-numeric-desc:before {
1169 content: "\f163";
1170 }
1171 .fa-thumbs-up:before {
1172 content: "\f164";
1173 }
1174 .fa-thumbs-down:before {
1175 content: "\f165";
1176 }
1177 .fa-youtube-square:before {
1178 content: "\f166";
1179 }
1180 .fa-youtube:before {
1181 content: "\f167";
1182 }
1183 .fa-xing:before {
1184 content: "\f168";
1185 }
1186 .fa-xing-square:before {
1187 content: "\f169";
1188 }
1189 .fa-youtube-play:before {
1190 content: "\f16a";
1191 }
1192 .fa-dropbox:before {
1193 content: "\f16b";
1194 }
1195 .fa-stack-overflow:before {
1196 content: "\f16c";
1197 }
1198 .fa-instagram:before {
1199 content: "\f16d";
1200 }
1201 .fa-flickr:before {
1202 content: "\f16e";
1203 }
1204 .fa-adn:before {
1205 content: "\f170";
1206 }
1207 .fa-bitbucket:before {
1208 content: "\f171";
1209 }
1210 .fa-bitbucket-square:before {
1211 content: "\f172";
1212 }
1213 .fa-tumblr:before {
1214 content: "\f173";
1215 }
1216 .fa-tumblr-square:before {
1217 content: "\f174";
1218 }
1219 .fa-long-arrow-down:before {
1220 content: "\f175";
1221 }
1222 .fa-long-arrow-up:before {
1223 content: "\f176";
1224 }
1225 .fa-long-arrow-left:before {
1226 content: "\f177";
1227 }
1228 .fa-long-arrow-right:before {
1229 content: "\f178";
1230 }
1231 .fa-apple:before {
1232 content: "\f179";
1233 }
1234 .fa-windows:before {
1235 content: "\f17a";
1236 }
1237 .fa-android:before {
1238 content: "\f17b";
1239 }
1240 .fa-linux:before {
1241 content: "\f17c";
1242 }
1243 .fa-dribbble:before {
1244 content: "\f17d";
1245 }
1246 .fa-skype:before {
1247 content: "\f17e";
1248 }
1249 .fa-foursquare:before {
1250 content: "\f180";
1251 }
1252 .fa-trello:before {
1253 content: "\f181";
1254 }
1255 .fa-female:before {
1256 content: "\f182";
1257 }
1258 .fa-male:before {
1259 content: "\f183";
1260 }
1261 .fa-gittip:before {
1262 content: "\f184";
1263 }
1264 .fa-sun-o:before {
1265 content: "\f185";
1266 }
1267 .fa-moon-o:before {
1268 content: "\f186";
1269 }
1270 .fa-archive:before {
1271 content: "\f187";
1272 }
1273 .fa-bug:before {
1274 content: "\f188";
1275 }
1276 .fa-vk:before {
1277 content: "\f189";
1278 }
1279 .fa-weibo:before {
1280 content: "\f18a";
1281 }
1282 .fa-renren:before {
1283 content: "\f18b";
1284 }
1285 .fa-pagelines:before {
1286 content: "\f18c";
1287 }
1288 .fa-stack-exchange:before {
1289 content: "\f18d";
1290 }
1291 .fa-arrow-circle-o-right:before {
1292 content: "\f18e";
1293 }
1294 .fa-arrow-circle-o-left:before {
1295 content: "\f190";
1296 }
1297 .fa-toggle-left:before,
1298 .fa-caret-square-o-left:before {
1299 content: "\f191";
1300 }
1301 .fa-dot-circle-o:before {
1302 content: "\f192";
1303 }
1304 .fa-wheelchair:before {
1305 content: "\f193";
1306 }
1307 .fa-vimeo-square:before {
1308 content: "\f194";
1309 }
1310 .fa-turkish-lira:before,
1311 .fa-try:before {
1312 content: "\f195";
1313 }
1314 .fa-plus-square-o:before {
1315 content: "\f196";
1316 }
1317 .fa-space-shuttle:before {
1318 content: "\f197";
1319 }
1320 .fa-slack:before {
1321 content: "\f198";
1322 }
1323 .fa-envelope-square:before {
1324 content: "\f199";
1325 }
1326 .fa-wordpress:before {
1327 content: "\f19a";
1328 }
1329 .fa-openid:before {
1330 content: "\f19b";
1331 }
1332 .fa-institution:before,
1333 .fa-bank:before,
1334 .fa-university:before {
1335 content: "\f19c";
1336 }
1337 .fa-mortar-board:before,
1338 .fa-graduation-cap:before {
1339 content: "\f19d";
1340 }
1341 .fa-yahoo:before {
1342 content: "\f19e";
1343 }
1344 .fa-google:before {
1345 content: "\f1a0";
1346 }
1347 .fa-reddit:before {
1348 content: "\f1a1";
1349 }
1350 .fa-reddit-square:before {
1351 content: "\f1a2";
1352 }
1353 .fa-stumbleupon-circle:before {
1354 content: "\f1a3";
1355 }
1356 .fa-stumbleupon:before {
1357 content: "\f1a4";
1358 }
1359 .fa-delicious:before {
1360 content: "\f1a5";
1361 }
1362 .fa-digg:before {
1363 content: "\f1a6";
1364 }
1365 .fa-pied-piper:before {
1366 content: "\f1a7";
1367 }
1368 .fa-pied-piper-alt:before {
1369 content: "\f1a8";
1370 }
1371 .fa-drupal:before {
1372 content: "\f1a9";
1373 }
1374 .fa-joomla:before {
1375 content: "\f1aa";
1376 }
1377 .fa-language:before {
1378 content: "\f1ab";
1379 }
1380 .fa-fax:before {
1381 content: "\f1ac";
1382 }
1383 .fa-building:before {
1384 content: "\f1ad";
1385 }
1386 .fa-child:before {
1387 content: "\f1ae";
1388 }
1389 .fa-paw:before {
1390 content: "\f1b0";
1391 }
1392 .fa-spoon:before {
1393 content: "\f1b1";
1394 }
1395 .fa-cube:before {
1396 content: "\f1b2";
1397 }
1398 .fa-cubes:before {
1399 content: "\f1b3";
1400 }
1401 .fa-behance:before {
1402 content: "\f1b4";
1403 }
1404 .fa-behance-square:before {
1405 content: "\f1b5";
1406 }
1407 .fa-steam:before {
1408 content: "\f1b6";
1409 }
1410 .fa-steam-square:before {
1411 content: "\f1b7";
1412 }
1413 .fa-recycle:before {
1414 content: "\f1b8";
1415 }
1416 .fa-automobile:before,
1417 .fa-car:before {
1418 content: "\f1b9";
1419 }
1420 .fa-cab:before,
1421 .fa-taxi:before {
1422 content: "\f1ba";
1423 }
1424 .fa-tree:before {
1425 content: "\f1bb";
1426 }
1427 .fa-spotify:before {
1428 content: "\f1bc";
1429 }
1430 .fa-deviantart:before {
1431 content: "\f1bd";
1432 }
1433 .fa-soundcloud:before {
1434 content: "\f1be";
1435 }
1436 .fa-database:before {
1437 content: "\f1c0";
1438 }
1439 .fa-file-pdf-o:before {
1440 content: "\f1c1";
1441 }
1442 .fa-file-word-o:before {
1443 content: "\f1c2";
1444 }
1445 .fa-file-excel-o:before {
1446 content: "\f1c3";
1447 }
1448 .fa-file-powerpoint-o:before {
1449 content: "\f1c4";
1450 }
1451 .fa-file-photo-o:before,
1452 .fa-file-picture-o:before,
1453 .fa-file-image-o:before {
1454 content: "\f1c5";
1455 }
1456 .fa-file-zip-o:before,
1457 .fa-file-archive-o:before {
1458 content: "\f1c6";
1459 }
1460 .fa-file-sound-o:before,
1461 .fa-file-audio-o:before {
1462 content: "\f1c7";
1463 }
1464 .fa-file-movie-o:before,
1465 .fa-file-video-o:before {
1466 content: "\f1c8";
1467 }
1468 .fa-file-code-o:before {
1469 content: "\f1c9";
1470 }
1471 .fa-vine:before {
1472 content: "\f1ca";
1473 }
1474 .fa-codepen:before {
1475 content: "\f1cb";
1476 }
1477 .fa-jsfiddle:before {
1478 content: "\f1cc";
1479 }
1480 .fa-life-bouy:before,
1481 .fa-life-buoy:before,
1482 .fa-life-saver:before,
1483 .fa-support:before,
1484 .fa-life-ring:before {
1485 content: "\f1cd";
1486 }
1487 .fa-circle-o-notch:before {
1488 content: "\f1ce";
1489 }
1490 .fa-ra:before,
1491 .fa-rebel:before {
1492 content: "\f1d0";
1493 }
1494 .fa-ge:before,
1495 .fa-empire:before {
1496 content: "\f1d1";
1497 }
1498 .fa-git-square:before {
1499 content: "\f1d2";
1500 }
1501 .fa-git:before {
1502 content: "\f1d3";
1503 }
1504 .fa-hacker-news:before {
1505 content: "\f1d4";
1506 }
1507 .fa-tencent-weibo:before {
1508 content: "\f1d5";
1509 }
1510 .fa-qq:before {
1511 content: "\f1d6";
1512 }
1513 .fa-wechat:before,
1514 .fa-weixin:before {
1515 content: "\f1d7";
1516 }
1517 .fa-send:before,
1518 .fa-paper-plane:before {
1519 content: "\f1d8";
1520 }
1521 .fa-send-o:before,
1522 .fa-paper-plane-o:before {
1523 content: "\f1d9";
1524 }
1525 .fa-history:before {
1526 content: "\f1da";
1527 }
1528 .fa-circle-thin:before {
1529 content: "\f1db";
1530 }
1531 .fa-header:before {
1532 content: "\f1dc";
1533 }
1534 .fa-paragraph:before {
1535 content: "\f1dd";
1536 }
1537 .fa-sliders:before {
1538 content: "\f1de";
1539 }
1540 .fa-share-alt:before {
1541 content: "\f1e0";
1542 }
1543 .fa-share-alt-square:before {
1544 content: "\f1e1";
1545 }
1546 .fa-bomb:before {
1547 content: "\f1e2";
1548 }
1549 .fa-soccer-ball-o:before,
1550 .fa-futbol-o:before {
1551 content: "\f1e3";
1552 }
1553 .fa-tty:before {
1554 content: "\f1e4";
1555 }
1556 .fa-binoculars:before {
1557 content: "\f1e5";
1558 }
1559 .fa-plug:before {
1560 content: "\f1e6";
1561 }
1562 .fa-slideshare:before {
1563 content: "\f1e7";
1564 }
1565 .fa-twitch:before {
1566 content: "\f1e8";
1567 }
1568 .fa-yelp:before {
1569 content: "\f1e9";
1570 }
1571 .fa-newspaper-o:before {
1572 content: "\f1ea";
1573 }
1574 .fa-wifi:before {
1575 content: "\f1eb";
1576 }
1577 .fa-calculator:before {
1578 content: "\f1ec";
1579 }
1580 .fa-paypal:before {
1581 content: "\f1ed";
1582 }
1583 .fa-google-wallet:before {
1584 content: "\f1ee";
1585 }
1586 .fa-cc-visa:before {
1587 content: "\f1f0";
1588 }
1589 .fa-cc-mastercard:before {
1590 content: "\f1f1";
1591 }
1592 .fa-cc-discover:before {
1593 content: "\f1f2";
1594 }
1595 .fa-cc-amex:before {
1596 content: "\f1f3";
1597 }
1598 .fa-cc-paypal:before {
1599 content: "\f1f4";
1600 }
1601 .fa-cc-stripe:before {
1602 content: "\f1f5";
1603 }
1604 .fa-bell-slash:before {
1605 content: "\f1f6";
1606 }
1607 .fa-bell-slash-o:before {
1608 content: "\f1f7";
1609 }
1610 .fa-trash:before {
1611 content: "\f1f8";
1612 }
1613 .fa-copyright:before {
1614 content: "\f1f9";
1615 }
1616 .fa-at:before {
1617 content: "\f1fa";
1618 }
1619 .fa-eyedropper:before {
1620 content: "\f1fb";
1621 }
1622 .fa-paint-brush:before {
1623 content: "\f1fc";
1624 }
1625 .fa-birthday-cake:before {
1626 content: "\f1fd";
1627 }
1628 .fa-area-chart:before {
1629 content: "\f1fe";
1630 }
1631 .fa-pie-chart:before {
1632 content: "\f200";
1633 }
1634 .fa-line-chart:before {
1635 content: "\f201";
1636 }
1637 .fa-lastfm:before {
1638 content: "\f202";
1639 }
1640 .fa-lastfm-square:before {
1641 content: "\f203";
1642 }
1643 .fa-toggle-off:before {
1644 content: "\f204";
1645 }
1646 .fa-toggle-on:before {
1647 content: "\f205";
1648 }
1649 .fa-bicycle:before {
1650 content: "\f206";
1651 }
1652 .fa-bus:before {
1653 content: "\f207";
1654 }
1655 .fa-ioxhost:before {
1656 content: "\f208";
1657 }
1658 .fa-angellist:before {
1659 content: "\f209";
1660 }
1661 .fa-cc:before {
1662 content: "\f20a";
1663 }
1664 .fa-shekel:before,
1665 .fa-sheqel:before,
1666 .fa-ils:before {
1667 content: "\f20b";
1668 }
1669 .fa-meanpath:before {
1670 content: "\f20c";
1671 }
+0
-61
faraday/server/www/styles/material-input.css less more
0 .form-input {
1 margin: 20px 0px 10px 0px;
2 width: 100%;
3 }
4 .form-input label {
5 position: relative;
6 display: block;
7 width: 100%;
8 min-height: 25px;
9 }
10 .form-input .placeholder {
11 position: absolute;
12 display: block;
13 top: 16px;
14 z-index: 2;
15 font-size: 16px;
16 font-weight: 400;
17 transition: all 100ms ease-in-out;
18 width: 100%;
19 cursor: text;
20 color: #a1a1a1;
21 }
22 .form-input input,
23 .form-input textarea {
24 position: absolute;
25 top: 15px;
26 z-index: 1;
27 width: 100%;
28 font-size: 16px;
29 font-weight: 300;
30 border: 0;
31 border-bottom: 1px dashed #d4d4d4;
32 transition: border-color 100ms ease-in-out;
33 outline: none;
34 padding: 0;
35 margin: 0;
36 color: #a1a1a1;
37 box-shadow: none; /* Firefox defaults to red so we clean it */
38 }
39 .form-input textarea {
40 min-height: 30px;
41 padding: 8px 0;
42 }
43 .form-input input {
44 height: 25px;
45 }
46
47 .form-input input.has-error,
48 .form-input textarea.has-error {
49 border-bottom: 1px dashed #de4456;
50 cursor: text;
51 }
52
53 .form-input input:focus + .placeholder,
54 .form-input input:valid + .placeholder,
55 .form-input textarea:focus + .placeholder,
56 .form-input textarea:valid + .placeholder {
57 cursor: text;
58 opacity: 0;
59 z-index: -1;
60 }
+0
-136
faraday/server/www/table-v3.css less more
0 .table-v3 .ui-grid-header {
1 border-top: solid #E5E5E5 2px;
2 border-bottom: 2px solid #d8d8d8;
3 background: none;
4 color: #E9E9E9;
5 padding: 0px;
6 height: 45px;
7 }
8
9 .table-v3 .ui-grid-header .ui-grid-cell-contents,
10 .table-v3 .ui-grid-header .ui-grid-cell-contents span {
11 color: #7c7c7c;
12 padding: 9px 3px 9px 5px !important;
13 text-align: left;
14 }
15
16 .table-v3 .ui-grid-cell-contents {
17 text-align: left;
18 border: none;
19 }
20
21 .table-v3 .ui-grid-cell-contents.confirm-toggle{
22 text-align: center;
23 }
24
25 .table-v3 .ui-grid-header-cell{
26 border-right: solid #E9E9E9 1px;
27 text-align: center;
28 }
29
30 .table-v3 .ui-grid-header-cell i, .table-v3 .grid_id{
31 padding: 11px 9px 9px 5px !important
32 }
33
34 .table-v3 .ui-grid-row {
35 height: 45px;
36 }
37
38 .table-v3 .date-cell {
39 opacity: 0.5;
40 }
41
42 .table-v3 .grid_id .ui-grid-cell-contents{
43 position: relative;
44 top: 3px;
45 }
46
47 .table-v3 .ui-grid-row-selected .ui-grid-cell{
48 background-color: #8DA2B7 !important;
49 color: #FFFFFF;
50 }
51
52 .table-v3 .ui-grid-row-selected a{
53 color: #FFFFFF;
54 }
55
56 .table-v3 .no-background{
57 background: none;
58 }
59
60 .table-v3 .ui-grid-row:last-child .ui-grid-cell{
61 border:none;
62 }
63
64 .table-v3 .ui-grid-pager-panel {
65 background-color: #f1f1f1;
66 }
67
68 .table-v3 .status.opened {
69 background-color: rgba(223, 57, 54, .6) !important;
70 text-align: center;
71 }
72
73 .table-v3 .status-wrapper {
74 height: 100%;
75 }
76
77 .table-v3 .status.opened span {
78 color: #DF3936;
79 }
80
81 .table-v3 .status.risk-accepted {
82 background-color: rgba(46, 151, 189, 0.6) !important;
83 text-align: center;
84 }
85
86 .table-v3 .status.re-opened span {
87 color: rgba(223, 191, 53, 1);
88 }
89
90 .table-v3 .status.re-opened {
91 background-color: rgba(223, 191, 53, 0.6) !important;
92 text-align: center;
93 }
94
95 .table-v3 .status.risk-accepted span {
96 color: rgba(46, 151, 189, 1);
97 }
98
99 .table-v3 .status.closed {
100 background-color: rgba(161, 206, 49, 0.6) !important;
101 text-align: center;
102 }
103
104 .table-v3 .status.closed span {
105 color: rgba(161, 206, 49, 1);
106 }
107
108 .table-v3 .confirm-icon {
109 width: 40%;
110 }
111
112 .table-v3 .ui-grid-header-cell{
113 text-align: center;
114 }
115
116 .table-v3 .ui-grid-header-cell .glyphicon-remove{
117 color: #ccc;
118 font-size: 8px;
119 font-weight: lighter;
120 top: 0px;
121 left: 4px;
122 }
123
124 .table-v3 .ui-grid-contents-wrapper{
125 clear: both;
126 }
127
128 .table-v3 .ui-grid-cell {
129 border: none ;
130 }
131
132 .table-v3 .ui-grid-header .hosts-list-checkall{
133 position: relative;
134 text-align: center;
135 }
+0
-9
faraday/server/www/views/commands/views/list/map.js less more
0 // Faraday Penetration Test IDE
1 // // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="CommandRunInformation"){
5 key = doc.command + " " + doc.params;
6 emit(key, {"startdate": doc.itime, "duration": doc.duration, "hostname": doc.hostname, "user": doc.user, "ip": doc.ip});
7 }
8 }
+0
-1
faraday/server/www/views/hosts/views/byinterfacecount/desc.txt less more
0 cuenta cantidad de interfaces por host, devuelve idHost, cant
+0
-11
faraday/server/www/views/hosts/views/byinterfacecount/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="Interface"){
5 if(doc.parent != 'null') {
6 var hid = doc._id.substring(0, doc._id.indexOf('.'));
7 emit(hid, 1);
8 }
9 }
10 }
+0
-10
faraday/server/www/views/hosts/views/byinterfacecount/reduce.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function (key, values) {
4
5 return values.reduce(function(previousValue, currentValue, index, array){
6 return previousValue + currentValue;
7 });
8
9 }
+0
-1
faraday/server/www/views/hosts/views/byservicecount/desc.txt less more
0 cuenta cantidad de servicios por host, devuelve idHost, cant
+0
-10
faraday/server/www/views/hosts/views/byservicecount/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 function(doc) {
5 if(doc.type=="Service" & (doc.status =='open' | doc.status =='running')){
6 var hid = doc._id.substring(0, doc._id.indexOf('.'));
7 emit(hid, 1);
8 }
9 }
+0
-8
faraday/server/www/views/hosts/views/byservicecount/reduce.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function (key, values) {
4 return values.reduce(function(previousValue, currentValue, index, array){
5 return previousValue + currentValue;
6 });
7 }
+0
-1
faraday/server/www/views/hosts/views/byservices/desc.txt less more
0 cuenta cantidad de servicios totales, devuelve nombreServicio, cant
+0
-11
faraday/server/www/views/hosts/views/byservices/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="Service"){
5 if(doc.parent != 'null' & (doc.status =='open' | doc.status =='running')) {
6 var hid = doc._id.substring(0, doc._id.indexOf('.'));
7 emit(doc.name, 1);
8 }
9 }
10 }
+0
-10
faraday/server/www/views/hosts/views/byservices/reduce.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function (key, values) {
4
5 return values.reduce(function(previousValue, currentValue, index, array){
6 return previousValue + currentValue;
7 });
8
9 }
+0
-1
faraday/server/www/views/hosts/views/hosts/desc.txt less more
0 cuenta hosts totales, devuelve idHost, nombreHost
+0
-19
faraday/server/www/views/hosts/views/hosts/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="Host"){
5 emit(doc._id, {
6 "_id": doc._id,
7 "_rev": doc._rev,
8 "categories": doc.categories,
9 "default_gateway": doc.default_gateway,
10 "description": doc.description,
11 "metadata": doc.metadata,
12 "name": doc.name,
13 "os": doc.os,
14 "owned": doc.owned,
15 "owner": doc.owner
16 });
17 }
18 }
+0
-1
faraday/server/www/views/hosts/views/summarized/desc.txt less more
0 cuenta cantidad de items totales, nombreItem, cant para Services, Serv owned, Hosts, Hosts owned, Interfaces, Notes, Total Vulnerabilities, Web Vulns, Common Vulns
+0
-22
faraday/server/www/views/hosts/views/summarized/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="Service") {
5 emit("services", 1);
6 } else if(doc.type=="Service" && doc.owned == "True") {
7 emit("services owned", 1);
8 } else if(doc.type=="Host") {
9 emit("hosts", 1);
10 } else if(doc.type=="Host" && doc.owned == "True") {
11 emit("hosts owned", 1);
12 } else if(doc.type=="Interface") {
13 emit("interfaces", 1);
14 } else if(doc.type=="Note") {
15 emit("notes", 1);
16 } else if(doc.type=="Vulnerability") {
17 emit("vulns", 1);
18 } else if(doc.type=="VulnerabilityWeb") {
19 emit("web vulns", 1);
20 }
21 }
+0
-10
faraday/server/www/views/hosts/views/summarized/reduce.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function (key, values) {
4
5 return values.reduce(function(previousValue, currentValue, index, array){
6 return previousValue + currentValue;
7 });
8
9 }
+0
-2
faraday/server/www/views/hosts/views/summarizedconfirmed/desc.txt less more
0 cuenta cantidad de items totales, nombreItem, cant para Services, Serv owned, Hosts, Hosts owned, Interfaces, Notes, Total Vulnerabilities, Web Vulns, Common Vulns
1 solo vulns confirmadas
+0
-22
faraday/server/www/views/hosts/views/summarizedconfirmed/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="Service") {
5 emit("services", 1);
6 } else if(doc.type=="Service" && doc.owned == "True") {
7 emit("services owned", 1);
8 } else if(doc.type=="Host") {
9 emit("hosts", 1);
10 } else if(doc.type=="Host" && doc.owned == "True") {
11 emit("hosts owned", 1);
12 } else if(doc.type=="Interface") {
13 emit("interfaces", 1);
14 } else if(doc.type=="Note") {
15 emit("notes", 1);
16 } else if(doc.type=="Vulnerability" && doc.confirmed) {
17 emit("vulns", 1);
18 } else if(doc.type=="VulnerabilityWeb" && doc.confirmed) {
19 emit("web vulns", 1);
20 }
21 }
+0
-10
faraday/server/www/views/hosts/views/summarizedconfirmed/reduce.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function (key, values) {
4
5 return values.reduce(function(previousValue, currentValue, index, array){
6 return previousValue + currentValue;
7 });
8
9 }
+0
-1
faraday/server/www/views/hosts/views/vulns/desc.txt less more
0 cuenta vulnerabilidades por prioridad, devuelve idPrioridad, cant donde idPrioridad esta entre 0 y 4 (info, low, medium, high, critical y 5 unclassified)
+0
-9
faraday/server/www/views/hosts/views/vulns/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 function(doc) {
5 if(doc.type=="Vulnerability" || doc.type=="VulnerabilityWeb") {
6 emit(doc.severity, 1);
7 }
8 }
+0
-12
faraday/server/www/views/hosts/views/vulns/reduce.js less more
0
1 // Faraday Penetration Test IDE
2 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
3 // See the file 'doc/LICENSE' for the license information
4 //
5 function (key, values) {
6
7 return values.reduce(function(previousValue, currentValue, index, array){
8 return previousValue + currentValue;
9 });
10
11 }
+0
-1
faraday/server/www/views/interfaces/views/interfaces/desc.txt less more
0 trae los todos los interfaces
+0
-12
faraday/server/www/views/interfaces/views/interfaces/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 function(doc) {
5 if(doc.type=="Interface"){
6 if(doc.parent != 'null') {
7 var hid = doc._id.substring(0, doc._id.indexOf('.'));
8 emit(hid, doc);
9 }
10 }
11 }
+0
-3
faraday/server/www/views/mapper/views/byparent/desc.txt less more
0 Get the documents grouped by parent.
1
2 The mapper needs to get the documents owned by some parent
+0
-8
faraday/server/www/views/mapper/views/byparent/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 function(doc) {
5 parent = doc.parent
6 emit(parent, {'_id': doc._id, 'type': doc.type});
7 }
+0
-3
faraday/server/www/views/mapper/views/byparentandtype/desc.txt less more
0 Get the documents grouped by parent and type.
1
2 The mapper needs to get the documents owned by some parent, and of some kind (type)
+0
-11
faraday/server/www/views/mapper/views/byparentandtype/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 function(doc) {
5 var parent = "None"
6 if (doc.parent) {
7 parent = doc.parent
8 }
9 emit([parent, doc.type], doc._id);
10 }
+0
-1
faraday/server/www/views/services/views/byhost/desc.txt less more
0 trae todos los servicios que tienen padre y usa como key el ID del host padre
+0
-17
faraday/server/www/views/services/views/byhost/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="Service"){
5 if(doc.parent != 'null') {
6 var hid = doc._id.substring(0, doc._id.indexOf('.'));
7 emit(hid, {"name": doc.name,
8 "description": doc.description,
9 "protocol": doc.protocol,
10 "ports": doc.ports,
11 "status": doc.status,
12 "owned": doc.owned,
13 "hid": hid});
14 }
15 }
16 }
+0
-1
faraday/server/www/views/services/views/byname/desc.txt less more
0 trae todos los servicios que tienen padre y usa como key el nombre del servicio
+0
-17
faraday/server/www/views/services/views/byname/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="Service"){
5 if(doc.parent != 'null' & (doc.status =='open' | doc.status =='running')) {
6 var hid = doc._id.substring(0, doc._id.indexOf('.'));
7 emit(doc.name, {"name": doc.name,
8 "description": doc.description,
9 "protocol": doc.protocol,
10 "ports": doc.ports,
11 "status": doc.status,
12 "owned": doc.owned,
13 "hid": hid});
14 }
15 }
16 }
+0
-1
faraday/server/www/views/services/views/services/desc.txt less more
0 cuenta services totales, devuelve idService, nombreService, ports, protocol.
+0
-21
faraday/server/www/views/services/views/services/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type=="Service"){
5 emit(doc._id, {
6 "_id": doc._id,
7 "_rev": doc._rev,
8 "description": doc.description,
9 "metadata": doc.metadata,
10 "name": doc.name,
11 "owned": doc.owned,
12 "owner": doc.owner,
13 "parent": doc.parent,
14 "ports": doc.ports,
15 "protocol": doc.protocol,
16 "status": doc.status,
17 "version": doc.version
18 });
19 }
20 }
+0
-1
faraday/server/www/views/utils/views/docs/desc.txt less more
0 retrieve all docs except design docs
+0
-7
faraday/server/www/views/utils/views/docs/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 function(doc){
5 emit(doc._id, doc);
6 }
+0
-1
faraday/server/www/views/vulns/views/all/desc.txt less more
0 gets all vulns from workspace, regardless of their type (regular/web).
+0
-60
faraday/server/www/views/vulns/views/all/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type == "Vulnerability" || doc.type == "VulnerabilityWeb"){
5 var easeofresolution = "",
6 impact = {
7 "accountability": false,
8 "availability": false,
9 "confidentiality": false,
10 "integrity": false
11 },
12 resolution = "",
13 confirmed = false;
14 if(doc.easeofresolution !== undefined) {
15 easeofresolution = doc.easeofresolution;
16 }
17 if(doc.impact !== undefined) {
18 impact = doc.impact;
19 }
20 if(doc.resolution !== undefined) {
21 resolution = doc.resolution;
22 }
23
24 var obj = {
25 "_id": doc._id,
26 "_rev": doc._rev,
27 "_attachments": doc._attachments,
28 "confirmed": doc.confirmed || confirmed,
29 "data": doc.data,
30 "desc": doc.desc,
31 "easeofresolution": easeofresolution,
32 "impact": impact,
33 "metadata": doc.metadata,
34 "name": doc.name,
35 "obj_id": doc.obj_id,
36 "owned": doc.owned,
37 "owner": doc.owner,
38 "parent": doc.parent,
39 "refs": doc.refs,
40 "resolution": resolution,
41 "severity": doc.severity,
42 "type": doc.type,
43 "external_id": doc.external_id,
44 };
45
46 if(doc.type == "VulnerabilityWeb") {
47 obj.method = doc.method;
48 obj.params = doc.params;
49 obj.path = doc.path;
50 obj.pname = doc.pname;
51 obj.query = doc.query;
52 obj.request = doc.request;
53 obj.response = doc.response;
54 obj.website = doc.website;
55 }
56
57 emit(doc._id, obj);
58 }
59 }
+0
-1
faraday/server/www/views/vulns/views/allconfirmed/desc.txt less more
0 gets all vulns from workspace, regardless of their type (regular/web).
+0
-59
faraday/server/www/views/vulns/views/allconfirmed/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if((doc.type == "Vulnerability" || doc.type == "VulnerabilityWeb") && doc.confirmed) {
5 var easeofresolution = "",
6 impact = {
7 "accountability": false,
8 "availability": false,
9 "confidentiality": false,
10 "integrity": false
11 },
12 resolution = "",
13 confirmed = false;
14 if(doc.easeofresolution !== undefined) {
15 easeofresolution = doc.easeofresolution;
16 }
17 if(doc.impact !== undefined) {
18 impact = doc.impact;
19 }
20 if(doc.resolution !== undefined) {
21 resolution = doc.resolution;
22 }
23
24 var obj = {
25 "_id": doc._id,
26 "_rev": doc._rev,
27 "_attachments": doc._attachments,
28 "confirmed": doc.confirmed || confirmed,
29 "data": doc.data,
30 "desc": doc.desc,
31 "easeofresolution": easeofresolution,
32 "impact": impact,
33 "metadata": doc.metadata,
34 "name": doc.name,
35 "obj_id": doc.obj_id,
36 "owned": doc.owned,
37 "owner": doc.owner,
38 "parent": doc.parent,
39 "refs": doc.refs,
40 "resolution": resolution,
41 "severity": doc.severity,
42 "type": doc.type,
43 };
44
45 if(doc.type == "VulnerabilityWeb") {
46 obj.method = doc.method;
47 obj.params = doc.params;
48 obj.path = doc.path;
49 obj.pname = doc.pname;
50 obj.query = doc.query;
51 obj.request = doc.request;
52 obj.response = doc.response;
53 obj.website = doc.website;
54 }
55
56 emit(doc._id, obj);
57 }
58 }
+0
-8
faraday/server/www/views/vulns/views/byhost/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type == "Vulnerability" || doc.type == "VulnerabilityWeb"){
5 emit(doc.parent, 1);
6 }
7 }
+0
-12
faraday/server/www/views/vulns/views/byhost/reduce.js less more
0
1 // Faraday Penetration Test IDE
2 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
3 // See the file 'doc/LICENSE' for the license information
4 //
5 function (key, values) {
6
7 return values.reduce(function(previousValue, currentValue, index, array){
8 return previousValue + currentValue;
9 });
10
11 }
+0
-1
faraday/server/www/views/vulns/views/byseverity/desc.txt less more
0 gets vulnerability count by severity for all vulns available in the workspace
+0
-8
faraday/server/www/views/vulns/views/byseverity/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type == "Vulnerability" || doc.type == "VulnerabilityWeb"){
5 emit(doc.severity, 1);
6 }
7 }
+0
-8
faraday/server/www/views/vulns/views/byseverity/reduce.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(key, values) {
4 return values.reduce(function(previousValue, currentValue, index, array) {
5 return previousValue + currentValue;
6 });
7 }
+0
-1
faraday/server/www/views/vulns/views/confirmedbyseverity/desc.txt less more
0 gets vulnerability count by severity for all vulns available in the workspace
+0
-10
faraday/server/www/views/vulns/views/confirmedbyseverity/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type == "Vulnerability" || doc.type == "VulnerabilityWeb"){
5 if(doc.confirmed) {
6 emit(doc.severity, 1);
7 }
8 }
9 }
+0
-8
faraday/server/www/views/vulns/views/confirmedbyseverity/reduce.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(key, values) {
4 return values.reduce(function(previousValue, currentValue, index, array) {
5 return previousValue + currentValue;
6 });
7 }
+0
-1
faraday/server/www/views/vulns/views/vulns/desc.txt less more
0 gets all vulnerabilities from workspace, except web ones.
+0
-45
faraday/server/www/views/vulns/views/vulns/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type == "Vulnerability"){
5 var easeofresolution = "",
6 impact = {
7 "accountability": false,
8 "availability": false,
9 "confidentiality": false,
10 "integrity": false
11 },
12 resolution = "";
13 if(doc.easeofresolution !== undefined) {
14 easeofresolution = doc.easeofresolution;
15 }
16 if(doc.impact !== undefined) {
17 impact = doc.impact;
18 }
19 if(doc.resolution !== undefined) {
20 resolution = doc.resolution;
21 }
22
23 var obj = {
24 "_rev": doc._rev,
25 "_attachments": doc._attachments,
26 "data": doc.data,
27 "desc": doc.desc,
28 "easeofresolution": easeofresolution,
29 "impact": impact,
30 "metadata": doc.metadata,
31 "name": doc.name,
32 "obj_id": doc.obj_id,
33 "owned": doc.owned,
34 "owner": doc.owner,
35 "parent": doc.parent,
36 "external_id": doc.external_id,
37 "refs": doc.refs,
38 "resolution": resolution,
39 "severity": doc.severity,
40 "type": doc.type
41 };
42 emit(doc._id, obj);
43 }
44 }
+0
-1
faraday/server/www/views/vulns/views/web/desc.txt less more
0 gets all web vulns from workspace.
+0
-54
faraday/server/www/views/vulns/views/web/map.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3 function(doc) {
4 if(doc.type == "VulnerabilityWeb"){
5 var easeofresolution = "",
6 impact = {
7 "accountability": false,
8 "availability": false,
9 "confidentiality": false,
10 "integrity": false
11 },
12 resolution = "";
13 if(doc.easeofresolution !== undefined) {
14 easeofresolution = doc.easeofresolution;
15 }
16 if(doc.impact !== undefined) {
17 impact = doc.impact;
18 }
19 if(doc.resolution !== undefined) {
20 resolution = doc.resolution;
21 }
22
23 var obj = {
24 "_rev": doc._rev,
25 "_attachments": doc._attachments,
26 "data": doc.data,
27 "desc": doc.desc,
28 "easeofresolution": easeofresolution,
29 "impact": impact,
30 "metadata": doc.metadata,
31 "name": doc.name,
32 "obj_id": doc.obj_id,
33 "owned": doc.owned,
34 "owner": doc.owner,
35 "parent": doc.parent,
36 "refs": doc.refs,
37 "resolution": resolution,
38 "severity": doc.severity,
39 "type": doc.type,
40 /*** specific fields of web vulns ***/
41 "method": doc.method,
42 "params": doc.params,
43 "path": doc.path,
44 "pname": doc.pname,
45 "query": doc.query,
46 "request": doc.request,
47 "response": doc.response,
48 "external_id": doc.external_id,
49 "website": doc.website
50 };
51 emit(doc._id, obj);
52 }
53 }
101101 ./packages/flask-security-too
102102 { };
103103
104 pyotp =
105 self.callPackage
106 ./packages/pyotp
107 { };
108
104109 simplekv =
105110 self.callPackage
106111 ./packages/simplekv
1919 pname =
2020 "faraday-plugins";
2121 version =
22 "1.4.1";
22 "1.4.4";
2323
2424 src =
2525 fetchPypi {
2727 pname
2828 version;
2929 sha256 =
30 "0jnacy9q4yv8b4hrld21qcdwsypbzndm1j9i4rwfi1lyvs78yqmp";
30 "0bcm4c0f9lhp48bzbn408m648w3b3wiq9xvfgs82kxkf6kas7q4z";
3131 };
3232
3333 propagatedBuildInputs =
2020 , flask
2121 , flask-classful
2222 , flask-kvsession-fork
23 , flask-limiter
2324 , flask-security-too
2425 , flask_login
2526 , flask_sqlalchemy
3435 , pyasn1
3536 , pylint
3637 , pyopenssl
38 , pyotp
3739 , pytest
3840 , pytest-factoryboy
3941 , pytestcov
5860 pname =
5961 "faradaysec";
6062 version =
61 "3.14.2";
63 "3.14.3";
6264
6365 src =
6466 lib.cleanSource
108110 apispec
109111 apispec-webframeworks
110112 pyyaml
113 pyotp
114 flask-limiter
111115 ];
112116 checkInputs =
113117 [
0 # WARNING: This file was automatically generated. You should avoid editing it.
1 # If you run pynixify again, the file will be either overwritten or
2 # deleted, and you will lose the changes you made to it.
3
4 { buildPythonPackage
5 , fetchPypi
6 , lib
7 }:
8
9 buildPythonPackage rec {
10 pname =
11 "pyotp";
12 version =
13 "2.6.0";
14
15 src =
16 fetchPypi {
17 inherit
18 pname
19 version;
20 sha256 =
21 "0cn4z5nv526f0l7v131piysiy9hhgbacfqd9kmmnl6qc1vadz3fj";
22 };
23
24 # TODO FIXME
25 doCheck =
26 false;
27
28 meta =
29 with lib; {
30 description =
31 "Python One Time Password Library";
32 homepage =
33 "https://github.com/pyotp/pyotp";
34 };
35 }
1010 WTForms>=2.1
1111 flask-login>=0.5.0
1212 Flask-Security-Too>=3.4.4,<4.0.0
13 marshmallow>=3.0.0
13 marshmallow>=3.0.0,<3.11.0
1414 Pillow>=4.2.1
1515 psycopg2
1616 pgcli
3131 simplekv>=0.13.0
3232 Flask-KVSession-fork>=0.6.3
3333 distro>=1.4.0
34 faraday-plugins>=1.4.1,<2.0.0
34 faraday-plugins>=1.4.4,<2.0.0
3535 apispec>=4.0.0
3636 apispec-webframeworks>=0.5.0
3737 pyyaml
38 pyotp>=2.6.0
39 Flask-Limiter
44 """
55
66 from unittest import mock
7
78 from posixpath import join as urljoin
9 import pyotp
810 import pytest
911
1012 from faraday.server.api.modules.agent import AgentWithWorkspacesView, AgentView
6062 return url
6163
6264 @mock.patch('faraday.server.api.modules.agent.faraday_server')
63 def test_create_agent_token(self, faraday_server_config, test_client, session):
64 faraday_server_config.agent_token = None
65 def test_get_agent_token(self, faraday_server_config, test_client, session):
66 faraday_server_config.agent_registration_secret = None
6567 res = test_client.get(self.check_url('/v2/agent_token/'))
66 assert 'token' in res.json
68 assert 'token' in res.json and 'expires_in' in res.json
6769 assert len(res.json['token'])
6870
6971 @mock.patch('faraday.server.api.modules.agent.faraday_server')
70 def test_create_agent_token_without_csrf_fails(self, faraday_server_config, test_client, session):
71 faraday_server_config.agent_token = None
72 def test_create_agent_token_fails(self, faraday_server_config, test_client, session):
73 faraday_server_config.agent_registration_secret = None
7274 res = test_client.post(self.check_url('/v2/agent_token/'))
73 assert res.status_code == 403
74
75 @mock.patch('faraday.server.api.modules.agent.faraday_server')
76 def test_create_new_agent_token(self, faraday_server_config, test_client, session, csrf_token):
77 faraday_server_config.agent_token = None
78 headers = {'Content-type': 'multipart/form-data'}
79 res = test_client.post(self.check_url('/v2/agent_token/'),
80 data={"csrf_token": csrf_token},
81 headers=headers,
82 use_json_data=False)
83 assert res.status_code == 200
84 assert len(res.json['token'])
75 assert res.status_code == 405
8576
8677
8778 @pytest.mark.usefixtures('logged_user')
10495 other_workspace = WorkspaceFactory.create()
10596 session.add(other_workspace)
10697 session.commit()
107 faraday_server_config.agent_token = 'sarasa'
98 secret = pyotp.random_base32()
99 faraday_server_config.agent_registration_secret = secret
108100 logout(test_client, [302])
109101 initial_agent_count = len(session.query(Agent).all())
110102 raw_data = get_raw_agent(
111103 name='new_agent',
112 token='sarasa',
104 token=pyotp.TOTP(secret).now(),
113105 workspaces=[workspace, other_workspace]
114106 )
115107 # /v2/agent_registration/
130122 workspace = WorkspaceFactory.create()
131123 session.add(workspace)
132124 session.commit()
133 faraday_server_config.agent_token = 'sarasa'
125 secret = pyotp.random_base32()
126 faraday_server_config.agent_registration_secret = secret
134127 logout(test_client, [302])
135128 initial_agent_count = len(session.query(Agent).all())
136129 raw_data = get_raw_agent(
137130 name=None,
138 token='sarasa',
131 token=pyotp.TOTP(secret).now(),
139132 workspaces=[workspace]
140133 )
141134 # /v2/agent_registration/
152145 workspace = WorkspaceFactory.create()
153146 session.add(workspace)
154147 session.commit()
155 faraday_server_config.agent_token = 'sarasa'
148 secret = pyotp.random_base32()
149 faraday_server_config.agent_registration_secret = secret
156150 logout(test_client, [302])
157151 raw_data = get_raw_agent(
158152 token="INVALID",
169163 workspace = WorkspaceFactory.create()
170164 session.add(workspace)
171165 session.commit()
172 faraday_server_config.agent_token = None
166 faraday_server_config.agent_registration_secret = None
173167 logout(test_client, [302])
174168 raw_data = get_raw_agent(
175169 name="test agent",
182176 @mock.patch('faraday.server.api.modules.agent.faraday_server')
183177 def test_create_agent_invalid_payload(self, faraday_server_config,
184178 test_client, session):
185 faraday_server_config.agent_token = None
179 faraday_server_config.agent_registration_secret = None
186180 logout(test_client, [302])
187181 raw_data = {"PEPE": 'INVALID'}
188182 # /v2/agent_registration/
195189 workspace = WorkspaceFactory.create()
196190 session.add(workspace)
197191 session.commit()
198 faraday_server_config.agent_token = 'sarasa'
192 secret = pyotp.random_base32()
193 faraday_server_config.agent_registration_secret = secret
199194 logout(test_client, [302])
200195 raw_data = get_raw_agent(
201 token="sarasa",
196 token=pyotp.TOTP(secret).now(),
202197 name="test agent",
203198 workspaces=[]
204199 )
212207 workspace = WorkspaceFactory.create()
213208 session.add(workspace)
214209 session.commit()
215 faraday_server_config.agent_token = 'sarasa'
210 secret = pyotp.random_base32()
211 faraday_server_config.agent_registration_secret = secret
216212 logout(test_client, [302])
217213 raw_data = get_raw_agent(
218 token="sarasa",
214 token=pyotp.TOTP(secret).now(),
219215 name="test agent",
220216 workspaces=[]
221217 )
230226 workspace = WorkspaceFactory.create()
231227 session.add(workspace)
232228 session.commit()
233 faraday_server_config.agent_token = 'sarasa'
229 secret = pyotp.random_base32()
230 faraday_server_config.agent_registration_secret = secret
234231 logout(test_client, [302])
235232 raw_data = get_raw_agent(
236233 name="test agent",
237 token='sarasa'
234 token=pyotp.TOTP(secret).now()
238235 )
239236 # /v2/agent_registration/
240237 res = test_client.post(self.check_url('/v2/agent_registration/'), data=raw_data)
542539 def test_happy_path_valid_json(self, test_client, session, csrf_token):
543540 agent = AgentFactory.create(workspaces=[self.workspace])
544541 executor = ExecutorFactory.create(agent=agent)
542 executor2 = ExecutorFactory.create(agent=agent)
545543
546544 session.add(executor)
547545 session.commit()
546
547 assert agent.last_run is None
548 assert executor.last_run is None
549 assert executor2.last_run is None
550
548551 payload = {
549552 'csrf_token': csrf_token,
550553 'executorData': {
562565 command_id = res.json["command_id"]
563566 command = Command.query.filter(Command.workspace_id == self.workspace.id).one()
564567 assert command_id == command.id
568 assert agent.last_run is not None
569 assert executor.last_run is not None
570 assert executor2.last_run is None
571 assert agent.last_run == executor.last_run
565572
566573 def test_invalid_json_on_executorData_breaks_the_api(self, csrf_token,
567574 session, test_client):
680680 # VulnerabilityFilterSet has duplicate fields with the same function.
681681 # This was designed to maintain backwards compatibility
682682
683 VulnerabilityGeneric.query.delete()
683 VulnerabilityGeneric.query.delete(synchronize_session='fetch')
684684
685685 # Vulns that shouldn't be shown
686686 not_expected = vulnerability_web_factory.create_batch(
2727 self.use_ldaps = ldap.use_ldaps
2828 self.use_start_tls = ldap.use_start_tls
2929
30 def test_ssl(self):
31 from faraday.server.config import ssl
32 self.certificate = ssl.certificate
33 self.keyfile = ssl.keyfile
34 self.port = ssl.port
3530
3631 def test_storage(self):
3732 from faraday.server.config import storage
+0
-222
tests_web/faradayApp/components/status_report/controllers/status_report_new_vuln_test.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 describe('StatusReport modalNewVulnCtrl', function() {
5 var $controller,
6 vm,
7 $scope;
8
9 var $cweFact,
10 cweFact,
11 targetFactMock;
12
13 var returnPromise;
14
15 var modalInstance;
16
17 beforeEach(function () {
18 module('faradayApp');
19
20 inject(function(_$rootScope_, _$controller_, _$q_) {
21 // The injector unwraps the underscores (_) from around the parameter names when matching
22 $scope = _$rootScope_.$new();
23 returnPromise = function(res) {
24 var deferred = _$q_.defer();
25 deferred.resolve(res);
26 return deferred.promise;
27 }
28
29 rejectPromise = function(res) {
30 var deferred = _$q_.defer();
31 deferred.reject(res);
32 return deferred.promise;
33 }
34
35 targetFactMock = {
36 getTargets: function(ws) {
37 return returnPromise([
38 {
39 _id: "1",
40 name: "host1",
41 hostnames: ['test1.faradaysec.com'],
42 services:[
43 {
44 _id: "1.1.1",
45 name: "srv1"
46 },
47 {
48 _id: "1.1.2",
49 name: "srv2"
50 }
51 ]
52 },
53 {
54 _id: "2",
55 name: "host2",
56 hostnames: ['test2.faradaysec.com'],
57 services:[
58 {
59 _id: "2.1.1",
60 name: "srv1"
61 },
62 {
63 _id: "2.1.2",
64 name: "srv2"
65 }
66 ]
67 },
68 {
69 _id: "3",
70 name: "host3",
71 hostnames: ['test3.faradaysec.com'],
72 services:[
73 {
74 _id: "3.1.1",
75 name: "srv1"
76 },
77 {
78 _id: "3.1.2",
79 name: "srv2"
80 }
81 ]
82 }
83 ])
84 }
85 }
86
87 cweFactMock = {
88 get: function() {
89 return returnPromise([]);
90 }
91 }
92
93 modalInstance = {
94 close: jasmine.createSpy('modalInstance.close'),
95 dismiss: jasmine.createSpy('modalInstance.dismiss')
96 }
97
98 $controller = _$controller_('modalNewVulnCtrl', {
99 $scope: $scope,
100 $modalInstance: modalInstance,
101 EASEOFRESOLUTION: ['simple', 'moderate', 'hard'],
102 severities: ['low', 'medium', 'high'],
103 workspace: 'test',
104 targetFact: targetFactMock,
105 cweFact: cweFactMock
106 });
107
108 });
109 });
110
111
112 describe('Modal controller init function', function() {
113 beforeEach(function() {
114 vm = $controller;
115 });
116 it('controller variables loaded', function() {
117 $scope.$apply();
118 vm.targets.forEach(function(target, j) {
119 expect(target.name).toEqual("host" + (j + 1));
120 expect(target.hostnames).toEqual(["test" + (j + 1) + ".faradaysec.com"]);
121 target.services.forEach(function(services, k) {
122 expect(services._id).toEqual((j + 1) + ".1." + (k + 1));
123 expect(services.name).toEqual("srv" + (k + 1));
124 });
125 });
126 });
127 });
128
129 describe('Modal controller functions', function() {
130 beforeEach(function() {
131 vm = $controller;
132 });
133 it('object changed after execution of toggleImpact function', function() {
134 $scope.$apply();
135 expect(vm.data.impact['accountability']).toEqual(false);
136 vm.toggleImpact('accountability');
137 expect(vm.data.impact['accountability']).toEqual(true);
138 });
139 it('add variable to data.refs after execution of newReference function', function() {
140 $scope.$apply();
141 vm.new_ref = "This is a new Reference";
142 vm.newReference();
143 expect(vm.data.refs).toContain({value: 'This is a new Reference'});
144
145 vm.new_ref = "This is another reference";
146 vm.newReference();
147 expect(vm.data.refs).toContain({value: 'This is another reference'});
148 });
149 it('selected is true of data.parent object execution of setTarget function', function() {
150 $scope.$apply();
151 var target = vm.targets[0];
152 vm.setTarget(target);
153 expect(vm.data.parent).toEqual(target);
154 expect(vm.data.parent.selected_modalNewCtrl).toEqual(true);
155
156 //if a service is the target
157 var service_target = target.services[0];
158 vm.setTarget(target.services[0]);
159 expect(vm.data.parent).toEqual(service_target);
160 expect(vm.data.parent.selected_modalNewCtrl).toEqual(true);
161 });
162 it('variables have proper values after execution of ok function', function() {
163 $scope.$apply();
164 var vuln = {
165 data: "data",
166 desc: "desc",
167 easeofresolution: "simple",
168 evidence: {"name": "evidence", "type":"image/vnd.microsoft.icon"},
169 impact: {
170 "accountability": true,
171 "availability": true,
172 "confidentiality": false,
173 "integrity": false
174 },
175 method: "method",
176 name: "name",
177 owned: true,
178 params: "params",
179 parent: {"_id":"d037090bfc65d5d94e95c9da29a2803249a65e0b","type":"Service"},
180 path: "path",
181 pname: "pname",
182 query: "query",
183 refs: [{value: "ref1"}, {value: "ref2"}],
184 request: "request",
185 resolution: "resolution",
186 response: "response",
187 severity: "info",
188 type: "VulnerabilityWeb",
189 website: "website"
190 };
191
192 for(var key in vuln){
193 if (vuln.hasOwnProperty(key)) {
194 vm.data[key] = vuln[key];
195 }
196 }
197 vm.ok();
198 expect(vm.data.data).toEqual('data');
199 expect(vm.data.desc).toEqual('desc');
200 expect(vm.data.easeofresolution).toEqual('simple');
201 expect(vm.data.evidence).toEqual({"name": "evidence", "type": "image/vnd.microsoft.icon"});
202 expect(vm.data.impact).toEqual({"accountability": true, "availability": true, "confidentiality": false, "integrity": false});
203 expect(vm.data.method).toEqual('method');
204 expect(vm.data.name).toEqual('name');
205 expect(vm.data.owned).toEqual(true);
206 expect(vm.data.params).toEqual('params');
207 expect(vm.data.parent).toEqual('d037090bfc65d5d94e95c9da29a2803249a65e0b');
208 expect(vm.data.path).toEqual('path');
209 expect(vm.data.pname).toEqual('pname');
210 expect(vm.data.query).toEqual('query');
211 expect(vm.data.refs).toContain('ref1');
212 expect(vm.data.refs).toContain('ref2');
213 expect(vm.data.request).toEqual('request');
214 expect(vm.data.resolution).toEqual('resolution');
215 expect(vm.data.response).toEqual('response');
216 expect(vm.data.severity).toEqual('info');
217 expect(vm.data.type).toEqual('VulnerabilityWeb');
218 expect(vm.data.website).toEqual('website');
219 });
220 });
221 });
+0
-874
tests_web/faradayApp/components/status_report/controllers/status_report_test.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 describe('statusReportCtrl', function() {
5 var $controller,
6 $scope;
7
8 var $vulnsManager,
9 vulnsManagerMock,
10 $hostsManager,
11 hostsManagerMock,
12 $workspacesFact,
13 workspacesFactMock,
14 getCurrentSelection,
15 vuln1, vuln2, vuln3;
16
17 var returnPromise;
18
19 var fakeModal = {
20 result: {
21 then: function(confirmCallback, cancelCallback) {
22 //Store the callbacks for later when the user clicks on the OK or Cancel button of the dialog
23 this.confirmCallBack = confirmCallback;
24 this.cancelCallback = cancelCallback;
25 return this;
26 }
27 },
28 close: function(item) {
29 //The user clicked OK on the modal dialog, call the stored confirm callback with the selected item
30 this.result.confirmCallBack(item);
31 },
32 dismiss: function(type) {
33 //The user clicked cancel on the modal dialog, call the stored cancel callback
34 if (this.result.cancelCallback) this.result.cancelCallback(type);
35 }
36 };
37
38 beforeEach(function () {
39 module('faradayApp');
40
41 inject(function(_$rootScope_, _$controller_, _$q_, _$modal_) {
42 // The injector unwraps the underscores (_) from around the parameter names when matching
43 $scope = _$rootScope_.$new();
44 // workspaces variables
45 vuln1 = {
46 "_id": "1.2.3.4",
47 "_rev": "1-abe16726389e434ca3f37384ea76128e",
48 "name": "Internet Key Exchange (IKE) Aggressive Mode with Pre-Shared Key",
49 "parent": "1.2.3",
50 "resolution": "Be careful",
51 "refs": [
52 "CVE-2002-1623",
53 "7423",
54 "OSVDB:3820, CERT:886601"
55 ],
56 "metadata": {
57 "update_time": 1429643049.395857,
58 "update_user": "john",
59 "update_action": 0,
60 "creator": "john",
61 "create_time": 1429643049.395857,
62 "update_controller_action": "ModelControler.newVuln",
63 "owner": "john"
64 },
65 "impact": {
66 accountability: false,
67 availability: false,
68 confidentiality: false,
69 integrity: false
70 },
71 "owned": false,
72 "severity": "med",
73 "type": "Vulnerability",
74 "owner": "john",
75 "desc": "I'm scared!",
76 "data": "",
77 "easeofresolution": "simple",
78 "description": "I'm scared!"
79 };
80 vuln2 = {
81 "_id": "1.2.3.5",
82 "_rev": "1-abe16726389e434ca3f37384ea76128e",
83 "name": "Another vuln",
84 "parent": "1.2.3",
85 "resolution": "Be careful",
86 "refs": [
87 "CVE-2002-1623",
88 "7423",
89 "OSVDB:3820, CERT:886601"
90 ],
91 "metadata": {
92 "update_time": 1429643049.395857,
93 "update_user": "john",
94 "update_action": 0,
95 "creator": "john",
96 "create_time": 1429643049.395857,
97 "update_controller_action": "ModelControler.newVuln",
98 "owner": "john"
99 },
100 "impact": {
101 accountability: false,
102 availability: false,
103 confidentiality: false,
104 integrity: false
105 },
106 "owned": false,
107 "severity": "med",
108 "type": "Vulnerability",
109 "owner": "john",
110 "desc": "I'm scared!",
111 "data": "",
112 "easeofresolution": "trivial",
113 "description": "I'm scared!"
114 };
115 vuln3 = {
116 "_id": "6.7.8.9",
117 "_rev": "3-f34c61eca3cb5ffc5654f710774708af",
118 "desc": "It was possible to identify the remote service by its banner.",
119 "metadata": {
120 "update_time": 1407530638.669383,
121 "update_user": "",
122 "update_action": 0,
123 "creator": "",
124 "create_time": 1407530638.669383,
125 "update_controller_action": "No model controller call",
126 "owner": ""
127 },
128 "easeofresolution": "simple",
129 "name": "Service Detection",
130 "obj_id": "008cba9b11897f2d52c53dd953d75fa233a7fffe",
131 "owned": false,
132 "owner": "",
133 "parent": "6.7.8",
134 "refs": [
135 ],
136 "impact": {
137 accountability: false,
138 availability: false,
139 confidentiality: false,
140 integrity: false
141 },
142 "severity": "low",
143 "type": "VulnerabilityWeb",
144 "method": "",
145 "params": "",
146 "path": "",
147 "pname": "",
148 "query": "",
149 "request": "",
150 "response": "",
151 "website": "test.test.com"
152 };
153
154 returnPromise = function(res) {
155 var deferred = _$q_.defer();
156 deferred.resolve(res);
157 return deferred.promise;
158 }
159
160 rejectPromise = function(res) {
161 var deferred = _$q_.defer();
162 deferred.reject(res);
163 return deferred.promise;
164 }
165
166 workspacesFactMock = {
167 list: function() {
168 return returnPromise(['ws1', 'ws2'])
169 }
170 }
171
172 hostsManagerMock = {
173 }
174
175 vulnsManagerMock = {
176 vulns: [],
177 getVulns: function(workspace) {
178 if (vulnsManagerMock.vulns.length == 0)
179 vulnsManagerMock.vulns = [vuln1, vuln2, vuln3];
180 return returnPromise({
181 vulnerabilities: vulnsManagerMock.vulns,
182 count: vulnsManagerMock.vulns.length});
183 },
184 deleteVuln: function(vuln) {
185 if (vuln._id === "1.2.3.4" ||
186 vuln._id === "1.2.3.5" ||
187 vuln._id === "6.7.8.9") {
188 for (var i = 0; i < vulnsManagerMock.vulns.length; i++) {
189 var v = vulnsManagerMock.vulns[i];
190 if (v._id == vuln._id) {
191 vulnsManagerMock.vulns.splice(i, 1);
192 break;
193 }
194 };
195 return returnPromise(vulnsManagerMock.vulns);
196 } else {
197 return rejectPromise("error");
198 }
199 },
200 createVuln: function(workspace, vuln) {
201 vuln["id"] = "1.2.3.6";
202 vulnsManagerMock.vulns.push(vuln);
203 return returnPromise(vuln);
204 },
205 updateVuln: function(vuln, vulnData) {
206 if (vuln._id === "1.2.3.4" ||
207 vuln._id === "1.2.3.5" ||
208 vuln._id === "6.7.8.9") {
209 angular.extend(vuln, vulnData);
210 return returnPromise();
211 } else {
212 return rejectPromise("error");
213 }
214 }
215
216 };
217
218 // fakeModal
219 spyOn(_$modal_, 'open').and.returnValue(fakeModal);
220
221 $controller = _$controller_('statusReportCtrl', {
222 $scope: $scope,
223 vulnsManager: vulnsManagerMock,
224 hostsManager: hostsManagerMock,
225 workspacesFact: workspacesFactMock,
226 $routeParams: {wsId: 'ws1'},
227 $uibModal: _$modal_,
228 });
229 });
230 });
231
232
233 describe('Status report init function without filter', function() {
234 it('vulns loaded after execution', function() {
235 $scope.$apply();
236 expect($scope.gridOptions.data.length).toEqual(3);
237 expect($scope.gridOptions.data).toContain(vuln1);
238 expect($scope.gridOptions.data).toContain(vuln2);
239 expect($scope.gridOptions.data).toContain(vuln3);
240 });
241 });
242
243 describe('Status report vuln deletion - remove method', function() {
244 it('remove valid vuln id 1.2.3.4', function() {
245 $scope.remove([vuln1]);
246 $scope.$apply();
247
248 expect($scope.gridOptions.data.length).toEqual(2);
249 expect($scope.gridOptions.data).not.toContain(vuln1);
250 expect($scope.gridOptions.data).toContain(vuln2);
251 expect($scope.gridOptions.data).toContain(vuln3);
252 });
253 it('remove invalid vuln id 9.9.9.9', function() {
254 vuln = {"_id": "9.9.9.9"}
255 $scope.remove([vuln]);
256 $scope.$apply();
257
258 expect($scope.gridOptions.data.length).toEqual(3);
259 expect($scope.gridOptions.data).toContain(vuln1);
260 expect($scope.gridOptions.data).toContain(vuln2);
261 expect($scope.gridOptions.data).toContain(vuln3);
262 });
263 it('remove valid id 1.2.3.4 and invalid id 9.9.9.9', function() {
264 vuln = {"_id": "9.9.9.9"}
265 $scope.remove([vuln1, vuln]);
266 $scope.$apply();
267
268 expect($scope.gridOptions.data.length).toEqual(2);
269 expect($scope.gridOptions.data).not.toContain(vuln1);
270 expect($scope.gridOptions.data).toContain(vuln2);
271 expect($scope.gridOptions.data).toContain(vuln3);
272 });
273 it('remove valid vulns ids', function() {
274 $scope.remove([vuln1, vuln2]);
275 $scope.$apply();
276
277 expect($scope.gridOptions.data.length).toEqual(1);
278 expect($scope.gridOptions.data).not.toContain(vuln1);
279 expect($scope.gridOptions.data).not.toContain(vuln2);
280 expect($scope.gridOptions.data).toContain(vuln3);
281 });
282 });
283
284 describe('Status report vuln deletion - delete method (modal)', function() {
285 it('call delete with no vulns selected', function() {
286 // we need $scope.gridOptions.data to have all the vulns before calling
287 // the delete method
288 $scope.getCurrentSelection = function() { return []; }
289 $scope.$apply();
290 $scope.delete();
291 $scope.$apply();
292
293 expect($scope.gridOptions.data.length).toEqual(3);
294 expect($scope.gridOptions.data).toContain(vuln1);
295 expect($scope.gridOptions.data).toContain(vuln2);
296 expect($scope.gridOptions.data).toContain(vuln3);
297 });
298 it('call delete with a valid vuln (1.2.3.4) selected and accept modal', function() {
299 // we need $scope.gridOptions.data to have all the vulns before calling
300 // the delete method
301 $scope.getCurrentSelection = function() { return [vuln1]; }
302 $scope.$apply();
303 $scope.delete();
304 fakeModal.close();
305 $scope.$apply();
306
307 expect($scope.gridOptions.data.length).toEqual(2);
308 expect($scope.gridOptions.data).not.toContain(vuln1);
309 expect($scope.gridOptions.data).toContain(vuln2);
310 expect($scope.gridOptions.data).toContain(vuln3);
311 });
312 it('call delete with a valid vuln (1.2.3.4) selected and cancel modal', function() {
313 // we need $scope.gridOptions.data to have all the vulns before calling
314 // the delete method
315 $scope.getCurrentSelection = function() { return [vuln1]; }
316 $scope.$apply();
317 $scope.delete();
318 fakeModal.dismiss();
319 $scope.$apply();
320
321 expect($scope.gridOptions.data.length).toEqual(3);
322 expect($scope.gridOptions.data).toContain(vuln1);
323 expect($scope.gridOptions.data).toContain(vuln2);
324 expect($scope.gridOptions.data).toContain(vuln3);
325 });
326 it('call delete with valid vulns selected and accept modal', function() {
327 $scope.getCurrentSelection = function() { return [vuln1, vuln2]; }
328 $scope.$apply();
329 $scope.delete();
330 fakeModal.close();
331 $scope.$apply();
332
333 expect($scope.gridOptions.data.length).toEqual(1);
334 expect($scope.gridOptions.data).not.toContain(vuln1);
335 expect($scope.gridOptions.data).not.toContain(vuln2);
336 expect($scope.gridOptions.data).toContain(vuln3);
337 });
338 });
339
340 describe('Status report vuln creation - insert method', function() {
341 it('create a valid vuln', function() {
342 var vulnNew = {
343 "name": "Just a test vuln",
344 "parent": "1.2.3",
345 "resolution": "Be careful",
346 "refs": [
347 "test"
348 ],
349 "metadata": {
350 "update_time": 1429643049.395857,
351 "update_user": "john",
352 "update_action": 0,
353 "creator": "john",
354 "create_time": 1429643049.395857,
355 "update_controller_action": "",
356 "owner": "john"
357 },
358 "owned": false,
359 "severity": "med",
360 "type": "Vulnerability",
361 "owner": "john",
362 "desc": "Test!",
363 "data": "",
364 "description": "Test!"
365 };
366 $scope.insert(vulnNew);
367 $scope.$apply();
368
369 expect($scope.gridOptions.data.length).toEqual(4);
370 expect($scope.gridOptions.data).toContain(vulnNew);
371 });
372 it('create a duplicated vuln', function() {
373 var vulnNew = {
374 "name": "Just a test vuln",
375 "parent": "1.2.3",
376 "resolution": "Be careful",
377 "refs": [
378 "test"
379 ],
380 "metadata": {
381 "update_time": 1429643049.395857,
382 "update_user": "john",
383 "update_action": 0,
384 "creator": "john",
385 "create_time": 1429643049.395857,
386 "update_controller_action": "",
387 "owner": "john"
388 },
389 "owned": false,
390 "severity": "med",
391 "type": "Vulnerability",
392 "owner": "john",
393 "desc": "Test!",
394 "data": "",
395 "description": "Test!"
396 };
397
398 // we change the mock to simulate an error during creation
399 spyOn(vulnsManagerMock, 'createVuln').and.returnValue(
400 rejectPromise("error"));
401 $scope.insert(vulnNew);
402 $scope.$apply();
403
404 expect($scope.gridOptions.data.length).toEqual(3);
405 expect($scope.gridOptions.data).not.toContain(vulnNew);
406 });
407 });
408
409 describe('Status report vuln creation - new method (modal)', function() {
410 it('create a valid vuln and accept modal', function() {
411 var vulnNew = {
412 "name": "Just a test vuln",
413 "parent": "1.2.3",
414 "resolution": "Be careful",
415 "refs": [
416 "test"
417 ],
418 "metadata": {
419 "update_time": 1429643049.395857,
420 "update_user": "john",
421 "update_action": 0,
422 "creator": "john",
423 "create_time": 1429643049.395857,
424 "update_controller_action": "",
425 "owner": "john"
426 },
427 "owned": false,
428 "severity": "med",
429 "type": "Vulnerability",
430 "owner": "john",
431 "desc": "Test!",
432 "data": "",
433 "description": "Test!"
434 };
435 $scope.new();
436 fakeModal.close(vulnNew);
437 $scope.$apply();
438
439 expect($scope.gridOptions.data.length).toEqual(4);
440 expect($scope.gridOptions.data).toContain(vulnNew);
441 });
442 it('create a valid vuln but cancel modal', function() {
443 var vulnNew = {
444 "name": "Just a test vuln",
445 "parent": "1.2.3",
446 "resolution": "Be careful",
447 "refs": [
448 "test"
449 ],
450 "metadata": {
451 "update_time": 1429643049.395857,
452 "update_user": "john",
453 "update_action": 0,
454 "creator": "john",
455 "create_time": 1429643049.395857,
456 "update_controller_action": "",
457 "owner": "john"
458 },
459 "owned": false,
460 "severity": "med",
461 "type": "Vulnerability",
462 "owner": "john",
463 "desc": "Test!",
464 "data": "",
465 "description": "Test!"
466 };
467
468 $scope.new();
469 fakeModal.dismiss();
470 $scope.$apply();
471
472 expect($scope.gridOptions.data.length).toEqual(3);
473 expect($scope.gridOptions.data).not.toContain(vulnNew);
474 });
475 });
476
477 describe('Status report vuln edition - update method', function() {
478 it('edit many vulns by property', function() {
479 $scope.getCurrentSelection = function() { return [vuln1, vuln2, vuln3]; };
480 var impact = {
481 accountability: true,
482 availability: true,
483 confidentiality: true,
484 integrity: false
485 };
486
487 $scope.$apply();
488 // String properties
489 $scope.editString('name');
490 fakeModal.close('Changed name');
491 // Text properties
492 $scope.editText('desc');
493 fakeModal.close('Changed description');
494 // Severity property
495 $scope.editSeverity();
496 fakeModal.close('high');
497 // Ease of resolution property(obj)
498 $scope.editEaseofresolution();
499 fakeModal.close('difficult');
500 // References property
501 $scope.editReferences();
502 fakeModal.close(['CVE-new-ref','OSVDB:new-ref']);
503 // Impact property(obj)
504 $scope.editImpact();
505 fakeModal.close(impact);
506 // Comfirm property
507 $scope.editConfirm();
508 fakeModal.close('Confirm');
509
510 $scope.gridOptions.data.forEach(function(v) {
511 expect(v.name).toEqual("Changed name");
512 expect(v.desc).toEqual("Changed description");
513 expect(v.severity).toEqual("high");
514 expect(v.easeofresolution).toEqual("difficult");
515 expect(v.refs).toContain('CVE-new-ref', 'OSVDB:new-ref');
516 expect(v.impact).toEqual(impact);
517 expect(v.confirmed).toEqual(true);
518 });
519 });
520 it('edit many vulns by property but cancel the modal', function() {
521 $scope.getCurrentSelection = function() { return [vuln1, vuln2, vuln3]; };
522 var impact = {
523 accountability: true,
524 availability: true,
525 confidentiality: true,
526 integrity: false
527 };
528
529 $scope.$apply();
530 // String properties
531 $scope.editString('name');
532 fakeModal.dismiss();
533 // Text properties
534 $scope.editText('desc');
535 fakeModal.dismiss();
536 // Severity property
537 $scope.editSeverity();
538 fakeModal.dismiss();
539 // Ease of resolution property(obj)
540 $scope.editEaseofresolution();
541 fakeModal.dismiss();
542 // References property
543 $scope.editReferences();
544 fakeModal.dismiss();
545 // Impact property(obj)
546 $scope.editImpact();
547 fakeModal.dismiss();
548 // Comfirm property
549 $scope.editConfirm();
550 fakeModal.dismiss();
551
552 $scope.gridOptions.data.forEach(function(v) {
553 expect(v.name).not.toEqual("Changed name");
554 expect(v.desc).not.toEqual("Changed description");
555 expect(v.severity).not.toEqual("high");
556 expect(v.easeofresolution).not.toEqual("difficult");
557 expect(v.refs).not.toContain('CVE-new-ref', 'OSVDB:new-ref');
558 expect(v.impact).not.toEqual(impact);
559 expect(v.confirmed).not.toEqual(true);
560 });
561 });
562 it('edit many vulns from CWE', function() {
563 $scope.getCurrentSelection = function() { return [vuln1, vuln2, vuln3]; };
564 var CWE_obj = {
565 name: "ES-Cisco ASA Error",
566 desc: "Summary: El cisco ASA es vulnerable",
567 refs: ['CVE-new-ref'],
568 resolution: "Actualizar la ultima version"
569 };
570
571 $scope.$apply();
572 $scope.editCWE();
573 fakeModal.close(CWE_obj);
574
575 $scope.gridOptions.data.forEach(function(v) {
576 expect(v.name).toEqual("ES-Cisco ASA Error");
577 expect(v.desc).toEqual("Summary: El cisco ASA es vulnerable");
578 expect(v.refs).toContain('CVE-new-ref');
579 expect(v.resolution).toEqual('Actualizar la ultima version');
580 });
581 });
582 it('edit many vulns from CWE but cancel the modal', function() {
583 $scope.getCurrentSelection = function() { return [vuln1, vuln2, vuln3]; };
584 var CWE_obj = {
585 name: "ES-Cisco ASA Error",
586 desc: "Summary: El cisco ASA es vulnerable",
587 refs: ['CVE-new-ref'],
588 resolution: "Actualizar la ultima version"
589 };
590
591 $scope.$apply();
592 $scope.editCWE();
593 fakeModal.dismiss();
594 $scope.$apply();
595
596 $scope.gridOptions.data.forEach(function(v) {
597 expect(v.name).not.toEqual("ES-Cisco ASA Error");
598 expect(v.desc).not.toEqual("Summary: El cisco ASA es vulnerable");
599 expect(v.refs).not.toContain('CVE-new-ref');
600 expect(v.resolution).not.toEqual('Actualizar la ultima version');
601 });
602 });
603 });
604
605 describe('Status report vuln edition - edit method (modal)', function() {
606 it('edit a vuln and accept modal', function() {
607 var vulnData = {
608 "name": "Changed name",
609 "resolution": "New resolution",
610 "refs": [
611 "test",
612 "another ref"
613 ],
614 "owned": true,
615 "severity": "high"
616 };
617
618 $scope.getCurrentSelection = function() { return [vuln1]; };
619
620 $scope.$apply();
621 $scope.edit();
622 fakeModal.close(vulnData);
623 $scope.$apply();
624
625 expect($scope.gridOptions.data.length).toEqual(3);
626 $scope.gridOptions.data.forEach(function(vuln) {
627 if (vuln._id == "1.2.3.4") {
628 expect(vuln.name).toEqual("Changed name");
629 expect(vuln.resolution).toEqual("New resolution");
630 expect(vuln.refs.length).toEqual(2);
631 expect(vuln.owned).toEqual(true);
632 expect(vuln.severity).toEqual("high");
633
634 }
635 });
636
637 });
638 it('edit a valid vuln but cancel modal', function() {
639 var vulnData = {
640 "name": "Changed name",
641 "resolution": "New resolution",
642 "refs": [
643 "test",
644 "another ref"
645 ],
646 "owned": true,
647 "severity": "high"
648 };
649 $scope.getCurrentSelection = function() { return [vuln1]; };
650 $scope.$apply();
651 $scope.edit();
652 fakeModal.dismiss();
653 $scope.$apply();
654
655 expect($scope.gridOptions.data.length).toEqual(3);
656 $scope.gridOptions.data.forEach(function(vuln) {
657 if (vuln._id == "1.2.3.4") {
658 expect(vuln.name).not.toEqual("Changed name");
659 expect(vuln.resolution).not.toEqual("New resolution");
660 expect(vuln.refs.length).not.toEqual(2);
661 expect(vuln.owned).not.toEqual(true);
662 expect(vuln.severity).not.toEqual("high");
663
664 }
665 });
666 });
667 });
668
669 describe('statusReportCtrl check all function', function() {
670 var $controller,
671 $scope;
672
673 var $vulnsManager,
674 vulnsManagerMock,
675 $workspacesFact,
676 workspacesFactMock;
677
678 var returnPromise;
679
680 beforeEach(function () {
681 module('faradayApp');
682
683 inject(function(_$rootScope_, _$controller_, _$q_, _$modal_) {
684 // The injector unwraps the underscores (_) from around the parameter names when matching
685 $scope = _$rootScope_.$new();
686 // workspaces variables
687
688 returnPromise = function(res) {
689 var deferred = _$q_.defer();
690 deferred.resolve(res);
691 return deferred.promise;
692 }
693
694 rejectPromise = function(res) {
695 var deferred = _$q_.defer();
696 deferred.reject(res);
697 return deferred.promise;
698 }
699
700 workspacesFactMock = {
701 list: function() {
702 return returnPromise(['ws1', 'ws2'])
703 }
704 }
705
706 vulnsManagerMock = {
707 vulns: [],
708 getVulns: function(workspace) {
709 vulnsManagerMock.vulns = [];
710 for (var i=0; i < 10; i++) {
711 var vuln1 = {
712 "_id": "1.2.3." + i,
713 "_rev": "1-abe16726389e434ca3f37384ea76128e",
714 "name": "vuln " + i,
715 "parent": "1.2.3",
716 "resolution": "Be careful",
717 "refs": [
718 "CVE-2002-1623",
719 "7423",
720 "OSVDB:3820, CERT:886601"
721 ],
722 "metadata": {
723 "update_time": 1429643049.395857,
724 "update_user": "john",
725 "update_action": 0,
726 "creator": "john",
727 "create_time": 1429643049.395857 + i,
728 "update_controller_action": "ModelControler.newVuln",
729 "owner": "john"
730 },
731 "owned": false,
732 "severity": "med",
733 "type": "Vulnerability",
734 "owner": "john",
735 "desc": "I'm scared!",
736 "data": "",
737 "description": "I'm scared!"
738 };
739 var vuln2 = {
740 "_id": "2.2.3." + i,
741 "_rev": "1-abe16726389e434ca3f37384ea76128e",
742 "name": "vuln " + i,
743 "parent": "2.2.3",
744 "resolution": "Be careful",
745 "refs": [
746 "CVE-2002-1623",
747 "7423",
748 "OSVDB:3820, CERT:886601"
749 ],
750 "metadata": {
751 "update_time": 1429643049.395857,
752 "update_user": "john",
753 "update_action": 0,
754 "creator": "john",
755 "create_time": 1429643049.395857 + i + 10,
756 "update_controller_action": "ModelControler.newVuln",
757 "owner": "john"
758 },
759 "owned": false,
760 "severity": "high",
761 "type": "Vulnerability",
762 "owner": "john",
763 "desc": "I'm scared!",
764 "data": "",
765 "description": "I'm scared!"
766 };
767 vulnsManagerMock.vulns.push(vuln1);
768 vulnsManagerMock.vulns.push(vuln2);
769 }
770 return returnPromise(vulnsManagerMock.vulns);
771 }
772 };
773
774 $controller = _$controller_('statusReportCtrl', {
775 $scope: $scope,
776 vulnsManager: vulnsManagerMock,
777 hostsManager: {},
778 workspacesFact: workspacesFactMock,
779 $routeParams: {wsId: 'ws1'},
780 $modal: _$modal_
781 });
782 });
783 });
784 });
785
786 describe('sort properly', function() {
787 beforeEach(function() {
788 $scope.selectall = false;
789 $scope.reverse = false;
790 $scope.pageSize = 5;
791 // we set the sort field to make sure that
792 // vulns are in the same order in every test
793 $scope.sortField = "metadata.create_time";
794 search_elem = function(aVulns, id){
795 for(var i=0; i < aVulns.length; i++){
796 if (aVulns[i]._id == id) {
797 return aVulns[i];
798 }
799 }
800 return {};
801 };
802 });
803 // it('when current page is 0', function() {
804 // $scope.currentPage = 0;
805 // $scope.$apply();
806 // $scope.checkAll();
807
808 // $scope.gridOptions.data.forEach(function(v) {
809 // if(v._id === "1.2.3.0" || v._id === "1.2.3.1" || v._id === "1.2.3.2" || v._id === "1.2.3.3" || v._id === "1.2.3.4") {
810 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).toEqual(true);
811 // } else {
812 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).not.toEqual(true);
813 // }
814 // });
815 // });
816 // it('when current page is 1', function() {
817 // $scope.currentPage = 1;
818 // $scope.$apply();
819 // $scope.checkAll();
820
821 // $scope.gridOptions.data.forEach(function(v) {
822 // if(v._id === "1.2.3.5" || v._id === "1.2.3.6" || v._id === "1.2.3.7" || v._id === "1.2.3.8" || v._id === "1.2.3.9") {
823 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).toEqual(true);
824 // } else {
825 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).not.toEqual(true);
826 // }
827 // });
828 // });
829 // it('when current page is 0 and filtering', function() {
830 // $scope.expression = {severity:"med"};
831 // $scope.$apply();
832 // $scope.checkAll();
833
834 // $scope.gridOptions.data.forEach(function(v) {
835 // if(v._id === "1.2.3.0" || v._id === "1.2.3.1" || v._id === "1.2.3.2" || v._id === "1.2.3.3" || v._id === "1.2.3.4") {
836 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).toEqual(true);
837 // } else {
838 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).not.toEqual(true);
839 // }
840 // });
841 // });
842 // it('when current page is 1 and filtering', function() {
843 // $scope.currentPage = 1;
844 // $scope.expression = {severity:"high"};
845 // $scope.$apply();
846 // $scope.checkAll();
847
848 // $scope.gridOptions.data.forEach(function(v) {
849 // if(v._id === "2.2.3.5" || v._id === "2.2.3.6" || v._id === "2.2.3.7" || v._id === "2.2.3.8" || v._id === "2.2.3.9") {
850 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).toEqual(true);
851 // } else {
852 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).not.toEqual(true);
853 // }
854 // });
855 // });
856 // it('when page size is the total of vulns', function() {
857 // $scope.currentPage = 0;
858 // $scope.pageSize = 20;
859 // $scope.expression = {severity:"high"};
860 // $scope.$apply();
861 // $scope.checkAll();
862
863 // $scope.gridOptions.data.forEach(function(v) {
864 // if(v._id.split(".")[0] === "2") {
865 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).toEqual(true);
866 // } else {
867 // expect(search_elem($scope.gridOptions.data, v._id).selected_statusreport_controller).not.toEqual(true);
868 // }
869 // });
870 // });
871 });
872
873 });
+0
-186
tests_web/faradayApp/components/vulns/providers/vuln.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 describe('Vulnerability Object', function() {
5 var Vuln,
6 $httpBackend,
7 BASEURL;
8
9 var new_data,
10 new_name,
11 new_id,
12 new_id_parent,
13 new_full_id,
14 old_data,
15 old_name,
16 old_id,
17 old_id_parent,
18 old_full_id;
19
20 // Set up the module
21 beforeEach(module('faradayApp'));
22
23 beforeEach(inject(function($injector, _$httpBackend_, _$q_, _Vuln_, _attachmentsFact_) {
24 $httpBackend = _$httpBackend_;
25 $q = _$q_;
26 Vuln = _Vuln_;
27 attachmentsFact = _attachmentsFact_;
28 BASEURL = 'http://localhost:9876/_api/';
29
30 new_name = "new name";
31 new_desc = "new desc";
32 new_id = CryptoJS.SHA1(new_name + "." + new_desc).toString();
33 new_id_parent = CryptoJS.SHA1("parent").toString();
34 new_full_id = new_id_parent + "." + new_id;
35
36 new_data = {
37 "data": "data",
38 "desc": new_desc,
39 "easeofresolution": "easeofresolution",
40 "impact": "impact",
41 "name": new_name,
42 "owned": false,
43 "parent": new_id_parent,
44 "refs": "refs",
45 "resolution": "resolution",
46 "severity": "severity",
47 "ws": "ws"
48 };
49
50 // this is used to create a web vuln that "already exists"
51 var now = new Date(),
52 old_date = now.getTime();
53
54 old_name = "old name";
55 old_desc = "old desc";
56 old_id = CryptoJS.SHA1(old_name + "." + old_desc).toString();
57 old_id_parent = CryptoJS.SHA1("parent").toString();
58 old_full_id = old_id_parent + "." + old_id;
59
60 old_data = {
61 "_id": old_full_id,
62 "_rev": "1-lalalala",
63 "data": "data",
64 "desc": old_desc,
65 "easeofresolution": "easeofresolution",
66 "impact": "impact",
67 "metadata": {
68 "update_time": old_date,
69 "update_user": "update_user",
70 "update_action": "update_action",
71 "creator": "creator",
72 "create_time": old_date,
73 "update_controller_action": "update_controller_action",
74 "owner": "owner"
75 },
76 "name": old_name,
77 "owned": false,
78 "parent": old_id_parent,
79 "refs": "refs",
80 "resolution": "resolution",
81 "severity": "severity",
82 "ws": "ws"
83 };
84 }));
85
86 afterEach(function() {
87 $httpBackend.verifyNoOutstandingExpectation();
88 $httpBackend.verifyNoOutstandingRequest();
89 });
90
91 describe('CRUD with invalid data', function() {
92 it('Setting new object', function() {
93 delete new_data.name;
94
95 expect(function() { new Vuln('ws', new_data); }).toThrowError(Error, "Unable to create Vuln without a name");
96 });
97 });
98
99 describe('CRUD with valid data', function() {
100 it('Setting new object', function() {
101 vuln = new Vuln('ws', new_data);
102
103 expect(vuln._id).toBeDefined();
104 expect(vuln._id).toEqual(new_full_id);
105 expect(vuln.type).toEqual("Vulnerability");
106
107 for(var prop in new_data) {
108 if(new_data.hasOwnProperty(prop)) {
109 expect(vuln[prop]).toEqual(new_data[prop]);
110 }
111 }
112 });
113
114 it('Setting existing object', function() {
115 vuln = new Vuln('ws', old_data);
116
117 expect(vuln._id).toBeDefined();
118 expect(vuln._id).toEqual(old_full_id);
119
120 for(var prop in old_data) {
121 if(old_data.hasOwnProperty(prop)) {
122 if(prop != "metadata") expect(vuln[prop]).toEqual(old_data[prop]);
123 }
124 }
125 });
126
127 xit('Saving new object', function() {
128 var url = BASEURL + "ws/ws/doc/" + new_full_id;
129 var vuln = new Vuln('ws', new_data);
130
131 $httpBackend.expect('PUT', url).respond(201, {"rev": "1234"});
132
133 vuln.save();
134
135 $httpBackend.flush();
136
137 expect(vuln._rev).toEqual("1234");
138 });
139
140 xit('Saving existing object', function() {
141 var url = BASEURL + "ws/ws/doc/" + old_full_id;
142 var vuln = new Vuln('ws', old_data);
143
144 $httpBackend.expect('PUT', url).respond(201, {"rev": "1234"});
145
146 vuln.save();
147
148 $httpBackend.flush();
149
150 expect(vuln._rev).toEqual("1234");
151 });
152
153 xit('Updating object', function() {
154 var url = BASEURL + "ws/ws/doc/" + new_full_id;
155 var vuln = new Vuln('ws', new_data);
156
157 $httpBackend.expect('PUT', url).respond(201, {"rev": "1234"});
158
159 delete old_data._id;
160 delete old_data._rev;
161 vuln.update(old_data);
162
163 $httpBackend.flush();
164
165 expect(vuln._rev).toEqual("1234");
166
167 for(var prop in old_data) {
168 if(old_data.hasOwnProperty(prop)) {
169 if(prop != "metadata") expect(vuln[prop]).toEqual(old_data[prop]);
170 }
171 }
172 });
173
174 it('Deleting object', function() {
175 var url = BASEURL + "ws/ws/doc/" + old_full_id + "?rev=" + old_data._rev;
176 var vuln = new Vuln('ws', old_data);
177
178 $httpBackend.expect('DELETE', url).respond(200);
179
180 vuln.remove();
181
182 $httpBackend.flush();
183 });
184 });
185 });
+0
-333
tests_web/faradayApp/components/vulns/providers/vulns.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 describe('vulnsManager', function() {
5 // Declare dependencies
6 var vulnsManager,
7 Vuln,
8 WebVuln,
9 hostsManager,
10 servicesManager;
11
12 var $filter,
13 $httpBackend,
14 $q,
15 BASEURL;
16
17 // Declare data
18 var vuln1,
19 couchVuln1,
20 vuln2,
21 couchVuln2,
22 couchVulnEmpty;
23
24 var hosts, interfaces,
25 hostnames = [];
26
27 // Set up the module
28 beforeEach(module('faradayApp'));
29
30 // Initialize data
31 beforeEach(function() {
32 vuln1 = {
33 "_id": "1.e29ba38bfa81e7f9050f6517babc14cf32cacdff",
34 "_rev": "1-abe16726389e434ca3f37384ea76128e",
35 "_attachments": {},
36 "desc": "I'm scared!",
37 "data": "",
38 "easeofresolution": 'trivial',
39 "impact": {
40 "availability": false,
41 "accountability": false,
42 "confidentiality": false,
43 "integrity": false
44 },
45 "metadata": {
46 "update_time": 1429643049.395857,
47 "update_user": "",
48 "update_action": 0,
49 "creator": "",
50 "create_time": 1429643049.395857,
51 "update_controller_action": "ModelControler.newVuln",
52 "owner": ""
53 },
54 "name": "Internet Key Exchange (IKE) Aggressive Mode with Pre-Shared Key",
55 "obj_id": "e29ba38bfa81e7f9050f6517babc14cf32cacdff",
56 "owned": false,
57 "owner": "john",
58 "parent": "1",
59 "resolution": "Be careful",
60 "refs": [
61 "CVE-2002-1623",
62 "7423",
63 "OSVDB:3820, CERT:886601"
64 ],
65 "severity": "med",
66 "type": "Vulnerability",
67 "ws": "ws"
68 };
69
70 couchVuln1 = {
71 "total_rows": 1,
72 "offset": 0,
73 "rows":[
74 {
75 "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de",
76 "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca",
77 "value": vuln1
78 }
79 ]
80 };
81
82 vuln2 = {
83 "_id": "1.e29ba38bfa81e7f9050f6517babc14cf32cacdff",
84 "_rev": "1-abe16726389e434ca3f37384ea76128e",
85 "desc": "Hello World!",
86 "data": "",
87 "metadata": {
88 "update_time": 1429643049.395857,
89 "update_user": "",
90 "update_action": 0,
91 "creator": "UI Web",
92 "create_time": 1429643049.395857,
93 "update_controller_action": "ModelControler.newVuln",
94 "owner": ""
95 },
96 "name": "Something something dark side",
97 "owned": false,
98 "owner": "john",
99 "parent": "1",
100 "resolution": "Be careful",
101 "refs": [
102 "CVE-2002-1623",
103 "7423",
104 "OSVDB:3820, CERT:886601"
105 ],
106 "severity": "med",
107 "type": "Vulnerability",
108 "ws": "ws"
109 };
110
111 couchVuln2 = {
112 "total_rows":1,
113 "offset":0,
114 "rows":[
115 {
116 "id": "1.2.3.8b4ffaedb84dd60d5f43c58eba66a7651458c8de",
117 "key":"4b84b15bff6ee5796152495a230e45e3d7e947d9.34ac3ea37a2854ce00f2d97c648bf3a7cc27ebca",
118 "value": vuln2
119 }
120 ]
121 };
122
123 couchVulnEmpty = {
124 "total_rows":0,
125 "offset":0,
126 "rows":[]
127 };
128
129 hosts = [
130 {
131 "_id": "1",
132 "name": "Host parent"
133 }
134 ];
135
136 interfaces = [
137 {
138 "parent": "1",
139 "hostnames": [
140 "h21",
141 "h22",
142 "h23"
143 ]
144 }, {
145 "parent": "1",
146 "hostnames": [
147 "h31",
148 "h32",
149 "h33"
150 ]
151 }, {
152 "parent": "1",
153 "hostnames": [
154 "h41",
155 "h42",
156 "h43"
157 ]
158 }
159 ];
160
161 services = [];
162
163 interfaces.forEach(function(interf) {
164 interf.hostnames.forEach(function(hostname) {
165 if(hostnames.indexOf(hostname) < 0) hostnames.push(hostname);
166 });
167 });
168 });
169
170 // Initialize dependencies
171 //beforeEach(inject(function($injector, _vulnsManager_, _Vuln_, _WebVuln_, _$filter_, _$httpBackend_, _$q_) {
172 beforeEach(function() {
173 var hostsManagerMock = {
174 getHosts: function(ws) {
175 var deferred = $q.defer();
176 deferred.resolve(hosts);
177 return deferred.promise;
178 },
179 getAllInterfaces: function(ws) {
180 var deferred = $q.defer();
181 deferred.resolve(interfaces);
182 return deferred.promise;
183 }
184 };
185
186 var servicesManagerMock = {
187 getServices: function(ws) {
188 var deferred = $q.defer();
189 deferred.resolve(services);
190 return deferred.promise;
191 }
192 };
193
194 module(function($provide) {
195 $provide.factory('hostsManager', function($q) { return hostsManagerMock; });
196 $provide.factory('servicesManager', function($q) { return servicesManagerMock; });
197 });
198
199 inject(function(_vulnsManager_, _Vuln_, _WebVuln_, _$filter_, _$httpBackend_, _$q_, _hostsManager_, _servicesManager_) {
200 $filter = _$filter_;
201 $httpBackend = _$httpBackend_;
202 $q = _$q_;
203 vulnsManager = _vulnsManager_;
204 Vuln = _Vuln_;
205 WebVuln = _WebVuln_;
206 hostsManager = _hostsManager_;
207 servicesManager = _servicesManager_;
208 BASEURL = 'http://localhost:9876/_api/ws/';
209 });
210
211 });
212
213 afterEach(function() {
214 $httpBackend.verifyNoOutstandingExpectation();
215 $httpBackend.verifyNoOutstandingRequest();
216 });
217
218 describe('Basic usage', function() {
219 xit('getVulns', function() {
220 var vulns;
221
222 $httpBackend.expect('GET', BASEURL + 'ws/vulns').respond(200, couchVuln1);
223
224 vulnsManager.getVulns("ws")
225 .then(function(vs) {
226 vulns = vs;
227 });
228
229 $httpBackend.flush();
230
231 expect(vulns.length).toEqual(1);
232 expect(vulnsManager.vulns.length).toEqual(1);
233
234 // promise is resolved correctly
235 vulns.forEach(function(v) {
236 for(var prop in vuln1) {
237 expect(v[prop]).toEqual(vuln1[prop]);
238 }
239 expect(v["target"]).toEqual(hosts[0].name);
240 expect(v["hostnames"]).toEqual(hostnames);
241 });
242
243 // array is updated correctly
244 vulnsManager.vulns.forEach(function(v) {
245 for(var prop in vuln1) {
246 expect(v[prop]).toEqual(vuln1[prop]);
247 }
248 expect(v["target"]).toEqual(hosts[0].name);
249 expect(v["hostnames"]).toEqual(hostnames);
250 });
251 });
252
253 xit('createVuln', function() {
254 var id = vuln1._id,
255 vuln = vuln1;
256
257 delete vuln._id;
258 delete vuln._rev;
259
260 var vulns = [];
261
262 // insert new vuln in Couch
263 $httpBackend.expect('PUT', BASEURL + "ws/doc/" + id).respond(201, {"rev": "1234"});
264
265 vulnsManager.createVuln("ws", vuln)
266 .then(function(vs) {
267 vulns = vs;
268 });
269
270 $httpBackend.flush();
271
272 expect(vulnsManager.vulns.length).toEqual(1);
273 expect(vulnsManager.vulns[0]._id).toEqual(id);
274 vulnsManager.vulns.forEach(function(v) {
275 for(var prop in vuln1) {
276 if(prop !== "metadata") expect(v[prop]).toEqual(vuln1[prop]);
277 }
278 expect(v["target"]).toEqual(hosts[0].name);
279 expect(v["hostnames"]).toEqual(hostnames);
280 });
281 });
282
283 xit('deleteVuln', function() {
284 var id = vuln1._id;
285 var vuln = angular.copy(vuln1);
286 delete vuln._id;
287 delete vuln._rev;
288
289 // insert new vuln in Couch
290 $httpBackend.expect('PUT', BASEURL + "ws/doc/" + id).respond(201, {"rev": vuln1._rev});
291
292 vulnsManager.createVuln("ws", vuln);
293
294 $httpBackend.flush();
295
296 // delete vuln
297 $httpBackend.expect('DELETE', BASEURL + 'ws/doc/' + id + "?rev=" + vuln1._rev).respond(200);
298
299 vulnsManager.deleteVuln(vulnsManager.vulns[0]);
300 $httpBackend.flush();
301
302 expect(vulnsManager.vulns.length).toEqual(0);
303 });
304
305 xit('updateVuln', function() {
306 var id = vuln1._id;
307 var vuln = angular.copy(vuln1);
308 delete vuln._id;
309 delete vuln._rev;
310
311 // insert new vuln in Couch
312 $httpBackend.expect('PUT', BASEURL + "ws/doc/" + id).respond(201, {"rev": "1234"});
313 // call to insert
314 vulnsManager.createVuln("ws", vuln);
315 $httpBackend.flush();
316
317 // update vuln
318 $httpBackend.expect('PUT', BASEURL + 'ws/doc/' + id).respond(200, {"rev": "1-abe16726389e434ca3f37384ea76128e"});
319
320 var vulns = vulnsManager.updateVuln(vulnsManager.vulns[0], vuln2);
321 $httpBackend.flush();
322
323 expect(vulnsManager.vulns.length).toEqual(1);
324
325 for(var prop in vuln2) {
326 if(vuln2.hasOwnProperty(prop)) {
327 if(prop != "metadata") expect(vulnsManager.vulns[0][prop]).toEqual(vuln2[prop]);
328 }
329 }
330 });
331 });
332 });
+0
-208
tests_web/faradayApp/components/vulns/providers/web.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 describe('WebVuln', function() {
5 var WebVuln,
6 $httpBackend,
7 BASEURL;
8
9 var new_data,
10 new_name,
11 new_website,
12 new_path,
13 new_id,
14 new_id_parent,
15 new_full_id,
16 old_data,
17 old_name,
18 old_website,
19 old_path,
20 old_id,
21 old_id_parent,
22 old_full_id;
23
24 // Set up the module
25 beforeEach(module('faradayApp'));
26
27 beforeEach(inject(function($injector, _WebVuln_) {
28 $httpBackend = $injector.get('$httpBackend');
29 WebVuln = _WebVuln_;
30 BASEURL = 'http://localhost:9876/_api/';
31
32 new_name = "new name";
33 new_website = "new website";
34 new_path = "new path";
35 new_desc = "new desc";
36 new_id = CryptoJS.SHA1(new_name + "." + new_website + "." + new_path + "." + new_desc).toString();
37 new_id_parent = CryptoJS.SHA1("parent").toString();
38 new_full_id = new_id_parent + "." + new_id;
39
40 new_data = {
41 "data": "data",
42 "desc": new_desc,
43 "easeofresolution": "easeofresolution",
44 "impact": "impact",
45 "method": "method",
46 "name": new_name,
47 "owned": false,
48 "params": "params",
49 "parent": new_id_parent,
50 "path": new_path,
51 "pname": "pname",
52 "query": "query",
53 "refs": "refs",
54 "request": "request",
55 "resolution": "resolution",
56 "response": "response",
57 "severity": "severity",
58 "website": new_website,
59 "ws": "ws"
60 };
61
62 // this is used to create a web vuln that "already exists"
63 var now = new Date(),
64 old_date = now.getTime();
65
66 old_name = "old name";
67 old_website = "old website";
68 old_path = "old path";
69 old_desc = "old desc";
70 old_id = CryptoJS.SHA1(old_name + "." + old_website + "." + old_path + "." + old_desc).toString();
71 old_id_parent = CryptoJS.SHA1("parent").toString();
72 old_full_id = old_id_parent + "." + old_id;
73
74 old_data = {
75 "_id": old_full_id,
76 "_rev": "1-lalalal",
77 "data": "data",
78 "desc": old_desc,
79 "easeofresolution": "easeofresolution",
80 "impact": "impact",
81 "metadata": {
82 "update_time": old_date,
83 "update_user": "update_user",
84 "update_action": "update_action",
85 "creator": "creator",
86 "create_time": old_date,
87 "update_controller_action": "update_controller_action",
88 "owner": "owner"
89 },
90 "method": "method",
91 "name": old_name,
92 "owned": false,
93 "params": "params",
94 "parent": old_id_parent,
95 "path": old_path,
96 "pname": "pname",
97 "query": "query",
98 "refs": "refs",
99 "request": "request",
100 "resolution": "resolution",
101 "response": "response",
102 "severity": "severity",
103 "website": old_website,
104 "ws": "ws"
105 };
106 }));
107
108 afterEach(function() {
109 $httpBackend.verifyNoOutstandingExpectation();
110 $httpBackend.verifyNoOutstandingRequest();
111 });
112
113 describe('CRUD with invalid data', function() {
114 it('Setting new object', function() {
115 delete new_data.name;
116
117 expect(function() { new WebVuln('ws', new_data); }).toThrowError(Error, "Unable to create Vuln without a name");
118 });
119 });
120
121 describe('CRUD with valid data', function() {
122 it('Setting new object', function() {
123 vuln = new WebVuln('ws', new_data);
124
125 expect(vuln._id).toBeDefined();
126 expect(vuln._id).toEqual(new_full_id);
127 expect(vuln.type).toEqual("VulnerabilityWeb");
128
129 for(var prop in new_data) {
130 if(new_data.hasOwnProperty(prop)) {
131 expect(vuln[prop]).toEqual(new_data[prop]);
132 }
133 }
134 });
135
136 it('Setting existing object', function() {
137 vuln = new WebVuln('ws', old_data);
138
139 expect(vuln._id).toBeDefined();
140 expect(vuln._id).toEqual(old_full_id);
141
142 for(var prop in old_data) {
143 if(old_data.hasOwnProperty(prop)) {
144 if(prop != "metadata") expect(vuln[prop]).toEqual(old_data[prop]);
145 }
146 }
147 });
148
149 xit('Saving new object', function() {
150 var url = BASEURL + "ws/ws/doc/" + new_full_id;
151 var vuln = new WebVuln('ws', new_data);
152
153 $httpBackend.expect('PUT', url).respond(201, {"rev": "1234"});
154
155 vuln.save();
156
157 $httpBackend.flush();
158
159 expect(vuln._rev).toEqual("1234");
160 });
161
162 xit('Saving existing object', function() {
163 var url = BASEURL + "ws/ws/doc/" + old_full_id;
164 var vuln = new WebVuln('ws', old_data);
165
166 $httpBackend.expect('PUT', url).respond(201, {"rev": "1234"});
167
168 vuln.save();
169
170 $httpBackend.flush();
171
172 expect(vuln._rev).toEqual("1234");
173 });
174
175 xit('Updating object', function() {
176 var url = BASEURL + "ws/ws/doc/" + new_full_id;
177 var vuln = new WebVuln('ws', new_data);
178
179 $httpBackend.expect('PUT', url).respond(201, {"rev": "1234"});
180
181 delete old_data._id;
182 delete old_data._rev;
183 vuln.update(old_data);
184
185 $httpBackend.flush();
186
187 expect(vuln._rev).toEqual("1234");
188
189 for(var prop in old_data) {
190 if(old_data.hasOwnProperty(prop)) {
191 if(prop != "metadata") expect(vuln[prop]).toEqual(old_data[prop]);
192 }
193 }
194 });
195
196 it('Deleting object', function() {
197 var url = BASEURL + "ws/ws/doc/" + old_full_id + "?rev=" + old_data._rev;
198 var vuln = new WebVuln('ws', old_data);
199
200 $httpBackend.expect('DELETE', url).respond(200);
201
202 vuln.remove();
203
204 $httpBackend.flush();
205 });
206 });
207 });
+0
-294
tests_web/faradayApp/components/workspaces/controllers/workspace_test.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 describe('workspacesCtrl', function() {
5 var $controller,
6 $scope;
7
8 // workspaces variables
9 var tmp_ws1 = {
10 "_id": "ws1",
11 "_rev": "2-bd88abf79cf2b7e8b419cd4387c64bef",
12 "children": [],
13 "customer": "",
14 "description": "Testing Workspaces",
15 "duration": {
16 "start": 1410832741.48194,
17 "end": 1410832741.48194
18 },
19 "name": "ws1",
20 "scope": "",
21 "selected": true,
22 "type": "Workspace"
23 };
24 var tmp_ws2 = {
25 "_id": "ws2",
26 "_rev": "10-bd88abf79cf2b7e8b419cd4387c64bef",
27 "children": [],
28 "customer": "",
29 "description": "Nuevo",
30 "duration": {
31 "startDate": 141083274148194,
32 "endDate": 141083274148194
33 },
34 "name": "ws2",
35 "scope": "",
36 "selected": true,
37 "type": "Workspace",
38 };
39 var tmp_ws3 = {
40 "_id": "ws3",
41 "_rev": "2-bd88abf79cf2b7e8b419cd4387c64bef",
42 "children": [],
43 "customer": "",
44 "description": "Testing Workspaces",
45 "duration": {
46 "start": 1410832741.48194,
47 "end": 1410832741.48194
48 },
49 "name": "ws3",
50 "scope": "",
51 "selected": true,
52 "type": "Workspace"
53 };
54
55 var $workspacesFact,
56 workspacesFactMock;
57
58 beforeEach(function () {
59 module('faradayApp');
60
61 inject(function(_$rootScope_, _$controller_, _$q_) {
62 // The injector unwraps the underscores (_) from around the parameter names when matching
63 $scope = _$rootScope_.$new();
64
65 dashboardSrvMock = {
66 getObjectsCount: function(ws) {
67 var deferred = _$q_.defer();
68 deferred.resolve([
69 {"key":"hosts","value":2},
70 {"key":"interfaces","value":2},
71 {"key":"services","value":1},
72 {"key":"total vulns","value":3},
73 {"key":"vulns","value":1},
74 {"key":"web vulns","value":2}
75 ]);
76 return deferred.promise;
77 }
78 };
79 workspacesFactMock = {
80 list: function(callback) {
81 var deferred = _$q_.defer();
82 deferred.resolve(['ws1', 'ws2']);
83 return deferred.promise;
84 },
85 update: function(workspace) {
86 var deferred = _$q_.defer();
87 deferred.resolve({
88 "_id": "ws2",
89 "_rev": "36-e56619bfa3a9ee9b09650d3fc8878d2c",
90 "children": [],
91 "customer": "",
92 "description": "Nuevo",
93 "duration": {
94 "start": 141083274148194,
95 "end": 141083274148194
96 },
97 "name": "ws2",
98 "scope": "Nuevo Scope",
99 "selected": true,
100 "type": "Workspace",
101 });
102 return deferred.promise;
103 },
104 get: function(workspace_name){
105 var objs = {
106 "ws1" : tmp_ws1,
107 "ws2" : tmp_ws2
108 };
109 var deferred = _$q_.defer();
110 deferred.resolve(objs[workspace_name]);
111 return deferred.promise;
112 },
113 put: function(workspace) {
114 var deferred = _$q_.defer();
115 deferred.resolve("");
116 return deferred.promise;
117 },
118 delete: function(workspace_name) {
119 var deferred = _$q_.defer();
120 deferred.resolve(workspace_name);
121 return deferred.promise;
122 },
123 exists: function(workspace_name){
124 return false;
125 }
126
127 };
128
129 $controller = _$controller_('workspacesCtrl', {
130 $scope: $scope,
131 dashboardSrv: dashboardSrvMock,
132 workspacesFact: workspacesFactMock
133 });
134 });
135 });
136
137
138 describe('Workspaces init function', function() {
139 beforeEach(function() {
140 spyOn(workspacesFactMock, 'get').and.callThrough();
141 });
142 it('variables are defined after execution', function() {
143 $scope.$apply();
144 expect($scope.wss).toBeDefined();
145 expect($scope.objects).toBeDefined();
146 expect($scope.workspaces).toBeDefined();
147 expect($scope.hash).toBeDefined();
148 });
149 it('variables have proper values after execution', function() {
150 $scope.$apply();
151 expect($scope.wss).toEqual(['ws1', 'ws2']);
152 expect($scope.objects).not.toEqual({});
153 expect($scope.workspaces).not.toEqual([]);
154 expect($scope.minDate).not.toEqual({});
155 expect($scope.dateOptions).not.toEqual({});
156 expect($scope.hash).not.toEqual(null);
157 expect(workspacesFactMock.get).toHaveBeenCalled();
158 $scope.workspaces.forEach(function(ws){
159 expect(ws.selected).toEqual(false);
160 });
161 expect($scope.workspaces.length).toEqual(2);
162 expect($scope.workspaces).toContain(tmp_ws1);
163 expect($scope.workspaces).toContain(tmp_ws2);
164 });
165 });
166
167 describe('Workspace update function', function() {
168 beforeEach(function() {
169 spyOn(workspacesFactMock, 'update').and.callThrough();
170 });
171 it('variables are defined after execution of update function', function() {
172
173 $scope.update(tmp_ws2);
174 $scope.$apply();
175 expect(workspacesFactMock.update).toHaveBeenCalled();
176
177 expect(workspace._id).toBeDefined();
178 expect(workspace._rev).toBeDefined();
179 expect(workspace.children).toBeDefined();
180 expect(workspace.customer).toBeDefined();
181 expect(workspace.description).toBeDefined();
182 expect(workspace.duration.start).toBeDefined();
183 expect(workspace.duration.end).toBeDefined();
184 expect(workspace.name).toBeDefined();
185 expect(workspace.scope).toBeDefined();
186 expect(workspace.selected).not.toBeDefined();
187 expect(workspace.type).toBeDefined();
188 });
189 it('variables changed after execution of update function', function() {
190 var tmp_ws2_modified = {
191 "_id": "ws2",
192 "_rev": "10-bd88abf79cf2b7e8b419cd4387c64bef",
193 "children": [],
194 "customer": "",
195 "description": "Nuevo",
196 "duration": {
197 "start": 141083274148194,
198 "end": 141083274148194
199 },
200 "name": "ws2",
201 "scope": "Nuevo Scope",
202 "selected": true,
203 "type": "Workspace",
204 };
205 $scope.$apply();
206 $scope.update(tmp_ws2_modified);
207 $scope.$apply();
208 for(var i = 0; i < $scope.workspaces.length; i++){
209 if($scope.workspaces[i]._id == workspace._id){
210 expect($scope.workspaces[i].description).toEqual(workspace.description);
211 expect($scope.workspaces[i]._rev).not.toEqual(workspace._rev);
212 expect($scope.workspaces[i].duration.start).toEqual(workspace.duration.start);
213 expect($scope.workspaces[i].duration.end).toEqual(workspace.duration.end);
214 expect($scope.workspaces[i].scope).toEqual(workspace.scope);
215 }
216 }
217 });
218 });
219
220 describe('Workspaces inserts in $scope.wss', function() {
221 beforeEach(function() {
222 spyOn(workspacesFactMock, 'put').and.callThrough();
223 spyOn($scope, 'onSuccessInsert').and.callThrough();
224 });
225 it('if put Mock is called after execution of insert function', function() {
226 $scope.insert(tmp_ws1);
227 $scope.$apply();
228
229 expect(workspacesFactMock.put).toHaveBeenCalledWith(tmp_ws1);
230 expect($scope.onSuccessInsert).toHaveBeenCalledWith(tmp_ws1);
231 });
232 it('variables update properly after execution of onSuccessInsert function', function() {
233 // define wss after execution
234 // if it is not defined, push to $scope.wss fails
235 $scope.wss = [];
236 $scope.$apply();
237 $scope.onSuccessInsert(tmp_ws3);
238 $scope.$apply();
239
240 expect($scope.wss).toContain(tmp_ws3.name);
241 expect($scope.workspaces).toContain(tmp_ws3);
242 });
243 });
244
245 describe('Workspaces object creation', function() {
246 it('tests if workspaces create object is consistent', function() {
247 var date = new Date();
248 workspace = $scope.create('wname','wdesc', date, date, '');
249 $scope.$apply();
250
251 expect(workspace._id).toBeDefined();
252 expect(workspace._rev).not.toBeDefined();
253 expect(workspace.customer).toBeDefined();
254 expect(workspace.name).toBeDefined();
255
256 expect(workspace.type).toBeDefined();
257 expect(workspace.children).toBeDefined();
258 expect(workspace.duration.start).toBeDefined();
259 expect(workspace.duration.end).toBeDefined();
260 expect(workspace.scope).toBeDefined();
261 expect(workspace.description).toBeDefined();
262
263 expect(workspace.name).toEqual('wname');
264 expect(workspace._id).toEqual('wname');
265 expect(workspace.description).toEqual('wdesc');
266 expect(workspace.duration.start).toEqual(date.getTime());
267 expect(workspace.duration.end).toEqual(date.getTime());
268 expect(workspace.scope).toEqual('');
269 });
270 });
271
272 describe('Workspaces removal properly', function() {
273 beforeEach(function() {
274 spyOn(workspacesFactMock, 'delete').and.callThrough();
275 });
276 it('tests if workspaces in scope.wss are removed after execution of remove function', function() {
277 $scope.remove('ws1');
278 $scope.$apply();
279
280 expect(workspacesFactMock.delete).toHaveBeenCalled();
281 expect($scope.wss).not.toContain('ws1');
282 });
283 it('tests if workspaces in scope.workspaces are removed after execution of onSuccessDelete function', function() {
284 $scope.onSuccessGet(tmp_ws3);
285 $scope.$apply();
286 $scope.onSuccessDelete('ws1');
287 $scope.$apply();
288
289 expect($scope.workspaces).not.toContain(tmp_ws1);
290 });
291 });
292
293 });
+0
-99
tests_web/faradayApp/components/workspaces/providers/workspaces_test.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 describe('workspacesFact', function() {
5 var $httpBackend, createFactory;
6
7 // Set up the module
8 beforeEach(module('faradayApp'));
9
10 beforeEach(inject(function($injector) {
11 // Set up the mock http service responses
12 $httpBackend = $injector.get('$httpBackend');
13 var $workspacesFact = $injector.get('workspacesFact');
14
15 createFactory = function() {
16 return $injector.get('workspacesFact', {'BASEURL' : 'http://localhost:9876/_api/',
17 '$http': $httpBackend});
18 };
19 }));
20
21
22 afterEach(function() {
23 $httpBackend.verifyNoOutstandingExpectation();
24 $httpBackend.verifyNoOutstandingRequest();
25 });
26
27 describe('Workspaces Service CRUD', function() {
28 xit('Tests if factory is well created', function() {
29 fact = createFactory();
30 });
31
32 xit('Tests if existence is well asked', function() {
33 $httpBackend.when('HEAD', 'http://localhost:9876/_api/ws/test_workspace')
34 .respond(200, '');
35
36 $httpBackend.expectHEAD('http://localhost:9876/_api/ws/test_workspace');
37 fact = createFactory();
38 fact.exists('test_workspace').then(function(exist){
39 expect(exist).toBe(true);
40 });
41 $httpBackend.flush();
42 });
43
44 xit('Tests if OK Inserts are well done', function() {
45 var workspace = {
46 "_id": "test_workspace",
47 "customer": "",
48 "name": "test_workspace",
49 "type": "Workspace",
50 "children": [
51 ],
52 "description": ""
53 };
54
55 var object = {
56 _attachments:
57 { views:
58 {"content_type": "application/javascript"}
59 }
60 };
61
62 $httpBackend.expectPUT('http://localhost:9876/_api/ws/test_workspace',
63 workspace).respond(200, {"ok": true});
64
65 $httpBackend.expectPUT('http://localhost:9876/_api/ws/test_workspace/test_workspace',
66 workspace).respond(200, {"ok": true});
67
68 $httpBackend.expectGET('http://localhost:9876/_api/ws/reports/_design/reports').respond(200, object);
69
70 $httpBackend.expectPOST('http://localhost:9876/_api/ws/test_workspace/_bulk_docs',
71 {'docs': []}).respond(200, {"ok": true});
72
73 $httpBackend.when('HEAD', 'http://localhost:9876/_api/ws/test_workspace')
74 .respond(200, '');
75
76 fact = createFactory();
77
78 fact.put(workspace);
79 fact.exists('test_workspace').then(function(exist){
80 expect(exist).toBe(true);
81 });
82 $httpBackend.flush();
83 });
84
85 xit('Tests if OK Delete are well done', function() {
86 $httpBackend.expectDELETE('http://localhost:9876/_api/ws/test_workspace').
87 respond(200, {"ok": true});
88
89 fact = createFactory();
90
91 fact.delete('test_workspace').then(function(resp) {
92 expect(resp).toBe('test_workspace');
93 });
94 $httpBackend.flush();
95 });
96 });
97
98 });
+0
-57
tests_web/karma.conf.js less more
0 // Faraday Penetration Test IDE
1 // Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
2 // See the file 'doc/LICENSE' for the license information
3
4 module.exports = function(config){
5 config.set({
6
7 basePath : './',
8
9 files : [
10 '../server/www/script/mousetrap.js',
11 '../server/www/script/jquery-1.9.1.js',
12 '../server/www/script/bootstrap.min.js',
13 '../server/www/script/angular.js',
14 '../server/www/script/angular-cookies.js',
15 '../server/www/script/angular-hotkeys.js',
16 '../server/www/script/angular-route.js',
17 '../server/www/script/angular-selection-model.js',
18 '../server/www/script/angular-file-upload-shim.js',
19 '../server/www/script/angular-file-upload.js',
20 '../server/www/script/angular-mocks.js',
21 '../server/www/script/ngClip.js',
22 '../server/www/script/ui-bootstrap-tpls-0.14.1.min.js',
23 '../server/www/script/cryptojs-sha1.js',
24 '../server/www/script/ZeroClipboard.min.js',
25 '../server/www/script/sanitize.js',
26 '../server/www/script/angular-ui-notification.min.js',
27 '../server/www/script/Chart.js',
28 '../server/www/script/angular-chart.min.js',
29 '../server/www/script/ui-grid.js',
30 '../server/www/script/moment.js',
31 '../server/www/script/angular-moment.js',
32 '../server/www/scripts/app.js',
33 '../server/www/scripts/**/*.js',
34 '../tests_web/faradayApp/components/**/*.js',
35 ],
36
37 autoWatch : true,
38
39 frameworks: ['jasmine'],
40
41 browsers : ['Chrome'],
42
43 plugins : [
44 'karma-chrome-launcher',
45 'karma-firefox-launcher',
46 'karma-jasmine',
47 'karma-junit-reporter'
48 ],
49
50 junitReporter : {
51 outputFile: 'test_out/unit.xml',
52 suite: 'unit'
53 }
54
55 });
56 };
+0
-31
tests_web/package.json less more
0 {
1 "name": "angular-seed",
2 "private": true,
3 "version": "0.0.0",
4 "description": "A starter project for AngularJS",
5 "repository": "https://github.com/angular/angular-seed",
6 "license": "MIT",
7 "devDependencies": {
8 "angular-mocks": "^1.3.0",
9 "http-server": "^0.6.1",
10 "jasmine-core": "^2.1.2",
11 "karma": "=1.4.1",
12 "karma-chrome-launcher": "^0.1.5",
13 "karma-jasmine": "^0.3.2",
14 "karma-junit-reporter": "^0.2.2",
15 "protractor": "^1.1.1",
16 "shelljs": "^0.2.6",
17 "karma-firefox-launcher": "^1.0.1"
18 },
19 "scripts": {
20 "prestart": "npm install",
21 "start": "http-server -a localhost -p 8000 -c-1",
22 "pretest": "npm install",
23 "test": "node_modules/karma/bin/karma start karma.conf.js",
24 "test-single-run": "node_modules/karma/bin/karma start karma.conf.js --single-run",
25 "preupdate-webdriver": "npm install",
26 "update-webdriver": "webdriver-manager update",
27 "preprotractor": "npm run update-webdriver",
28 "protractor": "protractor e2e-tests/protractor.conf.js"
29 }
30 }